]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Retire direction.cpp
[stockfish] / src / search.cpp
index 83d052bbeb54c5bb656c053913ab2f8ceb782e65..8dc695d0e83faec353c58b129577f20733f52fde 100644 (file)
@@ -84,7 +84,7 @@ namespace {
     void read_uci_options();
     bool available_thread_exists(int master) const;
     bool thread_is_available(int slave, int master) const;
-    bool thread_should_stop(int threadID) const;
+    bool cutoff_at_splitpoint(int threadID) const;
     void wake_sleeping_thread(int threadID);
     void idle_loop(int threadID, SplitPoint* sp);
 
@@ -993,7 +993,8 @@ namespace {
         threatMove = sp->threatMove;
         mateThreat = sp->mateThreat;
         goto split_point_start;
-    } else {} // Hack to fix icc's "statement is unreachable" warning
+    }
+    else {} // Hack to fix icc's "statement is unreachable" warning
 
     // Step 1. Initialize node and poll. Polling can abort search
     ss->currentMove = ss->bestMove = threatMove = MOVE_NONE;
@@ -1006,8 +1007,10 @@ namespace {
     }
 
     // Step 2. Check for aborted search and immediate draw
-    if (   AbortSearch   || ThreadsMgr.thread_should_stop(threadID)
-        || pos.is_draw() || ply >= PLY_MAX - 1)
+    if (   AbortSearch
+        || ThreadsMgr.cutoff_at_splitpoint(threadID)
+        || pos.is_draw()
+        || ply >= PLY_MAX - 1)
         return VALUE_DRAW;
 
     // Step 3. Mate distance pruning
@@ -1145,6 +1148,7 @@ namespace {
             threatMove = (ss+1)->bestMove;
             if (   depth < ThreatDepth
                 && (ss-1)->reduction
+                && threatMove != MOVE_NONE
                 && connected_moves(pos, (ss-1)->currentMove, threatMove))
                 return beta - 1;
         }
@@ -1196,7 +1200,7 @@ split_point_start: // At split points actual search starts from here
     // Loop through all legal moves until no moves remain or a beta cutoff occurs
     while (   bestValue < beta
            && (move = mp.get_next_move()) != MOVE_NONE
-           && !ThreadsMgr.thread_should_stop(threadID))
+           && !ThreadsMgr.cutoff_at_splitpoint(threadID))
     {
       assert(move_is_ok(move));
 
@@ -1284,7 +1288,7 @@ split_point_start: // At split points actual search starts from here
               continue;
           }
 
-          // Prune neg. see moves at low depths
+          // Prune moves with negative SEE at low depths
           if (   predictedDepth < 2 * ONE_PLY
               && bestValue > value_mated_in(PLY_MAX)
               && pos.see_sign(move) < 0)
@@ -1301,7 +1305,7 @@ split_point_start: // At split points actual search starts from here
 
       // Step extra. pv search (only in PV nodes)
       // The first move in list is the expected PV
