]> git.sesse.net Git - remoteglot/blobdiff - remoteglot.pl
Put a one-move PV on even the not-found hash probe entries, so they are selectable.
[remoteglot] / remoteglot.pl
index e605b8733eb3a551a5f7a0cdda8f9170c8172bfe..2c5fd9f31cdba5d6649122b288d7211b28a9b4a0 100755 (executable)
@@ -5,7 +5,7 @@
 #              analysis, or for live analysis of relayed games. (Do not use for
 #              cheating! Cheating is bad for your karma, and your abuser flag.)
 #
-# Copyright 2007 Steinar H. Gunderson <sgunderson@bigfoot.com>
+# Copyright 2007 Steinar H. Gunderson <steinar+remoteglot@gunderson.no>
 # Licensed under the GNU General Public License, version 2.
 #
 
@@ -530,6 +530,61 @@ sub prettyprint_pv {
        }
 }
 
+sub complete_using_tbprobe {
+       my ($pos, $info, $mpv) = @_;
+
+       # We need Fathom installed to do standalone TB probes.
+       return if (!defined($remoteglotconf::fathom_cmdline));
+
+       # If we already have a mate, don't bother; in some cases, it would even be
+       # better than a tablebase score.
+       return if defined($info->{'score_mate' . $mpv});
+
+       # If we have a draw or near-draw score, there's also not much interesting
+       # we could add from a tablebase. We only really want mates.
+       return if ($info->{'score_cp' . $mpv} >= -12250 && $info->{'score_cp' . $mpv} <= 12250);
+
+       # Run through the PV until we are at a 6-man position.
+       # TODO: We could in theory only have 5-man data.
+       my @pv = @{$info->{'pv' . $mpv}};
+       my $key = join('', @pv);
+       my @moves = ();
+       if (exists($pos->{'tbprobe_cache'}{$key})) {
+               @moves = $pos->{'tbprobe_cache'}{$key};
+       } else {
+               while ($pos->num_pieces() > 6 && $#pv > -1) {
+                       my $move = shift @pv;
+                       push @moves, $move;
+                       $pos = $pos->make_move(parse_uci_move($move));
+               }
+
+               return if ($pos->num_pieces() > 6);
+
+               my $fen = $pos->fen();
+               my $pgn_text = `fathom --path=/srv/syzygy "$fen"`;
+               my $pgn = Chess::PGN::Parse->new(undef, $pgn_text);
+               return if (!defined($pgn) || !$pgn->read_game() || ($pgn->result ne '0-1' && $pgn->result ne '1-0'));
+               $pgn->quick_parse_game;
+               $info->{'pv' . $mpv} = \@moves;
+
+               # Splice the PV from the tablebase onto what we have so far.
+               for my $move (@{$pgn->moves}) {
+                       my $uci_move;
+                       ($pos, $uci_move) = $pos->make_pretty_move($move);
+                       push @moves, $uci_move;
+               }
+       }
+
+       $info->{'pv' . $mpv} = \@moves;
+
+       my $matelen = int((1 + scalar @moves) / 2);
+       if ((scalar @moves) % 2 == 0) {
+               $info->{'score_mate' . $mpv} = -$matelen;
+       } else {
+               $info->{'score_mate' . $mpv} = $matelen;
+       }
+}
+
 sub output {
        #return;
 
@@ -594,6 +649,8 @@ sub output {
                for my $key (qw(pv score_cp score_mate nodes nps depth seldepth tbhits)) {
                        if (exists($info->{$key . '1'})) {
                                $info->{$key} = $info->{$key . '1'};
+                       } else {
+                               delete $info->{$key};
                        }
                }
        }
@@ -620,6 +677,17 @@ sub output {
                return;
        }
 
+       # Now do our own Syzygy tablebase probes to convert scores like +123.45 to mate.
+       if (exists($info->{'pv'})) {
+               complete_using_tbprobe($pos_calculating, $info, '');
+       }
+
+       my $mpv = 1;
+       while (exists($info->{'pv' . $mpv})) {
+               complete_using_tbprobe($pos_calculating, $info, $mpv);
+               ++$mpv;
+       }
+
        output_screen();
        output_json(0);
        $latest_update = [Time::HiRes::gettimeofday];
@@ -708,8 +776,8 @@ sub output_screen {
                        my $info = $engine2->{'info'};
                        last if (!exists($info->{'pv' . $mpv}));
                        eval {
+                               complete_using_tbprobe($pos_calculating_second_engine, $info, $mpv);
                                my $pv = $info->{'pv' . $mpv};
-
                                my $pretty_move = join('', prettyprint_pv($pos_calculating_second_engine, $pv->[0]));
                                my @pretty_pv = prettyprint_pv($pos_calculating_second_engine, @$pv);
                                if (scalar @pretty_pv > 5) {
@@ -786,13 +854,14 @@ sub output_json {
                        last if (!exists($info->{'pv' . $mpv}));
 
                        eval {
+                               complete_using_tbprobe($pos_calculating, $info, $mpv);
                                my $pv = $info->{'pv' . $mpv};
                                my $pretty_move = join('', prettyprint_pv($pos_calculating, $pv->[0]));
                                my @pretty_pv = prettyprint_pv($pos_calculating, @$pv);
                                $refutation_lines{$pv->[0]} = {
                                        sort_key => $pretty_move,
                                        depth => $info->{'depth' . $mpv},
-                                       score_sort_key => score_sort_key($info, $pos_calculating, $mpv, 0),
+                                       score_sort_key => score_sort_key($info, $mpv, 0),
                                        pretty_score => short_score($info, $pos_calculating, $mpv),
                                        pretty_move => $pretty_move,
                                        pv_pretty => \@pretty_pv,
@@ -983,7 +1052,7 @@ sub short_score {
 }
 
 sub score_sort_key {
-       my ($info, $pos, $mpv, $invert) = @_;
+       my ($info, $mpv, $invert) = @_;
 
        if (defined($info->{'score_mate' . $mpv})) {
                my $mate = $info->{'score_mate' . $mpv};