]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Add and use update_killers()
[stockfish] / src / search.cpp
index a4ea9aa4b36e455057c66aa6934b99896fe62dca..0763cd37e31a9cdf98abf0d6c9e6a9b25f372dee 100644 (file)
@@ -244,14 +244,14 @@ namespace {
   void update_pv(SearchStack ss[], int ply);
   void sp_update_pv(SearchStack *pss, SearchStack ss[], int ply);
   bool connected_moves(const Position &pos, Move m1, Move m2);
-  Depth extension(const Position &pos, Move m, bool pvNode, bool check,
-                  bool singleReply, bool mateThreat);
+  bool move_is_killer(Move m, const SearchStack& ss);
+  Depth extension(const Position &pos, Move m, bool pvNode, bool check, bool singleReply, bool mateThreat);
   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);
+  void update_history(const Position& pos, Move m, Depth depth, Move movesSearched[], int moveCount);
+  void update_killers(Move m, SearchStack& ss);
 
   bool fail_high_ply_1();
   int current_search_time();
@@ -998,8 +998,7 @@ namespace {
             && !move_promotion(move)
             && !moveIsPassedPawnPush
             && !move_is_castle(move)
-            &&  move != ss[ply].killers[0]
-            &&  move != ss[ply].killers[1])
+            && !move_is_killer(move, ss[ply]))
         {
             ss[ply].reduction = OnePly;
             value = -search(pos, ss, -alpha, newDepth-OnePly, ply+1, true, threadID);
@@ -1081,11 +1080,7 @@ namespace {
         if (ok_to_history(pos, m)) // Only non capture moves are considered
         {
             update_history(pos, m, depth, movesSearched, moveCount);
-            if (m != ss[ply].killers[0])
-            {
-                ss[ply].killers[1] = ss[ply].killers[0];
-                ss[ply].killers[0] = m;
-            }
+            update_killers(m, ss[ply]); 
         }
         TT.store(pos, value_to_tt(bestValue, ply), depth, m, VALUE_TYPE_LOWER);
     }
@@ -1272,8 +1267,7 @@ namespace {
           && !move_promotion(move)
           && !moveIsPassedPawnPush
           && !move_is_castle(move)
-          &&  move != ss[ply].killers[0]
-          &&  move != ss[ply].killers[1])
+          && !move_is_killer(move, ss[ply]))
       {
           ss[ply].reduction = OnePly;
           value = -search(pos, ss, -(beta-1), newDepth-OnePly, ply+1, true, threadID);
@@ -1332,11 +1326,7 @@ namespace {
         if (ok_to_history(pos, m)) // Only non capture moves are considered
         {
             update_history(pos, m, depth, movesSearched, moveCount);
-            if (m != ss[ply].killers[0])
-            {
-                ss[ply].killers[1] = ss[ply].killers[0];
-                ss[ply].killers[0] = m;
-            }
+            update_killers(m, ss[ply]);
         }
         TT.store(pos, value_to_tt(bestValue, ply), depth, m, VALUE_TYPE_LOWER);
     }
@@ -1481,12 +1471,7 @@ namespace {
     if (alpha >= beta && ok_to_history(pos, m)) // Only non capture moves are considered
     {
         // Wrong to update history when depth is <= 0
-
-        if (m != ss[ply].killers[0])
-        {
-            ss[ply].killers[1] = ss[ply].killers[0];
-            ss[ply].killers[0] = m;
-        }
+        update_killers(m, ss[ply]);
     }
     return bestValue;
   }
@@ -1556,8 +1541,7 @@ namespace {
           && !moveIsPassedPawnPush
           && !move_promotion(move)
           && !move_is_castle(move)
-          &&  move != ss[sp->ply].killers[0]
-          &&  move != ss[sp->ply].killers[1])
+          && !move_is_killer(move, ss[sp->ply]))
       {
           ss[sp->ply].reduction = OnePly;
           value = -search(pos, ss, -(sp->beta-1), newDepth - OnePly, sp->ply+1, true, threadID);
@@ -1664,8 +1648,7 @@ namespace {
           && !moveIsPassedPawnPush
           && !move_promotion(move)
           && !move_is_castle(move)
-          &&  move != ss[sp->ply].killers[0]
-          &&  move != ss[sp->ply].killers[1])
+          && !move_is_killer(move, ss[sp->ply]))
       {
           ss[sp->ply].reduction = OnePly;
           value = -search(pos, ss, -sp->alpha, newDepth - OnePly, sp->ply+1, true, threadID);
@@ -1944,10 +1927,11 @@ namespace {
 
     ss[ply].pv[ply] = ss[ply].pv[ply+1] = ss[ply].currentMove = MOVE_NONE;
     ss[ply+2].mateKiller = MOVE_NONE;
-    ss[ply+2].killers[0] = ss[ply+2].killers[1] = MOVE_NONE;
     ss[ply].threatMove = MOVE_NONE;
     ss[ply].reduction = Depth(0);
     ss[ply].currentMoveCaptureValue = Value(0);
+    for (int j = 0; j < KILLER_MAX; j++)
+        ss[ply+2].killers[j] = MOVE_NONE;
 
     if(Threads[threadID].printCurrentLine)
       print_current_line(ss, ply, threadID);
@@ -2050,6 +2034,20 @@ namespace {
   }
 
 
+  // move_is_killer() checks if the given move is among the
+  // killer moves of that ply.
+
+  bool move_is_killer(Move m, const SearchStack& ss) {
+    
+      const Move* k = ss.killers;
+      for (int i = 0; i < KILLER_MAX; i++, k++)
+          if (*k == m)
+              return true;
+
+      return false;
+  }
+
+
   // extension() decides whether a move should be searched with normal depth,
   // or with extended depth.  Certain classes of moves (checking moves, in
   // particular) are searched with bigger depth than ordinary moves.
@@ -2197,6 +2195,21 @@ namespace {
     }
   }
 
+
+  // update_killers() add a good move that produced a beta-cutoff
+  // among the killer moves of that ply.
+
+  void update_killers(Move m, SearchStack& ss) {
+
+    if (m == ss.killers[0])
+        return;
+
+    for (int i = KILLER_MAX - 1; i > 0; i--)
+        ss.killers[i] = ss.killers[i - 1]; 
+    ss.killers[0] = m;    
+  }
+
   // 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.