]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Introduce update_gains() and refactor some code
[stockfish] / src / search.cpp
index f259ab707fe7983a271bdd6b05093490d6fe404a..defe00d6f16fde3353b1cdf9c99840d796b8b166 100644 (file)
@@ -289,6 +289,7 @@ namespace {
   Value refine_eval(const TTEntry* tte, Value defaultEval, int ply);
   void update_history(const Position& pos, Move move, Depth depth, Move movesSearched[], int moveCount);
   void update_killers(Move m, SearchStack& ss);
+  void update_gains(const Position& pos, Move move, Value before, Value after);
 
   bool fail_high_ply_1();
   int current_search_time();
@@ -1165,21 +1166,14 @@ namespace {
         tte = TT.retrieve(pos.get_key());
     }
 
-    // Evaluate the position statically
     isCheck = pos.is_check();
-    EvalInfo ei;
     if (!isCheck)
     {
+        // Update gain statistics of the previous move that lead
+        // us in this position.
+        EvalInfo ei;
         ss[ply].eval = evaluate(pos, ei, threadID);
-
-        // Store gain statistics
-        Move m = ss[ply - 1].currentMove;
-        if (   m != MOVE_NULL
-            && pos.captured_piece() == NO_PIECE_TYPE
-            && !move_is_castle(m)
-            && !move_is_promotion(m))
-            MG.store(pos.piece_on(move_to(m)), move_from(m), move_to(m), ss[ply - 1].eval, -ss[ply].eval);
-
+        update_gains(pos, ss[ply - 1].currentMove, ss[ply - 1].eval, ss[ply].eval);
     }
 
     // Initialize a MovePicker object for the current position, and prepare
@@ -1359,7 +1353,7 @@ namespace {
     Move ttMove, move;
     Depth ext, newDepth;
     Value bestValue, staticValue, nullValue, value, futilityValue, futilityValueScaled;
-    bool isCheck, useFutilityPruning, singleEvasion, moveIsCheck, captureOrPromotion, dangerous;
+    bool isCheck, singleEvasion, moveIsCheck, captureOrPromotion, dangerous;
     bool mateThreat = false;
     int moveCount = 0;
     futilityValue = staticValue = bestValue = value = -VALUE_INFINITE;
@@ -1419,18 +1413,11 @@ namespace {
         ss[ply].eval = staticValue;
         futilityValue = staticValue + PostFutilityValueMargin; //FIXME: Remove me, only for split
         staticValue = refine_eval(tte, staticValue, ply); // Enhance accuracy with TT value if possible
-
-        // Store gain statistics
-        Move m = ss[ply - 1].currentMove;
-        if (   m != MOVE_NULL
-            && pos.captured_piece() == NO_PIECE_TYPE
-            && !move_is_castle(m)
-            && !move_is_promotion(m))
-            MG.store(pos.piece_on(move_to(m)), move_from(m), move_to(m), ss[ply - 1].eval, -ss[ply].eval);
+        update_gains(pos, ss[ply - 1].currentMove, ss[ply - 1].eval, ss[ply].eval);
     }
 
     // Post futility pruning
-    if (staticValue - PostFutilityValueMargin >= beta)
+    if (depth < SelectiveDepth && staticValue - PostFutilityValueMargin >= beta)
         return (staticValue - PostFutilityValueMargin);
 
     // Null move search
@@ -1510,7 +1497,6 @@ namespace {
     // to search all moves.
     MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]);
     CheckInfo ci(pos);
-    useFutilityPruning = depth < SelectiveDepth && !isCheck;
 
     // Loop through all legal moves until no moves remain or a beta cutoff occurs
     while (   bestValue < beta
@@ -1559,7 +1545,8 @@ namespace {
       // Futility pruning for captures
       Color them = opposite_color(pos.side_to_move());
 
-      if (    useFutilityPruning
+      if (   !isCheck
+          && newDepth < SelectiveDepth
           && !dangerous
           && pos.move_is_capture(move)
           && !pos.move_is_check(move, ci)
@@ -1579,7 +1566,7 @@ namespace {
 
 
       // Futility pruning
-      if (    useFutilityPruning
+      if (   !isCheck
           && !dangerous
           && !captureOrPromotion
           && !move_is_castle(move)
@@ -1599,19 +1586,22 @@ namespace {
           if (red >= 1.0)
               predictedDepth -= int(floor(red * int(OnePly)));
 
-          int preFutilityValueMargin = 0;
-          if (predictedDepth >= OnePly)
-              preFutilityValueMargin = 112 * bitScanReverse32(int(predictedDepth) * int(predictedDepth) / 2);
+          if (predictedDepth < SelectiveDepth)
+          {
+              int preFutilityValueMargin = 0;
+              if (predictedDepth >= OnePly)
+                  preFutilityValueMargin = 112 * bitScanReverse32(int(predictedDepth) * int(predictedDepth) / 2);
 
-          preFutilityValueMargin += MG.retrieve(pos.piece_on(move_from(move)), move_from(move), move_to(move)) + 45;
+              preFutilityValueMargin += MG.retrieve(pos.piece_on(move_from(move)), move_from(move), move_to(move)) + 45;
 
-          futilityValueScaled = ss[ply].eval + preFutilityValueMargin - moveCount * IncrementalFutilityMargin;
+              futilityValueScaled = ss[ply].eval + preFutilityValueMargin - moveCount * IncrementalFutilityMargin;
 
-          if (futilityValueScaled < beta)
-          {
-              if (futilityValueScaled > bestValue)
-                  bestValue = futilityValueScaled;
-              continue;
+              if (futilityValueScaled < beta)
+              {
+                  if (futilityValueScaled > bestValue)
+                      bestValue = futilityValueScaled;
+                  continue;
+              }
           }
       }
 
@@ -1761,16 +1751,9 @@ namespace {
     if (!isCheck)
     {
         ss[ply].eval = staticValue;
-        // Store gain statistics
-        Move m = ss[ply - 1].currentMove;
-        if (   m != MOVE_NULL
-            && pos.captured_piece() == NO_PIECE_TYPE
-            && !move_is_castle(m)
-            && !move_is_promotion(m))
-            MG.store(pos.piece_on(move_to(m)), move_from(m), move_to(m), ss[ply - 1].eval, -ss[ply].eval);
+        update_gains(pos, ss[ply - 1].currentMove, ss[ply - 1].eval, ss[ply].eval);
     }
 
-
     // Initialize "stand pat score", and return it immediately if it is
     // at least beta.
     bestValue = staticValue;
@@ -2652,6 +2635,21 @@ namespace {
   }
 
 
+  // update_gains() updates the gains table of a non-capture move given
+  // the static position evaluation before and after the move.
+
+  void update_gains(const Position& pos, Move m, Value before, Value after) {
+
+    if (   m != MOVE_NULL
+        && before != VALUE_NONE
+        && after != VALUE_NONE
+        && pos.captured_piece() == NO_PIECE_TYPE
+        && !move_is_castle(m)
+        && !move_is_promotion(m))
+        MG.store(pos.piece_on(move_to(m)), move_from(m), move_to(m), -(before + after));
+  }
+
+
   // fail_high_ply_1() checks if some thread is currently resolving a fail
   // high at ply 1 at the node below the first root node.  This information
   // is used for time management.