]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Introduce Null Threat extension
[stockfish] / src / search.cpp
index 292faf0412a35e01f18320b275fed883c5efe56b..c05a714578be3ce0da1b7d4fb0d3fca841b6d96d 100644 (file)
@@ -188,7 +188,7 @@ void Search::think() {
   {
       RootMoves.push_back(MOVE_NONE);
       sync_cout << "info depth 0 score "
-                << score_to_uci(RootPos.in_check() ? -VALUE_MATE : VALUE_DRAW)
+                << score_to_uci(RootPos.checkers() ? -VALUE_MATE : VALUE_DRAW)
                 << sync_endl;
 
       goto finalize;
@@ -485,13 +485,14 @@ namespace {
     Value bestValue, value, ttValue;
     Value eval, nullValue, futilityValue;
     bool inCheck, givesCheck, pvMove, singularExtensionNode;
-    bool captureOrPromotion, dangerous, doFullDepthSearch;
+    bool captureOrPromotion, dangerous, doFullDepthSearch, threatExtension;
     int moveCount, playedMoveCount;
 
     // Step 1. Initialize node
     Thread* thisThread = pos.this_thread();
     moveCount = playedMoveCount = 0;
-    inCheck = pos.in_check();
+    threatExtension = false;
+    inCheck = pos.checkers();
 
     if (SpNode)
     {
@@ -675,16 +676,15 @@ namespace {
             // The null move failed low, which means that we may be faced with
             // some kind of threat. If the previous move was reduced, check if
             // the move that refuted the null move was somehow connected to the
-            // move which was reduced. If a connection is found, return a fail
-            // low score (which will cause the reduced move to fail high in the
-            // parent node, which will trigger a re-search with full depth).
+            // move which was reduced. If a connection is found extend moves that
+            // defend against threat.
             threatMove = (ss+1)->currentMove;
 
             if (   depth < 5 * ONE_PLY
                 && (ss-1)->reduction
                 && threatMove != MOVE_NONE
                 && yields_to_threat(pos, (ss-1)->currentMove, threatMove))
-                return beta - 1;
+                threatExtension = true;
         }
     }
 
@@ -802,6 +802,9 @@ split_point_start: // At split points actual search starts from here
       if (PvNode && dangerous)
           ext = ONE_PLY;
 
+      else if (threatExtension && prevents_threat(pos, move, threatMove))
+          ext = ONE_PLY;
+
       else if (givesCheck && pos.see_sign(move) >= 0)
           ext = ONE_PLY / 2;
 
@@ -1081,7 +1084,7 @@ split_point_start: // At split points actual search starts from here
     const bool PvNode = (NT == PV);
 
     assert(NT == PV || NT == NonPV);
-    assert(InCheck == pos.in_check());
+    assert(InCheck == !!pos.checkers());
     assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
     assert(PvNode || (alpha == beta - 1));
     assert(depth <= DEPTH_ZERO);
@@ -1540,7 +1543,8 @@ void RootMove::extract_pv_from_tt(Position& pos) {
   do {
       pv.push_back(m);
 
-      assert(pos.move_is_legal(pv[ply]));
+      assert(MoveList<LEGAL>(pos).contains(pv[ply]));
+
       pos.do_move(pv[ply++], *st++);
       tte = TT.probe(pos.key());
 
@@ -1572,7 +1576,8 @@ void RootMove::insert_pv_in_tt(Position& pos) {
       if (!tte || tte->move() != pv[ply]) // Don't overwrite correct entries
           TT.store(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[ply]);
 
-      assert(pos.move_is_legal(pv[ply]));
+      assert(MoveList<LEGAL>(pos).contains(pv[ply]));
+
       pos.do_move(pv[ply++], *st++);
 
   } while (pv[ply] != MOVE_NONE);