From 573fe84ebd13143c1d6329c6b714f59118c44f5e Mon Sep 17 00:00:00 2001 From: Disservin Date: Sun, 24 Mar 2024 12:03:26 +0100 Subject: [PATCH] Improve on Feedback Bench: 1823302 --- src/Makefile | 4 +-- src/engine.cpp | 11 +++----- src/engine.h | 11 ++++---- src/main.cpp | 4 +++ src/score.cpp | 48 +++++++++++++++++++++++++++++++++++ src/score.h | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/search.cpp | 8 +++--- src/search.h | 5 ++-- src/uci.cpp | 66 +++++++++++++++++++++++++---------------------- src/uci.h | 5 +++- 10 files changed, 180 insertions(+), 51 deletions(-) create mode 100644 src/score.cpp create mode 100644 src/score.h diff --git a/src/Makefile b/src/Makefile index 6315bda82df..550f5404d14 100644 --- a/src/Makefile +++ b/src/Makefile @@ -55,7 +55,7 @@ PGOBENCH = $(WINE_PATH) ./$(EXE) bench SRCS = benchmark.cpp bitboard.cpp evaluate.cpp main.cpp \ misc.cpp movegen.cpp movepick.cpp position.cpp \ search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \ - nnue/nnue_misc.cpp nnue/features/half_ka_v2_hm.cpp nnue/network.cpp engine.cpp + nnue/nnue_misc.cpp nnue/features/half_ka_v2_hm.cpp nnue/network.cpp engine.cpp score.cpp HEADERS = benchmark.h bitboard.h evaluate.h misc.h movegen.h movepick.h \ nnue/nnue_misc.h nnue/features/half_ka_v2_hm.h nnue/layers/affine_transform.h \ @@ -63,7 +63,7 @@ HEADERS = benchmark.h bitboard.h evaluate.h misc.h movegen.h movepick.h \ nnue/layers/sqr_clipped_relu.h nnue/nnue_accumulator.h nnue/nnue_architecture.h \ nnue/nnue_common.h nnue/nnue_feature_transformer.h position.h \ search.h syzygy/tbprobe.h thread.h thread_win32_osx.h timeman.h \ - tt.h tune.h types.h uci.h ucioption.h perft.h nnue/network.h engine.h + tt.h tune.h types.h uci.h ucioption.h perft.h nnue/network.h engine.h score.h OBJS = $(notdir $(SRCS:.cpp=.o)) diff --git a/src/engine.cpp b/src/engine.cpp index 39feec89ab5..e0c1afe8276 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -18,7 +18,6 @@ #include "engine.h" -#include #include #include #include @@ -33,7 +32,6 @@ #include "position.h" #include "search.h" #include "syzygy/tbprobe.h" -#include "tune.h" #include "types.h" #include "uci.h" #include "ucioption.h" @@ -50,7 +48,6 @@ Engine::Engine(std::string path) : networks(NN::Networks( NN::NetworkBig({EvalFileDefaultNameBig, "None", ""}, NN::EmbeddedNNUEType::BIG), NN::NetworkSmall({EvalFileDefaultNameSmall, "None", ""}, NN::EmbeddedNNUEType::SMALL))) { - Tune::init(options); pos.set(StartFEN, false, &states->back()); } @@ -77,19 +74,19 @@ void Engine::search_clear() { Tablebases::init(options["SyzygyPath"]); // Free mapped files } -void Engine::set_on_update_short(std::function f) { +void Engine::set_on_update_short(std::function&& f) { updateContext.onUpdateShort = std::move(f); } -void Engine::set_on_update_full(std::function f) { +void Engine::set_on_update_full(std::function&& f) { updateContext.onUpdateFull = std::move(f); } -void Engine::set_on_iter(std::function f) { +void Engine::set_on_iter(std::function&& f) { updateContext.onIter = std::move(f); } -void Engine::set_on_bestmove(std::function f) { +void Engine::set_on_bestmove(std::function&& f) { updateContext.onBestmove = std::move(f); } diff --git a/src/engine.h b/src/engine.h index b4d04f47bba..f216964fd20 100644 --- a/src/engine.h +++ b/src/engine.h @@ -20,10 +20,11 @@ #define ENGINE_H_INCLUDED #include -#include #include #include #include +#include +#include #include "nnue/network.h" #include "position.h" @@ -61,10 +62,10 @@ class Engine { // clears the search void search_clear(); - void set_on_update_short(std::function); - void set_on_update_full(std::function); - void set_on_iter(std::function); - void set_on_bestmove(std::function); + void set_on_update_short(std::function&&); + void set_on_update_full(std::function&&); + void set_on_iter(std::function&&); + void set_on_bestmove(std::function&&); // network related diff --git a/src/main.cpp b/src/main.cpp index 20a9507a302..a6a3d1c4e85 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ #include "position.h" #include "types.h" #include "uci.h" +#include "tune.h" using namespace Stockfish; @@ -34,6 +35,9 @@ int main(int argc, char* argv[]) { Position::init(); UCIEngine uci(argc, argv); + + Tune::init(uci.engine_options()); + uci.loop(); return 0; diff --git a/src/score.cpp b/src/score.cpp new file mode 100644 index 00000000000..d1a8a6abe4d --- /dev/null +++ b/src/score.cpp @@ -0,0 +1,48 @@ +/* + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + + Stockfish is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Stockfish is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "score.h" + +#include +#include +#include + +#include "uci.h" + +namespace Stockfish { + +Score::Score(Value v, const Position& pos) { + assert(-VALUE_INFINITE < v && v < VALUE_INFINITE); + + if (std::abs(v) < VALUE_TB_WIN_IN_MAX_PLY) + { + score = InternalUnits{UCIEngine::to_cp(v, pos)}; + } + else if (std::abs(v) <= VALUE_TB) + { + auto distance = VALUE_TB - std::abs(v); + score = (v > 0) ? TBWin{distance} : TBWin{-distance}; + } + else + { + auto distance = VALUE_MATE - std::abs(v); + score = (v > 0) ? Mate{distance} : Mate{-distance}; + } +} + +} \ No newline at end of file diff --git a/src/score.h b/src/score.h new file mode 100644 index 00000000000..b94d9f7fb6b --- /dev/null +++ b/src/score.h @@ -0,0 +1,69 @@ +/* + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + + Stockfish is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Stockfish is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef SCORE_H_INCLUDED +#define SCORE_H_INCLUDED + +#include +#include + +#include "types.h" + +namespace Stockfish { + +class Position; + +class Score { + public: + struct Mate { + int plies; + }; + + struct TBWin { + int plies; + }; + + struct InternalUnits { + int value; + }; + + Score() = default; + Score(Value v, const Position& pos); + + template + bool is() const { + return std::holds_alternative(score); + } + + template + T get() const { + return std::get(score); + } + + template + decltype(auto) visit(F&& f) const { + return std::visit(std::forward(f), score); + } + + private: + std::variant score; +}; + +} + +#endif // #ifndef SCORE_H_INCLUDED diff --git a/src/search.cpp b/src/search.cpp index c9e665953e7..605cc8990f8 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -156,7 +156,7 @@ void Search::Worker::start_searching() { { rootMoves.emplace_back(Move::none()); main_manager()->updates.onUpdateShort( - {0, UCIEngine::to_score(rootPos.checkers() ? -VALUE_MATE : VALUE_DRAW, rootPos)}); + {0, {rootPos.checkers() ? -VALUE_MATE : VALUE_DRAW, rootPos}}); } else { @@ -1909,15 +1909,15 @@ void SearchManager::pv(const Search::Worker& worker, info.depth = d; info.selDepth = rootMoves[i].selDepth; info.multiPV = i + 1; - info.score = UCIEngine::to_score(v, pos); + info.score = {v, pos}; if (worker.options["UCI_ShowWDL"]) info.wdl = UCIEngine::wdl(v, pos); if (i == pvIdx && !tb && updated) // tablebase- and previous-scores are exact info.bound = rootMoves[i].scoreLowerbound - ? " lowerbound" - : (rootMoves[i].scoreUpperbound ? " upperbound" : ""); + ? "lowerbound" + : (rootMoves[i].scoreUpperbound ? "upperbound" : ""); info.timeMs = time; info.nodes = nodes; diff --git a/src/search.h b/src/search.h index 38bc107ac4b..0b6bc3d0aa6 100644 --- a/src/search.h +++ b/src/search.h @@ -35,6 +35,7 @@ #include "syzygy/tbprobe.h" #include "timeman.h" #include "types.h" +#include "score.h" namespace Stockfish { @@ -157,8 +158,8 @@ class ISearchManager { }; struct InfoShort { - int depth; - std::string score; + int depth; + Score score; }; struct InfoFull: InfoShort { diff --git a/src/uci.cpp b/src/uci.cpp index 7ca62025bce..a228d21c367 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -19,11 +19,9 @@ #include "uci.h" #include -#include #include #include #include -#include #include #include #include @@ -37,6 +35,7 @@ #include "movegen.h" #include "position.h" #include "search.h" +#include "score.h" #include "syzygy/tbprobe.h" #include "types.h" #include "ucioption.h" @@ -46,6 +45,13 @@ namespace Stockfish { constexpr auto StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048; +template +struct overload: Ts... { + using Ts::operator()...; +}; + +template +overload(Ts...) -> overload; UCIEngine::UCIEngine(int argc, char** argv) : engine(argv[0]), @@ -349,22 +355,22 @@ int win_rate_model(Value v, const Position& pos) { } } -std::string UCIEngine::to_score(Value v, const Position& pos) { - assert(-VALUE_INFINITE < v && v < VALUE_INFINITE); - - std::stringstream ss; - - if (std::abs(v) < VALUE_TB_WIN_IN_MAX_PLY) - ss << "cp " << to_cp(v, pos); - else if (std::abs(v) <= VALUE_TB) - { - const int ply = VALUE_TB - std::abs(v); // recompute ss->ply - ss << "cp " << (v > 0 ? 20000 - ply : -20000 + ply); - } - else - ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2; - - return ss.str(); +std::string UCIEngine::format_score(const Score& s) { + constexpr int TB_CP = 20000; + constexpr auto format = + overload{[](Score::Mate mate) -> std::string { + auto m = (mate.plies > 0 ? (mate.plies + 1) : -mate.plies) / 2; + return std::string("mate ") + std::to_string(m); + }, + [](Score::TBWin tb) -> std::string { + return std::string("cp ") + + std::to_string((tb.plies > 0 ? TB_CP - tb.plies : -TB_CP + tb.plies)); + }, + [](Score::InternalUnits units) -> std::string { + return std::string("cp ") + std::to_string(units.value); + }}; + + return s.visit(format); } // Turns a Value to an integer centipawn number, @@ -429,28 +435,28 @@ Move UCIEngine::to_move(const Position& pos, std::string str) { } void UCIEngine::on_update_short(const Engine::InfoShort& info) { - sync_cout << "info depth" << info.depth << " score " << info.score << sync_endl; + sync_cout << "info depth" << info.depth << " score " << format_score(info.score) << sync_endl; } void UCIEngine::on_update_full(const Engine::InfoFull& info, bool showWDL) { std::stringstream ss; ss << "info"; - ss << " depth " << info.depth // - << " seldepth " << info.selDepth // - << " multipv " << info.multiPV // - << " score " << info.score; // + ss << " depth " << info.depth // + << " seldepth " << info.selDepth // + << " multipv " << info.multiPV // + << " score " << format_score(info.score); // if (showWDL) ss << " wdl " << info.wdl; - ss << info.bound // - << " nodes " << info.nodes // - << " nps " << info.nps // - << " hashfull " << info.hashfull // - << " tbhits " << info.tbHits // - << " time " << info.timeMs // - << " pv " << info.pv; // + ss << (!info.bound.empty() ? " " + info.bound : "") // + << " nodes " << info.nodes // + << " nps " << info.nps // + << " hashfull " << info.hashfull // + << " tbhits " << info.tbHits // + << " time " << info.timeMs // + << " pv " << info.pv; // sync_cout << ss.str() << sync_endl; } diff --git a/src/uci.h b/src/uci.h index 871e3d6bd74..a8ba1089574 100644 --- a/src/uci.h +++ b/src/uci.h @@ -30,6 +30,7 @@ namespace Stockfish { class Position; class Move; +class Score; enum Square : int; using Value = int; @@ -40,7 +41,7 @@ class UCIEngine { void loop(); static int to_cp(Value v, const Position& pos); - static std::string to_score(Value v, const Position& pos); + static std::string format_score(const Score& s); static std::string square(Square s); static std::string move(Move m, bool chess960); static std::string wdl(Value v, const Position& pos); @@ -48,6 +49,8 @@ class UCIEngine { static Search::LimitsType parse_limits(const Position& pos, std::istream& is); + auto& engine_options() { return engine.get_options(); } + private: Engine engine; CommandLine cli;