]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
qsearch: do not prune pv nodes with negative SEE
[stockfish] / src / search.cpp
index 97ed196acede459112754e6892f2b88fba8a75cc..7cc307d854705baeff687b39de006f75e379ea17 100644 (file)
@@ -1389,11 +1389,13 @@ namespace {
     // to search the moves.  Because the depth is <= 0 here, only captures,
     // queen promotions and checks (only if depth == 0) will be generated.
     MovePicker mp = MovePicker(pos, false, MOVE_NONE, MOVE_NONE, MOVE_NONE,
-                               MOVE_NONE, depth);
+                               MOVE_NONE, depth, &ei);
     Move move;
     int moveCount = 0;
     Bitboard dcCandidates = mp.discovered_check_candidates();
     bool isCheck = pos.is_check();
+    bool pvNode = (beta - alpha != 1);
+    bool enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame;
 
     // Loop through the moves until no moves remain or a beta cutoff
     // occurs.
@@ -1414,8 +1416,8 @@ namespace {
           && !moveIsCheck
           && !move_promotion(move)
           && !moveIsPassedPawnPush
-          &&  beta - alpha == 1
-          &&  pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame)
+          && !pvNode
+          &&  enoughMaterial)
       {
           Value futilityValue = staticValue
                               + Max(pos.midgame_value_of_piece_on(move_to(move)),
@@ -1431,9 +1433,10 @@ namespace {
           }
       }
 
-      // Don't search captures and checks with negative SEE values.
+      // Don't search captures and checks with negative SEE values
       if (   !isCheck
           && !move_promotion(move)
+          && !pvNode
           && (pos.midgame_value_of_piece_on(move_from(move)) >
               pos.midgame_value_of_piece_on(move_to(move)))
           &&  pos.see(move) < 0)
@@ -1469,6 +1472,18 @@ namespace {
     // Update transposition table
     TT.store(pos, value_to_tt(bestValue, ply), depth, MOVE_NONE, VALUE_TYPE_EXACT);
 
+    // Update killers only for good check moves
+    Move m = ss[ply].currentMove;
+    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].killer1)
+        {
+            ss[ply].killer2 = ss[ply].killer1;
+            ss[ply].killer1 = m;
+        }
+    }
     return bestValue;
   }
 
@@ -2143,13 +2158,11 @@ namespace {
 
 
   // ok_to_history() returns true if a move m can be stored
-  // in history. Should be a non capturing move.
+  // in history. Should be a non capturing move nor a promotion.
 
   bool ok_to_history(const Position& pos, Move m) {
 
-    return    pos.square_is_empty(move_to(m))
-          && !move_promotion(m)
-          && !move_is_ep(m);
+    return !pos.move_is_capture(m) && !move_promotion(m);
   }
 
 
@@ -2162,8 +2175,11 @@ namespace {
     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])
+    {
+        assert(m != movesSearched[i]);
+        if (ok_to_history(pos, 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