]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Fix an assert in SMP case
[stockfish] / src / search.cpp
index b7a242f98470422cfeacd7041cefdd917d3fe7fc..39e4be3d8ae0bb1f8958b8647704a4deb0875858 100644 (file)
@@ -82,6 +82,7 @@ namespace {
   double BestMoveChanges;
   Value DrawValue[COLOR_NB];
   HistoryStats History;
+  GainsStats Gains;
   CountermovesStats Countermoves;
 
   template <NodeType NT>
@@ -293,6 +294,7 @@ namespace {
     Value bestValue, alpha, beta, delta;
 
     std::memset(ss-2, 0, 5 * sizeof(Stack));
+    (ss-1)->currentMove = MOVE_NULL; // Hack to skip update gains
 
     depth = 0;
     BestMoveChanges = 0;
@@ -301,6 +303,7 @@ namespace {
 
     TT.new_search();
     History.clear();
+    Gains.clear();
     Countermoves.clear();
 
     PVSize = Options["MultiPV"];
@@ -325,7 +328,7 @@ namespace {
             RootMoves[i].prevScore = RootMoves[i].score;
 
         // MultiPV loop. We perform a full root search for each PV line
-        for (PVIdx = 0; PVIdx < PVSize; ++PVIdx)
+        for (PVIdx = 0; PVIdx < PVSize && !Signals.stop; ++PVIdx)
         {
             // Reset aspiration window starting size
             if (depth >= 5)
@@ -354,11 +357,11 @@ namespace {
                 for (size_t i = 0; i <= PVIdx; ++i)
                     RootMoves[i].insert_pv_in_tt(pos);
 
-                // If search has been stopped return immediately. Sorting and
+                // If search has been stopped break immediately. Sorting and
                 // writing PV back to TT is safe becuase RootMoves is still
                 // valid, although refers to previous iteration.
                 if (Signals.stop)
-                    return;
+                    break;
 
                 // When failing high/low give some update (without cluttering
                 // the UI) before to research.
@@ -415,7 +418,7 @@ namespace {
             Signals.stop = true;
 
         // Do we have time for the next iteration? Can we stop searching now?
-        if (Limits.use_time_management() && !Signals.stopOnPonderhit)
+        if (Limits.use_time_management() && !Signals.stop && !Signals.stopOnPonderhit)
         {
             bool stop = false; // Local variable, not the volatile Signals.stop
 
@@ -481,18 +484,16 @@ namespace {
     assert(PvNode || (alpha == beta - 1));
     assert(depth > DEPTH_ZERO);
 
-    Move quietsSearched[64];
     StateInfo st;
     const TTEntry *tte;
     SplitPoint* splitPoint;
     Key posKey;
     Move ttMove, move, excludedMove, bestMove, threatMove;
-    Depth ext, newDepth;
-    Value bestValue, value, ttValue;
-    Value eval, nullValue;
+    Depth ext, newDepth, predictedDepth;
+    Value bestValue, value, ttValue, eval, nullValue, futilityValue;
     bool inCheck, givesCheck, pvMove, singularExtensionNode, improving;
     bool captureOrPromotion, dangerous, doFullDepthSearch;
-    int moveCount, quietCount;
+    int moveCount;
 
     // Step 1. Initialize node
     Thread* thisThread = pos.this_thread();
@@ -513,7 +514,7 @@ namespace {
         goto moves_loop;
     }
 
-    moveCount = quietCount = 0;
+    moveCount = 0;
     bestValue = -VALUE_INFINITE;
     ss->currentMove = threatMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
     ss->ply = (ss-1)->ply + 1;
@@ -601,6 +602,16 @@ namespace {
         TT.store(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE, ss->staticEval);
     }
 
+    if (   !pos.captured_piece_type()
+        &&  ss->staticEval != VALUE_NONE
+        && (ss-1)->staticEval != VALUE_NONE
+        && (move = (ss-1)->currentMove) != MOVE_NULL
+        &&  type_of(move) == NORMAL)
+    {
+        Square to = to_sq(move);
+        Gains.update(pos.piece_on(to), to, -(ss-1)->staticEval - ss->staticEval);
+    }
+
     // Step 6. Razoring (skipped when in check)
     if (   !PvNode
         &&  depth < 4 * ONE_PLY
@@ -847,12 +858,13 @@ moves_loop: // When in check and at SpNode search starts from here
               continue;
           }
 
-          Depth predictedDepth = newDepth - reduction<PvNode>(improving, depth, moveCount);
+          predictedDepth = newDepth - reduction<PvNode>(improving, depth, moveCount);
 
           // Futility pruning: parent node
           if (predictedDepth < 7 * ONE_PLY)
           {
-              Value futilityValue = ss->staticEval + futility_margin(predictedDepth) + Value(128);
+              futilityValue = ss->staticEval + futility_margin(predictedDepth)
+                            + Value(128) + Gains[pos.moved_piece(move)][to_sq(move)];
 
               if (futilityValue <= alpha)
               {
@@ -869,8 +881,7 @@ moves_loop: // When in check and at SpNode search starts from here
           }
 
           // Prune moves with negative SEE at low depths
-          if (   predictedDepth < 4 * ONE_PLY
-              && pos.see_sign(move) < 0)
+          if (predictedDepth < 4 * ONE_PLY && pos.see_sign(move) < 0)
           {
               if (SpNode)
                   splitPoint->mutex.lock();
@@ -883,14 +894,12 @@ moves_loop: // When in check and at SpNode search starts from here
       // Check for legality only before to do the move
       if (!RootNode && !SpNode && !pos.legal(move, ci.pinned))
       {
-          --moveCount;
+          moveCount--;
           continue;
       }
 
       pvMove = PvNode && moveCount == 1;
       ss->currentMove = move;
-      if (!SpNode && !captureOrPromotion && quietCount < 64)
-          quietsSearched[quietCount++] = move;
 
       // Step 14. Make the move
       pos.do_move(move, st, ci, givesCheck);
@@ -1065,11 +1074,9 @@ moves_loop: // When in check and at SpNode search starts from here
         // played non-capture moves.
         Value bonus = Value(int(depth) * int(depth));
         History.update(pos.moved_piece(bestMove), to_sq(bestMove), bonus);
-        for (int i = 0; i < quietCount - 1; ++i)
-        {
-            Move m = quietsSearched[i];
-            History.update(pos.moved_piece(m), to_sq(m), -bonus);
-        }
+
+        for (const ExtMove* em = mp.quiet_moves(); em && em->move != bestMove; ++em)
+            History.update(pos.moved_piece(em->move), to_sq(em->move), -bonus);
 
         if (is_ok((ss-1)->currentMove))
             Countermoves.update(pos.piece_on(prevMoveSq), prevMoveSq, bestMove);
@@ -1331,7 +1338,7 @@ moves_loop: // When in check and at SpNode search starts from here
     // We exclude the trivial case where a sliding piece does in two moves what
     // it could do in one move: eg. Ra1a2, Ra2a3.
     if (    m2to == m1from
-        || (m1to == m2from && !squares_aligned(m1from, m2from, m2to)))
+        || (m1to == m2from && !aligned(m1from, m2from, m2to)))
         return true;
 
     // Second one moves through the square vacated by first one