]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Allow to prune bad captures
[stockfish] / src / search.cpp
index c05bbd4c54d12a790ab38bc1f9be8a7a4bf34662..2a6ba30b8367e93a6d84869d31b2c7fa5ca01a4f 100644 (file)
@@ -22,7 +22,6 @@
 ////
 
 #include <cassert>
 ////
 
 #include <cassert>
-#include <cstdio>
 #include <fstream>
 #include <iostream>
 #include <sstream>
 #include <fstream>
 #include <iostream>
 #include <sstream>
@@ -70,16 +69,16 @@ namespace {
 
   public:
     RootMoveList(Position &pos, Move searchMoves[]);
 
   public:
     RootMoveList(Position &pos, Move searchMoves[]);
-    Move get_move(int moveNum) const;
-    Value get_move_score(int moveNum) const;
-    void set_move_score(int moveNum, Value score);
-    void set_move_nodes(int moveNum, int64_t nodes);
+    inline Move get_move(int moveNum) const;
+    inline Value get_move_score(int moveNum) const;
+    inline void set_move_score(int moveNum, Value score);
+    inline void set_move_nodes(int moveNum, int64_t nodes);
     void set_move_pv(int moveNum, const Move pv[]);
     void set_move_pv(int moveNum, const Move pv[]);
-    Move get_move_pv(int moveNum, int i) const;
-    int64_t get_move_cumulative_nodes(int moveNum) const;
-    int move_count() const;
+    inline Move get_move_pv(int moveNum, int i) const;
+    inline int64_t get_move_cumulative_nodes(int moveNum) const;
+    inline int move_count() const;
     Move scan_for_easy_move() const;
     Move scan_for_easy_move() const;
-    void sort();
+    inline void sort();
     void sort_multipv(int n);
 
   private:
     void sort_multipv(int n);
 
   private:
@@ -417,7 +416,7 @@ void think(const Position &pos, bool infinite, bool ponder, int side_to_move,
   int myTime = time[side_to_move];
   int myIncrement = increment[side_to_move];
   int oppTime = time[1 - side_to_move];
   int myTime = time[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
   TimeAdvantage = myTime - oppTime;
 
   if(!movesToGo) { // Sudden death time control
@@ -1123,9 +1122,7 @@ namespace {
         }
     }
     // Null move search not allowed, try razoring
         }
     }
     // Null move search not allowed, try razoring
-    else if (   depth < RazorDepth
-             && approximateEval < beta - RazorMargin
-             && evaluate(pos, ei, threadID) < beta - RazorMargin)
+    else if (depth < RazorDepth && approximateEval < beta - RazorMargin)
     {
         Value v = qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID);
         if (v < beta)
     {
         Value v = qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID);
         if (v < beta)
@@ -1150,6 +1147,7 @@ namespace {
     Value value, bestValue = -VALUE_INFINITE;
     Bitboard dcCandidates = mp.discovered_check_candidates();
     Value futilityValue = VALUE_NONE;
     Value value, bestValue = -VALUE_INFINITE;
     Bitboard dcCandidates = mp.discovered_check_candidates();
     Value futilityValue = VALUE_NONE;
+    MovePicker::MovegenPhase moveType;
     bool isCheck = pos.is_check();
     bool useFutilityPruning =   UseFutilityPruning
                              && depth < SelectiveDepth
     bool isCheck = pos.is_check();
     bool useFutilityPruning =   UseFutilityPruning
                              && depth < SelectiveDepth
@@ -1158,14 +1156,14 @@ namespace {
     // Loop through all legal moves until no moves remain or a beta cutoff
     // occurs.
     while (   bestValue < beta
     // Loop through all legal moves until no moves remain or a beta cutoff
     // occurs.
     while (   bestValue < beta
-           && (move = mp.get_next_move()) != MOVE_NONE
+           && (move = mp.get_next_move(&moveType)) != MOVE_NONE
            && !thread_should_stop(threadID))
     {
       assert(move_is_ok(move));
 
       bool singleReply = (isCheck && mp.number_of_moves() == 1);
       bool moveIsCheck = pos.move_is_check(move, dcCandidates);
            && !thread_should_stop(threadID))
     {
       assert(move_is_ok(move));
 
       bool singleReply = (isCheck && mp.number_of_moves() == 1);
       bool moveIsCheck = pos.move_is_check(move, dcCandidates);
-      bool moveIsCapture = pos.move_is_capture(move);
+      bool moveIsGoodCapture = (moveType == MovePicker::PH_GOOD_CAPTURES);
       bool moveIsPassedPawnPush = pos.move_is_passed_pawn_push(move);
 
       movesSearched[moveCount++] = ss[ply].currentMove = move;
       bool moveIsPassedPawnPush = pos.move_is_passed_pawn_push(move);
 
       movesSearched[moveCount++] = ss[ply].currentMove = move;
@@ -1177,7 +1175,7 @@ namespace {
       // Futility pruning
       if (    useFutilityPruning
           &&  ext == Depth(0)
       // Futility pruning
       if (    useFutilityPruning
           &&  ext == Depth(0)
-          && !moveIsCapture
+          && !moveIsGoodCapture
           && !moveIsPassedPawnPush
           && !move_promotion(move))
       {
           && !moveIsPassedPawnPush
           && !move_promotion(move))
       {
@@ -1209,7 +1207,7 @@ namespace {
       if (   depth >= 2*OnePly
           && ext == Depth(0)
           && moveCount >= LMRNonPVMoves
       if (   depth >= 2*OnePly
           && ext == Depth(0)
           && moveCount >= LMRNonPVMoves
-          && !moveIsCapture
+          && !moveIsGoodCapture
           && !move_promotion(move)
           && !moveIsPassedPawnPush
           && !move_is_castle(move)
           && !move_promotion(move)
           && !moveIsPassedPawnPush
           && !move_is_castle(move)
@@ -2023,7 +2021,6 @@ namespace {
     assert(threat == MOVE_NONE || move_is_ok(threat));
     assert(!move_promotion(m));
     assert(!pos.move_is_check(m));
     assert(threat == MOVE_NONE || move_is_ok(threat));
     assert(!move_promotion(m));
     assert(!pos.move_is_check(m));
-    assert(!pos.move_is_capture(m));
     assert(!pos.move_is_passed_pawn_push(m));
     assert(d >= OnePly);
 
     assert(!pos.move_is_passed_pawn_push(m));
     assert(d >= OnePly);
 
@@ -2136,62 +2133,64 @@ namespace {
   // search.
 
   void poll() {
   // search.
 
   void poll() {
-    int t, data;
-    static int lastInfoTime;
 
 
-    t = current_search_time();
+    static int lastInfoTime;
+    int t = current_search_time();
 
     //  Poll for input
 
     //  Poll for input
-    data = Bioskey();
-    if(data) {
-      char input[256];
-      if(fgets(input, 255, stdin) == NULL)
-        strncpy(input, "quit\n", 5);
-      if(strncmp(input, "quit", 4) == 0) {
-        AbortSearch = true;
-        PonderSearch = false;
-        Quit = true;
-      }
-      else if(strncmp(input, "stop", 4) == 0) {
-        AbortSearch = true;
-        PonderSearch = false;
-      }
-      else if(strncmp(input, "ponderhit", 9) == 0)
-        ponderhit();
-    }
+    if (Bioskey())
+    {
+        // We are line oriented, don't read single chars
+        std::string command;
+        if (!std::getline(std::cin, command))
+            command = "quit";
 
 
-    // Print search information
-    if(t < 1000)
-      lastInfoTime = 0;
-    else if(lastInfoTime > t)
-      // HACK: Must be a new search where we searched less than
-      // NodesBetweenPolls nodes during the first second of search.
-      lastInfoTime = 0;
-    else if(t - lastInfoTime >= 1000) {
-      lastInfoTime = t;
-      lock_grab(&IOLock);
-      std::cout << "info nodes " << nodes_searched() << " nps " << nps()
-                << " time " << t << " hashfull " << TT.full() << std::endl;
-      lock_release(&IOLock);
-      if(ShowCurrentLine)
-        Threads[0].printCurrentLine = true;
+        if (command == "quit")
+        {
+            AbortSearch = true;
+            PonderSearch = false;
+            Quit = true;
+        }
+        else if(command == "stop")
+        {
+            AbortSearch = true;
+            PonderSearch = false;
+        }
+        else if(command == "ponderhit")
+            ponderhit();
     }
     }
+    // Print search information
+    if (t < 1000)
+        lastInfoTime = 0;
 
 
+    else if (lastInfoTime > t)
+        // HACK: Must be a new search where we searched less than
+        // NodesBetweenPolls nodes during the first second of search.
+        lastInfoTime = 0;
+
+    else if (t - lastInfoTime >= 1000)
+    {
+        lastInfoTime = t;
+        lock_grab(&IOLock);
+        std::cout << "info nodes " << nodes_searched() << " nps " << nps()
+                  << " time " << t << " hashfull " << TT.full() << std::endl;
+        lock_release(&IOLock);
+        if (ShowCurrentLine)
+            Threads[0].printCurrentLine = true;
+    }
     // Should we stop the search?
     // Should we stop the search?
-    if(!PonderSearch && Iteration >= 2 &&
-       (!InfiniteSearch && (t > AbsoluteMaxSearchTime ||
-                            (RootMoveNumber == 1 &&
-                             t > MaxSearchTime + ExtraSearchTime) ||
-                            (!FailHigh && !fail_high_ply_1() && !Problem &&
-                             t > 6*(MaxSearchTime + ExtraSearchTime)))))
-      AbortSearch = true;
+    if (PonderSearch)
+        return;
 
 
-    if(!PonderSearch && ExactMaxTime && t >= ExactMaxTime)
-      AbortSearch = true;
+    bool overTime =     t > AbsoluteMaxSearchTime
+                     || (RootMoveNumber == 1 && t > MaxSearchTime + ExtraSearchTime)
+                     || (  !FailHigh && !fail_high_ply_1() && !Problem
+                         && t > 6*(MaxSearchTime + ExtraSearchTime));
 
 
-    if(!PonderSearch && Iteration >= 3 && MaxNodes
-       && nodes_searched() >= MaxNodes)
-      AbortSearch = true;
+    if (   (Iteration >= 2 && (!InfiniteSearch && overTime))
+        || (ExactMaxTime && t >= ExactMaxTime)
+        || (Iteration >= 3 && MaxNodes && nodes_searched() >= MaxNodes))
+        AbortSearch = true;
   }
 
 
   }