From c5f6bd517c68e16c3ead7892e1d83a6b1bb89b69 Mon Sep 17 00:00:00 2001 From: Jerry Donald Watson Date: Tue, 13 Mar 2018 23:19:36 +0100 Subject: [PATCH] Tweak probcut margin with 'improving' flag Adjust ProbCut rBeta by whether the score is improving, and also set improving to false when in check. More precisely, this patch has two parts: 1) the increased beta threshold for ProbCut is now adjusted based on whether the score is improving 2) when in check, improving is always set to false. Co-authored by Joost VandeVondele (@vondele) and Bill Henry (@VoyagerOne). STC: LLR: 2.96 (-2.94,2.94) [0.00,5.00] Total: 13480 W: 2840 L: 2648 D: 7992 http://tests.stockfishchess.org/tests/view/5aa693fe0ebc59029781004c LTC: LLR: 2.97 (-2.94,2.94) [0.00,5.00] Total: 25895 W: 4099 L: 3880 D: 17916 http://tests.stockfishchess.org/tests/view/5aa6ac940ebc59029781006e In terms of opportunities for future work opened up by this patch, the ProbCut rBeta formula could probably be tuned to gain more Elo. Closes https://github.com/official-stockfish/Stockfish/pull/1485 Bench: 5328254 --- src/search.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 8639393c..b2622ab3 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -654,7 +654,7 @@ namespace { if (inCheck) { ss->staticEval = eval = VALUE_NONE; - improving = true; + improving = false; goto moves_loop; } else if (ttHit) @@ -761,7 +761,7 @@ namespace { { assert(is_ok((ss-1)->currentMove)); - Value rbeta = std::min(beta + 200, VALUE_INFINITE); + Value rbeta = std::min(beta + 216 - 48 * improving, VALUE_INFINITE); MovePicker mp(pos, ttMove, rbeta - ss->staticEval, &thisThread->captureHistory); int probCutCount = 0; @@ -1009,8 +1009,8 @@ moves_loop: // When in check, search starts from here // Step 17. Full depth search when LMR is skipped or fails high if (doFullDepthSearch) - value = newDepth < ONE_PLY ? -qsearch(pos, ss+1, -(alpha+1), -alpha) - : - search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode, false); + value = newDepth < ONE_PLY ? -qsearch(pos, ss+1, -(alpha+1), -alpha) + : - search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode, false); // For PV nodes only, do a full PV search on the first move or after a fail // high (in the latter case search only if value < beta), otherwise let the @@ -1020,8 +1020,8 @@ moves_loop: // When in check, search starts from here (ss+1)->pv = pv; (ss+1)->pv[0] = MOVE_NONE; - value = newDepth < ONE_PLY ? -qsearch(pos, ss+1, -beta, -alpha) - : - search(pos, ss+1, -beta, -alpha, newDepth, false, false); + value = newDepth < ONE_PLY ? -qsearch(pos, ss+1, -beta, -alpha) + : - search(pos, ss+1, -beta, -alpha, newDepth, false, false); } // Step 18. Undo move @@ -1154,7 +1154,7 @@ moves_loop: // When in check, search starts from here Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) { const bool PvNode = NT == PV; - const bool InCheck = bool(pos.checkers()); + const bool inCheck = bool(pos.checkers()); assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE); assert(PvNode || (alpha == beta - 1)); @@ -1185,14 +1185,14 @@ moves_loop: // When in check, search starts from here // Check for an immediate draw or maximum ply reached if ( pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) - return (ss->ply >= MAX_PLY && !InCheck) ? evaluate(pos) : VALUE_DRAW; + return (ss->ply >= MAX_PLY && !inCheck) ? evaluate(pos) : VALUE_DRAW; assert(0 <= ss->ply && ss->ply < MAX_PLY); // Decide whether or not to include checks: this fixes also the type of // TT entry depth that we are going to use. Note that in qsearch we use // only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS. - ttDepth = InCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS + ttDepth = inCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS : DEPTH_QS_NO_CHECKS; // Transposition table lookup posKey = pos.key(); @@ -1209,7 +1209,7 @@ moves_loop: // When in check, search starts from here return ttValue; // Evaluate the position statically - if (InCheck) + if (inCheck) { ss->staticEval = VALUE_NONE; bestValue = futilityBase = -VALUE_INFINITE; @@ -1264,7 +1264,7 @@ moves_loop: // When in check, search starts from here moveCount++; // Futility pruning - if ( !InCheck + if ( !inCheck && !givesCheck && futilityBase > -VALUE_KNOWN_WIN && !pos.advanced_pawn_push(move)) @@ -1287,13 +1287,13 @@ moves_loop: // When in check, search starts from here } // Detect non-capture evasions that are candidates to be pruned - evasionPrunable = InCheck + evasionPrunable = inCheck && (depth != DEPTH_ZERO || moveCount > 2) && bestValue > VALUE_MATED_IN_MAX_PLY && !pos.capture(move); // Don't search moves with negative SEE values - if ( (!InCheck || evasionPrunable) + if ( (!inCheck || evasionPrunable) && !pos.see_ge(move)) continue; @@ -1344,7 +1344,7 @@ moves_loop: // When in check, search starts from here // All legal moves have been searched. A special case: If we're in check // and no legal moves were found, it is checkmate. - if (InCheck && bestValue == -VALUE_INFINITE) + if (inCheck && bestValue == -VALUE_INFINITE) return mated_in(ss->ply); // Plies to mate from the root tte->save(posKey, value_to_tt(bestValue, ss->ply), -- 2.39.2