1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-29 16:23:09 +00:00

Reformat sending of PV information

Introduce pv_info_to_log() and pv_info_to_uci() and
greatly cleanup this stuff.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba 2011-12-14 09:21:00 +01:00
parent 852d45a600
commit 0af3af5d25

View file

@ -174,10 +174,8 @@ namespace {
void do_skill_level(Move* best, Move* ponder); void do_skill_level(Move* best, Move* ponder);
int elapsed_time(bool reset = false); int elapsed_time(bool reset = false);
string score_to_uci(Value v, Value alpha = -VALUE_INFINITE, Value beta = VALUE_INFINITE); string score_to_uci(Value v, Value alpha = -VALUE_INFINITE, Value beta = VALUE_INFINITE);
string speed_to_uci(int64_t nodes); void pv_info_to_log(Position& pos, int depth, Value score, int time, Move pv[]);
string pv_to_uci(const Move pv[], int pvNum, bool chess960); void pv_info_to_uci(const Position& pos, int depth, Value alpha, Value beta);
string pretty_pv(Position& pos, int depth, Value score, int time, Move pv[]);
string depth_to_uci(Depth depth);
// MovePickerExt class template extends MovePicker and allows to choose at // MovePickerExt class template extends MovePicker and allows to choose at
// compile time the proper moves source according to the type of node. In the // compile time the proper moves source according to the type of node. In the
@ -448,7 +446,7 @@ namespace {
// Handle special case of searching on a mate/stalemate position // Handle special case of searching on a mate/stalemate position
if (RootMoves.empty()) if (RootMoves.empty())
{ {
cout << "info" << depth_to_uci(DEPTH_ZERO) cout << "info depth 0"
<< score_to_uci(pos.in_check() ? -VALUE_MATE : VALUE_DRAW, alpha, beta) << endl; << score_to_uci(pos.in_check() ? -VALUE_MATE : VALUE_DRAW, alpha, beta) << endl;
return MOVE_NONE; return MOVE_NONE;
@ -466,7 +464,7 @@ namespace {
// MultiPV loop. We perform a full root search for each PV line // MultiPV loop. We perform a full root search for each PV line
for (MultiPVIdx = 0; MultiPVIdx < std::min(MultiPV, RootMoves.size()); MultiPVIdx++) for (MultiPVIdx = 0; MultiPVIdx < std::min(MultiPV, RootMoves.size()); MultiPVIdx++)
{ {
// Calculate dynamic aspiration window based on previous iteration // Aspiration window
if (depth >= 5 && abs(RootMoves[MultiPVIdx].prevScore) < VALUE_KNOWN_WIN) if (depth >= 5 && abs(RootMoves[MultiPVIdx].prevScore) < VALUE_KNOWN_WIN)
{ {
delta = Value(16); delta = Value(16);
@ -513,27 +511,9 @@ namespace {
break; break;
// Send full PV info to GUI if we are going to leave the loop or // Send full PV info to GUI if we are going to leave the loop or
// if we have a fail high/low and we are deep in the search. UCI // if we have a fail high/low and we are deep in the search.
// protocol requires to send all the PV lines also if are still
// to be searched and so refer to the previous search's score.
if ((bestValue > alpha && bestValue < beta) || elapsed_time() > 2000) if ((bestValue > alpha && bestValue < beta) || elapsed_time() > 2000)
for (size_t i = 0; i < std::min(UCIMultiPV, RootMoves.size()); i++) pv_info_to_uci(pos, depth, alpha, beta);
{
bool updated = (i <= MultiPVIdx);
if (depth == 1 && !updated)
continue;
Depth d = (updated ? depth : depth - 1) * ONE_PLY;
Value s = (updated ? RootMoves[i].score : RootMoves[i].prevScore);
cout << "info"
<< depth_to_uci(d)
<< (i == MultiPVIdx ? score_to_uci(s, alpha, beta) : score_to_uci(s))
<< speed_to_uci(pos.nodes_searched())
<< pv_to_uci(&RootMoves[i].pv[0], i + 1, pos.is_chess960())
<< endl;
}
// In case of failing high/low increase aspiration window and // In case of failing high/low increase aspiration window and
// research, otherwise exit the fail high/low loop. // research, otherwise exit the fail high/low loop.
@ -567,10 +547,7 @@ namespace {
do_skill_level(&skillBest, &skillPonder); do_skill_level(&skillBest, &skillPonder);
if (Options["Use Search Log"].value<bool>()) if (Options["Use Search Log"].value<bool>())
{ pv_info_to_log(pos, depth, bestValue, elapsed_time(), &RootMoves[0].pv[0]);
Log log(Options["Search Log Filename"].value<string>());
log << pretty_pv(pos, depth, bestValue, elapsed_time(), &RootMoves[0].pv[0]) << endl;
}
// Filter out startup noise when monitoring best move stability // Filter out startup noise when monitoring best move stability
if (depth > 2 && bestMoveChanges[depth]) if (depth > 2 && bestMoveChanges[depth])
@ -960,7 +937,7 @@ split_point_start: // At split points actual search starts from here
nodes = pos.nodes_searched(); nodes = pos.nodes_searched();
if (pos.thread() == 0 && elapsed_time() > 2000) if (pos.thread() == 0 && elapsed_time() > 2000)
cout << "info" << depth_to_uci(depth) cout << "info depth " << depth / ONE_PLY
<< " currmove " << move << " currmove " << move
<< " currmovenumber " << moveCount + MultiPVIdx << endl; << " currmovenumber " << moveCount + MultiPVIdx << endl;
} }
@ -1701,61 +1678,49 @@ split_point_start: // At split points actual search starts from here
} }
// speed_to_uci() returns a string with time stats of current search suitable // pv_info_to_uci() sends search info to GUI. UCI protocol requires to send all
// to be sent to UCI gui. // the PV lines also if are still to be searched and so refer to the previous
// search score.
string speed_to_uci(int64_t nodes) { void pv_info_to_uci(const Position& pos, int depth, Value alpha, Value beta) {
std::stringstream s;
int t = elapsed_time(); int t = elapsed_time();
s << " nodes " << nodes
<< " nps " << (t > 0 ? int(nodes * 1000 / t) : 0)
<< " time " << t;
return s.str();
}
// pv_to_uci() returns a string with information on the current PV line
// formatted according to UCI specification.
string pv_to_uci(const Move pv[], int pvNum, bool chess960) {
std::stringstream s;
s << " multipv " << pvNum << " pv " << set960(chess960);
for ( ; *pv != MOVE_NONE; pv++)
s << *pv << " ";
return s.str();
}
// depth_to_uci() returns a string with information on the current depth and
// seldepth formatted according to UCI specification.
string depth_to_uci(Depth depth) {
std::stringstream s;
int selDepth = 0; int selDepth = 0;
// Retrieve max searched depth among threads
for (int i = 0; i < Threads.size(); i++) for (int i = 0; i < Threads.size(); i++)
if (Threads[i].maxPly > selDepth) if (Threads[i].maxPly > selDepth)
selDepth = Threads[i].maxPly; selDepth = Threads[i].maxPly;
s << " depth " << depth / ONE_PLY << " seldepth " << selDepth; for (size_t i = 0; i < std::min(UCIMultiPV, RootMoves.size()); i++)
{
bool updated = (i <= MultiPVIdx);
return s.str(); if (depth == 1 && !updated)
continue;
int d = (updated ? depth : depth - 1);
Value s = (updated ? RootMoves[i].score : RootMoves[i].prevScore);
cout << "info"
<< " depth " << d
<< " seldepth " << selDepth
<< (i == MultiPVIdx ? score_to_uci(s, alpha, beta) : score_to_uci(s))
<< " nodes " << pos.nodes_searched()
<< " nps " << (t > 0 ? pos.nodes_searched() * 1000 / t : 0)
<< " time " << t
<< " multipv " << i + 1 << " pv";
for (int j = 0; RootMoves[i].pv[j] != MOVE_NONE; j++)
cout << " " << RootMoves[i].pv[j];
cout << endl;
}
} }
// pretty_pv() creates a human-readable string from a position and a PV. It is // pv_info_to_log() writes human-readable search information to the log file
// used to write search information to the log file (which is created when the // (which is created when the UCI parameter "Use Search Log" is "true"). It
// UCI parameter "Use Search Log" is "true"). It uses the two below helper to // uses the two below helpers to pretty format time and score respectively.
// pretty format time and score respectively.
string time_to_string(int millisecs) { string time_to_string(int millisecs) {
@ -1791,7 +1756,7 @@ split_point_start: // At split points actual search starts from here
return s.str(); return s.str();
} }
string pretty_pv(Position& pos, int depth, Value value, int time, Move pv[]) { void pv_info_to_log(Position& pos, int depth, Value value, int time, Move pv[]) {
const int64_t K = 1000; const int64_t K = 1000;
const int64_t M = 1000000; const int64_t M = 1000000;
@ -1809,8 +1774,10 @@ split_point_start: // At split points actual search starts from here
if (pos.nodes_searched() < M) if (pos.nodes_searched() < M)
s << std::setw(8) << pos.nodes_searched() / 1 << " "; s << std::setw(8) << pos.nodes_searched() / 1 << " ";
else if (pos.nodes_searched() < K * M) else if (pos.nodes_searched() < K * M)
s << std::setw(7) << pos.nodes_searched() / K << "K "; s << std::setw(7) << pos.nodes_searched() / K << "K ";
else else
s << std::setw(7) << pos.nodes_searched() / M << "M "; s << std::setw(7) << pos.nodes_searched() / M << "M ";
@ -1833,11 +1800,11 @@ split_point_start: // At split points actual search starts from here
pos.do_move(*m++, *st++); pos.do_move(*m++, *st++);
} }
// Restore original position before to leave
while (m != pv) while (m != pv)
pos.undo_move(*--m); pos.undo_move(*--m);
return s.str(); Log l(Options["Search Log Filename"].value<string>());
l << s.str() << endl;
} }
@ -1932,7 +1899,7 @@ split_point_start: // At split points actual search starts from here
Value v, m = VALUE_NONE; Value v, m = VALUE_NONE;
int ply = 0; int ply = 0;
assert(pv[0] != MOVE_NONE && pos.is_pseudo_legal(pv[0])); assert(pv[ply] != MOVE_NONE && pos.is_pseudo_legal(pv[ply]));
do { do {
k = pos.get_key(); k = pos.get_key();