]> git.sesse.net Git - remoteglot/blobdiff - remoteglot.pl
Fix another Chess960 Chess.js issue.
[remoteglot] / remoteglot.pl
index 00e470763fafeb65ee56ea62ebdf7c33697aa67d..d8a7925c9137cfe548b0b9729a98f8daf3defac7 100755 (executable)
@@ -76,17 +76,11 @@ my $last_move;
 my $last_text = '';
 my ($pos_calculating, $pos_calculating_second_engine);
 
-uciprint($engine, "setoption name UCI_AnalyseMode value true");
-while (my ($key, $value) = each %remoteglotconf::engine_config) {
-       uciprint($engine, "setoption name $key value $value");
-}
+setoptions($engine, \%remoteglotconf::engine_config);
 uciprint($engine, "ucinewgame");
 
 if (defined($engine2)) {
-       uciprint($engine2, "setoption name UCI_AnalyseMode value true");
-       while (my ($key, $value) = each %remoteglotconf::engine2_config) {
-               uciprint($engine2, "setoption name $key value $value");
-       }
+       setoptions($engine2, \%remoteglotconf::engine2_config);
        uciprint($engine2, "setoption name MultiPV value 500");
        uciprint($engine2, "ucinewgame");
 }
@@ -124,7 +118,7 @@ if (defined($remoteglotconf::server)) {
        );
 }
 if (defined($remoteglotconf::target)) {
-       if ($remoteglotconf::target =~ /^https?:/) {
+       if ($remoteglotconf::target =~ /^(?:\/|https?:)/) {
                fetch_pgn($remoteglotconf::target);
        } elsif (defined($t)) {
                $t->cmd("observe $remoteglotconf::target");
@@ -248,9 +242,26 @@ sub handle_fics {
 # Starts periodic fetching of PGNs from the given URL.
 sub fetch_pgn {
        my ($url) = @_;
-       AnyEvent::HTTP::http_get($url, sub {
-               handle_pgn(@_, $url);
-       });
+       if ($url =~ m#^/#) {  # Local file.
+               eval {
+                       local $/ = undef;
+                       open my $fh, "<", $url
+                               or die "$url: $!";
+                       my $pgn = <$fh>;
+                       close $fh;
+                       handle_pgn($pgn, '', $url);
+               };
+               if ($@) {
+                       warn "$url: $@";
+                       $http_timer = AnyEvent->timer(after => 1.0, cb => sub {
+                               fetch_pgn($url);
+                       });
+               }
+       } else {
+               AnyEvent::HTTP::http_get($url, sub {
+                       handle_pgn(@_, $url);
+               });
+       }
 }
 
 my ($last_pgn_white, $last_pgn_black);
@@ -286,7 +297,23 @@ sub handle_pgn {
                        my $black = $pgn->black;
                        $white =~ s/,.*//;  # Remove first name.
                        $black =~ s/,.*//;  # Remove first name.
-                       my $pos = Position->start_pos($white, $black);
+                       my $tags = $pgn->tags();
+                       my $pos;
+                       if (exists($tags->{'FEN'})) {
+                               $pos = Position->from_fen($tags->{'FEN'});
+                               $pos->{'last_move'} = 'none';
+                               $pos->{'player_w'} = $white;
+                               $pos->{'player_b'} = $black;
+                               $pos->{'start_fen'} = $tags->{'FEN'};
+                       } else {
+                               $pos = Position->start_pos($white, $black);
+                       }
+                       if (exists($tags->{'Variant'}) &&
+                           $tags->{'Variant'} =~ /960|fischer/i) {
+                               $pos->{'chess960'} = 1;
+                       } else {
+                               $pos->{'chess960'} = 0;
+                       }
                        my $moves = $pgn->moves;
                        my @uci_moves = ();
                        my @repretty_moves = ();
@@ -377,6 +404,10 @@ sub handle_position {
        # It's wrong to just give the FEN (the move history is useful,
        # and per the UCI spec, we should really have sent "ucinewgame"),
        # but it's easier, and it works around a Stockfish repetition issue.
+       if ($engine->{'chess960'} != $pos->{'chess960'}) {
+               uciprint($engine, "setoption name UCI_Chess960 value " . ($pos->{'chess960'} ? 'true' : 'false'));
+               $engine->{'chess960'} = $pos->{'chess960'};
+       }
        uciprint($engine, "position fen " . $pos->fen());
        uciprint($engine, "go infinite");
        $pos_calculating = $pos;
@@ -386,6 +417,10 @@ sub handle_position {
                        $engine2->{'stopping'} = 1;
                        uciprint($engine2, "stop");
                }
+               if ($engine2->{'chess960'} != $pos->{'chess960'}) {
+                       uciprint($engine2, "setoption name UCI_Chess960 value " . ($pos->{'chess960'} ? 'true' : 'false'));
+                       $engine2->{'chess960'} = $pos->{'chess960'};
+               }
                uciprint($engine2, "position fen " . $pos->fen());
                uciprint($engine2, "go infinite");
                $pos_calculating_second_engine = $pos;
@@ -550,13 +585,13 @@ sub complete_using_tbprobe {
                        $pos = $pos->make_move(parse_uci_move($move));
                }
 
-               while ($pos->num_pieces() > 6 && $#pv > -1) {
+               while ($pos->num_pieces() > 7 && $#pv > -1) {
                        my $move = shift @pv;
                        push @moves, $move;
                        $pos = $pos->make_move(parse_uci_move($move));
                }
 
-               return if ($pos->num_pieces() > 6);
+               return if ($pos->num_pieces() > 7);
 
                my $fen = $pos->fen();
                my $pgn_text = `fathom --path=/srv/syzygy "$fen"`;
@@ -568,6 +603,9 @@ sub complete_using_tbprobe {
                # Splice the PV from the tablebase onto what we have so far.
                for my $move (@{$pgn->moves}) {
                        last if $move eq '#';
+                       last if $move eq '1-0';
+                       last if $move eq '0-1';
+                       last if $move eq '1/2-1/2';
                        my $uci_move;
                        ($pos, $uci_move) = $pos->make_pretty_move($move);
                        push @moves, $uci_move;
@@ -880,7 +918,13 @@ sub output_json {
 
                local $dbh->{AutoCommit} = 0;
                my $q = $dbh->prepare('SELECT * FROM scores WHERE id=?');
-               my $pos = Position->start_pos('white', 'black');
+               my $pos;
+               if (exists($pos_calculating->{'start_fen'})) {
+                       $pos = Position->from_fen($pos_calculating->{'start_fen'});
+               } else {
+                       $pos = Position->start_pos('white', 'black');
+               }
+               $pos->{'chess960'} = $pos_calculating->{'chess960'};
                my $halfmove_num = 0;
                for my $move (@{$pos_calculating->{'history'}}) {
                        my $id = id_for_pos($pos, $halfmove_num);
@@ -1275,7 +1319,7 @@ sub find_clock_start {
        }
 
        my $id = id_for_pos($pos);
-       my $clock_info = $dbh->selectrow_hashref('SELECT * FROM clock_info WHERE id=?', undef, $id);
+       my $clock_info = $dbh->selectrow_hashref('SELECT * FROM clock_info WHERE id=? AND COALESCE(white_clock_target, black_clock_target) >= EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - INTERVAL \'1 day\'));', undef, $id);
        if (defined($clock_info)) {
                $pos->{'white_clock'} //= $clock_info->{'white_clock'};
                $pos->{'black_clock'} //= $clock_info->{'black_clock'};
@@ -1426,3 +1470,16 @@ sub parse_uci_move {
        my $promo    = substr($move, 4, 1);
        return ($from_row, $from_col, $to_row, $to_col, $promo);
 }
+
+sub setoptions {
+       my ($engine, $config) = @_;
+       uciprint($engine, "setoption name UCI_AnalyseMode value true");
+       uciprint($engine, "setoption name Analysis Contempt value Off");
+       if (exists($config->{'Threads'})) {  # Threads first, because clearing hash can be multithreaded then.
+               uciprint($engine, "setoption name Threads value " . $config->{'Threads'});
+       }
+       while (my ($key, $value) = each %$config) {
+               next if $key eq 'Threads';
+               uciprint($engine, "setoption name $key value $value");
+       }
+}