-      if (!SpNode && PvNode && moveCount == 1)
+      if (PvNode && moveCount == 1)
           value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, ply+1);
       else
       {
@@ -1313,9 +1317,11 @@ split_point_start: // At split points actual search starts from here
               && !captureOrPromotion
               && !dangerous
               && !move_is_castle(move)
-              && !(ss->killers[0] == move || ss->killers[1] == move))
+              &&  ss->killers[0] != move
+              &&  ss->killers[1] != move)
           {
               ss->reduction = reduction<PvNode>(depth, moveCount);
+
               if (ss->reduction)
               {
                   alpha = SpNode ? sp->alpha : alpha;
@@ -1367,7 +1373,7 @@ split_point_start: // At split points actual search starts from here
           alpha = sp->alpha;
       }
 
-      if (value > bestValue && !(SpNode && ThreadsMgr.thread_should_stop(threadID)))
+      if (value > bestValue && !(SpNode && ThreadsMgr.cutoff_at_splitpoint(threadID)))
       {
           bestValue = value;
 
@@ -1376,15 +1382,15 @@ split_point_start: // At split points actual search starts from here
 
           if (value > alpha)
           {
-              if (SpNode && (!PvNode || value >= beta))
-                  sp->stopRequest = true;
-
               if (PvNode && value < beta) // We want always alpha < beta
               {
                   alpha = value;
+
                   if (SpNode)
                       sp->alpha = value;
               }
+              else if (SpNode)
+                  sp->betaCutoff = true;
 
               if (value == value_mate_in(ply + 1))
                   ss->mateKiller = move;
@@ -1403,7 +1409,7 @@ split_point_start: // At split points actual search starts from here
           && bestValue < beta
           && ThreadsMgr.available_thread_exists(threadID)
           && !AbortSearch
-          && !ThreadsMgr.thread_should_stop(threadID)
+          && !ThreadsMgr.cutoff_at_splitpoint(threadID)
           && Iteration <= 99)
           ThreadsMgr.split<FakeSplit>(pos, ss, ply, &alpha, beta, &bestValue, depth,
                                       threatMove, mateThreat, moveCount, &mp, PvNode);
@@ -1419,7 +1425,7 @@ split_point_start: // At split points actual search starts from here
     // Step 20. Update tables
     // If the search is not aborted, update the transposition table,
     // history counters, and killer moves.
-    if (!SpNode && !AbortSearch && !ThreadsMgr.thread_should_stop(threadID))
+    if (!SpNode && !AbortSearch && !ThreadsMgr.cutoff_at_splitpoint(threadID))
     {
         move = bestValue <= oldAlpha ? MOVE_NONE : ss->bestMove;
         vt   = bestValue <= oldAlpha ? VALUE_TYPE_UPPER
@@ -1468,6 +1474,7 @@ split_point_start: // At split points actual search starts from here
     Value bestValue, value, evalMargin, futilityValue, futilityBase;
     bool isCheck, enoughMaterial, moveIsCheck, evasionPrunable;
     const TTEntry* tte;
+    Depth ttDepth;
     Value oldAlpha = alpha;
 
     ss->bestMove = ss->currentMove = MOVE_NONE;
@@ -1476,21 +1483,18 @@ split_point_start: // At split points actual search starts from here
     if (pos.is_draw() || ply >= PLY_MAX - 1)
         return VALUE_DRAW;
 
-    // Decide whether or not to include checks
+    // Decide whether or not to include checks, this fixes also the type of
+    // TT entry depth that we are going to use. Note that in qsearch we use
+    // only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
     isCheck = pos.is_check();
-
-    Depth d;
-    if (isCheck || depth >= -ONE_PLY)
-        d = DEPTH_ZERO;
-    else
-        d = DEPTH_ZERO - ONE_PLY;
+    ttDepth = (isCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS : DEPTH_QS_NO_CHECKS);
 
     // Transposition table lookup. At PV nodes, we don't use the TT for
     // pruning, but only for move ordering.
     tte = TT.retrieve(pos.get_key());
     ttMove = (tte ? tte->move() : MOVE_NONE);
 
-    if (!PvNode && tte && ok_to_use_TT(tte, d, beta, ply))
+    if (!PvNode && tte && ok_to_use_TT(tte, ttDepth, beta, ply))
     {
         ss->bestMove = ttMove; // Can be MOVE_NONE
         return value_from_tt(tte->value(), ply);
@@ -1536,9 +1540,9 @@ split_point_start: // At split points actual search starts from here
 
     // Initialize a MovePicker object for the current position, and prepare
     // to search the moves. Because the depth is <= 0 here, only captures,
-    // queen promotions and checks (only if depth == 0 or depth == -ONE_PLY
-    // and we are near beta) will be generated.
-    MovePicker mp = MovePicker(pos, ttMove, d, H);
+    // queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
+    // be generated.
+    MovePicker mp(pos, ttMove, depth, H);
     CheckInfo ci(pos);
 
     // Loop through the moves until no moves remain or a beta cutoff occurs
@@ -1628,7 +1632,7 @@ split_point_start: // At split points actual search starts from here
 
     // Update transposition table
     ValueType vt = (bestValue <= oldAlpha ? VALUE_TYPE_UPPER : bestValue >= beta ? VALUE_TYPE_LOWER : VALUE_TYPE_EXACT);
-    TT.store(pos.get_key(), value_to_tt(bestValue, ply), vt, d, ss->bestMove, ss->eval, evalMargin);
+    TT.store(pos.get_key(), value_to_tt(bestValue, ply), vt, ttDepth, ss->bestMove, ss->eval, evalMargin);
 
     assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
 
@@ -1704,11 +1708,8 @@ split_point_start: // At split points actual search starts from here
     Square f1, t1, f2, t2;
     Piece p;
 
-    assert(move_is_ok(m1));
-    assert(move_is_ok(m2));
-
-    if (m2 == MOVE_NONE)
-        return false;
+    assert(m1 && move_is_ok(m1));
+    assert(m2 && move_is_ok(m2));
 
     // Case 1: The moving piece is the same in both moves
     f2 = move_from(m2);
@@ -2467,17 +2468,17 @@ split_point_start: // At split points actual search starts from here
   }
 
 
-  // thread_should_stop() checks whether the thread should stop its search.
-  // This can happen if a beta cutoff has occurred in the thread's currently
-  // active split point, or in some ancestor of the current split point.
+  // cutoff_at_splitpoint() checks whether a beta cutoff has occurred in
+  // the thread's currently active split point, or in some ancestor of
+  // the current split point.
 
-  bool ThreadsManager::thread_should_stop(int threadID) const {
+  bool ThreadsManager::cutoff_at_splitpoint(int threadID) const {
 
     assert(threadID >= 0 && threadID < activeThreads);
 
     SplitPoint* sp = threads[threadID].splitPoint;
 
-    for ( ; sp && !sp->stopRequest; sp = sp->parent) {}
+    for ( ; sp && !sp->betaCutoff; sp = sp->parent) {}
     return sp != NULL;
   }
 
@@ -2576,7 +2577,7 @@ split_point_start: // At split points actual search starts from here
     // Initialize the split point object
     splitPoint.parent = masterThread.splitPoint;
     splitPoint.master = master;
-    splitPoint.stopRequest = false;
+    splitPoint.betaCutoff = false;
     splitPoint.ply = ply;
     splitPoint.depth = depth;
     splitPoint.threatMove = threatMove;
@@ -2710,7 +2711,7 @@ split_point_start: // At split points actual search starts from here
   {
       Move move;
       int score = 1000;
-      MovePicker mp = MovePicker(pos, MOVE_NONE, ONE_PLY, H);
+      MovePicker mp(pos, MOVE_NONE, ONE_PLY, H);
 
       while ((move = mp.get_next_move()) != MOVE_NONE)
           for (int i = 0; i < count; i++)