From ecf5646f6e8446a3498aca04723dcee2b74f2d77 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Fri, 1 Nov 2024 02:04:35 +0300 Subject: [PATCH 01/19] Refine definition of improving This patch also allows improving flag to be true if static evaluation of the position is good enough. Passed STC: https://tests.stockfishchess.org/tests/view/6720906086d5ee47d953d4d0 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 34816 W: 9172 L: 8858 D: 16786 Ptnml(0-2): 113, 3988, 8887, 4312, 108 Passed LTC: https://tests.stockfishchess.org/tests/view/6721162686d5ee47d953d597 LLR: 2.96 (-2.94,2.94) <0.50,2.50> Total: 145374 W: 37118 L: 36574 D: 71682 Ptnml(0-2): 91, 15875, 40212, 16417, 92 closes https://github.com/official-stockfish/Stockfish/pull/5662 Bench: 1518856 --- src/search.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index d6914da0b..1b9b745ca 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -795,6 +795,8 @@ Value Search::Worker::search( && eval < VALUE_TB_WIN_IN_MAX_PLY) return beta + (eval - beta) / 3; + improving |= ss->staticEval >= beta + 100; + // Step 9. Null move search with verification search (~35 Elo) if (cutNode && (ss - 1)->currentMove != Move::null() && eval >= beta && ss->staticEval >= beta - 23 * depth + 400 && !excludedMove && pos.non_pawn_material(us) From 54cf226604cfc9d17f432fa0b5bca56277e5561c Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Fri, 1 Nov 2024 13:54:50 +0300 Subject: [PATCH 02/19] Revert VLTC regression from #5634 https://tests.stockfishchess.org/tests/view/671bf61b86d5ee47d953cf23 And thanks to @xu-shawn for suggesting running a VLTC regress test since depth modifications affect scaling. Also, the LTC was showing a slight regress after 680+k games ~= -0.34 , for reference: https://tests.stockfishchess.org/tests/view/67042b1f86d5ee47d953be7c closes https://github.com/official-stockfish/Stockfish/pull/5663 Bench: 1307308 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 1b9b745ca..5c6a62c8b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -850,7 +850,7 @@ Value Search::Worker::search( // For cutNodes, if depth is high enough, decrease depth by 2 if there is no ttMove, // or by 1 if there is a ttMove with an upper bound. if (cutNode && depth >= 7 && (!ttData.move || ttData.bound == BOUND_UPPER)) - depth -= 2; + depth -= 1 + !ttData.move; // Step 11. ProbCut (~10 Elo) // If we have a good enough capture (or queen promotion) and a reduced search From f77bac3dcab84a31238289ade55f9d85b650ac1a Mon Sep 17 00:00:00 2001 From: mstembera Date: Sun, 3 Nov 2024 16:50:47 -0800 Subject: [PATCH 03/19] Remove stale Cache::clear() method closes https://github.com/official-stockfish/Stockfish/pull/5666 No functional change --- src/nnue/nnue_accumulator.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/nnue/nnue_accumulator.h b/src/nnue/nnue_accumulator.h index b8dcf1e48..b92901e4a 100644 --- a/src/nnue/nnue_accumulator.h +++ b/src/nnue/nnue_accumulator.h @@ -80,11 +80,6 @@ struct AccumulatorCaches { entry.clear(network.featureTransformer->biases); } - void clear(const BiasType* biases) { - for (auto& entry : entries) - entry.clear(biases); - } - std::array& operator[](Square sq) { return entries[sq]; } std::array, SQUARE_NB> entries; From cc5c67c564f52a0611ba38d04af02636291280b6 Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Sun, 27 Oct 2024 14:07:03 -0700 Subject: [PATCH 04/19] Introduce Fractional LMR Tuning Run (90k Games): https://tests.stockfishchess.org/tests/view/67202b1c86d5ee47d953d442 Passed STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 241024 W: 62616 L: 62001 D: 116407 Ptnml(0-2): 716, 28231, 62015, 28822, 728 https://tests.stockfishchess.org/tests/view/6725196786d5ee47d953d9f2 Passed LTC: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 92532 W: 23678 L: 23246 D: 45608 Ptnml(0-2): 45, 9981, 25797, 10383, 60 https://tests.stockfishchess.org/tests/view/6727d3cb86d5ee47d953db9d closes https://github.com/official-stockfish/Stockfish/pull/5667 Bench: 1066071 --- src/search.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 5c6a62c8b..c807f1bdf 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -999,7 +999,7 @@ moves_loop: // When in check, search starts here mp.skip_quiet_moves(); // Reduced depth of the next LMR search - int lmrDepth = newDepth - r; + int lmrDepth = newDepth - r / 1024; if (capture || givesCheck) { @@ -1156,36 +1156,36 @@ moves_loop: // When in check, search starts here // Decrease reduction if position is or has been on the PV (~7 Elo) if (ss->ttPv) - r -= 1 + (ttData.value > alpha) + (ttData.depth >= depth); + r -= 1024 + (ttData.value > alpha) * 1024 + (ttData.depth >= depth) * 1024; // Decrease reduction for PvNodes (~0 Elo on STC, ~2 Elo on LTC) if (PvNode) - r--; + r -= 1024; // These reduction adjustments have no proven non-linear scaling // Increase reduction for cut nodes (~4 Elo) if (cutNode) - r += 2 - (ttData.depth >= depth && ss->ttPv); + r += 2518 - (ttData.depth >= depth && ss->ttPv) * 991; // Increase reduction if ttMove is a capture but the current move is not a capture (~3 Elo) if (ttCapture && !capture) - r += 1 + (depth < 8); + r += 1043 + (depth < 8) * 999; // Increase reduction if next ply has a lot of fail high (~5 Elo) if ((ss + 1)->cutoffCnt > 3) - r += 1 + allNode; + r += 938 + allNode * 960; // For first picked move (ttMove) reduce reduction (~3 Elo) else if (move == ttData.move) - r -= 2; + r -= 1879; ss->statScore = 2 * thisThread->mainHistory[us][move.from_to()] + (*contHist[0])[movedPiece][move.to_sq()] + (*contHist[1])[movedPiece][move.to_sq()] - 4410; // Decrease/increase reduction for moves with a good/bad history (~8 Elo) - r -= ss->statScore / 11016; + r -= ss->statScore * 1287 / 16384; // Step 17. Late moves reduction / extension (LMR, ~117 Elo) if (depth >= 2 && moveCount > 1) @@ -1195,7 +1195,7 @@ moves_loop: // When in check, search starts here // beyond the first move depth. // To prevent problems when the max value is less than the min value, // std::clamp has been replaced by a more robust implementation. - Depth d = std::max(1, std::min(newDepth - r, newDepth + !allNode)); + Depth d = std::max(1, std::min(newDepth - r / 1024, newDepth + !allNode)); value = -search(pos, ss + 1, -(alpha + 1), -alpha, d, true); @@ -1223,10 +1223,11 @@ moves_loop: // When in check, search starts here { // Increase reduction if ttMove is not present (~6 Elo) if (!ttData.move) - r += 2; + r += 2037; // Note that if expected reduction is high, we reduce search depth by 1 here (~9 Elo) - value = -search(pos, ss + 1, -(alpha + 1), -alpha, newDepth - (r > 3), !cutNode); + value = + -search(pos, ss + 1, -(alpha + 1), -alpha, newDepth - (r > 2983), !cutNode); } // For PV nodes only, do a full PV search on the first move or after a fail high, @@ -1700,7 +1701,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) Depth Search::Worker::reduction(bool i, Depth d, int mn, int delta) const { int reductionScale = reductions[d] * reductions[mn]; - return (reductionScale + 1239 - delta * 795 / rootDelta) / 1024 + (!i && reductionScale > 1341); + return (reductionScale + 1239 - delta * 795 / rootDelta) + (!i && reductionScale > 1341) * 1135; } // elapsed() returns the time elapsed since the search started. If the From 3d084e9164a96bff265b3afb32f2da0aa4e97c47 Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Wed, 13 Nov 2024 20:18:36 +0100 Subject: [PATCH 05/19] VVLTC Search Tune A single tuning run of 190k games was conducted: https://tests.stockfishchess.org/tests/view/670f3e3786d5ee47d953c554. Passed VVLTC 1st sprt: https://tests.stockfishchess.org/tests/view/672344dc86d5ee47d953d8c3 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 56768 W: 14615 L: 14323 D: 27830 Ptnml(0-2): 3, 5152, 17789, 5430, 10 Passed VVLTC 2nd sprt (rebased): https://tests.stockfishchess.org/tests/view/6726d83786d5ee47d953db03 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 57884 W: 14885 L: 14554 D: 28445 Ptnml(0-2): 5, 5300, 17999, 5635, 3 closes https://github.com/official-stockfish/Stockfish/pull/5669 Bench: 920336 --- src/search.cpp | 102 ++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index c807f1bdf..2a2331cb4 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -67,7 +67,7 @@ namespace { // Futility margin Value futility_margin(Depth d, bool noTtCutNode, bool improving, bool oppWorsening) { - Value futilityMult = 118 - 33 * noTtCutNode; + Value futilityMult = 109 - 27 * noTtCutNode; Value improvingDeduction = improving * futilityMult * 2; Value worseningDeduction = oppWorsening * futilityMult / 3; @@ -94,16 +94,16 @@ Value to_corrected_static_eval(Value v, const Worker& w, const Position& pos, St cntcv = int((*(ss - 2)->continuationCorrectionHistory)[pos.piece_on(m.to_sq())][m.to_sq()]); const auto cv = - (5932 * pcv + 3269 * macv + 5660 * micv + 6666 * (wnpcv + bnpcv) + 5555 * cntcv) / 131072; + (6384 * pcv + 3583 * macv + 6492 * micv + 6725 * (wnpcv + bnpcv) + cntcv * 5880) / 131072; v += cv; return std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); } // History and stats update bonus, based on depth -int stat_bonus(Depth d) { return std::min(179 * d - 108, 1598); } +int stat_bonus(Depth d) { return std::min(168 * d - 100, 1718); } // History and stats update malus, based on depth -int stat_malus(Depth d) { return std::min(820 * d - 261, 2246); } +int stat_malus(Depth d) { return std::min(768 * d - 257, 2351); } // Add a small random component to draw evaluations to avoid 3-fold blindness Value value_draw(size_t nodes) { return VALUE_DRAW - 1 + Value(nodes & 0x2); } @@ -311,13 +311,13 @@ void Search::Worker::iterative_deepening() { selDepth = 0; // Reset aspiration window starting size - delta = 5 + std::abs(rootMoves[pvIdx].meanSquaredScore) / 13797; + delta = 5 + std::abs(rootMoves[pvIdx].meanSquaredScore) / 13461; Value avg = rootMoves[pvIdx].averageScore; alpha = std::max(avg - delta, -VALUE_INFINITE); beta = std::min(avg + delta, VALUE_INFINITE); // Adjust optimism based on root move's averageScore (~4 Elo) - optimism[us] = 132 * avg / (std::abs(avg) + 89); + optimism[us] = 150 * avg / (std::abs(avg) + 85); optimism[~us] = -optimism[us]; // Start with a small aspiration window and, in the case of a fail @@ -502,8 +502,8 @@ void Search::Worker::iterative_deepening() { void Search::Worker::clear() { mainHistory.fill(0); lowPlyHistory.fill(0); - captureHistory.fill(-753); - pawnHistory.fill(-1152); + captureHistory.fill(-758); + pawnHistory.fill(-1158); pawnCorrectionHistory.fill(0); majorPieceCorrectionHistory.fill(0); minorPieceCorrectionHistory.fill(0); @@ -518,10 +518,10 @@ void Search::Worker::clear() { for (StatsType c : {NoCaptures, Captures}) for (auto& to : continuationHistory[inCheck][c]) for (auto& h : to) - h->fill(-678); + h->fill(-645); for (size_t i = 1; i < reductions.size(); ++i) - reductions[i] = int((18.43 + std::log(size_t(options["Threads"])) / 2) * std::log(i)); + reductions[i] = int((19.43 + std::log(size_t(options["Threads"])) / 2) * std::log(i)); refreshTable.clear(networks[numaAccessToken]); } @@ -760,7 +760,7 @@ Value Search::Worker::search( // Use static evaluation difference to improve quiet move ordering (~9 Elo) if (((ss - 1)->currentMove).is_ok() && !(ss - 1)->inCheck && !priorCapture) { - int bonus = std::clamp(-10 * int((ss - 1)->staticEval + ss->staticEval), -1641, 1423) + 760; + int bonus = std::clamp(-10 * int((ss - 1)->staticEval + ss->staticEval), -1831, 1428) + 623; thisThread->mainHistory[~us][((ss - 1)->currentMove).from_to()] << bonus; if (type_of(pos.piece_on(prevSq)) != PAWN && ((ss - 1)->currentMove).type_of() != PROMOTION) thisThread->pawnHistory[pawn_structure_index(pos)][pos.piece_on(prevSq)][prevSq] @@ -778,7 +778,7 @@ Value Search::Worker::search( // Step 7. Razoring (~1 Elo) // If eval is really low, check with qsearch if we can exceed alpha. If the // search suggests we cannot exceed alpha, return a speculative fail low. - if (eval < alpha - 501 - 272 * depth * depth) + if (eval < alpha - 469 - 307 * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha && std::abs(value) < VALUE_TB_WIN_IN_MAX_PLY) @@ -787,9 +787,9 @@ Value Search::Worker::search( // Step 8. Futility pruning: child node (~40 Elo) // The depth condition is important for mate finding. - if (!ss->ttPv && depth < 13 + if (!ss->ttPv && depth < 14 && eval - futility_margin(depth, cutNode && !ss->ttHit, improving, opponentWorsening) - - (ss - 1)->statScore / 272 + - (ss - 1)->statScore / 290 >= beta && eval >= beta && (!ttData.move || ttCapture) && beta > VALUE_TB_LOSS_IN_MAX_PLY && eval < VALUE_TB_WIN_IN_MAX_PLY) @@ -799,13 +799,13 @@ Value Search::Worker::search( // Step 9. Null move search with verification search (~35 Elo) if (cutNode && (ss - 1)->currentMove != Move::null() && eval >= beta - && ss->staticEval >= beta - 23 * depth + 400 && !excludedMove && pos.non_pawn_material(us) + && ss->staticEval >= beta - 21 * depth + 421 && !excludedMove && pos.non_pawn_material(us) && ss->ply >= thisThread->nmpMinPly && beta > VALUE_TB_LOSS_IN_MAX_PLY) { assert(eval - beta >= 0); // Null move dynamic reduction based on depth and eval - Depth R = std::min(int(eval - beta) / 209, 6) + depth / 3 + 5; + Depth R = std::min(int(eval - beta) / 235, 7) + depth / 3 + 5; ss->currentMove = Move::null(); ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; @@ -855,7 +855,7 @@ Value Search::Worker::search( // Step 11. ProbCut (~10 Elo) // If we have a good enough capture (or queen promotion) and a reduced search // returns a value much above beta, we can (almost) safely prune the previous move. - probCutBeta = beta + 189 - 53 * improving - 30 * opponentWorsening; + probCutBeta = beta + 187 - 53 * improving - 27 * opponentWorsening; if (!PvNode && depth > 3 && std::abs(beta) < VALUE_TB_WIN_IN_MAX_PLY // If value from transposition table is lower than probCutBeta, don't attempt @@ -926,7 +926,7 @@ Value Search::Worker::search( moves_loop: // When in check, search starts here // Step 12. A small Probcut idea (~4 Elo) - probCutBeta = beta + 379; + probCutBeta = beta + 417; if ((ttData.bound & BOUND_LOWER) && ttData.depth >= depth - 4 && ttData.value >= probCutBeta && std::abs(beta) < VALUE_TB_WIN_IN_MAX_PLY && std::abs(ttData.value) < VALUE_TB_WIN_IN_MAX_PLY) @@ -1010,15 +1010,15 @@ moves_loop: // When in check, search starts here // Futility pruning for captures (~2 Elo) if (!givesCheck && lmrDepth < 7 && !ss->inCheck) { - Value futilityValue = ss->staticEval + 300 + 238 * lmrDepth + Value futilityValue = ss->staticEval + 287 + 253 * lmrDepth + PieceValue[capturedPiece] + captHist / 7; if (futilityValue <= alpha) continue; } // SEE based pruning for captures and checks (~11 Elo) - int seeHist = std::clamp(captHist / 32, -159 * depth, 160 * depth); - if (!pos.see_ge(move, -167 * depth - seeHist)) + int seeHist = std::clamp(captHist / 33, -161 * depth, 156 * depth); + if (!pos.see_ge(move, -162 * depth - seeHist)) continue; } else @@ -1029,15 +1029,15 @@ moves_loop: // When in check, search starts here + thisThread->pawnHistory[pawn_structure_index(pos)][movedPiece][move.to_sq()]; // Continuation history based pruning (~2 Elo) - if (history < -4071 * depth) + if (history < -3884 * depth) continue; history += 2 * thisThread->mainHistory[us][move.from_to()]; - lmrDepth += history / 3653; + lmrDepth += history / 3609; Value futilityValue = - ss->staticEval + (bestValue < ss->staticEval - 51 ? 145 : 49) + 144 * lmrDepth; + ss->staticEval + (bestValue < ss->staticEval - 45 ? 140 : 43) + 141 * lmrDepth; // Futility pruning: parent node (~13 Elo) if (!ss->inCheck && lmrDepth < 12 && futilityValue <= alpha) @@ -1051,7 +1051,7 @@ moves_loop: // When in check, search starts here lmrDepth = std::max(lmrDepth, 0); // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, -24 * lmrDepth * lmrDepth)) + if (!pos.see_ge(move, -25 * lmrDepth * lmrDepth)) continue; } } @@ -1074,11 +1074,11 @@ moves_loop: // When in check, search starts here // and lower extension margins scale well. if (!rootNode && move == ttData.move && !excludedMove - && depth >= 4 - (thisThread->completedDepth > 36) + ss->ttPv + && depth >= 4 - (thisThread->completedDepth > 33) + ss->ttPv && std::abs(ttData.value) < VALUE_TB_WIN_IN_MAX_PLY && (ttData.bound & BOUND_LOWER) && ttData.depth >= depth - 3) { - Value singularBeta = ttData.value - (54 + 77 * (ss->ttPv && !PvNode)) * depth / 64; + Value singularBeta = ttData.value - (56 + 79 * (ss->ttPv && !PvNode)) * depth / 64; Depth singularDepth = newDepth / 2; ss->excludedMove = move; @@ -1088,8 +1088,8 @@ moves_loop: // When in check, search starts here if (value < singularBeta) { - int doubleMargin = 262 * PvNode - 204 * !ttCapture; - int tripleMargin = 97 + 266 * PvNode - 255 * !ttCapture + 94 * ss->ttPv; + int doubleMargin = 249 * PvNode - 194 * !ttCapture; + int tripleMargin = 94 + 287 * PvNode - 249 * !ttCapture + 99 * ss->ttPv; extension = 1 + (value < singularBeta - doubleMargin) + (value < singularBeta - tripleMargin); @@ -1127,7 +1127,7 @@ moves_loop: // When in check, search starts here else if (PvNode && move.to_sq() == prevSq && thisThread->captureHistory[movedPiece][move.to_sq()] [type_of(pos.piece_on(move.to_sq()))] - > 4299) + > 4321) extension = 1; } @@ -1182,7 +1182,7 @@ moves_loop: // When in check, search starts here ss->statScore = 2 * thisThread->mainHistory[us][move.from_to()] + (*contHist[0])[movedPiece][move.to_sq()] - + (*contHist[1])[movedPiece][move.to_sq()] - 4410; + + (*contHist[1])[movedPiece][move.to_sq()] - 3996; // Decrease/increase reduction for moves with a good/bad history (~8 Elo) r -= ss->statScore * 1287 / 16384; @@ -1204,8 +1204,8 @@ moves_loop: // When in check, search starts here { // Adjust full-depth search based on LMR results - if the result was // good enough search deeper, if it was bad enough search shallower. - const bool doDeeperSearch = value > (bestValue + 38 + 2 * newDepth); // (~1 Elo) - const bool doShallowerSearch = value < bestValue + 8; // (~2 Elo) + const bool doDeeperSearch = value > (bestValue + 42 + 2 * newDepth); // (~1 Elo) + const bool doShallowerSearch = value < bestValue + 10; // (~2 Elo) newDepth += doDeeperSearch - doShallowerSearch; @@ -1377,29 +1377,29 @@ 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 = (118 * (depth > 5) + 38 * !allNode + 169 * ((ss - 1)->moveCount > 8) - + 116 * (!ss->inCheck && bestValue <= ss->staticEval - 101) - + 133 * (!(ss - 1)->inCheck && bestValue <= -(ss - 1)->staticEval - 92)); + int bonus = (117 * (depth > 5) + 39 * !allNode + 168 * ((ss - 1)->moveCount > 8) + + 115 * (!ss->inCheck && bestValue <= ss->staticEval - 108) + + 119 * (!(ss - 1)->inCheck && bestValue <= -(ss - 1)->staticEval - 83)); // Proportional to "how much damage we have to undo" - bonus += std::min(-(ss - 1)->statScore / 102, 305); + bonus += std::min(-(ss - 1)->statScore / 113, 300); bonus = std::max(bonus, 0); update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, - stat_bonus(depth) * bonus / 107); + stat_bonus(depth) * bonus / 93); thisThread->mainHistory[~us][((ss - 1)->currentMove).from_to()] - << stat_bonus(depth) * bonus / 174; + << stat_bonus(depth) * bonus / 179; if (type_of(pos.piece_on(prevSq)) != PAWN && ((ss - 1)->currentMove).type_of() != PROMOTION) thisThread->pawnHistory[pawn_structure_index(pos)][pos.piece_on(prevSq)][prevSq] - << stat_bonus(depth) * bonus / 25; + << stat_bonus(depth) * bonus / 24; } // Bonus when search fails low and there is a TT move else if (ttData.move && !allNode) - thisThread->mainHistory[us][ttData.move.from_to()] << stat_bonus(depth) / 4; + thisThread->mainHistory[us][ttData.move.from_to()] << stat_bonus(depth) * 23 / 100; if (PvNode) bestValue = std::min(bestValue, maxValue); @@ -1428,13 +1428,13 @@ moves_loop: // When in check, search starts here auto bonus = std::clamp(int(bestValue - ss->staticEval) * depth / 8, -CORRECTION_HISTORY_LIMIT / 4, CORRECTION_HISTORY_LIMIT / 4); thisThread->pawnCorrectionHistory[us][pawn_structure_index(pos)] - << bonus * 101 / 128; - thisThread->majorPieceCorrectionHistory[us][major_piece_index(pos)] << bonus * 157 / 128; - thisThread->minorPieceCorrectionHistory[us][minor_piece_index(pos)] << bonus * 153 / 128; + << bonus * 107 / 128; + thisThread->majorPieceCorrectionHistory[us][major_piece_index(pos)] << bonus * 162 / 128; + thisThread->minorPieceCorrectionHistory[us][minor_piece_index(pos)] << bonus * 148 / 128; thisThread->nonPawnCorrectionHistory[WHITE][us][non_pawn_index(pos)] - << bonus * 123 / 128; + << bonus * 122 / 128; thisThread->nonPawnCorrectionHistory[BLACK][us][non_pawn_index(pos)] - << bonus * 165 / 128; + << bonus * 185 / 128; if (m.is_ok()) (*(ss - 2)->continuationCorrectionHistory)[pos.piece_on(m.to_sq())][m.to_sq()] << bonus; @@ -1566,7 +1566,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) if (bestValue > alpha) alpha = bestValue; - futilityBase = ss->staticEval + 280; + futilityBase = ss->staticEval + 306; } const PieceToHistory* contHist[] = {(ss - 1)->continuationHistory, @@ -1629,11 +1629,11 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) + (*contHist[1])[pos.moved_piece(move)][move.to_sq()] + thisThread->pawnHistory[pawn_structure_index(pos)][pos.moved_piece(move)] [move.to_sq()] - <= 5036) + <= 5095) continue; // Do not search moves with bad enough SEE values (~5 Elo) - if (!pos.see_ge(move, -82)) + if (!pos.see_ge(move, -83)) continue; } @@ -1701,7 +1701,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) Depth Search::Worker::reduction(bool i, Depth d, int mn, int delta) const { int reductionScale = reductions[d] * reductions[mn]; - return (reductionScale + 1239 - delta * 795 / rootDelta) + (!i && reductionScale > 1341) * 1135; + return (reductionScale + 1304 - delta * 814 / rootDelta) + (!i && reductionScale > 1423) * 1135; } // elapsed() returns the time elapsed since the search started. If the @@ -1832,7 +1832,7 @@ void update_all_stats(const Position& pos, // at ply -1, -2, -3, -4, and -6 with current move. void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus) { - bonus = bonus * 53 / 64; + bonus = bonus * 50 / 64; for (int i : {1, 2, 3, 4, 6}) { From 43e100ae06376d63461005422f26e5517db07c6d Mon Sep 17 00:00:00 2001 From: Nonlinear2 <131959792+Nonlinear2@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:35:59 +0100 Subject: [PATCH 06/19] Use cutnode as TT Cutoff Condition At low enough depths, fail high with TT only when expected cutnode. Passed STC: https://tests.stockfishchess.org/tests/view/6726357b86d5ee47d953da8c LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 41184 W: 10873 L: 10551 D: 19760 Ptnml(0-2): 131, 4728, 10554, 5046, 133 Passed LTC: https://tests.stockfishchess.org/tests/view/6727326a86d5ee47d953db30 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 270888 W: 69040 L: 68243 D: 133605 Ptnml(0-2): 180, 29385, 75485, 30246, 148 closes https://github.com/official-stockfish/Stockfish/pull/5670 Bench: 805776 --- src/search.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 2a2331cb4..5fdfdeb2d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -636,7 +636,8 @@ Value Search::Worker::search( // At non-PV nodes we check for an early TT cutoff if (!PvNode && !excludedMove && ttData.depth > depth - (ttData.value <= beta) && ttData.value != VALUE_NONE // Can happen when !ttHit or when access race in probe() - && (ttData.bound & (ttData.value >= beta ? BOUND_LOWER : BOUND_UPPER))) + && (ttData.bound & (ttData.value >= beta ? BOUND_LOWER : BOUND_UPPER)) + && (cutNode == (ttData.value >= beta) || depth > 8)) { // If ttMove is quiet, update move sorting heuristics on TT hit (~2 Elo) if (ttData.move && ttData.value >= beta) From 070db8b3a1ecfb4753753a3e285578b35acd63cd Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Sun, 3 Nov 2024 22:48:42 -0500 Subject: [PATCH 07/19] Update default main net to nn-1c0000000000.nnue Found by updating 489 L2 weights with values found from around 31k / 60k spsa games. Spsa was configured to use 60k games, down from 120k games in: https://github.com/official-stockfish/Stockfish/pull/5459 623 spsa params: L2 weights from `nn-1cedc0ffeeee.nnue` where 24 <= |value| <= 30 A: 3000, alpha: 0.602, gamma: 0.101 weights: [-127, 127], c_end = 6 Passed STC: https://tests.stockfishchess.org/tests/view/6728d61e86d5ee47d953dcaf LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 187168 W: 48642 L: 48107 D: 90419 Ptnml(0-2): 558, 21888, 48213, 22311, 614 Passed LTC: https://tests.stockfishchess.org/tests/view/672b018f86d5ee47d953de98 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 235074 W: 59924 L: 59202 D: 115948 Ptnml(0-2): 131, 25467, 65610, 26207, 122 closes https://github.com/official-stockfish/Stockfish/pull/5673 Bench: 898850 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 9bd436b58..4604321d3 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -33,7 +33,7 @@ namespace Eval { // for the build process (profile-build and fishtest) to work. Do not change the // name of the macro or the location where this macro is defined, as it is used // in the Makefile/Fishtest. -#define EvalFileDefaultNameBig "nn-1cedc0ffeeee.nnue" +#define EvalFileDefaultNameBig "nn-1c0000000000.nnue" #define EvalFileDefaultNameSmall "nn-37f18f62d772.nnue" namespace NNUE { From ce2d9e27ea8b10abbd69ebd5dd73e7dcf0aa0655 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Sun, 10 Nov 2024 18:52:29 +0300 Subject: [PATCH 08/19] Simplify big-net reevaluation Passed STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 37408 W: 9699 L: 9477 D: 18232 Ptnml(0-2): 130, 4326, 9577, 4534, 137 https://tests.stockfishchess.org/tests/view/672ffd8086d5ee47d953e633 Passed LTC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 151062 W: 38087 L: 37999 D: 74976 Ptnml(0-2): 63, 16686, 41958, 16748, 76 https://tests.stockfishchess.org/tests/view/673087aa86d5ee47d953e66b closes https://github.com/official-stockfish/Stockfish/pull/5674 Bench: 848812 --- src/evaluate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 7c7b54a4f..bc86a7420 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -66,7 +66,7 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks, Value nnue = (125 * psqt + 131 * positional) / 128; // Re-evaluate the position when higher eval accuracy is worth the time spent - if (smallNet && (nnue * psqt < 0 || std::abs(nnue) < 227)) + if (smallNet && (std::abs(nnue) < 236)) { std::tie(psqt, positional) = networks.big.evaluate(pos, &caches.big); nnue = (125 * psqt + 131 * positional) / 128; From 49138b8c33ca7bacff710efba4a90630a3490c08 Mon Sep 17 00:00:00 2001 From: Disservin Date: Wed, 13 Nov 2024 14:56:19 +0100 Subject: [PATCH 09/19] Fix CI Docker Buildx closes https://github.com/official-stockfish/Stockfish/pull/5678 No functional change --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a826e6f06..b97aaa29c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -139,7 +139,7 @@ jobs: - name: Build Docker container if: matrix.config.base_image run: | - docker buildx build --load -t sf_builder - << EOF + docker buildx build --platform ${{ matrix.config.platform }} --load -t sf_builder - << EOF FROM ${{ matrix.config.base_image }} WORKDIR /app RUN apk update && apk add make g++ From 82b092ca48c2efeadf2108a8351bb1309c4b7780 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Wed, 13 Nov 2024 20:43:04 +0300 Subject: [PATCH 10/19] Adjust statscore for captures Instead of using quiet histories use capture history with a different offset. Passed STC: https://tests.stockfishchess.org/tests/view/6731d5cc86d5ee47d953e719 LLR: 2.96 (-2.94,2.94) <0.00,2.00> Total: 428896 W: 111160 L: 110269 D: 207467 Ptnml(0-2): 1220, 50296, 110534, 51169, 1229 Passed LTC: https://tests.stockfishchess.org/tests/view/6733d9fd86d5ee47d953e962 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 105882 W: 26918 L: 26458 D: 52506 Ptnml(0-2): 66, 11430, 29482, 11904, 59 closes https://github.com/official-stockfish/Stockfish/pull/5679 Bench: 840721 --- src/search.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 5fdfdeb2d..94b20c85b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1181,9 +1181,14 @@ moves_loop: // When in check, search starts here else if (move == ttData.move) r -= 1879; - ss->statScore = 2 * thisThread->mainHistory[us][move.from_to()] - + (*contHist[0])[movedPiece][move.to_sq()] - + (*contHist[1])[movedPiece][move.to_sq()] - 3996; + if (capture) + ss->statScore = + thisThread->captureHistory[movedPiece][move.to_sq()][type_of(pos.captured_piece())] + - 13000; + else + ss->statScore = 2 * thisThread->mainHistory[us][move.from_to()] + + (*contHist[0])[movedPiece][move.to_sq()] + + (*contHist[1])[movedPiece][move.to_sq()] - 3996; // Decrease/increase reduction for moves with a good/bad history (~8 Elo) r -= ss->statScore * 1287 / 16384; From f129bf0de94f2c5a7ee19e697612a7e83ccd28ff Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Sun, 17 Nov 2024 09:19:06 +0300 Subject: [PATCH 11/19] Tweak statscore for captures Followup of a recent patch that separated statscore for captures and non-captures. Lower value that we subtract from statscore if a move is a capture. Passed STC: https://tests.stockfishchess.org/tests/view/67385b6786d5ee47d953eeba LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 50592 W: 13223 L: 12888 D: 24481 Ptnml(0-2): 154, 5853, 12931, 6220, 138 Passed LTC: https://tests.stockfishchess.org/tests/view/6739056e86d5ee47d953ef3f LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 23598 W: 6155 L: 5862 D: 11581 Ptnml(0-2): 16, 2466, 6543, 2757, 17 closes https://github.com/official-stockfish/Stockfish/pull/5682 Bench: 771180 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 94b20c85b..50b31d2ad 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1184,7 +1184,7 @@ moves_loop: // When in check, search starts here if (capture) ss->statScore = thisThread->captureHistory[movedPiece][move.to_sq()][type_of(pos.captured_piece())] - - 13000; + - 11000; else ss->statScore = 2 * thisThread->mainHistory[us][move.from_to()] + (*contHist[0])[movedPiece][move.to_sq()] From 0282edc0b06017b5f03971510cdb23e105fe9851 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Wed, 20 Nov 2024 01:09:39 +0300 Subject: [PATCH 12/19] Simplify bonus formula Give full bonus instead of half. Passed STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 23872 W: 6254 L: 6018 D: 11600 Ptnml(0-2): 80, 2691, 6152, 2939, 74 https://tests.stockfishchess.org/tests/view/673b709686d5ee47d953f19d Passed LTC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 42894 W: 10924 L: 10725 D: 21245 Ptnml(0-2): 30, 4592, 12011, 4777, 37 https://tests.stockfishchess.org/tests/view/673bb50386d5ee47d953f1eb closes https://github.com/official-stockfish/Stockfish/pull/5683 Bench: 836558 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 50b31d2ad..f1942a4f3 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -765,7 +765,7 @@ Value Search::Worker::search( thisThread->mainHistory[~us][((ss - 1)->currentMove).from_to()] << bonus; if (type_of(pos.piece_on(prevSq)) != PAWN && ((ss - 1)->currentMove).type_of() != PROMOTION) thisThread->pawnHistory[pawn_structure_index(pos)][pos.piece_on(prevSq)][prevSq] - << bonus / 2; + << bonus; } // Set up the improving flag, which is true if current static evaluation is From d29c8bd5d456b2a6fcee2069e1440ef82cba2b1e Mon Sep 17 00:00:00 2001 From: Guenther Demetz Date: Wed, 20 Nov 2024 14:48:23 +0100 Subject: [PATCH 13/19] Rewrite of 'Adjust correction history' condition Current condition is convoluted and hard to understand because of several negations. Also added 2 comments to make the concept behind the condition better understandable. closes https://github.com/official-stockfish/Stockfish/pull/5685 No functional change --- src/search.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index f1942a4f3..93036398d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1425,9 +1425,9 @@ moves_loop: // When in check, search starts here depth, bestMove, unadjustedStaticEval, tt.generation()); // Adjust correction history - if (!ss->inCheck && (!bestMove || !pos.capture(bestMove)) - && !(bestValue >= beta && bestValue <= ss->staticEval) - && !(!bestMove && bestValue >= ss->staticEval)) + if (!ss->inCheck && !(bestMove && pos.capture(bestMove)) + && ((bestValue < ss->staticEval && bestValue < beta) // negative correction & no fail high + || (bestValue > ss->staticEval && bestMove))) // positive correction & no fail low { const auto m = (ss - 1)->currentMove; From cd3c13a883b2d1e8dc32400202f8e0bae7d8123a Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Wed, 20 Nov 2024 17:03:56 +0300 Subject: [PATCH 14/19] Further tweak statscore for captures Even lower offset. Passed STC: https://tests.stockfishchess.org/tests/view/673a66d786d5ee47d953f070 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 63776 W: 16570 L: 16216 D: 30990 Ptnml(0-2): 178, 7371, 16478, 7641, 220 Passed LTC: https://tests.stockfishchess.org/tests/view/673b2e2a86d5ee47d953f14b LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 156960 W: 39999 L: 39435 D: 77526 Ptnml(0-2): 96, 16965, 43803, 17511, 105 closes https://github.com/official-stockfish/Stockfish/pull/5686 Bench: 867931 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 93036398d..213bbdab7 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1184,7 +1184,7 @@ moves_loop: // When in check, search starts here if (capture) ss->statScore = thisThread->captureHistory[movedPiece][move.to_sq()][type_of(pos.captured_piece())] - - 11000; + - 5454; else ss->statScore = 2 * thisThread->mainHistory[us][move.from_to()] + (*contHist[0])[movedPiece][move.to_sq()] From 4fcd78ceb4a5cf25ee652ee7793bb0a3fa1f95df Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Mon, 18 Nov 2024 09:08:26 -0800 Subject: [PATCH 15/19] Simplify Probcut Bonus Passed STC: LLR: 2.99 (-2.94,2.94) <-1.75,0.25> Total: 172288 W: 44656 L: 44580 D: 83052 Ptnml(0-2): 507, 20650, 43782, 20670, 535 https://tests.stockfishchess.org/tests/view/673b74f986d5ee47d953f1a3 Passed LTC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 94596 W: 24098 L: 23953 D: 46545 Ptnml(0-2): 57, 10322, 26393, 10471, 55 https://tests.stockfishchess.org/tests/view/673d191886d5ee47d953f337 closes https://github.com/official-stockfish/Stockfish/pull/5688 Bench: 1031022 --- src/search.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 213bbdab7..ace6385d7 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -910,8 +910,7 @@ Value Search::Worker::search( if (value >= probCutBeta) { - thisThread->captureHistory[movedPiece][move.to_sq()][type_of(captured)] - << stat_bonus(depth - 2); + thisThread->captureHistory[movedPiece][move.to_sq()][type_of(captured)] << 1300; // Save ProbCut data into transposition table ttWriter.write(posKey, value_to_tt(value, ss->ply), ss->ttPv, BOUND_LOWER, From fb6be17ad40d321b5fff02395bc156568fce3091 Mon Sep 17 00:00:00 2001 From: Daniel Monroe Date: Sun, 17 Nov 2024 20:46:30 -0800 Subject: [PATCH 16/19] Simplify statscore at captures Simplify statscores for captures, setting them to 0 A recent tweak of Vizvezdenec finds substantial elo gain from giving captures a separate statscore, which is used mainly for reductions. The idea is that the old combination of quiet histories was inappropriate and that a value based on the capture history is more suitable. This simplification sets the statscore for captures to 0, suggesting that the elo gain came from rectifying the quiet history/capture mismatch. Passed STC (against a slightly older version of Viz's patch) https://tests.stockfishchess.org/tests/view/673ac6e286d5ee47d953f0ec LR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 57312 W: 14872 L: 14672 D: 27768 Ptnml(0-2): 152, 6761, 14649, 6923, 171 Passed LTC (against Viz's newest patch) https://tests.stockfishchess.org/tests/view/673cd00686d5ee47d953f2db LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 88236 W: 22510 L: 22358 D: 43368 Ptnml(0-2): 70, 9530, 24745, 9724, 49 closes https://github.com/official-stockfish/Stockfish/pull/5691 Bench: 959947 --- src/search.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index ace6385d7..560b031ba 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -538,7 +538,7 @@ Value Search::Worker::search( // Dive into quiescence search when the depth reaches zero if (depth <= 0) - return qsearch < PvNode ? PV : NonPV > (pos, ss, alpha, beta); + return qsearch(pos, ss, alpha, beta); // Limit the depth if extensions made it too large depth = std::min(depth, MAX_PLY - 1); @@ -1181,9 +1181,7 @@ moves_loop: // When in check, search starts here r -= 1879; if (capture) - ss->statScore = - thisThread->captureHistory[movedPiece][move.to_sq()][type_of(pos.captured_piece())] - - 5454; + ss->statScore = 0; else ss->statScore = 2 * thisThread->mainHistory[us][move.from_to()] + (*contHist[0])[movedPiece][move.to_sq()] From b7f17346e55a9494d8fed610f613e1722da3042d Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Thu, 21 Nov 2024 22:17:47 -0800 Subject: [PATCH 17/19] Fix Sanitizer Tests closes https://github.com/official-stockfish/Stockfish/pull/5692 No functional change --- tests/instrumented.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/instrumented.py b/tests/instrumented.py index a3747d4e9..db5ec8e08 100644 --- a/tests/instrumented.py +++ b/tests/instrumented.py @@ -352,10 +352,10 @@ class TestInteractive(metaclass=OrderedClassMembers): def test_fen_position_depth_27(self): self.stockfish.send_command("ucinewgame") self.stockfish.send_command( - "position fen 1NR2B2/5p2/5p2/1p1kpp2/1P2rp2/2P1pB2/2P1P1K1/8 b - -" + "position fen r1b2r1k/pp1p2pp/2p5/2B1q3/8/8/P1PN2PP/R4RK1 w - - 0 18" ) - self.stockfish.send_command("go depth 27") - self.stockfish.contains("score mate -2") + self.stockfish.send_command("go") + self.stockfish.contains("score mate 1") self.stockfish.starts_with("bestmove") From 55905e562a0de4aeef9c5081a9eab80e6ed4c542 Mon Sep 17 00:00:00 2001 From: Daniel Monroe Date: Wed, 13 Nov 2024 12:56:29 -0800 Subject: [PATCH 18/19] Simplify movepick coefficients This commit sets movepick weights for all continuation histories to 1 and doubles the weight for the main history, inspired by a recent tune. Passed STC https://tests.stockfishchess.org/tests/view/6735151a86d5ee47d953eaa2 LLR: 2.92 (-2.94,2.94) <-1.75,0.25> Total: 29984 W: 7840 L: 7612 D: 14532 Ptnml(0-2): 85, 3511, 7571, 3741, 84 Passed LTC https://tests.stockfishchess.org/tests/view/673667a986d5ee47d953ec78 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 26268 W: 6726 L: 6510 D: 13032 Ptnml(0-2): 16, 2797, 7288, 3021, 12 closes https://github.com/official-stockfish/Stockfish/pull/5680 Bench: 1130293 --- src/movepick.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index 720f2e031..df722eceb 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -158,11 +158,11 @@ void MovePicker::score() { Square to = m.to_sq(); // histories - m.value = (*mainHistory)[pos.side_to_move()][m.from_to()]; + m.value = 2 * (*mainHistory)[pos.side_to_move()][m.from_to()]; m.value += 2 * (*pawnHistory)[pawn_structure_index(pos)][pc][to]; - m.value += 2 * (*continuationHistory[0])[pc][to]; + m.value += (*continuationHistory[0])[pc][to]; m.value += (*continuationHistory[1])[pc][to]; - m.value += (*continuationHistory[2])[pc][to] / 3; + m.value += (*continuationHistory[2])[pc][to]; m.value += (*continuationHistory[3])[pc][to]; m.value += (*continuationHistory[5])[pc][to]; From 70bb317afe870c8bc1979ef955f120e4d81f504e Mon Sep 17 00:00:00 2001 From: Daniel Monroe Date: Fri, 22 Nov 2024 16:56:50 -0800 Subject: [PATCH 19/19] Bonus for a prior capture that causes a fail low. This tweak adds a bonus equal to twice the stat_bonus for the current depth for a prior capture that caused a fail high, similar to the prior countermove bonus we currently have. Passed STC https://tests.stockfishchess.org/tests/view/673bc14b86d5ee47d953f1f2 LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 105824 W: 27538 L: 27118 D: 51168 Ptnml(0-2): 358, 12370, 27024, 12814, 346 Passed LTC https://tests.stockfishchess.org/tests/view/673ccbff86d5ee47d953f2d9 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 134502 W: 34340 L: 33820 D: 66342 Ptnml(0-2): 102, 14634, 37229, 15214, 72 closes https://github.com/official-stockfish/Stockfish/pull/5695 Bench: 1107054 --- src/search.cpp | 19 +++++++++++++++---- src/search.h | 3 ++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 560b031ba..45f0f10fc 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -538,7 +538,7 @@ Value Search::Worker::search( // Dive into quiescence search when the depth reaches zero if (depth <= 0) - return qsearch(pos, ss, alpha, beta); + return qsearch < PvNode ? PV : NonPV > (pos, ss, alpha, beta); // Limit the depth if extensions made it too large depth = std::min(depth, MAX_PLY - 1); @@ -889,7 +889,8 @@ Value Search::Worker::search( // Prefetch the TT entry for the resulting position prefetch(tt.first_entry(pos.key_after(move))); - ss->currentMove = move; + ss->currentMove = move; + ss->capturedPiece = captured; ss->continuationHistory = &this->continuationHistory[ss->inCheck][true][pos.moved_piece(move)][move.to_sq()]; ss->continuationCorrectionHistory = @@ -1138,7 +1139,8 @@ moves_loop: // When in check, search starts here prefetch(tt.first_entry(pos.key_after(move))); // Update the current move (this must be done after singular extension search) - ss->currentMove = move; + ss->currentMove = move; + ss->capturedPiece = pos.piece_on(move.to_sq()); ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck][capture][movedPiece][move.to_sq()]; ss->continuationCorrectionHistory = @@ -1400,6 +1402,14 @@ moves_loop: // When in check, search starts here << stat_bonus(depth) * bonus / 24; } + else if (priorCapture && prevSq != SQ_NONE) + { + // bonus for prior countermoves that caused the fail low + Piece capturedPiece = (ss - 1)->capturedPiece; + thisThread->captureHistory[pos.piece_on(prevSq)][prevSq][type_of(capturedPiece)] + << stat_bonus(depth) * 2; + } + // Bonus when search fails low and there is a TT move else if (ttData.move && !allNode) thisThread->mainHistory[us][ttData.move.from_to()] << stat_bonus(depth) * 23 / 100; @@ -1644,7 +1654,8 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) prefetch(tt.first_entry(pos.key_after(move))); // Update the current move - ss->currentMove = move; + ss->currentMove = move; + ss->capturedPiece = pos.piece_on(move.to_sq()); ss->continuationHistory = &thisThread ->continuationHistory[ss->inCheck][capture][pos.moved_piece(move)][move.to_sq()]; diff --git a/src/search.h b/src/search.h index b618855b9..7868f6078 100644 --- a/src/search.h +++ b/src/search.h @@ -66,6 +66,7 @@ struct Stack { CorrectionHistory* continuationCorrectionHistory; int ply; Move currentMove; + Piece capturedPiece; Move excludedMove; Value staticEval; int statScore; @@ -356,4 +357,4 @@ class Worker { } // namespace Stockfish -#endif // #ifndef SEARCH_H_INCLUDED +#endif // #ifndef SEARCH_H_INCLUDED \ No newline at end of file