This patch introduces a heuristic that is similar to countermove based pruning but for captures - capture history pruning. The idea is that we can (almost) safely prune really late captures with negative history if they don't give check so will most likely not produce some king-attacking tactic.
passed STC
https://tests.stockfishchess.org/tests/view/
5e8c60d40ffd2be7f15e5470
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 23748 W: 4758 L: 4529 D: 14461
Ptnml(0-2): 421, 2712, 5400, 2899, 442
passed LTC
https://tests.stockfishchess.org/tests/view/
5e8c72bf0ffd2be7f15e547f
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 17330 W: 2415 L: 2190 D: 12725
Ptnml(0-2): 126, 1561, 5107, 1704, 167
closes https://github.com/official-stockfish/Stockfish/pull/2618
bench
4417023
+ CapturePieceToHistory& captureHistory = thisThread->captureHistory;
+
// Step 6. Static evaluation of the position
if (inCheck)
{
// Step 6. Static evaluation of the position
if (inCheck)
{
&& abs(beta) < VALUE_TB_WIN_IN_MAX_PLY)
{
Value raisedBeta = std::min(beta + 189 - 45 * improving, VALUE_INFINITE);
&& abs(beta) < VALUE_TB_WIN_IN_MAX_PLY)
{
Value raisedBeta = std::min(beta + 189 - 45 * improving, VALUE_INFINITE);
- MovePicker mp(pos, ttMove, raisedBeta - ss->staticEval, &thisThread->captureHistory);
+ MovePicker mp(pos, ttMove, raisedBeta - ss->staticEval, &captureHistory);
int probCutCount = 0;
while ( (move = mp.next_move()) != MOVE_NONE
int probCutCount = 0;
while ( (move = mp.next_move()) != MOVE_NONE
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory,
&thisThread->lowPlyHistory,
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory,
&thisThread->lowPlyHistory,
- &thisThread->captureHistory,
contHist,
countermove,
ss->killers,
contHist,
countermove,
ss->killers,
// Skip quiet moves if movecount exceeds our FutilityMoveCount threshold
moveCountPruning = moveCount >= futility_move_count(improving, depth);
// Skip quiet moves if movecount exceeds our FutilityMoveCount threshold
moveCountPruning = moveCount >= futility_move_count(improving, depth);
+ // Reduced depth of the next LMR search
+ int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount), 0);
+
if ( !captureOrPromotion
&& !givesCheck)
{
if ( !captureOrPromotion
&& !givesCheck)
{
- // Reduced depth of the next LMR search
- int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount), 0);
-
// Countermoves based pruning (~20 Elo)
if ( lmrDepth < 4 + ((ss-1)->statScore > 0 || (ss-1)->moveCount == 1)
&& (*contHist[0])[movedPiece][to_sq(move)] < CounterMovePruneThreshold
// Countermoves based pruning (~20 Elo)
if ( lmrDepth < 4 + ((ss-1)->statScore > 0 || (ss-1)->moveCount == 1)
&& (*contHist[0])[movedPiece][to_sq(move)] < CounterMovePruneThreshold
if (!pos.see_ge(move, Value(-(32 - std::min(lmrDepth, 18)) * lmrDepth * lmrDepth)))
continue;
}
if (!pos.see_ge(move, Value(-(32 - std::min(lmrDepth, 18)) * lmrDepth * lmrDepth)))
continue;
}
- else if (!pos.see_ge(move, Value(-194) * depth)) // (~25 Elo)
- continue;
+ else
+ {
+ if ( !givesCheck
+ && lmrDepth < 1
+ && captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] < 0)
+ continue;
+
+ if (!pos.see_ge(move, Value(-194) * depth)) // (~25 Elo)
+ continue;
+ }
}
// Step 14. Extensions (~75 Elo)
}
// Step 14. Extensions (~75 Elo)