Chess-Plisco
view release on metacpan or search on metacpan
lib/Chess/Plisco.pm view on Meta::CPAN
$self->[CP_POS_MATERIAL] += $material_deltas[$to_move | ($promote << 1) | ($captured << 4)];
$self->[CP_POS_LAST_MOVE] = $move;
}
sub doMove {
my ($self, $move) = @_;
my @check_info = $self->inCheck;
return if !$self->checkPseudoLegalMove($move, @check_info);
my @backup = @$self;
$self->move($move);
return \@backup;
}
sub undoMove {
my ($self, $backup) = @_;
@$self = @$backup;
}
sub bMagic {
my ($self, $shift, $occupancy) = @_;
return CP_MAGICMOVESBDB->[$shift][(((($occupancy) & CP_MAGICMOVES_B_MASK->[$shift]) * CP_MAGICMOVES_B_MAGICS->[$shift]) >> 55) & ((1 << (64 - 55)) - 1)];
}
sub rMagic {
my ($self, $shift, $occupancy) = @_;
lib/Chess/Plisco.pm view on Meta::CPAN
return $self->__parseUCIMove($1, $2, $3);
}
sub perft {
my ($self, $depth) = @_;
my $nodes = 0;
my @check_info = $self->inCheck;
my @moves = $self->pseudoLegalMoves;
my @backup = @$self;
foreach my $move (@moves) {
next if !checkPseudoLegalMove($self, $move, @check_info);
$self->move($move);
if ($depth > 1) {
$nodes += perft($self, $depth - 1);
} else {
++$nodes;
}
@$self = @backup;
}
return $nodes;
}
sub perftWithOutput {
my ($self, $depth, $fh) = @_;
return if $depth <= 0;
require Time::HiRes;
my $started = [Time::HiRes::gettimeofday()];
my $nodes = 0;
my @check_info = $self->inCheck;
my @moves = $self->pseudoLegalMoves;
my @backup = @$self;
foreach my $move (@moves) {
next if !$self->checkPseudoLegalMove($move, @check_info);
my $movestr = $self->moveCoordinateNotation($move);
$fh->print("$movestr: ");
$self->move($move);
my $subnodes;
if ($depth > 1) {
$subnodes = $self->perft($depth - 1);
} else {
$subnodes = 1;
}
$nodes += $subnodes;
$fh->print("$subnodes\n");
@$self = @backup;
}
no integer;
my $elapsed = Time::HiRes::tv_interval($started, [Time::HiRes::gettimeofday()]);
my $nps = '+INF';
if ($elapsed) {
$nps = int (0.5 + $nodes / $elapsed);
}
lib/Chess/Plisco.pod view on Meta::CPAN
=item B<move(MOVE>)
Does the move B<MOVE> which must be legal because no legality check is
performed.
Unlike B<doMove()>, the method does not return state information that can be
used to later undo the move. The caller is responsible for that. A typical
pattern looks like this:
my @backup = @$position; # A shallow copy is sufficient.
foreach my $move ($position->legalMoves) {
my $state = $position->move($move);
# ... do something with $position.
@$position = @backup;
}
Consequently, there is no B<unmove()> method.
=item B<SEE(MOVE)>
Does a static exchange evaluation SEE for move B<MOVE>. B<MOVE> B<must> be
a capture, a promotion, a move giving check, or any combination of it. It
returns the raw material balance expected from the move.
lib/Chess/Plisco/Engine/Tree.pm view on Meta::CPAN
}
my $legal = 0;
my $moveno = 0;
my $pv_found;
my $is_null_window = $beta - $alpha == 1;
my $best_move = 0;
my $print_current_move = $ply == 1 && $self->{print_current_move};
my $signature_slot = $self->{history_length} + $ply;
my @check_info = $position->inCheck;
my @backup = @$position;
foreach my $move (@moves) {
next if !$position->checkPseudoLegalMove($move, @check_info);
my @line;
$position->move($move, 1);
$signatures->[$signature_slot] = $position->[CP_POS_SIGNATURE];
my $nodes_before = $self->{nodes}++;
$self->printCurrentMove($move, $legal) if $print_current_move;
my $score;
if (DEBUG) {
my $cn = $position->moveCoordinateNotation($move);
lib/Chess/Plisco/Engine/Tree.pm view on Meta::CPAN
\@line, $pv_node ? PV_NODE : NON_PV_NODE, 0, $tt_pvs,
$min_probe_ply);
}
++$legal;
++$moveno;
if (DEBUG) {
my $cn = $position->moveCoordinateNotation($move);
$self->indent($ply, "move $cn: value $score");
}
@$position = @backup;
if (DEBUG) {
pop @{$self->{line}};
}
my $root_move;
if ($node_type == ROOT_NODE) {
$root_move = $self->{root_moves}->{$move & 0xffff_ffff};
# The constants for the time management are taken from Stockfish
# and they use their own units which seem to be 3.5-4.0 centipawns.
$root_move->{average_score} =
$root_move->{average_score} != -INF ? ($score + $root_move->{average_score}) >> 1 : $score;
lib/Chess/Plisco/Engine/Tree.pm view on Meta::CPAN
$captures{$move} = $see if $see >= -80;
}
}
my @captures = sort { $captures{$b} <=> $captures{$a} || $b <=> $a } keys %captures;
@moves = (@tt, @promotions, @checks, @captures);
my $signatures = $self->{signatures};
my $signature_slot = $self->{history_length} + $ply;
my @check_info = $position->inCheck;
my @backup = @$position;
my $legal = 0;
my $best_move = 0;
foreach my $move (@moves) {
next if !$position->checkPseudoLegalMove($move, @check_info);
$position->move($move, 1);
$signatures->[$signature_slot] = $position->[CP_POS_SIGNATURE];
if (DEBUG) {
my $cn = $position->moveCoordinateNotation($move);
push @{$self->{line}}, $cn;
lib/Chess/Plisco/Engine/Tree.pm view on Meta::CPAN
++$legal;
if (DEBUG) {
$self->indent($ply, "recurse quiescence search");
}
my $score = -quiesce($self, $ply + 1, -$beta, -$alpha, $node_type, $min_probe_ply);
if (DEBUG) {
my $cn = $position->moveCoordinateNotation($move);
$self->indent($ply, "move $cn: value: $score");
pop @{$self->{line}};
}
@$position = @backup;
if ($score > $best_value) {
$best_value = $score;
if ($score > $alpha) {
$best_move = $move;
if ($score < $beta) {
if (DEBUG) {
$self->indent($ply, "raise quiescence alpha to $alpha");
}
lib/Chess/Plisco/Engine/Tree.pm view on Meta::CPAN
# First determine whether we are winning or losing.
my $winning = $wdl > 0;
if ($wdl == 0) {
# In case of a draw, we want to escape there, if we are behind.
my $static_eval = $pos->evaluate;
$winning = $static_eval > 0;
}
# Pass 1. Probe all root moves.
my $root_moves = $self->{root_moves};
my @backup = @$pos;
# Pass 2.
# Discard all moves that change the outcome of the game. They cannot be
# part of the PV.
#
# We want to order the moves by the DTZ of the position after the move
# has been made.
foreach my $move (keys %{$root_moves}) {
my $san = $pos->SAN($move);
$pos->move($move);
lib/Chess/Plisco/Engine/Tree.pm view on Meta::CPAN
if ($is_draw) {
$root_moves->{$move}->{tb_rank} = 0;
} else {
$root_moves->{$move}->{tb_rank} = $dtz;
}
}
$root_moves->{$move}->{tb_abs_dtz} = $hmc - 1 + abs $dtz;
UNDO_MOVE: @$pos = @backup; # Undo move.
}
if ($self->{tb_50_move_rule}) {
my (@drawing, @rule50, @other);
foreach my $move (keys %{$root_moves}) {
my $root_move = $root_moves->{$move};
if ($root_move->{tb_rank} == 0) {
push @drawing, $move;
} elsif ($root_move->{tb_abs_dtz} > 100) {
( run in 1.178 second using v1.01-cache-2.11-cpan-63428c044ed )