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:
parent
852d45a600
commit
0af3af5d25
1 changed files with 44 additions and 77 deletions
121
src/search.cpp
121
src/search.cpp
|
@ -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();
|
||||||
|
|
Loading…
Add table
Reference in a new issue