#! perl -w use lib "/afs/sipb.mit.edu/user/kenta/chess-rep-0.4/share/perl/5.8.8"; use Chess::Rep; use Expect; use strict; $::command = "./glaurung"; $::killswitch = "killswitch"; $::matemult=100000; #die unless $ARGV[0] =~ /^\d+$/; $::timethink=$ARGV[0]; shift @ARGV; &start_engine; &main; $::exp->send("quit\n"); $::exp->soft_close(); sub main { #@moves_so_far=qw/c2c4 g8f6 c4c5 f6g8 c5c6 g8f6 c6b7 f6g8/; print << 'EOF';
$ARGV[1], Pondering move ",(2+scalar@moves_so_far)/2, ", Glaurung $::timethink
\n\n"; my $rep=Chess::Rep->new; my $canon=""; my $parity=1; for(@moves_so_far){ $canon.=" ".canonicalmove($rep,$_); $parity=not$parity; } $canon.=" "; my $current_fen=$rep->get_fen(); my @themoves=basic_algebraic_moves(@{$rep->status->{moves}}); print STDERR "$canon\n"; my $total=@themoves; my %continuation_score; my $count=1; for(@themoves){ if (-e $::killswitch) { unlink $::killswitch; die "killswitch"; } my($computer,$score,$pv,$depth,$nps)= &engine($canon.$_,$::timethink); print STDERR " $count/$total is $_ -> $computer $score/$depth $nps $pv \n"; $count++; my@sans=san_sequence($current_fen,$_,split /\s+/,$pv); my$line=&concat_san(@sans)." depth $depth nps $nps"; $continuation_score{$line}=$score; } my@sorted_keys=(sort {score_compare($continuation_score{$a},$continuation_score{$b})} (keys %continuation_score)); $count=1; for (@sorted_keys){ my $i; if ($parity){ $i=invert_score($continuation_score{$_}); }else{ $i=$continuation_score{$_}; } print "$count. $i: $_\n"; $count++; } print "\n
Moves:\n",&concat_san(@moves_so_far); print"
\n\nFEN $current_fen
\n"; print << 'EOF';See the RCS file for previous moves. Here is the script used to generate this analysis.
"cp" = centi-pawn
EOF } sub engine { my $movelist1=shift; my $timethink=shift; #print "movelist1 $movelist1\n"; $::exp->send( << "EOF" ucinewgame position startpos moves $movelist1 go $timethink EOF #go wtime $two btime $two winc $hour binc $hour ); my($depth,$score,$pv,$nps); for(;;){ if (-e $::killswitch) { unlink $::killswitch; die "killswitch internal"; } #($matched_pattern_position, $error, $successfully_matching_string, $before_match, $after_match); my@expect_result=$::exp->expect(undef,("-re",'bestmove.*\r',"-re",'info depth.*score.*\r')) or die; my$successfully_matching_string=$expect_result[2]; #print STDERR "gotsms $successfully_matching_string\n"; if ($successfully_matching_string =~ /info depth .* score.*/){ die unless ($depth,$score,$nps,$pv)=($successfully_matching_string =~ /info depth (\d+) score (.*) time .* nodes .* nps (.*) pv (.*)/); } last if $successfully_matching_string =~ /bestmove/; } my$gotmatch=$::exp->match; die $_ unless $gotmatch=~/bestmove (\S+)/; my $computermove=$1; #print "$computermove: score $score, pv $pv\n"; ($computermove,$score,$pv,$depth,$nps) } sub basic_algebraic_moves { my @yesmoves; for(@_){ #printf("%02x ",$$_{piece}); my$go=lc(Chess::Rep::get_field_id($$_{from}) .Chess::Rep::get_field_id($$_{to})); if (($$_{piece}==0x81 and (Chess::Rep::get_row_col($$_{to}))[0] == 7) or ($$_{piece}==0x01 and (Chess::Rep::get_row_col($$_{to}))[0] == 0)) { for my $p (qw/n b r q/){ push @yesmoves,"$go$p" } } else { push @yesmoves,$go; } } @yesmoves; } sub canonicalmove { my($rep,$usermove)=@_; die if $rep->status->{mate}; die if $rep->status->{stalemate}; my %rh=%{${$rep->status}{hash_moves}}; my $r; eval {$r=$rep->go_move($usermove);}; if ($@){ print "Died $@\n"; die; } unless ($rh{"$$r{from_index}-$$r{to_index}"}) { print "bad\n"; die; } if ($$r{piece} eq 'P' and $$r{to_row}==7 and not $$r{promote}) { die "need promotion"; } my $gomove="$$r{from}$$r{to}"; $gomove .= $$r{promote} if ($$r{promote}); $gomove=lc$gomove; } sub san_sequence { my $current_fen=shift; my $rep=Chess::Rep->new($current_fen); my @sans; for(@_){ #print "doing $_\n"; my $result=$rep->go_move($_); push @sans,$$result{san} } @sans; } sub mate_convert { my $rawmoves=shift; if ($rawmoves<0){ -($::matemult+$rawmoves); } elsif ($rawmoves>0){ $::matemult-$rawmoves; } else { die "cannot convert $rawmoves" ; } } sub string_convert { if ($_[0] =~ /cp\s+(\S+)/) { $1; } elsif ($_[0] =~ /mate\s+(\S*)/){ &mate_convert($1); } else { die "cant convert $_[0]"; } } sub score_compare { (&string_convert($_[0])<=>(&string_convert($_[1]))); } sub concat_san { my $o=""; for(@_){ $o.=" $_"; } $o; } sub invert_score { my $answer; for($_[0]){ die "$_" unless /(.*)\s+(-?\d+)/; $answer=$1." ".(0-$2); } $answer; } sub start_engine { $::exp = Expect->spawn($::command) or die; $::exp->log_stdout(0); $::exp->log_file("/tmp/glauxz12.log"); $::exp->expect(15, ("Tord Romstad.\r")) or die; $::exp->send("uci\n"); $::exp->expect(5,("uciok\r")) or die; $::exp->send("isready\n"); $::exp->expect(5,"readyok\r") or die; }