]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Revert LMR reduction based on thinking time
[stockfish] / src / search.cpp
index ab37e480fc5d50bdb10f79b6e3f08b8e2d0d1e5a..882fee6f0ee8ec5940c54b2601f085581dd88918 100644 (file)
@@ -215,14 +215,12 @@ namespace {
 
   // Step 14. Reduced search
 
-  int ReductionLevel = 2; // 0 = most aggressive reductions, 7 = minimum reductions
-
   // Reduction lookup tables (initialized at startup) and their getter functions
-  int8_t    PVReductionMatrix[8][64][64]; // [depth][moveNumber]
-  int8_t NonPVReductionMatrix[8][64][64]; // [depth][moveNumber]
+  int8_t    PVReductionMatrix[64][64]; // [depth][moveNumber]
+  int8_t NonPVReductionMatrix[64][64]; // [depth][moveNumber]
 
-  inline Depth    pv_reduction(Depth d, int mn) { return (Depth)    PVReductionMatrix[ReductionLevel][Min(d / 2, 63)][Min(mn, 63)]; }
-  inline Depth nonpv_reduction(Depth d, int mn) { return (Depth) NonPVReductionMatrix[ReductionLevel][Min(d / 2, 63)][Min(mn, 63)]; }
+  inline Depth    pv_reduction(Depth d, int mn) { return (Depth)    PVReductionMatrix[Min(d / 2, 63)][Min(mn, 63)]; }
+  inline Depth nonpv_reduction(Depth d, int mn) { return (Depth) NonPVReductionMatrix[Min(d / 2, 63)][Min(mn, 63)]; }
 
   // Common adjustments
 
@@ -546,31 +544,20 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
   return !Quit;
 }
 
-// init_reduction_tables()
 
-void init_reduction_tables(int8_t pvTable[64][64], int8_t nonPvTable[64][64], int pvInhib, int nonPvInhib)
-{
-  double pvBase = 1.001 - log(3.0) * log(16.0) / pvInhib;
-  double nonPvBase = 1.001 - log(3.0) * log(4.0) / nonPvInhib;
+/// init_search() is called during startup. It initializes various lookup tables
+
+void init_search() {
 
-  // Init reduction lookup tables
+  // Init our reduction lookup tables
   for (int i = 1; i < 64; i++) // i == depth (OnePly = 1)
       for (int j = 1; j < 64; j++) // j == moveNumber
       {
-          double    pvRed = pvBase    + log(double(i)) * log(double(j)) / pvInhib;
-          double nonPVRed = nonPvBase + log(double(i)) * log(double(j)) / nonPvInhib;
-
-          pvTable[i][j]    = (int8_t) (   pvRed >= 1.0 ? floor(   pvRed * int(OnePly)) : 0);
-          nonPvTable[i][j] = (int8_t) (nonPVRed >= 1.0 ? floor(nonPVRed * int(OnePly)) : 0);
+          double    pvRed = 0.5 + log(double(i)) * log(double(j)) / 6.0;
+          double nonPVRed = 0.5 + log(double(i)) * log(double(j)) / 3.0;
+          PVReductionMatrix[i][j]    = (int8_t) (   pvRed >= 1.0 ? floor(   pvRed * int(OnePly)) : 0);
+          NonPVReductionMatrix[i][j] = (int8_t) (nonPVRed >= 1.0 ? floor(nonPVRed * int(OnePly)) : 0);
       }
-}
-
-// init_search() is called during startup. It initializes various lookup tables
-
-void init_search() {
-
-  for (int i = 0; i < 8; i++)
-      init_reduction_tables(PVReductionMatrix[i], NonPVReductionMatrix[i], 4.0 * pow(1.3, i), 2.0 * pow(1.3, i));
 
   // Init futility margins array
   for (int i = 0; i < 16; i++) // i == depth (OnePly = 2)
@@ -673,19 +660,6 @@ namespace {
             beta  = Min(ValueByIteration[Iteration - 1] + AspirationDelta,  VALUE_INFINITE);
         }
 
-        // Choose optimum reduction level
-        ReductionLevel = 2;
-
-        if (UseTimeManagement)
-        {
-            int level = int(floor(log(float(MaxSearchTime) / current_search_time()) / log(2.0) + 1.0));
-            ReductionLevel = Min(Max(level, 0), 7);
-        }
-        else
-        {
-            //FIXME
-        }
-
         // Search to the current depth, rml is updated and sorted, alpha and beta could change
         value = root_search(p, ss, rml, &alpha, &beta);
 
@@ -1127,14 +1101,13 @@ namespace {
         tte = TT.retrieve(pos.get_key());
     }
 
-    // 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
     mateThreat = pos.has_mate_threat(opposite_color(pos.side_to_move()));
     MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]);
     CheckInfo ci(pos);
 
