Games-Nonogram
view release on metacpan or search on metacpan
lib/Games/Nonogram/Clue.pm view on Meta::CPAN
if ( $block->left == $id ) {
my $left = $block->left;
$self->line->on( $_ ) for ( $left .. $left + $offset );
}
if ( $block->right == $id ) {
my $right = $block->right;
$self->line->on( $_ ) for ( $right - $offset .. $right );
}
}
sub off {
my ($self, $id) = @_;
$self->line->off( $id );
foreach my $block ( $self->blocks ) {
$block->cant_have( $id );
}
my $block = $self->might_have( $id );
return unless ref $block;
my $offset = $block->length - 1;
my $left = $id + 1;
$block->left( $left ) if $block->left + $offset > $left;
my $right = $id - 1;
$block->right( $right ) if $block->right - $offset < $right;
}
sub value {
my ($self, $id, $value) = @_;
if ( defined $value ) {
if ( $value == 0 ) { $self->off( $id ) }
elsif ( $value == 1 ) { $self->on( $id ) }
}
else {
$self->line->value( $id );
}
}
sub might_have {
my ($self, $id) = @_;
my $hit;
foreach my $block ( $self->blocks ) {
if ( $block->might_have( $id ) ) {
return -1 if $hit; # multiple candidates; cannot decide
$hit = $block;
}
}
return $hit ? $hit : 0;
}
sub update {
my ($self, $mode) = @_;
unless ( $mode ) {
$self->_update_basic;
}
elsif ( $mode eq 'more' ) {
$self->_update_more;
}
foreach my $ct ( 1 .. $self->size ) {
my $block = $self->might_have( $ct );
unless ( $block ) {
$self->off( $ct );
}
elsif ( ref $block ) {
my $value = $self->line->value( $ct );
if ( $value == -1 ) {
$self->on( $ct ) if $block->must_have( $ct );
}
elsif ( $value == 0 ) {
$self->off( $ct );
}
elsif ( $value == 1 ) {
$self->on( $ct ) unless $block->must_have( $ct );
}
}
}
}
sub _update_basic {
my $self = shift;
my $left = 1;
foreach my $block ( $self->blocks ) {
$left = $block->left if $block->left > $left;
while (
$self->line->value( $left ) == 0
or
$left > 1 && $self->line->value( $left - 1 ) == 1
) {
$left++;
if ( $left > $self->size ) {
die "puzzle data may be broken, unless you're trying to solve by brute force";
}
}
$block->left( $left );
$left += ( $block->length + 1 );
}
my $right = $self->size;
foreach my $block ( reverse $self->blocks ) {
$right = $block->right if $block->right < $right;
while (
$self->line->value( $right ) == 0
or
$right < $self->size && $self->line->value( $right + 1 ) == 1
) {
( run in 0.990 second using v1.01-cache-2.11-cpan-39bf76dae61 )