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 )