]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Search code documentation, take III
[stockfish] / src / search.cpp
index 7f64cd9410ae3436ee55eba00e90216c92011e66..5426ce489ab851ade016e01d648a98f100de67f9 100644 (file)
@@ -1331,16 +1331,19 @@ namespace {
           return v; //FIXME: Logically should be: return (v + 0x200 + 16 * depth);
     }
 
-    // Static null move pruning. We're betting that the opponent doesn't have
-    // a move that will reduce the score by more than FutilityMargins[int(depth)]
-    // if we do a null move.
+    // Step 7. Static null move pruning
+    // We're betting that the opponent doesn't have a move that will reduce
+    // the score by more than fuility_margin(depth) if we do a null move.
     if (  !isCheck
         && allowNullmove
         && depth < RazorDepth
         && staticValue - futility_margin(depth, 0) >= beta)
         return staticValue - futility_margin(depth, 0);
 
-    // Null move search
+    // Step 8. Null move search with verification search
+    // When we jump directly to qsearch() we do a null move only if static value is
+    // at least beta. Otherwise we do a null move if static value is not more than
+    // NullMoveMargin under beta.
     if (    allowNullmove
         &&  depth > OnePly
         && !isCheck
@@ -1390,21 +1393,22 @@ namespace {
         }
     }
 
-    // Go with internal iterative deepening if we don't have a TT move
+    // Step 9. Internal iterative deepening
     if (UseIIDAtNonPVNodes && ttMove == MOVE_NONE && depth >= 8*OnePly &&
         !isCheck && ss[ply].eval >= beta - IIDMargin)
     {
-        search(pos, ss, beta, Min(depth/2, depth-2*OnePly), ply, false, threadID);
+        search(pos, ss, beta, depth/2, ply, false, threadID);
         ttMove = ss[ply].pv[ply];
         tte = TT.retrieve(posKey);
     }
 
-    // Initialize a MovePicker object for the current position, and prepare
-    // to search all moves.
+    // Step 10. Loop through moves
+    // Loop through all legal moves until no moves remain or a beta cutoff occurs
+
+    // Initialize a MovePicker object for the current position
     MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]);
     CheckInfo ci(pos);
 
-    // Loop through all legal moves until no moves remain or a beta cutoff occurs
     while (   bestValue < beta
            && (move = mp.get_next_move()) != MOVE_NONE
            && !TM.thread_should_stop(threadID))
@@ -1418,7 +1422,7 @@ namespace {
       singleEvasion = (isCheck && mp.number_of_evasions() == 1);
       captureOrPromotion = pos.move_is_capture_or_promotion(move);
 
-      // Decide the new search depth
+      // Step 11. Decide the new search depth
       ext = extension(pos, move, false, captureOrPromotion, moveIsCheck, singleEvasion, mateThreat, &dangerous);
 
       // Singular extension search. We extend the TT move if its value is much better than
@@ -1445,10 +1449,10 @@ namespace {
 
       newDepth = depth - OnePly + ext;
 
-      // Update current move
+      // Update current move (this must be done after singular extension search)
       movesSearched[moveCount++] = ss[ply].currentMove = move;
 
-      // Futility pruning
+      // Step 12. Futility pruning
       if (   !isCheck
           && !dangerous
           && !captureOrPromotion
@@ -1474,10 +1478,10 @@ namespace {
           }
       }
 
-      // Make and search the move
+      // Step 13. Make the move
       pos.do_move(move, st, ci, moveIsCheck);
 
-      // Try to reduce non-pv search depth by one ply if move seems not problematic,
+      // Step 14. Reduced search
       // if the move fails high will be re-searched at full depth.
       bool doFullDepthSearch = true;
 
@@ -1495,16 +1499,19 @@ namespace {
           }
       }
 
-      if (doFullDepthSearch) // Go with full depth non-pv search
+      // Step 15. Full depth search
+      if (doFullDepthSearch)
       {
           ss[ply].reduction = Depth(0);
           value = -search(pos, ss, -(beta-1), newDepth, ply+1, true, threadID);
       }
+
+      // Step 16. Undo move
       pos.undo_move(move);
 
       assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
 
-      // New best move?
+      // Step 17. Check for new best move
       if (value > bestValue)
       {
           bestValue = value;
@@ -1515,7 +1522,7 @@ namespace {
               ss[ply].mateKiller = move;
       }
 
-      // Split?
+      // Step 18. Check for split
       if (   TM.active_threads() > 1
           && bestValue < beta
           && depth >= MinimumSplitDepth
@@ -1528,11 +1535,14 @@ namespace {
           break;
     }
 
-    // All legal moves have been searched. A special case: If there were
+    // Step 19. Check for mate and stalemate
+    // All legal moves have been searched and if there were
     // no legal moves, it must be mate or stalemate.
+    // If one move was excluded return fail low.
     if (!moveCount)
         return excludedMove ? beta - 1 : (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW);
 
+    // Step 20. Update tables
     // If the search is not aborted, update the transposition table,
     // history counters, and killer moves.
     if (AbortSearch || TM.thread_should_stop(threadID))