From d30af4f669fa9a47e26a54967c571ffa7987d660 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Fri, 27 Oct 2023 13:28:55 +0300 Subject: [PATCH] Rewarding Quiet Moves that Enable Razoring The main idea of the patch comes from @peregrineshahin : https://tests.stockfishchess.org/tests/view/65205363ac57711436728781 Another small idea (tuning) comes from @Vizvezdenec https://tests.stockfishchess.org/tests/view/652e071ade6d262d08d318f4 And a long phases of tuning and tests was done by me in order to make the patch be able to pass both tests. The idea, as mentioned by Peregrine is that in our standard code, if no best move found after searching all moves, we give a bonus to the previous move that caused the fail high. So in razoring we assume no bestmove will be found so we might as well do the same. Passed STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 82336 W: 20997 L: 20610 D: 40729 Ptnml(0-2): 288, 9710, 20753, 10161, 256 https://tests.stockfishchess.org/tests/view/6538fafbcc309ae83955d8f0 Passed LTC: LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 46584 W: 11753 L: 11411 D: 23420 Ptnml(0-2): 21, 5133, 12642, 5475, 21 https://tests.stockfishchess.org/tests/view/653a3f2ccc309ae83955f223 closes https://github.com/official-stockfish/Stockfish/pull/4850 Bench: 1258079 Co-Authored-By: Shahin M. Shahin <41402573+peregrineshahin@users.noreply.github.com> --- src/evaluate.cpp | 4 ++-- src/search.cpp | 34 +++++++++++++++++++++------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index c405cfb5..9c39d4c0 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -144,8 +144,8 @@ void NNUE::verify() { } -// Returns a static, purely materialistic evaluation of the position -// from the point of view of the given color. It can be divided by PawnValue to get +// Returns a static, purely materialistic evaluation of the position from +// the point of view of the given color. It can be divided by PawnValue to get // an approximation of the material advantage on the board in terms of pawns. Value Eval::simple_eval(const Position& pos, Color c) { return PawnValue * (pos.count(c) - pos.count(~c)) diff --git a/src/search.cpp b/src/search.cpp index 0ffca247..65b27d16 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -77,7 +77,7 @@ enum NodeType { // Futility margin Value futility_margin(Depth d, bool noTtCutNode, bool improving) { - return Value((126 - 42 * noTtCutNode) * (d - improving)); + return Value((125 - 43 * noTtCutNode) * (d - improving)); } // Reductions lookup table initialized at startup @@ -85,8 +85,8 @@ int Reductions[MAX_MOVES]; // [depth or moveNumber] Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) { int reductionScale = Reductions[d] * Reductions[mn]; - return (reductionScale + 1560 - int(delta) * 945 / int(rootDelta)) / 1024 - + (!i && reductionScale > 791); + return (reductionScale + 1487 - int(delta) * 976 / int(rootDelta)) / 1024 + + (!i && reductionScale > 808); } constexpr int futility_move_count(bool improving, Depth depth) { @@ -94,7 +94,7 @@ constexpr int futility_move_count(bool improving, Depth depth) { } // History and stats update bonus, based on depth -int stat_bonus(Depth d) { return std::min(334 * d - 531, 1538); } +int stat_bonus(Depth d) { return std::min(357 * d - 483, 1511); } // Add a small random component to draw evaluations to avoid 3-fold blindness Value value_draw(const Thread* thisThread) { @@ -761,11 +761,19 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo // If eval is really low check with qsearch if it can exceed alpha, if it can't, // return a fail low. // Adjust razor margin according to cutoffCnt. (~1 Elo) - if (eval < alpha - 492 - (257 - 200 * ((ss + 1)->cutoffCnt > 3)) * depth * depth) + if (eval < alpha - 474 - (270 - 174 * ((ss + 1)->cutoffCnt > 3)) * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha) + { + if (!priorCapture && prevSq != SQ_NONE) + { + int bonus = (depth > 6) + (PvNode || cutNode) + (value < alpha - 658) + ((ss-1)->moveCount > 11); + update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus); + thisThread->mainHistory[~us][from_to((ss-1)->currentMove)] << stat_bonus(depth) * bonus * 57 / 100; + } return value; + } } // Step 8. Futility pruning: child node (~40 Elo) @@ -993,22 +1001,22 @@ moves_loop: // When in check, search starts here + thisThread->pawnHistory[pawn_structure(pos)][movedPiece][to_sq(move)]; // Continuation history based pruning (~2 Elo) - if (lmrDepth < 6 && history < -3498 * depth) + if (lmrDepth < 6 && history < -3645 * depth) continue; history += 2 * thisThread->mainHistory[us][from_to(move)]; - lmrDepth += history / 7815; - lmrDepth = std::max(lmrDepth, -2); + lmrDepth += history / 7836; + lmrDepth = std::max(lmrDepth, -1); // Futility pruning: parent node (~13 Elo) - if (!ss->inCheck && lmrDepth < 13 && ss->staticEval + 80 + 122 * lmrDepth <= alpha) + if (!ss->inCheck && lmrDepth < 13 && ss->staticEval + 77 + 124 * lmrDepth <= alpha) continue; lmrDepth = std::max(lmrDepth, 0); // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, Value(-27 * lmrDepth * lmrDepth))) + if (!pos.see_ge(move, Value(-26 * lmrDepth * lmrDepth))) continue; } } @@ -1318,12 +1326,12 @@ moves_loop: // When in check, search starts here // Bonus for prior countermove that caused the fail low else if (!priorCapture && prevSq != SQ_NONE) { - int bonus = (depth > 6) + (PvNode || cutNode) + (bestValue < alpha - 653) - + ((ss - 1)->moveCount > 11); + int bonus = (depth > 6) + (PvNode || cutNode) + (bestValue < alpha - 657) + + ((ss - 1)->moveCount > 10); update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus); thisThread->mainHistory[~us][from_to((ss - 1)->currentMove)] - << stat_bonus(depth) * bonus / 2; + << stat_bonus(depth) * bonus * 61 / 100; } if (PvNode) -- 2.39.2