Skip to content

Commit 62d34f0

Browse files
committed
feat: libchess UCI printing now supports multipv (#452)
1 parent 2c0a82b commit 62d34f0

File tree

3 files changed

+42
-25
lines changed

3 files changed

+42
-25
lines changed

libbenbot/src/search/Result.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ auto Result::to_libchess(const bool includeDebugInfo) const -> LibchessResult
5555
.selDepth = qDepth,
5656
.time = duration,
5757
.nodes = nodesSearched,
58+
.multiPV = std::nullopt,
5859
.pv = pv,
5960
.hashfull = hashfull,
6061
.tbHits = 0uz,

libchess/include/libchess/uci/Printing.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ struct SearchInfo final {
111111
/** The total number of nodes searched. */
112112
size_t nodes { 0uz };
113113

114+
/** In MultiPV mode, this integer should be the number of the line that this info is for.
115+
In non-MultiPV mode, this should be ``nullopt``.
116+
*/
117+
std::optional<size_t> multiPV;
118+
114119
/** The principal variation found. */
115120
moves::MoveList pv;
116121

libchess/src/uci/Printing.cpp

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -44,32 +44,27 @@ using std::string_view;
4444

4545
using MaybeMove = std::optional<Move>;
4646

47-
std::monostate info_string(const string_view info)
47+
auto info_string(const string_view info) -> std::monostate
4848
{
4949
println(cout, "info string {}", info);
5050

51+
cout.flush();
52+
5153
return std::monostate { };
5254
}
5355

54-
namespace {
55-
[[nodiscard]] auto ponder_move_string(
56-
const MaybeMove ponderMove)
57-
-> string
58-
{
59-
return ponderMove
60-
.transform([](const Move move) {
61-
return std::format(" ponder {}", to_uci(move));
62-
})
63-
.value_or(string { });
64-
}
65-
} // namespace
66-
6756
void best_move(
6857
const Move bestMove, const MaybeMove ponderMove)
6958
{
59+
const auto ponderMoveString = ponderMove
60+
.transform([](const Move move) {
61+
return std::format(" ponder {}", to_uci(move));
62+
})
63+
.value_or(string { });
64+
7065
println(cout,
7166
"bestmove {}{}",
72-
to_uci(bestMove), ponder_move_string(ponderMove));
67+
to_uci(bestMove), ponderMoveString);
7368

7469
cout.flush();
7570
}
@@ -101,18 +96,14 @@ auto SearchInfo::get_nps() const noexcept -> size_t
10196
namespace {
10297
using Score = SearchInfo::Score;
10398

104-
[[nodiscard]] auto base_score_string(const Score& score) -> string
99+
// [cp <x>]|[mate <x>] [lowerbound|upperbound]
100+
[[nodiscard]] auto score_string(const Score& score) -> string
105101
{
106-
return std::visit(
102+
auto string = std::visit(
107103
util::Visitor {
108104
[](const Score::Centipawns& centipawns) { return std::format("cp {}", centipawns.value); },
109105
[](const Score::MateIn& mate) { return std::format("mate {}", mate.moves()); } },
110106
score.value);
111-
}
112-
113-
[[nodiscard]] auto score_string(const Score& score) -> string
114-
{
115-
auto string = base_score_string(score);
116107

117108
assert(not(score.lowerBound and score.upperBound));
118109

@@ -124,6 +115,9 @@ namespace {
124115
return string;
125116
}
126117

118+
// if not empty, begins with a space:
119+
// * ""
120+
// * " pv <move...>"
127121
[[nodiscard]] auto pv_string(const std::span<const Move> pv) -> string
128122
{
129123
if (pv.empty()) {
@@ -139,6 +133,22 @@ namespace {
139133
return result;
140134
}
141135

136+
// if not empty, begins with a space:
137+
// * ""
138+
// * " multipv <n>"
139+
[[nodiscard]] auto multipv_string(
140+
const std::optional<size_t> multiPV) -> string
141+
{
142+
return multiPV
143+
.transform([](const size_t lineNum) {
144+
return std::format(" multipv {}", lineNum);
145+
})
146+
.value_or(string { });
147+
}
148+
149+
// if not empty, begins with a space:
150+
// * ""
151+
// * " string <text>"
142152
[[nodiscard]] auto get_extra_info_string(const string_view info) -> string
143153
{
144154
if (info.empty())
@@ -151,12 +161,13 @@ namespace {
151161
void search_info(const SearchInfo& info)
152162
{
153163
println(cout,
154-
"info depth {} score {} time {} hashfull {} nodes {} nps {} seldepth {} tbhits {}{}{}",
155-
info.depth,
164+
"info depth {} seldepth {}{} score {} time {} hashfull {} nodes {} nps {} tbhits {}{}{}",
165+
info.depth, info.selDepth,
166+
multipv_string(info.multiPV),
156167
score_string(info.score),
157168
info.time.count(), info.hashfull, info.nodes,
158169
info.get_nps(),
159-
info.selDepth, info.tbHits,
170+
info.tbHits,
160171
pv_string(info.pv),
161172
get_extra_info_string(info.extraInformation));
162173

0 commit comments

Comments
 (0)