]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Use past SE information also for success cases
[stockfish] / src / search.cpp
index 35565d87841b083bb8527aac4c01520e98942bc3..58feb77d7038fc49dcb24821dbf9b762fa84925c 100644 (file)
@@ -38,6 +38,7 @@
 #include "lock.h"
 #include "san.h"
 #include "search.h"
+#include "timeman.h"
 #include "thread.h"
 #include "tt.h"
 #include "ucioption.h"
@@ -198,7 +199,7 @@ namespace {
   Depth PassedPawnExtension[2], PawnEndgameExtension[2], MateThreatExtension[2];
 
   // Minimum depth for use of singular extension
-  const Depth SingularExtensionDepth[2] = { 8 * OnePly /* non-PV */, 6 * OnePly /* PV */};
+  const Depth SingularExtensionDepth[2] = { 7 * OnePly /* non-PV */, 6 * OnePly /* PV */};
 
   // If the TT move is at least SingularExtensionMargin better then the
   // remaining ones we will extend it.
@@ -250,8 +251,8 @@ namespace {
   int MultiPV;
 
   // Time managment variables
-  int SearchStartTime, MaxNodes, MaxDepth, MaxSearchTime;
-  int AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime;
+  int SearchStartTime, MaxNodes, MaxDepth, OptimumSearchTime;
+  int MaximumSearchTime, ExtraSearchTime, ExactMaxTime;
   bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit;
   bool FirstRootMove, AbortSearch, Quit, AspirationFailLow;
 
@@ -360,20 +361,6 @@ void init_search() {
 }
 
 
-// SearchStack::init() initializes a search stack entry.
-// Called at the beginning of search() when starting to examine a new node.
-void SearchStack::init() {
-
-  currentMove = bestMove = MOVE_NONE;
-}
-
-// SearchStack::initKillers() initializes killers for a search stack entry
-void SearchStack::initKillers() {
-
-  killers[0] = killers[1] = mateKiller = MOVE_NONE;
-}
-
-
 /// perft() is our utility to verify move generation is bug free. All the legal
 /// moves up to given depth are generated and counted and the sum returned.
 
@@ -414,7 +401,7 @@ bool think(const Position& pos, bool infinite, bool ponder, int time[], int incr
 
   // Initialize global search variables
   StopOnPonderhit = AbortSearch = Quit = AspirationFailLow = false;
-  MaxSearchTime = AbsoluteMaxSearchTime = ExtraSearchTime = 0;
+  OptimumSearchTime = MaximumSearchTime = ExtraSearchTime = 0;
   NodesSincePoll = 0;
   TM.resetNodeCounters();
   SearchStartTime = get_system_time();
@@ -487,37 +474,13 @@ bool think(const Position& pos, bool infinite, bool ponder, int time[], int incr
   int myIncrement = increment[pos.side_to_move()];
   if (UseTimeManagement)
   {
-      if (!movesToGo) // Sudden death time control
-      {
-          if (myIncrement)
-          {
-              MaxSearchTime = myTime / 30 + myIncrement;
-              AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
-          }
-          else // Blitz game without increment
-          {
-              MaxSearchTime = myTime / 30;
-              AbsoluteMaxSearchTime = myTime / 8;
-          }
-      }
-      else // (x moves) / (y minutes)
-      {
-          if (movesToGo == 1)
-          {
-              MaxSearchTime = myTime / 2;
-              AbsoluteMaxSearchTime = (myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4);
-          }
-          else
-          {
-              MaxSearchTime = myTime / Min(movesToGo, 20);
-              AbsoluteMaxSearchTime = Min((4 * myTime) / movesToGo, myTime / 3);
-          }
-      }
+      get_search_times(myTime, myIncrement, movesToGo, pos.startpos_ply_counter(),
+                       &OptimumSearchTime, &MaximumSearchTime);
 
       if (get_option_value_bool("Ponder"))
       {
-          MaxSearchTime += MaxSearchTime / 4;
-          MaxSearchTime = Min(MaxSearchTime, AbsoluteMaxSearchTime);
+          OptimumSearchTime += OptimumSearchTime / 4;
+          OptimumSearchTime = Min(OptimumSearchTime, MaximumSearchTime);
       }
   }
 
@@ -663,20 +626,20 @@ namespace {
             if (   Iteration >= 8
                 && EasyMove == pv[0]
                 && (  (   rml.get_move_cumulative_nodes(0) > (nodes * 85) / 100
-                       && current_search_time() > MaxSearchTime / 16)
+                       && current_search_time() > OptimumSearchTime / 16)
                     ||(   rml.get_move_cumulative_nodes(0) > (nodes * 98) / 100
-                       && current_search_time() > MaxSearchTime / 32)))
+                       && current_search_time() > OptimumSearchTime / 32)))
                 stopSearch = true;
 
             // Add some extra time if the best move has changed during the last two iterations
             if (Iteration > 5 && Iteration <= 50)
-                ExtraSearchTime = BestMoveChangesByIteration[Iteration]   * (MaxSearchTime / 2)
-                                + BestMoveChangesByIteration[Iteration-1] * (MaxSearchTime / 3);
+                ExtraSearchTime = BestMoveChangesByIteration[Iteration]   * (OptimumSearchTime / 2)
+                                + BestMoveChangesByIteration[Iteration-1] * (OptimumSearchTime / 3);
 
             // Stop search if most of MaxSearchTime is consumed at the end of the
             // iteration. We probably don't have enough time to search the first
             // move at the next iteration anyway.
-            if (current_search_time() > ((MaxSearchTime + ExtraSearchTime) * 80) / 128)
+            if (current_search_time() > ((OptimumSearchTime + ExtraSearchTime) * 80) / 128)
                 stopSearch = true;
 
             if (stopSearch)
@@ -763,7 +726,7 @@ namespace {
     isCheck = pos.is_check();
 
     // Step 1. Initialize node (polling is omitted at root)
-    ss->init();
+    ss->currentMove = ss->bestMove = MOVE_NONE;
 
     // Step 2. Check for aborted search (omitted at root)
     // Step 3. Mate distance pruning (omitted at root)
@@ -1016,9 +979,9 @@ namespace {
     Move movesSearched[256];
     EvalInfo ei;
     StateInfo st;
-    const TTEntry* tte;
+    const TTEntry *tte, *ttx;
     Key posKey;
-    Move ttMove, move, excludedMove;
+    Move ttMove, move, excludedMove, threatMove;
     Depth ext, newDepth;
     Value bestValue, value, oldAlpha;
     Value refinedValue, nullValue, futilityValueScaled; // Non-PV specific
@@ -1026,14 +989,13 @@ namespace {
     bool mateThreat = false;
     int moveCount = 0;
     int threadID = pos.thread();
-    Move threatMove = MOVE_NONE;
     refinedValue = bestValue = value = -VALUE_INFINITE;
     oldAlpha = alpha;
 
     // Step 1. Initialize node and poll. Polling can abort search
     TM.incrementNodeCounter(threadID);
-    ss->init();
-    (ss+2)->initKillers();
+    ss->currentMove = ss->bestMove = threatMove = MOVE_NONE;
+    (ss+2)->killers[0] = (ss+2)->killers[1] = (ss+2)->mateKiller = MOVE_NONE;
 
     if (threadID == 0 && ++NodesSincePoll > NodesBetweenPolls)
     {
@@ -1077,7 +1039,7 @@ namespace {
         // Refresh tte entry to avoid aging
         TT.store(posKey, tte->value(), tte->type(), tte->depth(), ttMove, tte->static_value(), tte->king_danger());
 
-        ss->currentMove = ttMove; // Can be MOVE_NONE
+        ss->bestMove = ttMove; // Can be MOVE_NONE
         return value_from_tt(tte->value(), ply);
     }
 
@@ -1191,7 +1153,7 @@ namespace {
             if (nullValue == value_mated_in(ply + 2))
                 mateThreat = true;
 
-            threatMove = (ss+1)->currentMove;
+            threatMove = (ss+1)->bestMove;
             if (   depth < ThreatDepth
                 && (ss-1)->reduction
                 && connected_moves(pos, (ss-1)->currentMove, threatMove))
@@ -1253,9 +1215,22 @@ namespace {
           && move == tte->move()
           && ext < OnePly)
       {
+          // Avoid to do an expensive singular extension search on nodes where
+          // such search have already been done in the past, so assume the last
+          // singular extension search result is still valid.
+          if (  !PvNode
+              && depth < SingularExtensionDepth[PvNode] + 5 * OnePly
+              && ((ttx = TT.retrieve(pos.get_exclusion_key())) != NULL))
+          {
+              if (is_upper_bound(ttx->type()))
+                  ext = OnePly;
+
+              singularExtensionNode = false;
+          }
+
           Value ttValue = value_from_tt(tte->value(), ply);
 
-          if (abs(ttValue) < VALUE_KNOWN_WIN)
+          if (singularExtensionNode && abs(ttValue) < VALUE_KNOWN_WIN)
           {
               Value b = ttValue - SingularExtensionMargin;
               ss->excludedMove = move;
@@ -1464,7 +1439,7 @@ namespace {
 
     if (!PvNode && tte && ok_to_use_TT(tte, depth, beta, ply))
     {
-        ss->currentMove = ttMove; // Can be MOVE_NONE
+        ss->bestMove = ttMove; // Can be MOVE_NONE
         return value_from_tt(tte->value(), ply);
     }
 
@@ -2169,9 +2144,9 @@ namespace {
 
     bool stillAtFirstMove =    FirstRootMove
                            && !AspirationFailLow
-                           &&  t > MaxSearchTime + ExtraSearchTime;
+                           &&  t > OptimumSearchTime + ExtraSearchTime;
 
-    bool noMoreTime =   t > AbsoluteMaxSearchTime
+    bool noMoreTime =   t > MaximumSearchTime
                      || stillAtFirstMove;
 
     if (   (Iteration >= 3 && UseTimeManagement && noMoreTime)
@@ -2192,9 +2167,9 @@ namespace {
 
     bool stillAtFirstMove =    FirstRootMove
                            && !AspirationFailLow
-                           &&  t > MaxSearchTime + ExtraSearchTime;
+                           &&  t > OptimumSearchTime + ExtraSearchTime;
 
-    bool noMoreTime =   t > AbsoluteMaxSearchTime
+    bool noMoreTime =   t > MaximumSearchTime
                      || stillAtFirstMove;
 
     if (Iteration >= 3 && UseTimeManagement && (noMoreTime || StopOnPonderhit))
@@ -2214,7 +2189,7 @@ namespace {
         ss->reduction = Depth(0);
 
         if (i < 3)
-            ss->initKillers();
+            ss->killers[0] = ss->killers[1] = ss->mateKiller = MOVE_NONE;
     }
   }
 
@@ -2485,8 +2460,8 @@ namespace {
 #endif
 
     // Initialize global locks
-    lock_init(&MPLock, NULL);
-    lock_init(&WaitLock, NULL);
+    lock_init(&MPLock);
+    lock_init(&WaitLock);
 
 #if !defined(_MSC_VER)
     pthread_cond_init(&WaitCond, NULL);
@@ -2498,7 +2473,7 @@ namespace {
     // Initialize splitPoints[] locks
     for (i = 0; i < MAX_THREADS; i++)
         for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
-            lock_init(&(threads[i].splitPoints[j].lock), NULL);
+            lock_init(&(threads[i].splitPoints[j].lock));
 
     // Will be set just before program exits to properly end the threads
     AllThreadsShouldExit = false;
@@ -2792,7 +2767,7 @@ namespace {
 
     // Initialize search stack
     init_ss_array(ss, PLY_MAX_PLUS_2);
-    ss[0].init();
+    ss[0].currentMove = ss[0].bestMove = MOVE_NONE;
     ss[0].eval = VALUE_NONE;
 
     // Generate all legal moves