From 748791f80dbc29793e473e3e9eda83ffa0afcfaa Mon Sep 17 00:00:00 2001 From: "Shahin M. Shahin" <41402573+peregrineshahin@users.noreply.github.com> Date: Wed, 6 Mar 2024 20:56:55 +0300 Subject: [PATCH] Fix `go mate x` in multithreading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes two issues with master for go mate x: - when running go mate x in losing positions, master always goes to the maximal depth, arguably against what the UCI protocol demands - when running go mate x in winning positions with multiple threads, master may return non-mate scores from the search (this issue is present in stockfish since at least sf16) The issues are fixed by (a) also checking if score is mate -x and by (b) only letting mainthread stop the search for go mate x commands, and by not looking for a best thread but using mainthread as per the default. Related: niklasf/python-chess#1070 More diagnostics can be found here peregrineshahin#6 (comment) closes https://github.com/official-stockfish/Stockfish/pull/5094 No functional change Co-Authored-By: Robert Nürnberg <28635489+robertnurnberg@users.noreply.github.com> --- src/search.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index ff32ecc1..7bf3e7f9 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -187,7 +187,7 @@ void Search::Worker::start_searching() { Skill skill = Skill(options["Skill Level"], options["UCI_LimitStrength"] ? int(options["UCI_Elo"]) : 0); - if (int(options["MultiPV"]) == 1 && !limits.depth && !skill.enabled() + if (int(options["MultiPV"]) == 1 && !limits.depth && !limits.mate && !skill.enabled() && rootMoves[0].pv[0] != Move::none()) bestThread = threads.get_best_thread()->worker.get(); @@ -399,14 +399,18 @@ void Search::Worker::iterative_deepening() { lastBestMoveDepth = rootDepth; } - // Have we found a "mate in x"? - if (limits.mate && bestValue >= VALUE_MATE_IN_MAX_PLY - && VALUE_MATE - bestValue <= 2 * limits.mate) - threads.stop = true; - if (!mainThread) continue; + // Have we found a "mate in x"? + if (limits.mate && rootMoves[0].score == rootMoves[0].uciScore + && ((rootMoves[0].score >= VALUE_MATE_IN_MAX_PLY + && VALUE_MATE - rootMoves[0].score <= 2 * limits.mate) + || (rootMoves[0].score != -VALUE_INFINITE + && rootMoves[0].score <= VALUE_TB_LOSS_IN_MAX_PLY + && VALUE_MATE + rootMoves[0].score <= 2 * limits.mate))) + threads.stop = true; + // If the skill level is enabled and time is up, pick a sub-optimal best move if (skill.enabled() && skill.time_to_pick(rootDepth)) skill.pick_best(rootMoves, multiPV);