]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Use TT in qsearch
[stockfish] / src / search.cpp
index 55533ddd9af8caba5ae9f009e407cd13d77f71fe..9636ee4065722b70a66a7169dc51f4e3433d0a55 100644 (file)
@@ -241,6 +241,9 @@ namespace {
   bool ok_to_do_nullmove(const Position &pos);
   bool ok_to_prune(const Position &pos, Move m, Move threat, Depth d);
   bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply);
+  bool ok_to_history(const Position &pos, Move m);
+  void update_history(const Position& pos, Move m, Depth depth,
+                      Move movesSearched[], int moveCount);
 
   bool fail_high_ply_1();
   int current_search_time();
@@ -993,8 +996,7 @@ namespace {
         return (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW);
 
     // If the search is not aborted, update the transposition table,
-    // history counters, and killer moves.  This code is somewhat messy,
-    // and definitely needs to be cleaned up.  FIXME
+    // history counters, and killer moves.
     if (AbortSearch || thread_should_stop(threadID))
         return bestValue;
 
@@ -1004,21 +1006,14 @@ namespace {
     else if (bestValue >= beta)
     {
         Move m = ss[ply].pv[ply];
-        if (pos.square_is_empty(move_to(m)) && !move_promotion(m) && !move_is_ep(m))
+        if (ok_to_history(pos, m)) // Only non capture moves are considered
         {
-            for (int i = 0; i < moveCount - 1; i++)
-                if (    pos.square_is_empty(move_to(movesSearched[i]))
-                    && !move_promotion(movesSearched[i])
-                    && !move_is_ep(movesSearched[i]))
-                    H.failure(pos.piece_on(move_from(movesSearched[i])), movesSearched[i]);
-
-            H.success(pos.piece_on(move_from(m)), m, depth);
-
-          if (m != ss[ply].killer1)
-          {
-            ss[ply].killer2 = ss[ply].killer1;
-            ss[ply].killer1 = m;
-          }
+            update_history(pos, m, depth, movesSearched, moveCount);
+            if (m != ss[ply].killer1)
+            {
+                ss[ply].killer2 = ss[ply].killer1;
+                ss[ply].killer1 = m;
+            }
         }
         TT.store(pos, value_to_tt(bestValue, ply), depth, m, VALUE_TYPE_LOWER);
     }
@@ -1255,8 +1250,7 @@ namespace {
         return (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW);
 
     // If the search is not aborted, update the transposition table,
-    // history counters, and killer moves.  This code is somewhat messy,
-    // and definitely needs to be cleaned up.  FIXME
+    // history counters, and killer moves.
     if (AbortSearch || thread_should_stop(threadID))
         return bestValue;
 
@@ -1265,16 +1259,9 @@ namespace {
     else
     {
         Move m = ss[ply].pv[ply];
-        if (pos.square_is_empty(move_to(m)) && !move_promotion(m) && !move_is_ep(m))
+        if (ok_to_history(pos, m)) // Only non capture moves are considered
         {
-            for (int i = 0; i < moveCount - 1; i++)
-                if (    pos.square_is_empty(move_to(movesSearched[i]))
-                    && !move_promotion(movesSearched[i])
-                    && !move_is_ep(movesSearched[i]))
-                    H.failure(pos.piece_on(move_from(movesSearched[i])), movesSearched[i]);
-
-            H.success(pos.piece_on(move_from(m)), m, depth);
-
+            update_history(pos, m, depth, movesSearched, moveCount);
             if (m != ss[ply].killer1)
             {
                 ss[ply].killer2 = ss[ply].killer1;
@@ -1312,6 +1299,11 @@ namespace {
     if (pos.is_draw())
         return VALUE_DRAW;
 
+    // Transposition table lookup
+    const TTEntry* tte = TT.retrieve(pos);
+    if (tte && ok_to_use_TT(tte, depth, beta, ply))
+        return value_from_tt(tte->value(), ply);
+
     // Evaluate the position statically:
     Value staticValue = evaluate(pos, ei, threadID);
 
@@ -1409,6 +1401,9 @@ namespace {
 
     assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
 
+    // Update transposition table
+    TT.store(pos, value_to_tt(bestValue, ply), depth, MOVE_NONE, VALUE_TYPE_EXACT);
+
     return bestValue;
   }
 
@@ -2044,6 +2039,30 @@ namespace {
   }
 
 
+  // ok_to_history() returns true if a move m can be stored
+  // in history. Should be a non capturing move.
+
+  bool ok_to_history(const Position& pos, Move m) {
+
+    return    pos.square_is_empty(move_to(m))
+          && !move_promotion(m)
+          && !move_is_ep(m);
+  }
+
+
+  // update_history() registers a good move that produced a beta-cutoff
+  // in history and marks as failures all the other moves of that ply.
+
+  void update_history(const Position& pos, Move m, Depth depth,
+                      Move movesSearched[], int moveCount) {
+
+    H.success(pos.piece_on(move_from(m)), m, depth);
+
+    for (int i = 0; i < moveCount - 1; i++)
+        if (ok_to_history(pos, movesSearched[i]) && m != movesSearched[i])
+            H.failure(pos.piece_on(move_from(movesSearched[i])), movesSearched[i]);
+  }
+
   // fail_high_ply_1() checks if some thread is currently resolving a fail
   // high at ply 1 at the node below the first root node.  This information
   // is used for time managment.