]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Incremental Futility Margin
[stockfish] / src / search.cpp
index 1786a6fdc60ebb235e708a7d7cfedaa63479987e..b420fb905203770005d92c9725b27ae99c4b938f 100644 (file)
@@ -176,6 +176,9 @@ namespace {
   // and near frontier nodes.
   const Value FutilityMarginQS = Value(0x80);
 
+  // Each move futility margin is decreased
+  const Value IncrementalFutilityMargin = Value(0xA);
+
   // Remaining depth:                  1 ply         1.5 ply       2 ply         2.5 ply       3 ply         3.5 ply
   const Value FutilityMargins[12] = { Value(0x100), Value(0x120), Value(0x200), Value(0x220), Value(0x250), Value(0x270),
   //                                   4 ply         4.5 ply       5 ply         5.5 ply       6 ply         6.5 ply
@@ -333,14 +336,14 @@ namespace {
 int perft(Position& pos, Depth depth)
 {
     Move move;
-    MovePicker mp = MovePicker(pos, MOVE_NONE, depth, H);
     int sum = 0;
+    MovePicker mp = MovePicker(pos, MOVE_NONE, depth, H);
 
     // If we are at the last ply we don't need to do and undo
     // the moves, just to count them.
     if (depth <= OnePly) // Replace with '<' to test also qsearch
     {
-        while ((move = mp.get_next_move()) != MOVE_NONE) sum++;
+        while (mp.get_next_move()) sum++;
         return sum;
     }
 
@@ -348,10 +351,10 @@ int perft(Position& pos, Depth depth)
     CheckInfo ci(pos);
     while ((move = mp.get_next_move()) != MOVE_NONE)
     {
-      StateInfo st;
-      pos.do_move(move, st, ci, pos.move_is_check(move, ci));
-      sum += perft(pos, depth - OnePly);
-      pos.undo_move(move);
+        StateInfo st;
+        pos.do_move(move, st, ci, pos.move_is_check(move, ci));
+        sum += perft(pos, depth - OnePly);
+        pos.undo_move(move);
     }
     return sum;
 }
@@ -1260,7 +1263,7 @@ namespace {
     const TTEntry* tte;
     Move ttMove, move;
     Depth ext, newDepth;
-    Value approximateEval, nullValue, value, futilityValue;
+    Value approximateEval, nullValue, value, futilityValue, futilityValueScaled;
     bool isCheck, useFutilityPruning, singleReply, moveIsCheck, captureOrPromotion, dangerous;
     bool mateThreat = false;
     int moveCount = 0;
@@ -1314,7 +1317,13 @@ namespace {
         ss[ply].currentMove = MOVE_NULL;
 
         pos.do_null_move(st);
-        int R = (depth >= 5 * OnePly ? 4 : 3); // Null move dynamic reduction
+
+        // Null move dynamic reduction based on depth
+        int R = (depth >= 5 * OnePly ? 4 : 3);
+
+        // Null move dynamic reduction based on value
+        if (approximateEval - beta > PawnValueMidgame)
+            R++;
 
         nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID);
 
@@ -1354,8 +1363,9 @@ namespace {
              && ttMove == MOVE_NONE
              && !pos.has_pawn_on_7th(pos.side_to_move()))
     {
-        Value v = qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID);
-        if (v < beta - RazorMargins[int(depth) - 2])
+        Value rbeta = beta - RazorMargins[int(depth) - 2];
+        Value v = qsearch(pos, ss, rbeta-1, rbeta, Depth(0), ply, threadID);
+        if (v < rbeta)
           return v;
     }
 
@@ -1413,12 +1423,15 @@ namespace {
           {
               if (futilityValue == VALUE_NONE)
                   futilityValue =  evaluate(pos, ei, threadID)
-                                 + FutilityMargins[int(depth) - 2];
+                                 + FutilityMargins[int(depth) - 2]
+                                 + 4*IncrementalFutilityMargin;
+
+              futilityValueScaled = futilityValue - moveCount * IncrementalFutilityMargin;
 
-              if (futilityValue < beta)
+              if (futilityValueScaled < beta)
               {
-                  if (futilityValue > bestValue)
-                      bestValue = futilityValue;
+                  if (futilityValueScaled > bestValue)
+                      bestValue = futilityValueScaled;
                   continue;
               }
           }