Post-NNUEv10 tune

Tune search parameters after the switch to NNUEv10.

The change is neutral at STC but increases with the TC. The main changes are more aggressive corrections, futility pruning, and extensions.

Failed STC
LLR: -2.96 (-2.94,2.94) <0.00,2.00>
Total: 108320 W: 27616 L: 27719 D: 52985
Ptnml(0-2): 332, 12833, 27884, 12828, 283
https://tests.stockfishchess.org/tests/view/69212e623b03dd3a060e6114

Passed LTC
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 43272 W: 11117 L: 10788 D: 21367
Ptnml(0-2): 20, 4543, 12180, 4874, 19
https://tests.stockfishchess.org/tests/view/692130813b03dd3a060e6123

Passed VLTC
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 22714 W: 5840 L: 5581 D: 11293
Ptnml(0-2): 2, 2152, 6795, 2401, 7
https://tests.stockfishchess.org/tests/view/6921387b3b03dd3a060e6191

Passed VLTC SMP
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 11868 W: 3142 L: 2896 D: 5830
Ptnml(0-2): 0, 1007, 3676, 1249, 2
https://tests.stockfishchess.org/tests/view/69212e953b03dd3a060e611b

closes https://github.com/official-stockfish/Stockfish/pull/6444

bench 2907929
This commit is contained in:
Daniel Monroe
2025-11-22 07:56:47 +01:00
committed by Joost VandeVondele
parent 035cb146d4
commit d9fd516547
2 changed files with 101 additions and 95 deletions
+6 -6
View File
@@ -65,7 +65,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 && (std::abs(nnue) < 236))
if (smallNet && (std::abs(nnue) < 277))
{
std::tie(psqt, positional) = networks.big.evaluate(pos, accumulators, caches.big);
nnue = (125 * psqt + 131 * positional) / 128;
@@ -74,14 +74,14 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks,
// Blend optimism and eval with nnue complexity
int nnueComplexity = std::abs(psqt - positional);
optimism += optimism * nnueComplexity / 468;
nnue -= nnue * nnueComplexity / 18000;
optimism += optimism * nnueComplexity / 476;
nnue -= nnue * nnueComplexity / 18236;
int material = 535 * pos.count<PAWN>() + pos.non_pawn_material();
int v = (nnue * (77777 + material) + optimism * (7777 + material)) / 77777;
int material = 534 * pos.count<PAWN>() + pos.non_pawn_material();
int v = (nnue * (77871 + material) + optimism * (7191 + material)) / 77871;
// Damp down the evaluation linearly when shuffling
v -= v * pos.rule50_count() / 212;
v -= v * pos.rule50_count() / 199;
// Guarantee evaluation does not hit the tablebase range
v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1);
+94 -88
View File
@@ -88,7 +88,7 @@ int correction_value(const Worker& w, const Position& pos, const Stack* const ss
+ (*(ss - 4)->continuationCorrectionHistory)[pos.piece_on(m.to_sq())][m.to_sq()]
: 8;
return 9536 * pcv + 8494 * micv + 10132 * (wnpcv + bnpcv) + 7156 * cntcv;
return 10347 * pcv + 8821 * micv + 11168 * (wnpcv + bnpcv) + 7841 * cntcv;
}
// Add correctionHistory value to raw staticEval and guarantee evaluation
@@ -104,10 +104,10 @@ void update_correction_history(const Position& pos,
const Move m = (ss - 1)->currentMove;
const Color us = pos.side_to_move();
constexpr int nonPawnWeight = 165;
constexpr int nonPawnWeight = 178;
workerThread.pawnCorrectionHistory[pawn_correction_history_index(pos)][us] << bonus;
workerThread.minorPieceCorrectionHistory[minor_piece_index(pos)][us] << bonus * 145 / 128;
workerThread.minorPieceCorrectionHistory[minor_piece_index(pos)][us] << bonus * 156 / 128;
workerThread.nonPawnCorrectionHistory[non_pawn_index<WHITE>(pos)][WHITE][us]
<< bonus * nonPawnWeight / 128;
workerThread.nonPawnCorrectionHistory[non_pawn_index<BLACK>(pos)][BLACK][us]
@@ -117,8 +117,8 @@ void update_correction_history(const Position& pos,
{
const Square to = m.to_sq();
const Piece pc = pos.piece_on(m.to_sq());
(*(ss - 2)->continuationCorrectionHistory)[pc][to] << bonus * 137 / 128;
(*(ss - 4)->continuationCorrectionHistory)[pc][to] << bonus * 64 / 128;
(*(ss - 2)->continuationCorrectionHistory)[pc][to] << bonus * 127 / 128;
(*(ss - 4)->continuationCorrectionHistory)[pc][to] << bonus * 59 / 128;
}
}
@@ -338,7 +338,7 @@ void Search::Worker::iterative_deepening() {
beta = std::min(avg + delta, VALUE_INFINITE);
// Adjust optimism based on root move's averageScore
optimism[us] = 137 * avg / (std::abs(avg) + 91);
optimism[us] = 142 * avg / (std::abs(avg) + 91);
optimism[~us] = -optimism[us];
// Start with a small aspiration window and, in the case of a fail
@@ -467,20 +467,23 @@ void Search::Worker::iterative_deepening() {
uint64_t nodesEffort =
rootMoves[0].effort * 100000 / std::max(size_t(1), size_t(nodes));
double fallingEval =
(11.325 + 2.115 * (mainThread->bestPreviousAverageScore - bestValue)
+ 0.987 * (mainThread->iterValue[iterIdx] - bestValue))
double fallingEval = (11.85 + 2.24 * (mainThread->bestPreviousAverageScore - bestValue)
+ 0.93 * (mainThread->iterValue[iterIdx] - bestValue))
/ 100.0;
fallingEval = std::clamp(fallingEval, 0.5688, 1.5698);
fallingEval = std::clamp(fallingEval, 0.57, 1.70);
// If the bestMove is stable over several iterations, reduce time accordingly
double k = 0.5189;
double center = lastBestMoveDepth + 11.57;
timeReduction = 0.723 + 0.79 / (1.104 + std::exp(-k * (completedDepth - center)));
double reduction =
(1.455 + mainThread->previousTimeReduction) / (2.2375 * timeReduction);
double bestMoveInstability = 1.04 + 1.8956 * totBestMoveChanges / threads.size();
double highBestMoveEffort = completedDepth >= 10 && nodesEffort >= 92425 ? 0.666 : 1.0;
double k = 0.51;
double center = lastBestMoveDepth + 12.15;
timeReduction = 0.66 + 0.85 / (0.98 + std::exp(-k * (completedDepth - center)));
double reduction = (1.43 + mainThread->previousTimeReduction) / (2.28 * timeReduction);
double bestMoveInstability = 1.02 + 2.14 * totBestMoveChanges / threads.size();
double highBestMoveEffort = completedDepth >= 10 && nodesEffort >= 93337 ? 0.75 : 1.0;
double totalTime = mainThread->tm.optimum() * fallingEval * reduction
* bestMoveInstability * highBestMoveEffort;
@@ -502,7 +505,7 @@ void Search::Worker::iterative_deepening() {
threads.stop = true;
}
else
threads.increaseDepth = mainThread->ponder || elapsedTime <= totalTime * 0.503;
threads.increaseDepth = mainThread->ponder || elapsedTime <= totalTime * 0.50;
}
mainThread->iterValue[iterIdx] = bestValue;
@@ -582,7 +585,7 @@ void Search::Worker::clear() {
h.fill(-529);
for (size_t i = 1; i < reductions.size(); ++i)
reductions[i] = int(2809 / 128.0 * std::log(i));
reductions[i] = int(2747 / 128.0 * std::log(i));
refreshTable.clear(networks[numaAccessToken]);
}
@@ -702,11 +705,12 @@ Value Search::Worker::search(
// Bonus for a quiet ttMove that fails high
if (!ttCapture)
update_quiet_histories(pos, ss, *this, ttData.move,
std::min(130 * depth - 71, 1043));
std::min(132 * depth - 72, 985));
// Extra penalty for early quiet moves of the previous ply
if (prevSq != SQ_NONE && (ss - 1)->moveCount < 4 && !priorCapture)
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -2142);
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -2060);
}
// Partial workaround for the graph history interaction problem
@@ -825,11 +829,11 @@ Value Search::Worker::search(
// Use static evaluation difference to improve quiet move ordering
if (((ss - 1)->currentMove).is_ok() && !(ss - 1)->inCheck && !priorCapture)
{
int evalDiff = std::clamp(-int((ss - 1)->staticEval + ss->staticEval), -200, 156) + 58;
int evalDiff = std::clamp(-int((ss - 1)->staticEval + ss->staticEval), -209, 167) + 59;
mainHistory[~us][((ss - 1)->currentMove).raw()] << evalDiff * 9;
if (!ttHit && type_of(pos.piece_on(prevSq)) != PAWN
&& ((ss - 1)->currentMove).type_of() != PROMOTION)
pawnHistory[pawn_history_index(pos)][pos.piece_on(prevSq)][prevSq] << evalDiff * 14;
pawnHistory[pawn_history_index(pos)][pos.piece_on(prevSq)][prevSq] << evalDiff * 13;
}
// Set up the improving flag, which is true if current static evaluation is
@@ -844,25 +848,25 @@ Value Search::Worker::search(
// Hindsight adjustment of reductions based on static evaluation difference.
if (priorReduction >= 3 && !opponentWorsening)
depth++;
if (priorReduction >= 2 && depth >= 2 && ss->staticEval + (ss - 1)->staticEval > 173)
if (priorReduction >= 2 && depth >= 2 && ss->staticEval + (ss - 1)->staticEval > 169)
depth--;
// Step 7. Razoring
// If eval is really low, skip search entirely and return the qsearch value.
// For PvNodes, we must have a guard against mates being returned.
if (!PvNode && eval < alpha - 514 - 294 * depth * depth)
if (!PvNode && eval < alpha - 485 - 281 * depth * depth)
return qsearch<NonPV>(pos, ss, alpha, beta);
// Step 8. Futility pruning: child node
// The depth condition is important for mate finding.
{
auto futility_margin = [&](Depth d) {
Value futilityMult = 81 - 21 * !ss->ttHit;
Value futilityMult = 76 - 23 * !ss->ttHit;
return futilityMult * d //
- 2094 * improving * futilityMult / 1024 //
- 2474 * improving * futilityMult / 1024 //
- 331 * opponentWorsening * futilityMult / 1024 //
+ std::abs(correctionValue) / 158105;
+ std::abs(correctionValue) / 174665;
};
if (!ss->ttPv && depth < 14 && eval - futility_margin(depth) >= beta && eval >= beta
@@ -871,7 +875,7 @@ Value Search::Worker::search(
}
// Step 9. Null move search with verification search
if (cutNode && ss->staticEval >= beta - 18 * depth + 390 && !excludedMove
if (cutNode && ss->staticEval >= beta - 18 * depth + 350 && !excludedMove
&& pos.non_pawn_material(us) && ss->ply >= nmpMinPly && !is_loss(beta))
{
assert((ss - 1)->currentMove != Move::null());
@@ -905,6 +909,7 @@ Value Search::Worker::search(
}
}
improving |= ss->staticEval >= beta;
// Step 10. Internal iterative reductions
@@ -916,7 +921,7 @@ Value Search::Worker::search(
// Step 11. ProbCut
// 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 + 224 - 64 * improving;
probCutBeta = beta + 235 - 63 * improving;
if (depth >= 3
&& !is_decisive(beta)
// If value from transposition table is lower than probCutBeta, don't attempt
@@ -926,7 +931,7 @@ Value Search::Worker::search(
assert(probCutBeta < VALUE_INFINITE && probCutBeta > beta);
MovePicker mp(pos, ttData.move, probCutBeta - ss->staticEval, &captureHistory);
Depth probCutDepth = std::clamp(depth - 5 - (ss->staticEval - beta) / 306, 0, depth);
Depth probCutDepth = std::clamp(depth - 5 - (ss->staticEval - beta) / 315, 0, depth);
while ((move = mp.next_move()) != Move::none())
{
@@ -1046,8 +1051,8 @@ moves_loop: // When in check, search starts here
// Futility pruning for captures
if (!givesCheck && lmrDepth < 7)
{
Value futilityValue = ss->staticEval + 231 + 211 * lmrDepth
+ PieceValue[capturedPiece] + 130 * captHist / 1024;
Value futilityValue = ss->staticEval + 232 + 217 * lmrDepth
+ PieceValue[capturedPiece] + 131 * captHist / 1024;
if (futilityValue <= alpha)
continue;
@@ -1055,7 +1060,7 @@ moves_loop: // When in check, search starts here
// SEE based pruning for captures and checks
// Avoid pruning sacrifices of our last piece for stalemate
int margin = std::max(157 * depth + captHist / 29, 0);
int margin = std::max(166 * depth + captHist / 29, 0);
if ((alpha >= VALUE_DRAW || pos.non_pawn_material(us) != PieceValue[movedPiece])
&& !pos.see_ge(move, -margin))
continue;
@@ -1067,21 +1072,21 @@ moves_loop: // When in check, search starts here
+ pawnHistory[pawn_history_index(pos)][movedPiece][move.to_sq()];
// Continuation history based pruning
if (history < -4312 * depth)
if (history < -4083 * depth)
continue;
history += 76 * mainHistory[us][move.raw()] / 32;
history += 69 * mainHistory[us][move.raw()] / 32;
// (*Scaler): Generally, lower divisors scales well
lmrDepth += history / 3220;
lmrDepth += history / 3208;
Value futilityValue = ss->staticEval + 47 + 171 * !bestMove + 134 * lmrDepth
+ 90 * (ss->staticEval > alpha);
Value futilityValue = ss->staticEval + 42 + 161 * !bestMove + 127 * lmrDepth
+ 85 * (ss->staticEval > alpha);
// Futility pruning: parent node
// (*Scaler): Generally, more frequent futility pruning
// scales well
if (!ss->inCheck && lmrDepth < 11 && futilityValue <= alpha)
if (!ss->inCheck && lmrDepth < 13 && futilityValue <= alpha)
{
if (bestValue <= futilityValue && !is_decisive(bestValue)
&& !is_win(futilityValue))
@@ -1092,7 +1097,7 @@ moves_loop: // When in check, search starts here
lmrDepth = std::max(lmrDepth, 0);
// Prune moves with negative SEE
if (!pos.see_ge(move, -27 * lmrDepth * lmrDepth))
if (!pos.see_ge(move, -25 * lmrDepth * lmrDepth))
continue;
}
}
@@ -1107,12 +1112,11 @@ moves_loop: // When in check, search starts here
// (*Scaler) Generally, higher singularBeta (i.e closer to ttValue)
// and lower extension margins scale well.
if (!rootNode && move == ttData.move && !excludedMove && depth >= 6 + ss->ttPv
&& is_valid(ttData.value) && !is_decisive(ttData.value) && (ttData.bound & BOUND_LOWER)
&& ttData.depth >= depth - 3)
{
Value singularBeta = ttData.value - (56 + 81 * (ss->ttPv && !PvNode)) * depth / 60;
Value singularBeta = ttData.value - (53 + 75 * (ss->ttPv && !PvNode)) * depth / 60;
Depth singularDepth = newDepth / 2;
ss->excludedMove = move;
@@ -1121,11 +1125,11 @@ moves_loop: // When in check, search starts here
if (value < singularBeta)
{
int corrValAdj = std::abs(correctionValue) / 229958;
int doubleMargin = -4 + 198 * PvNode - 212 * !ttCapture - corrValAdj
- 921 * ttMoveHistory / 127649 - (ss->ply > rootDepth) * 45;
int tripleMargin = 76 + 308 * PvNode - 250 * !ttCapture + 92 * ss->ttPv - corrValAdj
- (ss->ply * 2 > rootDepth * 3) * 52;
int corrValAdj = std::abs(correctionValue) / 230673;
int doubleMargin = -4 + 199 * PvNode - 201 * !ttCapture - corrValAdj
- 897 * ttMoveHistory / 127649 - (ss->ply > rootDepth) * 42;
int tripleMargin = 73 + 302 * PvNode - 248 * !ttCapture + 90 * ss->ttPv - corrValAdj
- (ss->ply * 2 > rootDepth * 3) * 50;
extension =
1 + (value < singularBeta - doubleMargin) + (value < singularBeta - tripleMargin);
@@ -1171,33 +1175,32 @@ moves_loop: // When in check, search starts here
// Decrease reduction for PvNodes (*Scaler)
if (ss->ttPv)
r -= 2618 + PvNode * 991 + (ttData.value > alpha) * 903
+ (ttData.depth >= depth) * (978 + cutNode * 1051);
r -= 2719 + PvNode * 983 + (ttData.value > alpha) * 922
+ (ttData.depth >= depth) * (934 + cutNode * 1011);
// These reduction adjustments have no proven non-linear scaling
r += 843; // Base reduction offset to compensate for other tweaks
r -= moveCount * 66;
r -= std::abs(correctionValue) / 30450;
r += 714; // Base reduction offset to compensate for other tweaks
r -= moveCount * 73;
r -= std::abs(correctionValue) / 30370;
// Increase reduction for cut nodes
if (cutNode)
r += 3094 + 1056 * !ttData.move;
r += 3372 + 997 * !ttData.move;
// Increase reduction if ttMove is a capture
if (ttCapture)
r += 1415;
r += 1119;
// Increase reduction if next ply has a lot of fail high
if ((ss + 1)->cutoffCnt > 2)
r += 1051 + allNode * 814;
r += 991 + allNode * 923;
// For first picked move (ttMove) reduce reduction
if (move == ttData.move)
r -= 2018;
r -= 2151;
if (capture)
ss->statScore = 803 * int(PieceValue[pos.captured_piece()]) / 128
ss->statScore = 868 * int(PieceValue[pos.captured_piece()]) / 128
+ captureHistory[movedPiece][move.to_sq()][type_of(pos.captured_piece())];
else
ss->statScore = 2 * mainHistory[us][move.raw()]
@@ -1205,7 +1208,8 @@ moves_loop: // When in check, search starts here
+ (*contHist[1])[movedPiece][move.to_sq()];
// Decrease/increase reduction for moves with a good/bad history
r -= ss->statScore * 794 / 8192;
r -= ss->statScore * 850 / 8192;
// Step 17. Late moves reduction / extension (LMR)
if (depth >= 2 && moveCount > 1)
@@ -1245,13 +1249,12 @@ moves_loop: // When in check, search starts here
{
// Increase reduction if ttMove is not present
if (!ttData.move)
r += 1118;
r += 1140;
// Note that if expected reduction is high, we reduce search depth here
value = -search<NonPV>(pos, ss + 1, -(alpha + 1), -alpha,
newDepth - (r > 3212) - (r > 4784 && newDepth > 2), !cutNode);
newDepth - (r > 3957) - (r > 5654 && newDepth > 2), !cutNode);
}
// For PV nodes only, do a full PV search on the first move or after a fail high,
// otherwise let the parent node fail low with value <= alpha and try another move.
if (PvNode && (moveCount == 1 || value > alpha))
@@ -1403,25 +1406,25 @@ moves_loop: // When in check, search starts here
// Bonus for prior quiet countermove that caused the fail low
else if (!priorCapture && prevSq != SQ_NONE)
{
int bonusScale = -228;
bonusScale -= (ss - 1)->statScore / 104;
bonusScale += std::min(63 * depth, 508);
int bonusScale = -215;
bonusScale -= (ss - 1)->statScore / 100;
bonusScale += std::min(56 * depth, 489);
bonusScale += 184 * ((ss - 1)->moveCount > 8);
bonusScale += 143 * (!ss->inCheck && bestValue <= ss->staticEval - 92);
bonusScale += 149 * (!(ss - 1)->inCheck && bestValue <= -(ss - 1)->staticEval - 70);
bonusScale += 147 * (!ss->inCheck && bestValue <= ss->staticEval - 107);
bonusScale += 156 * (!(ss - 1)->inCheck && bestValue <= -(ss - 1)->staticEval - 65);
bonusScale = std::max(bonusScale, 0);
const int scaledBonus = std::min(144 * depth - 92, 1365) * bonusScale;
const int scaledBonus = std::min(141 * depth - 87, 1351) * bonusScale;
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq,
scaledBonus * 400 / 32768);
scaledBonus * 406 / 32768);
mainHistory[~us][((ss - 1)->currentMove).raw()] << scaledBonus * 220 / 32768;
mainHistory[~us][((ss - 1)->currentMove).raw()] << scaledBonus * 243 / 32768;
if (type_of(pos.piece_on(prevSq)) != PAWN && ((ss - 1)->currentMove).type_of() != PROMOTION)
pawnHistory[pawn_history_index(pos)][pos.piece_on(prevSq)][prevSq]
<< scaledBonus * 1164 / 32768;
<< scaledBonus * 1160 / 32768;
}
// Bonus for prior capture countermove that caused the fail low
@@ -1429,9 +1432,10 @@ moves_loop: // When in check, search starts here
{
Piece capturedPiece = pos.captured_piece();
assert(capturedPiece != NO_PIECE);
captureHistory[pos.piece_on(prevSq)][prevSq][type_of(capturedPiece)] << 964;
captureHistory[pos.piece_on(prevSq)][prevSq][type_of(capturedPiece)] << 1012;
}
if (PvNode)
bestValue = std::min(bestValue, maxValue);
@@ -1579,9 +1583,10 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta)
if (bestValue > alpha)
alpha = bestValue;
futilityBase = ss->staticEval + 352;
futilityBase = ss->staticEval + 351;
}
const PieceToHistory* contHist[] = {(ss - 1)->continuationHistory};
Square prevSq = ((ss - 1)->currentMove).is_ok() ? ((ss - 1)->currentMove).to_sq() : SQ_NONE;
@@ -1640,7 +1645,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta)
continue;
// Do not search moves with bad enough SEE values
if (!pos.see_ge(move, -78))
if (!pos.see_ge(move, -80))
continue;
}
@@ -1713,9 +1718,10 @@ 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 - delta * 757 / rootDelta + !i * reductionScale * 218 / 512 + 1200;
return reductionScale - delta * 608 / rootDelta + !i * reductionScale * 238 / 512 + 1182;
}
// elapsed() returns the time elapsed since the search started. If the
// 'nodestime' option is enabled, it will return the count of nodes searched
// instead. This function is called to check whether the search should be
@@ -1809,35 +1815,35 @@ void update_all_stats(const Position& pos,
Piece movedPiece = pos.moved_piece(bestMove);
PieceType capturedPiece;
int bonus = std::min(121 * depth - 77, 1633) + 375 * (bestMove == ttMove);
int malus = std::min(825 * depth - 196, 2159) - 16 * moveCount;
int bonus = std::min(116 * depth - 81, 1515) + 347 * (bestMove == ttMove);
int malus = std::min(848 * depth - 207, 2446) - 17 * moveCount;
if (!pos.capture_stage(bestMove))
{
update_quiet_histories(pos, ss, workerThread, bestMove, bonus * 881 / 1024);
update_quiet_histories(pos, ss, workerThread, bestMove, bonus * 910 / 1024);
// Decrease stats for all non-best quiet moves
for (Move move : quietsSearched)
update_quiet_histories(pos, ss, workerThread, move, -malus * 1083 / 1024);
update_quiet_histories(pos, ss, workerThread, move, -malus * 1085 / 1024);
}
else
{
// Increase stats for the best move in case it was a capture move
capturedPiece = type_of(pos.piece_on(bestMove.to_sq()));
captureHistory[movedPiece][bestMove.to_sq()][capturedPiece] << bonus * 1482 / 1024;
captureHistory[movedPiece][bestMove.to_sq()][capturedPiece] << bonus * 1395 / 1024;
}
// Extra penalty for a quiet early move that was not a TT move in
// previous ply when it gets refuted.
if (prevSq != SQ_NONE && ((ss - 1)->moveCount == 1 + (ss - 1)->ttHit) && !pos.captured_piece())
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -malus * 614 / 1024);
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -malus * 602 / 1024);
// Decrease stats for all non-best capture moves
for (Move move : capturesSearched)
{
movedPiece = pos.moved_piece(move);
capturedPiece = type_of(pos.piece_on(move.to_sq()));
captureHistory[movedPiece][move.to_sq()][capturedPiece] << -malus * 1397 / 1024;
captureHistory[movedPiece][move.to_sq()][capturedPiece] << -malus * 1448 / 1024;
}
}
@@ -1845,8 +1851,8 @@ void update_all_stats(const Position& pos,
// Updates histories of the move pairs formed by moves
// at ply -1, -2, -3, -4, and -6 with current move.
void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus) {
static constexpr std::array<ConthistBonus, 6> conthist_bonuses = {
{{1, 1157}, {2, 648}, {3, 288}, {4, 576}, {5, 140}, {6, 441}}};
static std::array<ConthistBonus, 6> conthist_bonuses = {
{{1, 1133}, {2, 683}, {3, 312}, {4, 582}, {5, 149}, {6, 474}}};
for (const auto [i, weight] : conthist_bonuses)
{
@@ -1867,13 +1873,13 @@ void update_quiet_histories(
workerThread.mainHistory[us][move.raw()] << bonus; // Untuned to prevent duplicate effort
if (ss->ply < LOW_PLY_HISTORY_SIZE)
workerThread.lowPlyHistory[ss->ply][move.raw()] << bonus * 761 / 1024;
workerThread.lowPlyHistory[ss->ply][move.raw()] << bonus * 805 / 1024;
update_continuation_histories(ss, pos.moved_piece(move), move.to_sq(), bonus * 955 / 1024);
update_continuation_histories(ss, pos.moved_piece(move), move.to_sq(), bonus * 896 / 1024);
int pIndex = pawn_history_index(pos);
workerThread.pawnHistory[pIndex][pos.moved_piece(move)][move.to_sq()]
<< bonus * (bonus > 0 ? 850 : 550) / 1024;
<< bonus * (bonus > 0 ? 905 : 505) / 1024;
}
}