+    // Step 10. Loop through moves
+    // Loop through all legal moves until no moves remain or a beta cutoff occurs
     while (   alpha < beta
            && (move = mp.get_next_move()) != MOVE_NONE
            && !TM.thread_should_stop(threadID))
@@ -1351,12 +1324,12 @@ namespace {
     }
 
     // Step 6. Razoring
-    if (   !value_is_mate(beta)
+    if (    refinedValue < beta - razor_margin(depth)
+        &&  ttMove == MOVE_NONE
+        &&  ss[ply - 1].currentMove != MOVE_NULL
+        &&  depth < RazorDepth
         && !isCheck
-        && depth < RazorDepth
-        && refinedValue < beta - razor_margin(depth)
-        && ss[ply - 1].currentMove != MOVE_NULL
-        && ttMove == MOVE_NONE
+        && !value_is_mate(beta)
         && !pos.has_pawn_on_7th(pos.side_to_move()))
     {
         Value rbeta = beta - razor_margin(depth);
@@ -1369,11 +1342,13 @@ namespace {
 
     // 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
-        && refinedValue - futility_margin(depth, 0) >= beta)
+    // the score by more than futility_margin(depth) if we do a null move.
+    if (    allowNullmove
+        &&  depth < RazorDepth
+        && !isCheck
+        && !value_is_mate(beta)
+        &&  ok_to_do_nullmove(pos)
+        &&  refinedValue >= beta + futility_margin(depth, 0))
         return refinedValue - futility_margin(depth, 0);
 
     // Step 8. Null move search with verification search
@@ -1389,8 +1364,6 @@ namespace {
     {
         ss[ply].currentMove = MOVE_NULL;
 
-        pos.do_null_move(st);
-
         // Null move dynamic reduction based on depth
         int R = 3 + (depth >= 5 * OnePly ? depth / 8 : 0);
 
@@ -1398,6 +1371,8 @@ namespace {
         if (refinedValue - beta > PawnValueMidgame)
             R++;
 
+        pos.do_null_move(st);
+
         nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID);
 
         pos.undo_null_move();
@@ -1444,13 +1419,12 @@ namespace {
         tte = TT.retrieve(posKey);
     }
 
-    // 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], beta);
     CheckInfo ci(pos);
 
+    // Step 10. Loop through moves
+    // 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))
@@ -1473,7 +1447,7 @@ namespace {
       if (   depth >= SingularExtensionDepthAtNonPVNodes
           && tte
           && move == tte->move()
-          && !excludedMove // Do not allow recursive single-reply search
+          && !excludedMove // Do not allow recursive singular extension search
           && ext < OnePly
           && is_lower_bound(tte->type())
           && tte->depth() >= depth - 3 * OnePly)
@@ -1523,8 +1497,8 @@ namespace {
       // Step 13. Make the move
       pos.do_move(move, st, ci, moveIsCheck);
 
-      // Step 14. Reduced search
-      // if the move fails high will be re-searched at full depth.
+      // Step 14. Reduced search, if the move fails high
+      // will be re-searched at full depth.
       bool doFullDepthSearch = true;
 
       if (    depth >= 3*OnePly
@@ -1578,11 +1552,11 @@ namespace {
     }
 
     // Step 19. Check for mate and stalemate
-    // All legal moves have been searched and if there were
+    // All legal moves have been searched and if there are
     // no legal moves, it must be mate or stalemate.
-    // If one move was excluded return fail low.
+    // If one move was excluded return fail low score.
     if (!moveCount)
-        return excludedMove ? beta - 1 : (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW);
+        return excludedMove ? beta - 1 : (isCheck ? value_mated_in(ply) : VALUE_DRAW);
 
     // Step 20. Update tables
     // If the search is not aborted, update the transposition table,
@@ -1702,8 +1676,7 @@ namespace {
     enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame;
     futilityBase = staticValue + FutilityMarginQS + ei.futilityMargin[pos.side_to_move()];
 
-    // Loop through the moves until no moves remain or a beta cutoff
-    // occurs.
+    // Loop through the moves until no moves remain or a beta cutoff occurs
     while (   alpha < beta
            && (move = mp.get_next_move()) != MOVE_NONE)
     {
@@ -1772,7 +1745,7 @@ namespace {
 
     // All legal moves have been searched. A special case: If we're in check
     // and no legal moves were found, it is checkmate.
-    if (!moveCount && pos.is_check()) // Mate!
+    if (!moveCount && isCheck) // Mate!
         return value_mated_in(ply);
 
     // Update transposition table