+ my @refutation_lines = ();
+ if (defined($engine2)) {
+ for (my $mpv = 1; $mpv < 500; ++$mpv) {
+ 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) {
+ @pretty_pv = @pretty_pv[0..4];
+ push @pretty_pv, "...";
+ }
+ my $key = $pretty_move;
+ my $line = sprintf(" %-6s %6s %3s %s",
+ $pretty_move,
+ short_score($info, $pos_calculating_second_engine, $mpv),
+ "d" . $info->{'depth' . $mpv},
+ join(', ', @pretty_pv));
+ push @refutation_lines, [ $key, $line ];
+ };
+ }
+ }
+
+ if ($#refutation_lines >= 0) {
+ $text .= "Shallow search of all legal moves:\n\n";
+ for my $line (sort { $a->[0] cmp $b->[0] } @refutation_lines) {
+ $text .= $line->[1] . "\n";
+ }
+ $text .= "\n\n";
+ }
+
+ if ($last_text ne $text) {
+ print "\e[H\e[2J"; # clear the screen
+ print $text;
+ $last_text = $text;
+ }
+}
+
+sub output_json {
+ my $historic_json_only = shift;
+ my $info = $engine->{'info'};
+
+ my $json = {};
+ $json->{'position'} = $pos_calculating->to_json_hash();
+ $json->{'engine'} = $engine->{'id'};
+ if (defined($remoteglotconf::engine_url)) {
+ $json->{'engine'}{'url'} = $remoteglotconf::engine_url;
+ }
+ if (defined($remoteglotconf::engine_details)) {
+ $json->{'engine'}{'details'} = $remoteglotconf::engine_details;
+ }
+ my @grpc_backends = ();
+ if (defined($remoteglotconf::engine_grpc_backend)) {
+ push @grpc_backends, $remoteglotconf::engine_grpc_backend;
+ }
+ if (defined($remoteglotconf::engine2_grpc_backend)) {
+ push @grpc_backends, $remoteglotconf::engine2_grpc_backend;
+ }
+ $json->{'internal'}{'grpc_backends'} = \@grpc_backends;
+ if (defined($remoteglotconf::move_source)) {
+ $json->{'move_source'} = $remoteglotconf::move_source;
+ }
+ if (defined($remoteglotconf::move_source_url)) {
+ $json->{'move_source_url'} = $remoteglotconf::move_source_url;
+ }
+ $json->{'score'} = score_digest($info, $pos_calculating, '');
+
+ $json->{'nodes'} = $info->{'nodes'};
+ $json->{'nps'} = $info->{'nps'};
+ $json->{'depth'} = $info->{'depth'};
+ $json->{'tbhits'} = $info->{'tbhits'};
+ $json->{'seldepth'} = $info->{'seldepth'};
+ $json->{'tablebase'} = $info->{'tablebase'};
+ $json->{'pv'} = [ prettyprint_pv($pos_calculating, @{$info->{'pv'}}) ];
+
+ my %refutation_lines = ();
+ my @refutation_lines = ();
+ if (defined($engine2)) {
+ for (my $mpv = 1; $mpv < 500; ++$mpv) {
+ my $info = $engine2->{'info'};
+ my $pretty_move = "";
+ my @pretty_pv = ();
+ 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{$pretty_move} = {
+ depth => $info->{'depth' . $mpv},
+ score => score_digest($info, $pos_calculating, $mpv),
+ move => $pretty_move,
+ pv => \@pretty_pv,
+ };
+ if (exists($info->{'splicepos' . $mpv})) {
+ $refutation_lines{$pretty_move}->{'splicepos'} = $info->{'splicepos' . $mpv};
+ }
+ };
+ }
+ }
+ $json->{'refutation_lines'} = \%refutation_lines;
+
+ # Piece together historic score information, to the degree we have it.
+ if (!$historic_json_only && exists($pos_calculating->{'history'})) {
+ my %score_history = ();
+
+ local $dbh->{AutoCommit} = 0;
+ my $q = $dbh->prepare('SELECT * FROM scores WHERE id=?');
+ 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);
+ my $ref = $dbh->selectrow_hashref($q, undef, $id);
+ if (defined($ref)) {
+ $score_history{$halfmove_num} = [
+ $ref->{'score_type'},
+ $ref->{'score_value'}
+ ];