]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Inline common path of pos.gives_check
[stockfish] / src / search.cpp
index d59fc521eedcba2815ae3cdeaf92f4bdb6e80730..95f1332ed1ddb6e1ca743e006cdf1039bcd034d8 100644 (file)
@@ -51,6 +51,12 @@ using std::string;
 using Eval::evaluate;
 using namespace Search;
 
 using Eval::evaluate;
 using namespace Search;
 
+// Fast wrapper for common case of pos.gives_check()
+#define FAST_GIVES_CHECK(pos, m, ci) \
+    ((type_of(m) == NORMAL && ci.dcCandidates == 0) \
+       ? (ci.checkSq[type_of(pos.piece_on(from_sq(m)))] & to_sq(m)) \
+          : pos.gives_check(m, ci))
+
 namespace {
 
   // Set to true to force running with one thread. Used for debugging
 namespace {
 
   // Set to true to force running with one thread. Used for debugging
@@ -595,16 +601,14 @@ namespace {
     // Step 6. Razoring (skipped when in check)
     if (   !PvNode
         &&  depth < 4 * ONE_PLY
     // Step 6. Razoring (skipped when in check)
     if (   !PvNode
         &&  depth < 4 * ONE_PLY
-        &&  eval + razor_margin(depth) < beta
+        &&  eval + razor_margin(depth) <= alpha
         &&  ttMove == MOVE_NONE
         &&  abs(beta) < VALUE_MATE_IN_MAX_PLY
         && !pos.pawn_on_7th(pos.side_to_move()))
     {
         &&  ttMove == MOVE_NONE
         &&  abs(beta) < VALUE_MATE_IN_MAX_PLY
         && !pos.pawn_on_7th(pos.side_to_move()))
     {
-        Value rbeta = beta - razor_margin(depth);
-        Value v = qsearch<NonPV, false>(pos, ss, rbeta-1, rbeta, DEPTH_ZERO);
-        if (v < rbeta)
-            // Logically we should return (v + razor_margin(depth)), but
-            // surprisingly this performed slightly weaker in tests.
+        Value ralpha = alpha - razor_margin(depth);
+        Value v = qsearch<NonPV, false>(pos, ss, ralpha, ralpha+1, DEPTH_ZERO);
+        if (v <= ralpha)
             return v;
     }
 
             return v;
     }
 
@@ -628,37 +632,22 @@ namespace {
     {
         ss->currentMove = MOVE_NULL;
 
     {
         ss->currentMove = MOVE_NULL;
 
-        // Null move dynamic reduction based on depth
-        Depth R = 3 * ONE_PLY + depth / 4;
+        assert(eval - beta >= 0);
 
 
-        // Null move dynamic reduction based on value
-        if (eval - PawnValueMg > beta)
-            R += ONE_PLY;
+        // Null move dynamic reduction based on depth and value
+        Depth R =  3 * ONE_PLY
+                 + depth / 4
+                 + int(eval - beta) / PawnValueMg * ONE_PLY;
 
         pos.do_null_move(st);
         (ss+1)->skipNullMove = true;
 
         pos.do_null_move(st);
         (ss+1)->skipNullMove = true;
-        nullValue = depth-R < ONE_PLY ? -qsearch<NonPV, false>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
-                                      : - search<NonPV>(pos, ss+1, -beta, -alpha, depth-R, !cutNode);
+        nullValue = depth-R < ONE_PLY ? -qsearch<NonPV, false>(pos, ss+1, -beta, -beta+1, DEPTH_ZERO)
+                                      : - search<NonPV>(pos, ss+1, -beta, -beta+1, depth-R, !cutNode);
         (ss+1)->skipNullMove = false;
         pos.undo_null_move();
 
         (ss+1)->skipNullMove = false;
         pos.undo_null_move();
 
-        if (nullValue >= beta)
-        {
-            // Do not return unproven mate scores
-            if (nullValue >= VALUE_MATE_IN_MAX_PLY)
-                nullValue = beta;
-
-            if (depth < 12 * ONE_PLY)
-                return nullValue;
-
-            // Do verification search at high depths
-            ss->skipNullMove = true;
-            Value v = search<NonPV>(pos, ss, alpha, beta, depth-R, false);
-            ss->skipNullMove = false;
-
-            if (v >= beta)
-                return nullValue;
-        }
+        if (nullValue >= beta) // Do not return unproven mate scores
+            return nullValue >= VALUE_MATE_IN_MAX_PLY ? beta : nullValue;
     }
 
     // Step 9. ProbCut (skipped when in check)
     }
 
     // Step 9. ProbCut (skipped when in check)
@@ -771,7 +760,7 @@ moves_loop: // When in check and at SpNode search starts from here
 
       ext = DEPTH_ZERO;
       captureOrPromotion = pos.capture_or_promotion(move);
 
       ext = DEPTH_ZERO;
       captureOrPromotion = pos.capture_or_promotion(move);
-      givesCheck = pos.gives_check(move, ci);
+      givesCheck = FAST_GIVES_CHECK(pos, move, ci);
       dangerous =   givesCheck
                  || type_of(move) != NORMAL
                  || pos.advanced_pawn_push(move);
       dangerous =   givesCheck
                  || type_of(move) != NORMAL
                  || pos.advanced_pawn_push(move);
@@ -1151,7 +1140,7 @@ moves_loop: // When in check and at SpNode search starts from here
     {
       assert(is_ok(move));
 
     {
       assert(is_ok(move));
 
-      givesCheck = pos.gives_check(move, ci);
+      givesCheck = FAST_GIVES_CHECK(pos, move, ci);
 
       // Futility pruning
       if (   !PvNode
 
       // Futility pruning
       if (   !PvNode