package Organism;
use strict;
# use warnings;
sub _pack {
my ( $x, $y ) = @_;
$x < 0 ? -(abs($x) << 16 | $y) : $x << 16 | $y;
}
sub _unpack {
my ( $n ) = @_;
return $n < 0
? ( -( abs($n) >> 16 ), abs($n) & 0xFFFF )
: ( $n >> 16 , $n & 0xFFFF );
}
sub count {
return scalar keys %{ shift->{Cells} };
}
# Input a list of [ x, y ] coords
sub insert_cells {
my $cells = shift->{Cells};
for my $r (@_) { $cells->{ _pack @{$r} } = undef }
}
# Return sorted list of cells in the Organism.
# Used for verification and testing the state of the organism.
sub get_live_cells {
sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] }
map { [ _unpack $_ ] }
keys %{ shift->{Cells} };
}
sub tick {
my $self = shift;
my $cells = $self->{Cells};
my ( $k1, $k2, $k3, $k4, $k5, $k6, $k7, $k8,
$x0, $x1, $x2, $y0, $y1, $y2, %new_cells, %dead_cells );
for my $c (keys %{ $cells }) {
# Get the (up to 8) dead cells surrounding the cell
( $x0, $y0 ) = $c < 0
? ( -( abs($c) >> 16 ), abs($c) & 0xFFFF )
: ( $c >> 16 , $c & 0xFFFF );
( $x1, $x2, $y1, $y2 ) = ( $x0 - 1, $x0 + 1, $y0 - 1, $y0 + 1 );
$dead_cells{$_}++ for my @zcells = (
($k1 = $x1 < 0 ? -(abs($x1) << 16 | $y1) : $x1 << 16 | $y1) x
+ !(exists $cells->{$k1}),
($k2 = $x1 < 0 ? -(abs($x1) << 16 | $y0) : $x1 << 16 | $y0) x
+ !(exists $cells->{$k2}),
($k3 = $x1 < 0 ? -(abs($x1) << 16 | $y2) : $x1 << 16 | $y2) x
+ !(exists $cells->{$k3}),
($k4 = $x0 < 0 ? -(abs($x0) << 16 | $y1) : $x0 << 16 | $y1) x
+ !(exists $cells->{$k4}),
($k5 = $x0 < 0 ? -(abs($x0) << 16 | $y2) : $x0 << 16 | $y2) x
+ !(exists $cells->{$k5}),
($k6 = $x2 < 0 ? -(abs($x2) << 16 | $y1) : $x2 << 16 | $y1) x
+ !(exists $cells->{$k6}),
($k7 = $x2 < 0 ? -(abs($x2) << 16 | $y0) : $x2 << 16 | $y0) x
+ !(exists $cells->{$k7}),
($k8 = $x2 < 0 ? -(abs($x2) << 16 | $y2) : $x2 << 16 | $y2) x
+ !(exists $cells->{$k8}) );
# Check the live cell
# Note: next line equivalent to nlive == 2 || nlive == 3
@zcells == 5 || @zcells == 6 and $new_cells{$c} = undef;
}
$dead_cells{$_} == 3 and $new_cells{$_} = undef for keys %dead_cell
+s;
$self->{Cells} = \%new_cells;
}
sub new {
my $class = shift;
my %init_self = ( Cells => {} );
bless \%init_self, $class;
}
1;