From: Steinar H. Gunderson Date: Sun, 24 Jan 2016 21:53:17 +0000 (+0100) Subject: Use standalone tablebase probes to convert +123.xx scores to mates. It causes some... X-Git-Url: https://git.sesse.net/?p=remoteglot;a=commitdiff_plain;h=92c3ae694d679a17fe546179c06b54ac8578eb9a;hp=233222cc738d382d962f69bdcfe9eedd01ad7e43 Use standalone tablebase probes to convert +123.xx scores to mates. It causes some funny effects, but is better than nothing. --- diff --git a/Position.pm b/Position.pm index 6840e7f..c3dbcca 100644 --- a/Position.pm +++ b/Position.pm @@ -38,6 +38,7 @@ sub new { } $pos->{'last_move'} = $x[29]; $pos->{'prettyprint_cache'} = {}; + $pos->{'tbprobe_cache'} = {}; bless $pos, $class; return $pos; @@ -78,6 +79,7 @@ sub from_fen { $pos->{'last_move_uci'} = undef; $pos->{'last_move'} = undef; $pos->{'prettyprint_cache'} = {}; + $pos->{'tbprobe_cache'} = {}; bless $pos, $class; return $pos; @@ -164,6 +166,7 @@ sub to_json_hash { my $json = { %$pos, fen => $pos->fen() }; delete $json->{'board'}; delete $json->{'prettyprint_cache'}; + delete $json->{'tbprobe_cache'}; delete $json->{'black_castle_k'}; delete $json->{'black_castle_q'}; delete $json->{'white_castle_k'}; diff --git a/config.pm b/config.pm index 77fa74e..55f6d35 100644 --- a/config.pm +++ b/config.pm @@ -61,6 +61,10 @@ our @masters = ( 'Sesse', ); +# Command line to run the Fathom tablebase lookup program, if installed, +# including the --path= argument. +our $fathom_cmdline = undef; + # ChessOK serial key (of the form NNNNN-NNNNN-NNNNN-NNNNN-NNNNN-NNNNN) # for looking up 7-man tablebases; undef means no lookup. Note that # you probably need specific prior permission to use this. diff --git a/remoteglot.pl b/remoteglot.pl index 9f0ac3f..ca5263c 100755 --- a/remoteglot.pl +++ b/remoteglot.pl @@ -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; @@ -622,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]; @@ -710,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) { @@ -788,6 +854,7 @@ 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);