]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Remove history counters
[stockfish] / src / search.cpp
index d8e60a129317f90acda38e5f6f1ae6b5c6b090bf..c1f90e119a24d82379eac5521bb950ca2732f4de 100644 (file)
@@ -173,19 +173,15 @@ namespace {
 
   // If the TT move is at least SingleReplyMargin better then the
   // remaining ones we will extend it.
-  const Value SingleReplyMargin = Value(0x64);
+  const Value SingleReplyMargin = Value(0x20);
 
   // Margins for futility pruning in the quiescence search, and at frontier
   // and near frontier nodes.
   const Value FutilityMarginQS = Value(0x80);
 
   // Each move futility margin is decreased
-  const Value IncrementalFutilityMargin = Value(0x4);
+  const Value IncrementalFutilityMargin = Value(0x8);
 
-  // Remaining depth:                  1 ply         1.5 ply       2 ply         2.5 ply       3 ply         3.5 ply
-  const Value FutilityMargins[12] = { Value(0x100), Value(0x120), Value(0x200), Value(0x220), Value(0x250), Value(0x270),
-  //                                   4 ply         4.5 ply       5 ply         5.5 ply       6 ply         6.5 ply
-                                      Value(0x2A0), Value(0x2C0), Value(0x340), Value(0x360), Value(0x3A0), Value(0x3C0) };
   // Razoring
   const Depth RazorDepth = 4*OnePly;
 
@@ -292,7 +288,7 @@ namespace {
   bool move_is_killer(Move m, const SearchStack& ss);
   Depth extension(const Position& pos, Move m, bool pvNode, bool capture, bool check, bool singleReply, bool mateThreat, bool* dangerous);
   bool ok_to_do_nullmove(const Position& pos);
-  bool ok_to_prune(const Position& pos, Move m, Move threat, Depth d);
+  bool ok_to_prune(const Position& pos, Move m, Move threat);
   bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply);
   void update_history(const Position& pos, Move m, Depth depth, Move movesSearched[], int moveCount);
   void update_killers(Move m, SearchStack& ss);
@@ -406,13 +402,13 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
   Problem = false;
   ExactMaxTime = maxTime;
 
+  if (button_was_pressed("New Game"))
+      loseOnTime = false; // reset at the beginning of a new game
+
   // Read UCI option values
   TT.set_size(get_option_value_int("Hash"));
   if (button_was_pressed("Clear Hash"))
-  {
       TT.clear();
-      loseOnTime = false; // reset at the beginning of a new game
-  }
 
   bool PonderingEnabled = get_option_value_bool("Ponder");
   MultiPV = get_option_value_int("MultiPV");
@@ -681,6 +677,14 @@ namespace {
     // searchMoves are verified, copied, scored and sorted
     RootMoveList rml(p, searchMoves);
 
+    if (rml.move_count() == 0)
+    {
+        if (PonderSearch)
+            wait_for_stop_or_ponderhit();
+
+        return pos.is_check()? -VALUE_MATE : VALUE_DRAW;
+    }
+
     // Print RootMoveList c'tor startup scoring to the standard output,
     // so that we print information also for iteration 1.
     std::cout << "info depth " << 1 << "\ninfo depth " << 1
@@ -1359,7 +1363,7 @@ namespace {
 
     if (tte && ok_to_use_TT(tte, depth, beta, ply))
     {
-        ss[ply].currentMove = ttMove; // can be MOVE_NONE
+        ss[ply].currentMove = ttMove; // Can be MOVE_NONE
         return value_from_tt(tte->value(), ply);
     }
 
@@ -1445,18 +1449,13 @@ namespace {
     futilityValue = VALUE_NONE;
     useFutilityPruning = depth < SelectiveDepth && !isCheck;
 
+    // Calculate depth dependant futility pruning parameters
+    const int FutilityMoveCountMargin = 3 + (1 << (3 * int(depth) / 8));
+    const int FutilityValueMargin = 112 * bitScanReverse32(int(depth) * int(depth) / 2);
+
     // Avoid calling evaluate() if we already have the score in TT
     if (tte && (tte->type() & VALUE_TYPE_EVAL))
-        futilityValue = value_from_tt(tte->value(), ply) + FutilityMargins[int(depth) - 2];
-
-    // Move count pruning limit
-    const int MCLimit = 3 + (1 << (3*int(depth)/8));
-
-    /*
-    for (int d = 2; d < 16; d++)
-        std::cout << d << " -> " << 56*(0+2*bitScanReverse32(1 * int(d) * int(d) / 2)) << std::endl;
-        //std::cout << d << " -> " << 32*(1+3*bitScanReverse32(1 * int(d) * int(d))) << std::endl;
-    */
+        futilityValue = value_from_tt(tte->value(), ply) + FutilityValueMargin;
 
     // Loop through all legal moves until no moves remain or a beta cutoff occurs
     while (   bestValue < beta
@@ -1511,28 +1510,23 @@ namespace {
           && !captureOrPromotion
           &&  move != ttMove)
       {
-          // History pruning. See ok_to_prune() definition
-          if (   moveCount >= MCLimit
-              && ok_to_prune(pos, move, ss[ply].threatMove, depth)
+          // Move count based pruning
+          if (   moveCount >= FutilityMoveCountMargin
+              && ok_to_prune(pos, move, ss[ply].threatMove)
               && bestValue > value_mated_in(PLY_MAX))
               continue;
 
           // Value based pruning
-          if (approximateEval < beta)
-          {//dbg_before();
-              if (futilityValue == VALUE_NONE)
-                  futilityValue =  evaluate(pos, ei, threadID)
-                                 + 56*(0+2*bitScanReverse32(1 * int(depth) * int(depth) / 2));
+          if (futilityValue == VALUE_NONE)
+              futilityValue = evaluate(pos, ei, threadID) + FutilityValueMargin;
 
-              futilityValueScaled = futilityValue - moveCount * IncrementalFutilityMargin;
+          futilityValueScaled = futilityValue - moveCount * IncrementalFutilityMargin;
 
-              if (futilityValueScaled < beta)
-              {
-                  if (futilityValueScaled > bestValue)
-                      bestValue = futilityValueScaled;
-                  continue;
-              }
-           //dbg_after(); // 36% (inc == 8), 40% (inc == 4), 37%(56)
+          if (futilityValueScaled < beta)
+          {
+              if (futilityValueScaled > bestValue)
+                  bestValue = futilityValueScaled;
+              continue;
           }
       }
 
@@ -1552,7 +1546,7 @@ namespace {
           value = -search(pos, ss, -(beta-1), newDepth-OnePly, ply+1, true, threadID);
       }
       else
-        value = beta; // Just to trigger next condition
+          value = beta; // Just to trigger next condition
 
       if (value >= beta) // Go with full depth non-pv search
       {
@@ -1566,12 +1560,12 @@ namespace {
       // New best move?
       if (value > bestValue)
       {
-        bestValue = value;
-        if (value >= beta)
-            update_pv(ss, ply);
+          bestValue = value;
+          if (value >= beta)
+              update_pv(ss, ply);
 
-        if (value == value_mate_in(ply + 1))
-            ss[ply].mateKiller = move;
+          if (value == value_mate_in(ply + 1))
+              ss[ply].mateKiller = move;
       }
 
       // Split?
@@ -1584,7 +1578,7 @@ namespace {
           && !thread_should_stop(threadID)
           && split(pos, ss, ply, &beta, &beta, &bestValue, futilityValue, approximateEval,
                    depth, &moveCount, &mp, threadID, false))
-        break;
+          break;
     }
 
     // All legal moves have been searched.  A special case: If there were
@@ -1663,10 +1657,10 @@ namespace {
     }
     ttMove = (tte ? tte->move() : MOVE_NONE);
 
-    // Evaluate the position statically
     isCheck = pos.is_check();
     ei.futilityMargin = Value(0); // Manually initialize futilityMargin
 
+    // Evaluate the position statically
     if (isCheck)
         staticValue = -VALUE_INFINITE;
 
@@ -1675,7 +1669,7 @@ namespace {
         // Use the cached evaluation score if possible
         assert(ei.futilityMargin == Value(0));
 
-        staticValue = tte->value();
+        staticValue = value_from_tt(tte->value(), ply);
     }
     else
         staticValue = evaluate(pos, ei, threadID);
@@ -1820,6 +1814,8 @@ namespace {
     bool useFutilityPruning =     sp->depth < SelectiveDepth
                               && !isCheck;
 
+    const int FutilityValueMargin = 112 * bitScanReverse32(int(sp->depth) * int(sp->depth) / 2);
+
     while (    sp->bestValue < sp->beta
            && !thread_should_stop(threadID)
            && (move = sp->mp->get_next_move(sp->lock)) != MOVE_NONE)
@@ -1845,9 +1841,9 @@ namespace {
           && !dangerous
           && !captureOrPromotion)
       {
-          // History pruning. See ok_to_prune() definition
+          // Move count based pruning
           if (   moveCount >= 2 + int(sp->depth)
-              && ok_to_prune(pos, move, ss[sp->ply].threatMove, sp->depth)
+              && ok_to_prune(pos, move, ss[sp->ply].threatMove)
               && sp->bestValue > value_mated_in(PLY_MAX))
               continue;
 
@@ -1857,8 +1853,7 @@ namespace {
               if (sp->futilityValue == VALUE_NONE)
               {
                   EvalInfo ei;
-                  sp->futilityValue =  evaluate(pos, ei, threadID)
-                                    + FutilityMargins[int(sp->depth) - 2];
+                  sp->futilityValue = evaluate(pos, ei, threadID) + FutilityValueMargin;
               }
 
               if (sp->futilityValue < sp->beta)
@@ -2469,7 +2464,7 @@ namespace {
   // non-tactical moves late in the move list close to the leaves are
   // candidates for pruning.
 
-  bool ok_to_prune(const Position& pos, Move m, Move threat, Depth d) {
+  bool ok_to_prune(const Position& pos, Move m, Move threat) {
 
     assert(move_is_ok(m));
     assert(threat == MOVE_NONE || move_is_ok(threat));
@@ -2503,11 +2498,7 @@ namespace {
         && pos.move_attacks_square(m, tto))
         return false;
 
-    // Case 4: Don't prune moves with good history
-    if (!H.ok_to_prune(pos.piece_on(mfrom), mto, d))
-        return false;
-
-    // Case 5: If the moving piece in the threatened move is a slider, don't
+    // Case 4: If the moving piece in the threatened move is a slider, don't
     // prune safe moves which block its ray.
     if (  !PruneBlockingMoves
         && threat != MOVE_NONE
@@ -2528,8 +2519,8 @@ namespace {
     Value v = value_from_tt(tte->value(), ply);
 
     return   (   tte->depth() >= depth
-              || v >= Max(value_mate_in(100), beta)
-              || v < Min(value_mated_in(100), beta))
+              || v >= Max(value_mate_in(PLY_MAX), beta)
+              || v < Min(value_mated_in(PLY_MAX), beta))
 
           && (   (is_lower_bound(tte->type()) && v >= beta)
               || (is_upper_bound(tte->type()) && v < beta));
@@ -2548,7 +2539,7 @@ namespace {
     {
         assert(m != movesSearched[i]);
         if (!pos.move_is_capture_or_promotion(movesSearched[i]))
-            H.failure(pos.piece_on(move_from(movesSearched[i])), move_to(movesSearched[i]));
+            H.failure(pos.piece_on(move_from(movesSearched[i])), move_to(movesSearched[i]), depth);
     }
   }