LimitsType Limits;
RootMoveVector RootMoves;
Position RootPos;
- TimePoint SearchTime;
StateStackPtr SetupStates;
}
void Search::think() {
- TimeMgr.init(Limits, RootPos.side_to_move(), RootPos.game_ply());
+ TimeMgr.init(Limits, RootPos.side_to_move(), RootPos.game_ply(), now());
int contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns
DrawValue[ RootPos.side_to_move()] = VALUE_DRAW - Value(contempt);
// the UI) before a re-search.
if ( multiPV == 1
&& (bestValue <= alpha || bestValue >= beta)
- && now() - SearchTime > 3000)
+ && TimeMgr.elapsed_time() > 3000)
sync_cout << UCI::pv(pos, depth, alpha, beta) << sync_endl;
// In case of failing low/high increase aspiration window and
if (Signals.stop)
sync_cout << "info nodes " << RootPos.nodes_searched()
- << " time " << now() - SearchTime << sync_endl;
+ << " time " << TimeMgr.elapsed_time() << sync_endl;
- else if (PVIdx + 1 == multiPV || now() - SearchTime > 3000)
+ else if (PVIdx + 1 == multiPV || TimeMgr.elapsed_time() > 3000)
sync_cout << UCI::pv(pos, depth, alpha, beta) << sync_endl;
}
// of the available time has been used or we matched an easyMove
// from the previous search and just did a fast verification.
if ( RootMoves.size() == 1
- || now() - SearchTime > TimeMgr.available_time()
+ || TimeMgr.elapsed_time() > TimeMgr.available_time()
|| ( RootMoves[0].pv[0] == easyMove
&& BestMoveChanges < 0.03
- && now() - SearchTime > TimeMgr.available_time() / 10))
+ && TimeMgr.elapsed_time() > TimeMgr.available_time() / 10))
{
// If we are allowed to ponder do not stop the search now but
// keep pondering until the GUI sends "ponderhit" or "stop".
// Clear any candidate easy move that wasn't stable for the last search
// iterations; the second condition prevents consecutive fast moves.
- if (EasyMove.stableCnt < 6 || now() - SearchTime < TimeMgr.available_time())
+ if (EasyMove.stableCnt < 6 || TimeMgr.elapsed_time() < TimeMgr.available_time())
EasyMove.clear();
// If skill level is enabled, swap best PV line with the sub-optimal one
{
Signals.firstRootMove = (moveCount == 1);
- if (thisThread == Threads.main() && now() - SearchTime > 3000)
+ if (thisThread == Threads.main() && TimeMgr.elapsed_time() > 3000)
sync_cout << "info depth " << depth / ONE_PLY
<< " currmove " << UCI::move(move, pos.is_chess960())
<< " currmovenumber " << moveCount + PVIdx << sync_endl;
string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
std::stringstream ss;
- TimePoint elapsed = now() - SearchTime + 1;
+ TimePoint elapsed = TimeMgr.elapsed_time() + 1;
size_t multiPV = std::min((size_t)Options["MultiPV"], RootMoves.size());
int selDepth = 0;
void check_time() {
static TimePoint lastInfoTime = now();
- TimePoint elapsed = now() - SearchTime;
+ TimePoint elapsed = TimeMgr.elapsed_time();
if (now() - lastInfoTime >= 1000)
{
/// inc > 0 && movestogo == 0 means: x basetime + z increment
/// inc > 0 && movestogo != 0 means: x moves in y minutes + z increment
-void TimeManager::init(const Search::LimitsType& limits, Color us, int ply)
+void TimeManager::init(const Search::LimitsType& limits, Color us, int ply, TimePoint now)
{
int minThinkingTime = Options["Minimum Thinking Time"];
int moveOverhead = Options["Move Overhead"];
int slowMover = Options["Slow Mover"];
- // Initialize unstablePvFactor to 1 and search times to maximum values
+ start = now;
unstablePvFactor = 1;
- optimumSearchTime = maximumSearchTime = std::max(limits.time[us], minThinkingTime);
+ optimumTime = maximumTime = std::max(limits.time[us], minThinkingTime);
const int MaxMTG = limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon;
int t1 = minThinkingTime + remaining<OptimumTime>(hypMyTime, hypMTG, ply, slowMover);
int t2 = minThinkingTime + remaining<MaxTime >(hypMyTime, hypMTG, ply, slowMover);
- optimumSearchTime = std::min(t1, optimumSearchTime);
- maximumSearchTime = std::min(t2, maximumSearchTime);
+ optimumTime = std::min(t1, optimumTime);
+ maximumTime = std::min(t2, maximumTime);
}
if (Options["Ponder"])
- optimumSearchTime += optimumSearchTime / 4;
+ optimumTime += optimumTime / 4;
- optimumSearchTime = std::min(optimumSearchTime, maximumSearchTime);
+ optimumTime = std::min(optimumTime, maximumTime);
}
#ifndef TIMEMAN_H_INCLUDED
#define TIMEMAN_H_INCLUDED
+#include "misc.h"
+
/// The TimeManager class computes the optimal time to think depending on the
/// maximum available time, the game move number and other parameters.
class TimeManager {
public:
- void init(const Search::LimitsType& limits, Color us, int ply);
+ void init(const Search::LimitsType& limits, Color us, int ply, TimePoint now);
void pv_instability(double bestMoveChanges) { unstablePvFactor = 1 + bestMoveChanges; }
- int available_time() const { return int(optimumSearchTime * unstablePvFactor * 0.76); }
- int maximum_time() const { return maximumSearchTime; }
+ int available_time() const { return int(optimumTime * unstablePvFactor * 0.76); }
+ int maximum_time() const { return maximumTime; }
+ int elapsed_time() const { return now() - start; }
private:
- int optimumSearchTime;
- int maximumSearchTime;
+ TimePoint start;
+ int optimumTime;
+ int maximumTime;
double unstablePvFactor;
};