]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Clean steps 8 and 9.
[stockfish] / src / search.cpp
index 723b701a0a1c8da991d8c7221835815de67f7e62..d2e3cd32caef87b97a523d53708532de0c9a0c71 100644 (file)
@@ -72,7 +72,6 @@ namespace {
     void set_active_threads(int newActiveThreads) { ActiveThreads = newActiveThreads; }
     void incrementNodeCounter(int threadID) { threads[threadID].nodes++; }
     void incrementBetaCounter(Color us, Depth d, int threadID) { threads[threadID].betaCutOffs[us] += unsigned(d); }
-    void print_current_line(SearchStack ss[], int ply, int threadID);
 
     void resetNodeCounters();
     void resetBetaCounters();
@@ -88,14 +87,14 @@ namespace {
                Depth depth, int* moves, MovePicker* mp, int master, bool pvNode);
 
   private:
-    friend void poll();
+    friend void poll(SearchStack ss[], int ply);
 
     int ActiveThreads;
     volatile bool AllThreadsShouldExit, AllThreadsShouldSleep;
     Thread threads[MAX_THREADS];
     SplitPoint SplitPointStack[MAX_THREADS][ACTIVE_SPLIT_POINTS_MAX];
 
-    Lock MPLock, IOLock;
+    Lock MPLock;
 
 #if !defined(_MSC_VER)
     pthread_cond_t WaitCond;
@@ -159,35 +158,40 @@ namespace {
   };
 
 
-  /// Constants
+  /// Adjustments
 
-  // Search depth at iteration 1
-  const Depth InitialDepth = OnePly;
+  // Step 6. Razoring
+
+  const Depth RazorDepth = 4 * OnePly;
+  inline Value razor_margin(Depth d) { return Value(0x200 + 0x10 * d); }
+
+  // Step 8. Null move search with verification search
+
+  // Null move margin. A null move search will not be done if the static
+  // evaluation of the position is more than NullMoveMargin below beta.
+  const Value NullMoveMargin = Value(0x200);
 
-  // Use internal iterative deepening?
-  const bool UseIIDAtPVNodes = true;
-  const bool UseIIDAtNonPVNodes = true;
+  // Step 9. Internal iterative deepening
 
-  // Internal iterative deepening margin. At Non-PV moves, when
-  // UseIIDAtNonPVNodes is true, we do an internal iterative deepening
+  const Depth IIDDepthAtPVNodes = 5 * OnePly;
+  const Depth IIDDepthAtNonPVNodes = 8 * OnePly;
+
+  // Internal iterative deepening margin. At Non-PV nodes
+  // we do an internal iterative deepening
   // search when the static evaluation is at most IIDMargin below beta.
   const Value IIDMargin = Value(0x100);
 
+  // Search depth at iteration 1
+  const Depth InitialDepth = OnePly;
+
   // Easy move margin. An easy move candidate must be at least this much
   // better than the second best move.
   const Value EasyMoveMargin = Value(0x200);
 
-  // Null move margin. A null move search will not be done if the static
-  // evaluation of the position is more than NullMoveMargin below beta.
-  const Value NullMoveMargin = Value(0x200);
-
   // If the TT move is at least SingleReplyMargin better then the
   // remaining ones we will extend it.
   const Value SingleReplyMargin = Value(0x20);
 
-  // Depth limit for razoring
-  const Depth RazorDepth = 4 * OnePly;
-
   /// Lookup tables initialized at startup
 
   // Reduction lookup tables and their getter functions
@@ -288,7 +292,7 @@ namespace {
 
   int current_search_time();
   int nps();
-  void poll();
+  void poll(SearchStack ss[], int ply);
   void ponderhit();
   void wait_for_stop_or_ponderhit();
   void init_ss_array(SearchStack ss[]);
@@ -1040,14 +1044,16 @@ namespace {
     assert(threadID >= 0 && threadID < TM.active_threads());
 
     Move movesSearched[256];
+    EvalInfo ei;
     StateInfo st;
     const TTEntry* tte;
     Move ttMove, move;
     Depth ext, newDepth;
-    Value oldAlpha, value;
-    bool isCheck, mateThreat, singleEvasion, moveIsCheck, captureOrPromotion, dangerous;
+    Value bestValue, value, oldAlpha;
+    bool isCheck, singleEvasion, moveIsCheck, captureOrPromotion, dangerous;
+    bool mateThreat = false;
     int moveCount = 0;
-    Value bestValue = value = -VALUE_INFINITE;
+    bestValue = value = -VALUE_INFINITE;
 
     if (depth < OnePly)
         return qsearch(pos, ss, alpha, beta, Depth(0), ply, threadID);
@@ -1086,7 +1092,6 @@ namespace {
     isCheck = pos.is_check();
     if (!isCheck)
     {
-        EvalInfo ei;
         ss[ply].eval = evaluate(pos, ei, threadID);
         update_gains(pos, ss[ply - 1].currentMove, ss[ply - 1].eval, ss[ply].eval);
     }
@@ -1096,8 +1101,7 @@ namespace {
     // Step 8. Null move search with verification search (is omitted in PV nodes)
 
     // Step 9. Internal iterative deepening
-    if (   UseIIDAtPVNodes
-        && depth >= 5*OnePly
+    if (   depth >= IIDDepthAtPVNodes
         && ttMove == MOVE_NONE)
     {
         search_pv(pos, ss, alpha, beta, depth-2*OnePly, ply, threadID);
@@ -1332,15 +1336,15 @@ namespace {
     if (   !value_is_mate(beta)
         && !isCheck
         && depth < RazorDepth
-        && refinedValue < beta - (0x200 + 16 * depth)
+        && refinedValue < beta - razor_margin(depth)
         && ss[ply - 1].currentMove != MOVE_NULL
         && ttMove == MOVE_NONE
         && !pos.has_pawn_on_7th(pos.side_to_move()))
     {
-        Value rbeta = beta - (0x200 + 16 * depth);
+        Value rbeta = beta - razor_margin(depth);
         Value v = qsearch(pos, ss, rbeta-1, rbeta, Depth(0), ply, threadID);
         if (v < rbeta)
-          return v; //FIXME: Logically should be: return (v + 0x200 + 16 * depth);
+          return v; //FIXME: Logically should be: return (v + razor_margin(depth));
     }
 
     // Step 7. Static null move pruning
@@ -1406,8 +1410,10 @@ namespace {
     }
 
     // Step 9. Internal iterative deepening
-    if (UseIIDAtNonPVNodes && ttMove == MOVE_NONE && depth >= 8*OnePly &&
-        !isCheck && ss[ply].eval >= beta - IIDMargin)
+    if (   depth >= IIDDepthAtNonPVNodes
+        && ttMove == MOVE_NONE
+        && !isCheck
+        && ss[ply].eval >= beta - IIDMargin)
     {
         search(pos, ss, beta, depth/2, ply, false, threadID);
         ttMove = ss[ply].pv[ply];
@@ -1779,20 +1785,25 @@ namespace {
   // splitting, we don't have to repeat all this work in sp_search().  We
   // also don't need to store anything to the hash table here:  This is taken
   // care of after we return from the split point.
+  // FIXME: We are currently ignoring mateThreat flag here
 
   void sp_search(SplitPoint* sp, int threadID) {
 
     assert(threadID >= 0 && threadID < TM.active_threads());
     assert(TM.active_threads() > 1);
 
-    Position pos(*sp->pos);
-    CheckInfo ci(pos);
-    SearchStack* ss = sp->sstack[threadID];
     StateInfo st;
-    Value value = -VALUE_INFINITE;
     Move move;
+    Depth ext, newDepth;
+    Value value, futilityValueScaled;
+    bool isCheck, moveIsCheck, captureOrPromotion, dangerous;
     int moveCount;
-    bool isCheck = pos.is_check();
+    value = -VALUE_INFINITE;
+
+    Position pos(*sp->pos);
+    CheckInfo ci(pos);
+    SearchStack* ss = sp->sstack[threadID];
+    isCheck = pos.is_check();
 
     // Step 10. Loop through moves
     // Loop through all legal moves until no moves remain or a beta cutoff occurs
@@ -1807,13 +1818,12 @@ namespace {
 
       assert(move_is_ok(move));
 
-      bool moveIsCheck = pos.move_is_check(move, ci);
-      bool captureOrPromotion = pos.move_is_capture_or_promotion(move);
+      moveIsCheck = pos.move_is_check(move, ci);
+      captureOrPromotion = pos.move_is_capture_or_promotion(move);
 
       // Step 11. Decide the new search depth
-      bool dangerous;
-      Depth ext = extension(pos, move, false, captureOrPromotion, moveIsCheck, false, false, &dangerous);
-      Depth newDepth = sp->depth - OnePly + ext;
+      ext = extension(pos, move, false, captureOrPromotion, moveIsCheck, false, false, &dangerous);
+      newDepth = sp->depth - OnePly + ext;
 
       // Update current move
       ss[sp->ply].currentMove = move;
@@ -1835,7 +1845,7 @@ namespace {
 
           // Value based pruning
           Depth predictedDepth = newDepth - nonpv_reduction(sp->depth, moveCount);
-          Value futilityValueScaled =  ss[sp->ply].eval + futility_margin(predictedDepth, moveCount)
+          futilityValueScaled =  ss[sp->ply].eval + futility_margin(predictedDepth, moveCount)
                                      + H.gain(pos.piece_on(move_from(move)), move_to(move)) + 45;
 
           if (futilityValueScaled < sp->beta)
@@ -1910,19 +1920,24 @@ namespace {
   // don't have to repeat all this work in sp_search_pv().  We also don't
   // need to store anything to the hash table here: This is taken care of
   // after we return from the split point.
+  // FIXME: We are ignoring mateThreat flag!
 
   void sp_search_pv(SplitPoint* sp, int threadID) {
 
     assert(threadID >= 0 && threadID < TM.active_threads());
     assert(TM.active_threads() > 1);
 
+    StateInfo st;
+    Move move;
+    Depth ext, newDepth;
+    Value value;
+    bool moveIsCheck, captureOrPromotion, dangerous;
+    int moveCount;
+    value = -VALUE_INFINITE;
+
     Position pos(*sp->pos);
     CheckInfo ci(pos);
     SearchStack* ss = sp->sstack[threadID];
-    StateInfo st;
-    Value value = -VALUE_INFINITE;
-    int moveCount;
-    Move move;
 
     // Step 10. Loop through moves
     // Loop through all legal moves until no moves remain or a beta cutoff occurs
@@ -1937,13 +1952,12 @@ namespace {
 
       assert(move_is_ok(move));
 
-      bool moveIsCheck = pos.move_is_check(move, ci);
-      bool captureOrPromotion = pos.move_is_capture_or_promotion(move);
+      moveIsCheck = pos.move_is_check(move, ci);
+      captureOrPromotion = pos.move_is_capture_or_promotion(move);
 
       // Step 11. Decide the new search depth
-      bool dangerous;
-      Depth ext = extension(pos, move, true, captureOrPromotion, moveIsCheck, false, false, &dangerous);
-      Depth newDepth = sp->depth - OnePly + ext;
+      ext = extension(pos, move, true, captureOrPromotion, moveIsCheck, false, false, &dangerous);
+      newDepth = sp->depth - OnePly + ext;
 
       // Update current move
       ss[sp->ply].currentMove = move;
@@ -2041,13 +2055,12 @@ namespace {
         NodesSincePoll++;
         if (NodesSincePoll >= NodesBetweenPolls)
         {
-            poll();
+            poll(ss, ply);
             NodesSincePoll = 0;
         }
     }
     ss[ply].init(ply);
     ss[ply + 2].initKillers();
-    TM.print_current_line(ss, ply, threadID);
   }
 
 
@@ -2405,7 +2418,7 @@ namespace {
   // looks at the time consumed so far and decides if it's time to abort the
   // search.
 
-  void poll() {
+  void poll(SearchStack ss[], int ply) {
 
     static int lastInfoTime;
     int t = current_search_time();
@@ -2447,7 +2460,6 @@ namespace {
     else if (t - lastInfoTime >= 1000)
     {
         lastInfoTime = t;
-        lock_grab(&TM.IOLock);
 
         if (dbg_show_mean)
             dbg_print_mean();
@@ -2458,10 +2470,15 @@ namespace {
         cout << "info nodes " << TM.nodes_searched() << " nps " << nps()
              << " time " << t << " hashfull " << TT.full() << endl;
 
-        lock_release(&TM.IOLock);
+        // We only support current line printing in single thread mode
+        if (ShowCurrentLine && TM.active_threads() == 1)
+        {
+            cout << "info currline";
+            for (int p = 0; p < ply; p++)
+                cout << " " << ss[p].currentMove;
 
-        if (ShowCurrentLine)
-            TM.threads[0].printCurrentLineRequest = true;
+            cout << endl;
+        }
     }
 
     // Should we stop the search?
@@ -2690,7 +2707,6 @@ namespace {
 
     // Initialize global locks
     lock_init(&MPLock, NULL);
-    lock_init(&IOLock, NULL);
 
     // Initialize SplitPointStack locks
     for (i = 0; i < MAX_THREADS; i++)
@@ -2992,47 +3008,8 @@ namespace {
 
     // This makes the threads to go to sleep
     AllThreadsShouldSleep = true;
-
-    // Reset flags to a known state.
-    for (int i = 1; i < ActiveThreads; i++)
-    {
-        // This flag can be in a random state
-        threads[i].printCurrentLineRequest = false;
-    }
   }
 
-  // print_current_line() prints _once_ the current line of search for a
-  // given thread and then setup the print request for the next thread.
-  // Called when the UCI option UCI_ShowCurrLine is 'true'.
-
-  void ThreadsManager::print_current_line(SearchStack ss[], int ply, int threadID) {
-
-    assert(ply >= 0 && ply < PLY_MAX);
-    assert(threadID >= 0 && threadID < ActiveThreads);
-
-    if (!threads[threadID].printCurrentLineRequest)
-        return;
-
-    // One shot only
-    threads[threadID].printCurrentLineRequest = false;
-
-    if (threads[threadID].state == THREAD_SEARCHING)
-    {
-        lock_grab(&IOLock);
-        cout << "info currline " << (threadID + 1);
-        for (int p = 0; p < ply; p++)
-            cout << " " << ss[p].currentMove;
-
-        cout << endl;
-        lock_release(&IOLock);
-    }
-
-    // Setup print request for the next thread ID
-    if (threadID + 1 < ActiveThreads)
-        threads[threadID + 1].printCurrentLineRequest = true;
-  }
-
-
   /// The RootMoveList class
 
   // RootMoveList c'tor