- // Do we have time for the next iteration? Can we stop searching now?
- if (Limits.use_time_management() && !Signals.stop && !Signals.stopOnPonderhit)
- {
- // Take some extra time if the best move has changed
- if (depth > 4 * ONE_PLY && multiPV == 1)
- TimeMgr.pv_instability(BestMoveChanges);
-
- // Stop the search if only one legal move is available or all
- // of the available time has been used.
- if ( RootMoves.size() == 1
- || Time::now() - SearchTime > TimeMgr.available_time())
- {
- // If we are allowed to ponder do not stop the search now but
- // keep pondering until the GUI sends "ponderhit" or "stop".
- if (Limits.ponder)
- Signals.stopOnPonderhit = true;
- else
- Signals.stop = true;
- }
- }
- }
+ assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
+ }
+
+ // Sort the PV lines searched so far and update the GUI
+ std::stable_sort(rootMoves.begin() + pvFirst, rootMoves.begin() + pvIdx + 1);
+
+ if ( mainThread
+ && (Threads.stop || pvIdx + 1 == multiPV || Time.elapsed() > 3000))
+ sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl;
+ }
+
+ if (!Threads.stop)
+ completedDepth = rootDepth;
+
+ if (rootMoves[0].pv[0] != lastBestMove) {
+ lastBestMove = rootMoves[0].pv[0];
+ lastBestMoveDepth = rootDepth;
+ }
+
+ // Have we found a "mate in x"?
+ if ( Limits.mate
+ && bestValue >= VALUE_MATE_IN_MAX_PLY
+ && VALUE_MATE - bestValue <= 2 * Limits.mate)
+ Threads.stop = true;
+
+ if (!mainThread)
+ continue;
+
+ // If skill level is enabled and time is up, pick a sub-optimal best move
+ if (skill.enabled() && skill.time_to_pick(rootDepth))
+ skill.pick_best(multiPV);
+
+ // Do we have time for the next iteration? Can we stop searching now?
+ if ( Limits.use_time_management()
+ && !Threads.stop
+ && !Threads.stopOnPonderhit)
+ {
+ const int F[] = { failedLow,
+ bestValue - mainThread->previousScore };
+
+ int improvingFactor = std::max(246, std::min(832, 306 + 119 * F[0] - 6 * F[1]));
+
+ // If the bestMove is stable over several iterations, reduce time accordingly
+ timeReduction = 1.0;
+ for (int i : {3, 4, 5})
+ if (lastBestMoveDepth * i < completedDepth)
+ timeReduction *= 1.25;
+
+ // Use part of the gained time from a previous stable move for the current move
+ double bestMoveInstability = 1.0 + mainThread->bestMoveChanges;
+ bestMoveInstability *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction;
+
+ // Stop the search if we have only one legal move, or if available time elapsed
+ if ( rootMoves.size() == 1
+ || Time.elapsed() > Time.optimum() * bestMoveInstability * improvingFactor / 581)
+ {
+ // If we are allowed to ponder do not stop the search now but
+ // keep pondering until the GUI sends "ponderhit" or "stop".
+ if (Threads.ponder)
+ Threads.stopOnPonderhit = true;
+ else
+ Threads.stop = true;
+ }
+ }