+my %tbprobe_cache = ();
+
+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 = $pos->fen() . " " . join('', @pv);
+ my @moves = ();
+ if (exists($tbprobe_cache{$key})) {
+ @moves = @{$tbprobe_cache{$key}};
+ } else {
+ if ($mpv ne '') {
+ # Force doing at least one move of the PV.
+ my $move = shift @pv;
+ push @moves, $move;
+ $pos = $pos->make_move(parse_uci_move($move));
+ }
+
+ 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;
+ }
+
+ $tbprobe_cache{$key} = \@moves;
+ }
+
+ $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;
+ }
+}
+