return best;
}
+} // namespace
- // uci_pv() formats PV information according to the UCI protocol. UCI
- // requires that all (if any) unsearched PV lines are sent using a previous
- // search score.
- string uci_pv(const Position& pos, Depth depth, Value alpha, Value beta) {
+/// UCI::pv() formats PV information according to the UCI protocol. UCI requires
+/// that all (if any) unsearched PV lines are sent using a previous search score.
- std::stringstream ss;
- Time::point elapsed = Time::now() - SearchTime + 1;
- size_t uciPVSize = std::min((size_t)Options["MultiPV"], RootMoves.size());
- int selDepth = 0;
+string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
- for (size_t i = 0; i < Threads.size(); ++i)
- if (Threads[i]->maxPly > selDepth)
- selDepth = Threads[i]->maxPly;
+ std::stringstream ss;
+ Time::point elapsed = Time::now() - SearchTime + 1;
+ size_t multiPV = std::min((size_t)Options["MultiPV"], RootMoves.size());
+ int selDepth = 0;
- for (size_t i = 0; i < uciPVSize; ++i)
- {
- bool updated = (i <= PVIdx);
+ for (Thread* th : Threads)
+ if (th->maxPly > selDepth)
+ selDepth = th->maxPly;
- if (depth == ONE_PLY && !updated)
- continue;
+ for (size_t i = 0; i < multiPV; ++i)
+ {
+ bool updated = (i <= PVIdx);
- Depth d = updated ? depth : depth - ONE_PLY;
- Value v = updated ? RootMoves[i].score : RootMoves[i].previousScore;
+ if (depth == ONE_PLY && !updated)
+ continue;
- bool tb = TB::RootInTB && abs(v) < VALUE_MATE - MAX_PLY;
- v = tb ? TB::Score : v;
+ Depth d = updated ? depth : depth - ONE_PLY;
+ Value v = updated ? RootMoves[i].score : RootMoves[i].previousScore;
- if (ss.rdbuf()->in_avail()) // Not at first line
- ss << "\n";
+ bool tb = TB::RootInTB && abs(v) < VALUE_MATE - MAX_PLY;
+ v = tb ? TB::Score : v;
- ss << "info depth " << d / ONE_PLY
- << " seldepth " << selDepth
- << " multipv " << i + 1
- << " score " << UCI::value(v);
+ if (ss.rdbuf()->in_avail()) // Not at first line
+ ss << "\n";
- if (!tb && i == PVIdx)
- ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : "");
+ ss << "info"
+ << " depth " << d / ONE_PLY
+ << " seldepth " << selDepth
+ << " multipv " << i + 1
+ << " score " << UCI::value(v);
- ss << " nodes " << pos.nodes_searched()
- << " nps " << pos.nodes_searched() * 1000 / elapsed;
+ if (!tb && i == PVIdx)
+ ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : "");
- if (elapsed > 1000) // Earlier makes little sense
- ss << " hashfull " << TT.hashfull();
+ ss << " nodes " << pos.nodes_searched()
- << " nps " << pos.nodes_searched() * 1000 / elapsed
- << " tbhits " << TB::Hits
++ << " nps " << pos.nodes_searched() * 1000 / elapsed;
+
- ss << " tbhits " << TB::Hits
- << " time " << elapsed
- << " pv";
++ if (elapsed > 1000) // Earlier makes little sense
++ ss << " hashfull " << TT.hashfull();
+
- for (size_t j = 0; j < RootMoves[i].pv.size(); ++j)
- ss << " " << UCI::move(RootMoves[i].pv[j], pos.is_chess960());
- }
++ ss << " tbhits " << TB::Hits
+ << " time " << elapsed
+ << " pv";
- return ss.str();
+ for (Move m : RootMoves[i].pv)
+ ss << " " << UCI::move(m, pos.is_chess960());
}
-} // namespace
+ return ss.str();
+}
/// RootMove::insert_pv_in_tt() is called at the end of a search iteration, and