From 282e15bf75bd1142de96306b22424f0cd2bb8dfa Mon Sep 17 00:00:00 2001 From: "Shahin M. Shahin" <41402573+peregrineshahin@users.noreply.github.com> Date: Fri, 17 Nov 2023 18:25:50 +0300 Subject: [PATCH] Fix TB score output in UCI without using TB This is a rewrite of the fix introduced for https://github.com/official-stockfish/Stockfish/issues/4413 in https://github.com/official-stockfish/Stockfish/pull/4591 by @windfishballad it targets only the relevant part of this issue that returns TB scores (CP 20000) without using TB due to the downgrading of potentially false mates from the TT to an optimal TB score. the difference is that it is a much clearer code that introduces a separate TB_VALUE constant to account for a correct distance from the TB_VALUE with MAX_PLY. the originally posted position in the issue does not trigger the problem anymore, so here is a new position to test: ``` position fen 3k4/8/8/8/8/8/3BN3/3K4 w - - 0 1 go infinite ``` Passed non-regression STC: https://tests.stockfishchess.org/tests/view/65578994136acbc57353b258 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 119264 W: 29993 L: 29863 D: 59408 Ptnml(0-2): 372, 13692, 31379, 13812, 377 Passed non-regression LTC: https://tests.stockfishchess.org/tests/view/6558323f136acbc57353c1ca LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 237834 W: 58791 L: 58792 D: 120251 Ptnml(0-2): 193, 26200, 66111, 26241, 172 fixes https://github.com/official-stockfish/Stockfish/issues/4413 closes https://github.com/official-stockfish/Stockfish/pull/4591 closes https://github.com/official-stockfish/Stockfish/pull/4882 Bench: 1305821 --- src/search.cpp | 39 +++++++++++++++++++++++++++------------ src/types.h | 12 +++++++----- src/uci.cpp | 4 ++-- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index f3980740..89879374 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -678,9 +678,11 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo int drawScore = TB::UseRule50 ? 1 : 0; - // use the range VALUE_MATE_IN_MAX_PLY to VALUE_TB_WIN_IN_MAX_PLY to score - value = wdl < -drawScore ? VALUE_MATED_IN_MAX_PLY + ss->ply + 1 - : wdl > drawScore ? VALUE_MATE_IN_MAX_PLY - ss->ply - 1 + Value tbValue = VALUE_TB - ss->ply; + + // use the range VALUE_TB to VALUE_TB_WIN_IN_MAX_PLY to score + value = wdl < -drawScore ? -tbValue + : wdl > drawScore ? tbValue : VALUE_DRAW + 2 * wdl * drawScore; Bound b = wdl < -drawScore ? BOUND_UPPER @@ -1631,25 +1633,38 @@ Value value_to_tt(Value v, int ply) { // Inverse of value_to_tt(): it adjusts a mate or TB score // from the transposition table (which refers to the plies to mate/be mated from // current position) to "plies to mate/be mated (TB win/loss) from the root". -// However, to avoid potentially false mate scores related to the 50 moves rule -// and the graph history interaction problem, we return an optimal TB score instead. +// However, to avoid potentially false mate or TB scores related to the 50 moves rule +// and the graph history interaction, we return highest non-TB score instead. + Value value_from_tt(Value v, int ply, int r50c) { if (v == VALUE_NONE) return VALUE_NONE; - if (v >= VALUE_TB_WIN_IN_MAX_PLY) // TB win or better + // handle TB win or better + if (v >= VALUE_TB_WIN_IN_MAX_PLY) { - if (v >= VALUE_MATE_IN_MAX_PLY && VALUE_MATE - v > 99 - r50c) - return VALUE_MATE_IN_MAX_PLY - 1; // do not return a potentially false mate score + // Downgrade a potentially false mate score + if (v >= VALUE_MATE_IN_MAX_PLY && VALUE_MATE - v > 100 - r50c) + return VALUE_TB_WIN_IN_MAX_PLY - 1; + + // Downgrade a potentially false TB score. + if (VALUE_TB - v > 100 - r50c) + return VALUE_TB_WIN_IN_MAX_PLY - 1; return v - ply; } - if (v <= VALUE_TB_LOSS_IN_MAX_PLY) // TB loss or worse + // handle TB loss or worse + if (v <= VALUE_TB_LOSS_IN_MAX_PLY) { - if (v <= VALUE_MATED_IN_MAX_PLY && VALUE_MATE + v > 99 - r50c) - return VALUE_MATED_IN_MAX_PLY + 1; // do not return a potentially false mate score + // Downgrade a potentially false mate score. + if (v <= VALUE_MATED_IN_MAX_PLY && VALUE_MATE + v > 100 - r50c) + return VALUE_TB_LOSS_IN_MAX_PLY + 1; + + // Downgrade a potentially false TB score. + if (VALUE_TB + v > 100 - r50c) + return VALUE_TB_LOSS_IN_MAX_PLY + 1; return v + ply; } @@ -1866,7 +1881,7 @@ string UCI::pv(const Position& pos, Depth depth) { if (v == -VALUE_INFINITE) v = VALUE_ZERO; - bool tb = TB::RootInTB && abs(v) < VALUE_MATE_IN_MAX_PLY; + bool tb = TB::RootInTB && abs(v) <= VALUE_TB; v = tb ? rootMoves[i].tbScore : v; if (ss.rdbuf()->in_avail()) // Not at first line diff --git a/src/types.h b/src/types.h index 0575f1d4..3e00d68d 100644 --- a/src/types.h +++ b/src/types.h @@ -164,14 +164,16 @@ enum Bound { enum Value : int { VALUE_ZERO = 0, VALUE_DRAW = 0, - VALUE_MATE = 32000, - VALUE_INFINITE = 32001, VALUE_NONE = 32002, + VALUE_INFINITE = 32001, + + VALUE_MATE = 32000, + VALUE_MATE_IN_MAX_PLY = VALUE_MATE - MAX_PLY, + VALUE_MATED_IN_MAX_PLY = -VALUE_MATE_IN_MAX_PLY, - VALUE_TB_WIN_IN_MAX_PLY = VALUE_MATE - 2 * MAX_PLY, + VALUE_TB = VALUE_MATE_IN_MAX_PLY - 1, + VALUE_TB_WIN_IN_MAX_PLY = VALUE_TB - MAX_PLY, VALUE_TB_LOSS_IN_MAX_PLY = -VALUE_TB_WIN_IN_MAX_PLY, - VALUE_MATE_IN_MAX_PLY = VALUE_MATE - MAX_PLY, - VALUE_MATED_IN_MAX_PLY = -VALUE_MATE_IN_MAX_PLY, // In the code, we make the assumption that these values // are such that non_pawn_material() can be used to uniquely diff --git a/src/uci.cpp b/src/uci.cpp index 95f6f349..d0341bd7 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -356,9 +356,9 @@ std::string UCI::value(Value v) { if (abs(v) < VALUE_TB_WIN_IN_MAX_PLY) ss << "cp " << UCI::to_cp(v); - else if (abs(v) < VALUE_MATE_IN_MAX_PLY) + else if (abs(v) <= VALUE_TB) { - const int ply = VALUE_MATE_IN_MAX_PLY - 1 - std::abs(v); // recompute ss->ply + const int ply = VALUE_TB - std::abs(v); // recompute ss->ply ss << "cp " << (v > 0 ? 20000 - ply : -20000 + ply); } else -- 2.39.2