]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Revert opponent time advantage logic
[stockfish] / src / search.cpp
index 0763cd37e31a9cdf98abf0d6c9e6a9b25f372dee..d02035183b07a262abd14de260b6baee824aa332 100644 (file)
@@ -188,7 +188,7 @@ namespace {
   // Time managment variables
   int SearchStartTime;
   int MaxNodes, MaxDepth;
-  int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime, TimeAdvantage;
+  int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime;
   Move BestRootMove, PonderMove, EasyMove;
   int RootMoveNumber;
   bool InfiniteSearch;
@@ -238,14 +238,14 @@ namespace {
                 Depth depth, int ply, int threadID);
   void sp_search(SplitPoint *sp, int threadID);
   void sp_search_pv(SplitPoint *sp, int threadID);
-  void init_search_stack(SearchStack ss);
+  void init_search_stack(SearchStack& ss);
   void init_search_stack(SearchStack ss[]);
   void init_node(const Position &pos, SearchStack ss[], int ply, int threadID);
   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);
   bool move_is_killer(Move m, const SearchStack& ss);
-  Depth extension(const Position &pos, Move m, bool pvNode, bool check, bool singleReply, bool mateThreat);
+  Depth extension(const Position &pos, Move m, bool pvNode, 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_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply);
@@ -427,16 +427,14 @@ void think(const Position &pos, bool infinite, bool ponder, int side_to_move,
   int myIncrement = increment[side_to_move];
   int oppTime = time[1 - side_to_move];
 
-  TimeAdvantage = myTime - oppTime;
-
   if (!movesToGo) // Sudden death time control
-  { 
-      if (increment)
+  {
+      if (myIncrement)
       {
           MaxSearchTime = myTime / 30 + myIncrement;
           AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
       } else { // Blitz game without increment
-          MaxSearchTime = myTime / 40;
+          MaxSearchTime = myTime / 30;
           AbsoluteMaxSearchTime = myTime / 8;
       }
   }
@@ -680,10 +678,6 @@ namespace {
                 ExtraSearchTime = BestMoveChangesByIteration[Iteration]   * (MaxSearchTime / 2)
                                 + BestMoveChangesByIteration[Iteration-1] * (MaxSearchTime / 3);
 
-            // If we need some more and we are in time advantage take it
-            if (ExtraSearchTime > 0 && TimeAdvantage > 2 * MaxSearchTime)
-                ExtraSearchTime += MaxSearchTime / 2;
-
             // Try to guess if the current iteration is the last one or the last two
             LastIterations = (current_search_time() > ((MaxSearchTime + ExtraSearchTime)*58) / 128);
 
@@ -778,7 +772,8 @@ namespace {
                       << " currmovenumber " << i + 1 << std::endl;
 
         // Decide search depth for this move
-        ext = extension(pos, move, true, pos.move_is_check(move), false, false);
+        bool dangerous;
+        ext = extension(pos, move, true, pos.move_is_check(move), false, false, &dangerous);
         newDepth = (Iteration - 2) * OnePly + ext + InitialDepth;
 
         // Make the move, and search it
@@ -795,7 +790,7 @@ namespace {
 
             if (Problem && StopOnPonderhit)
                 StopOnPonderhit = false;
-        } 
+        }
         else
         {
             value = -search(pos, ss, -alpha, newDepth, 1, true, 0);
@@ -952,8 +947,7 @@ namespace {
     Value value, bestValue = -VALUE_INFINITE;
     Bitboard dcCandidates = mp.discovered_check_candidates();
     bool isCheck = pos.is_check();
-    bool mateThreat =   MateThreatExtension[1] > Depth(0)
-                     && pos.has_mate_threat(opposite_color(pos.side_to_move()));
+    bool mateThreat = pos.has_mate_threat(opposite_color(pos.side_to_move()));
 
     // Loop through all legal moves until no moves remain or a beta cutoff
     // occurs.
@@ -966,7 +960,6 @@ namespace {
       bool singleReply = (isCheck && mp.number_of_moves() == 1);
       bool moveIsCheck = pos.move_is_check(move, dcCandidates);
       bool moveIsCapture = pos.move_is_capture(move);
-      bool moveIsPassedPawnPush = pos.move_is_passed_pawn_push(move);
 
       movesSearched[moveCount++] = ss[ply].currentMove = move;
 
@@ -978,7 +971,8 @@ namespace {
           ss[ply].currentMoveCaptureValue = Value(0);
 
       // Decide the new search depth
-      Depth ext = extension(pos, move, true, moveIsCheck, singleReply, mateThreat);
+      bool dangerous;
+      Depth ext = extension(pos, move, true, moveIsCheck, singleReply, mateThreat, &dangerous);
       Depth newDepth = depth - OnePly + ext;
 
       // Make and search the move
@@ -992,11 +986,10 @@ namespace {
         // Try to reduce non-pv search depth by one ply if move seems not problematic,
         // if the move fails high will be re-searched at full depth.
         if (    depth >= 2*OnePly
-            &&  ext == Depth(0)
             &&  moveCount >= LMRPVMoves
+            && !dangerous
             && !moveIsCapture
             && !move_promotion(move)
-            && !moveIsPassedPawnPush
             && !move_is_castle(move)
             && !move_is_killer(move, ss[ply]))
         {
@@ -1080,7 +1073,7 @@ namespace {
         if (ok_to_history(pos, m)) // Only non capture moves are considered
         {
             update_history(pos, m, depth, movesSearched, moveCount);
-            update_killers(m, ss[ply]); 
+            update_killers(m, ss[ply]);
         }
         TT.store(pos, value_to_tt(bestValue, ply), depth, m, VALUE_TYPE_LOWER);
     }
@@ -1220,19 +1213,18 @@ namespace {
       bool singleReply = (isCheck && mp.number_of_moves() == 1);
       bool moveIsCheck = pos.move_is_check(move, dcCandidates);
       bool moveIsCapture = pos.move_is_capture(move);
-      bool moveIsPassedPawnPush = pos.move_is_passed_pawn_push(move);
 
       movesSearched[moveCount++] = ss[ply].currentMove = move;
 
       // Decide the new search depth
-      Depth ext = extension(pos, move, false, moveIsCheck, singleReply, mateThreat);
+      bool dangerous;
+      Depth ext = extension(pos, move, false, moveIsCheck, singleReply, mateThreat, &dangerous);
       Depth newDepth = depth - OnePly + ext;
 
       // Futility pruning
       if (    useFutilityPruning
-          &&  ext == Depth(0)
+          && !dangerous
           && !moveIsCapture
-          && !moveIsPassedPawnPush
           && !move_promotion(move))
       {
           if (   moveCount >= 2 + int(depth)
@@ -1260,12 +1252,11 @@ namespace {
 
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
-      if (   depth >= 2*OnePly
-          && ext == Depth(0)
-          && moveCount >= LMRNonPVMoves
+      if (    depth >= 2*OnePly
+          &&  moveCount >= LMRNonPVMoves
+          && !dangerous
           && !moveIsCapture
           && !move_promotion(move)
-          && !moveIsPassedPawnPush
           && !move_is_castle(move)
           && !move_is_killer(move, ss[ply]))
       {
@@ -1398,20 +1389,17 @@ namespace {
     {
       assert(move_is_ok(move));
 
-      bool moveIsCheck = pos.move_is_check(move, dcCandidates);
-      bool moveIsPassedPawnPush = pos.move_is_passed_pawn_push(move);
-
       moveCount++;
       ss[ply].currentMove = move;
 
       // Futility pruning
       if (    UseQSearchFutilityPruning
+          &&  enoughMaterial
           && !isCheck
-          && !moveIsCheck
-          && !move_promotion(move)
-          && !moveIsPassedPawnPush
           && !pvNode
-          &&  enoughMaterial)
+          && !move_promotion(move)
+          && !pos.move_is_check(move, dcCandidates)
+          && !pos.move_is_passed_pawn_push(move))
       {
           Value futilityValue = staticValue
                               + Max(pos.midgame_value_of_piece_on(move_to(move)),
@@ -1430,7 +1418,6 @@ namespace {
       // 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)
@@ -1507,7 +1494,6 @@ namespace {
 
       bool moveIsCheck = pos.move_is_check(move, sp->dcCandidates);
       bool moveIsCapture = pos.move_is_capture(move);
-      bool moveIsPassedPawnPush = pos.move_is_passed_pawn_push(move);
 
       lock_grab(&(sp->lock));
       int moveCount = ++sp->moves;
@@ -1516,14 +1502,14 @@ namespace {
       ss[sp->ply].currentMove = move;
 
       // Decide the new search depth.
-      Depth ext = extension(pos, move, false, moveIsCheck, false, false);
+      bool dangerous;
+      Depth ext = extension(pos, move, false, moveIsCheck, false, false, &dangerous);
       Depth newDepth = sp->depth - OnePly + ext;
 
       // Prune?
       if (    useFutilityPruning
-          &&  ext == Depth(0)
+          && !dangerous
           && !moveIsCapture
-          && !moveIsPassedPawnPush
           && !move_promotion(move)
           &&  moveCount >= 2 + int(sp->depth)
           &&  ok_to_prune(pos, move, ss[sp->ply].threatMove, sp->depth))
@@ -1535,10 +1521,9 @@ namespace {
 
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
-      if (    ext == Depth(0)
+      if (   !dangerous
           &&  moveCount >= LMRNonPVMoves
           && !moveIsCapture
-          && !moveIsPassedPawnPush
           && !move_promotion(move)
           && !move_is_castle(move)
           && !move_is_killer(move, ss[sp->ply]))
@@ -1619,7 +1604,6 @@ namespace {
     {
       bool moveIsCheck = pos.move_is_check(move, sp->dcCandidates);
       bool moveIsCapture = pos.move_is_capture(move);
-      bool moveIsPassedPawnPush = pos.move_is_passed_pawn_push(move);
 
       assert(move_is_ok(move));
 
@@ -1633,7 +1617,8 @@ namespace {
       ss[sp->ply].currentMove = move;
 
       // Decide the new search depth.
-      Depth ext = extension(pos, move, true, moveIsCheck, false, false);
+      bool dangerous;
+      Depth ext = extension(pos, move, true, moveIsCheck, false, false, &dangerous);
       Depth newDepth = sp->depth - OnePly + ext;
 
       // Make and search the move.
@@ -1642,10 +1627,9 @@ namespace {
 
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
-      if (    ext == Depth(0)
+      if (   !dangerous
           &&  moveCount >= LMRPVMoves
           && !moveIsCapture
-          && !moveIsPassedPawnPush
           && !move_promotion(move)
           && !move_is_castle(move)
           && !move_is_killer(move, ss[sp->ply]))
@@ -1879,7 +1863,7 @@ namespace {
 
   // init_search_stack() initializes a search stack at the beginning of a
   // new search from the root.
-  void init_search_stack(SearchStack ss) {
+  void init_search_stack(SearchStack& ss) {
 
     ss.pv[0] = MOVE_NONE;
     ss.pv[1] = MOVE_NONE;
@@ -1887,7 +1871,7 @@ namespace {
     ss.threatMove = MOVE_NONE;
     ss.reduction = Depth(0);
     for (int j = 0; j < KILLER_MAX; j++)
-        ss.killers[j] = MOVE_NONE;    
+        ss.killers[j] = MOVE_NONE;
   }
 
   void init_search_stack(SearchStack ss[]) {
@@ -1924,7 +1908,6 @@ namespace {
         NodesSincePoll = 0;
       }
     }
-
     ss[ply].pv[ply] = ss[ply].pv[ply+1] = ss[ply].currentMove = MOVE_NONE;
     ss[ply+2].mateKiller = MOVE_NONE;
     ss[ply].threatMove = MOVE_NONE;
@@ -2038,7 +2021,7 @@ namespace {
   // 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)
@@ -2050,12 +2033,16 @@ namespace {
 
   // 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.
+  // particular) are searched with bigger depth than ordinary moves and in
+  // any case are marked as 'dangerous'. Note that also if a move is not
+  // extended, as example because the corresponding UCI option is set to zero,
+  // the move is marked as 'dangerous' so, at least, we avoid to prune it.
 
-  Depth extension(const Position &pos, Move m, bool pvNode,
-                  bool check, bool singleReply, bool mateThreat) {
+  Depth extension(const Position &pos, Move m, bool pvNode, bool check,
+                  bool singleReply, bool mateThreat, bool* dangerous) {
 
     Depth result = Depth(0);
+    *dangerous = check || singleReply || mateThreat;
 
     if (check)
         result += CheckExtension[pvNode];
@@ -2063,26 +2050,37 @@ namespace {
     if (singleReply)
         result += SingleReplyExtension[pvNode];
 
+    if (mateThreat)
+        result += MateThreatExtension[pvNode];
+
     if (pos.move_is_pawn_push_to_7th(m))
+    {
         result += PawnPushTo7thExtension[pvNode];
-
+        *dangerous = true;
+    }
     if (pos.move_is_passed_pawn_push(m))
+    {
         result += PassedPawnExtension[pvNode];
-
-    if (mateThreat)
-        result += MateThreatExtension[pvNode];
+        *dangerous = true;
+    }
 
     if (   pos.midgame_value_of_piece_on(move_to(m)) >= RookValueMidgame
         && (  pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK)
             - pos.midgame_value_of_piece_on(move_to(m)) == Value(0))
         && !move_promotion(m))
+    {
         result += PawnEndgameExtension[pvNode];
-    
+        *dangerous = true;
+    }
+
     if (   pvNode
         && pos.move_is_capture(m)
         && pos.type_of_piece_on(move_to(m)) != PAWN
         && pos.see(m) >= 0)
+    {
         result += OnePly/2;
+        *dangerous = true;
+    }
 
     return Min(result, OnePly);
   }
@@ -2205,9 +2203,9 @@ namespace {
         return;
 
     for (int i = KILLER_MAX - 1; i > 0; i--)
-        ss.killers[i] = ss.killers[i - 1]; 
-    ss.killers[0] = m;    
+        ss.killers[i] = ss.killers[i - 1];
+
+    ss.killers[0] = m;
   }
 
   // fail_high_ply_1() checks if some thread is currently resolving a fail