Introduce capture history pruning
authorVizvezdenec <Vizvezdenec@gmail.com>
Tue, 7 Apr 2020 13:53:24 +0000 (16:53 +0300)
committerJoost VandeVondele <Joost.VandeVondele@gmail.com>
Tue, 7 Apr 2020 15:47:01 +0000 (17:47 +0200)
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

src/search.cpp

index cfda94b8080110112b1bac35b20472fd09719e22..dba8857efdacee98ab84a2e075b9af0e97593e2e 100644 (file)
@@ -789,6 +789,8 @@ namespace {
         }
     }
 
+    CapturePieceToHistory& captureHistory = thisThread->captureHistory;
+
     // Step 6. Static evaluation of the position
     if (inCheck)
     {
@@ -899,7 +901,7 @@ namespace {
         &&  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
@@ -954,7 +956,7 @@ moves_loop: // When in check, search starts from here
 
     MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory,
                                       &thisThread->lowPlyHistory,
-                                      &thisThread->captureHistory,
+                                      &captureHistory,
                                       contHist,
                                       countermove,
                                       ss->killers,
@@ -1010,12 +1012,12 @@ moves_loop: // When in check, search starts from here
           // 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)
           {
-              // 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
@@ -1035,8 +1037,16 @@ moves_loop: // When in check, search starts from here
               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)