};
size_t PVIdx;
- TimeManagement Time;
EasyMoveManager EasyMove;
double BestMoveChanges;
Value DrawValue[COLOR_NB];
void Search::think() {
- Time.init(Limits, RootPos.side_to_move(), RootPos.game_ply(), now());
+ Color us = RootPos.side_to_move();
+ Time.init(Limits, us, RootPos.game_ply(), now());
int contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns
- DrawValue[ RootPos.side_to_move()] = VALUE_DRAW - Value(contempt);
- DrawValue[~RootPos.side_to_move()] = VALUE_DRAW + Value(contempt);
+ DrawValue[ us] = VALUE_DRAW - Value(contempt);
+ DrawValue[~us] = VALUE_DRAW + Value(contempt);
TB::Hits = 0;
TB::RootInTB = false;
Threads.timer->run = false;
}
+ // When playing in 'nodes as time' mode, subtract the searched nodes from
+ // the available ones before to exit.
+ if (Limits.npmsec)
+ Time.availableNodes += Limits.inc[us] - RootPos.nodes_searched();
+
// When we reach the maximum depth, we can arrive here without a raise of
// Signals.stop. However, if we are pondering or in an infinite search,
// the UCI protocol states that we shouldn't print the best move before the
struct LimitsType {
LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC
- nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = movestogo =
+ nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = npmsec = movestogo =
depth = movetime = mate = infinite = ponder = 0;
}
}
std::vector<Move> searchmoves;
- int time[COLOR_NB], inc[COLOR_NB], movestogo, depth, movetime, mate, infinite, ponder;
+ int time[COLOR_NB], inc[COLOR_NB], npmsec, movestogo, depth, movetime, mate, infinite, ponder;
int64_t nodes;
};
#include "timeman.h"
#include "uci.h"
+TimeManagement Time; // Our global time management object
+
namespace {
enum TimeType { OptimumTime, MaxTime };
/// inc > 0 && movestogo == 0 means: x basetime + z increment
/// inc > 0 && movestogo != 0 means: x moves in y minutes + z increment
-void TimeManagement::init(const Search::LimitsType& limits, Color us, int ply, TimePoint now)
+void TimeManagement::init(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"];
+ int npmsec = Options["nodestime"];
+
+ // If we have to play in 'nodes as time' mode, then convert from time
+ // to nodes, and use resulting values in time management formulas.
+ // WARNING: Given npms (nodes per millisecond) must be much lower then
+ // real engine speed to avoid time losses.
+ if (npmsec)
+ {
+ if (!availableNodes) // Only once at game start
+ availableNodes = npmsec * limits.time[us]; // Time is in msec
+
+ // Convert from millisecs to nodes
+ limits.time[us] = (int)availableNodes;
+ limits.inc[us] *= npmsec;
+ limits.npmsec = npmsec;
+ }
start = now;
unstablePvFactor = 1;
class TimeManagement {
public:
- void init(const Search::LimitsType& limits, Color us, int ply, TimePoint now);
+ void init(Search::LimitsType& limits, Color us, int ply, TimePoint now);
void pv_instability(double bestMoveChanges) { unstablePvFactor = 1 + bestMoveChanges; }
int available() const { return int(optimumTime * unstablePvFactor * 0.76); }
int maximum() const { return maximumTime; }
int elapsed() const { return now() - start; }
+ int64_t availableNodes; // When in 'nodes as time' mode
+
private:
TimePoint start;
int optimumTime;
double unstablePvFactor;
};
+extern TimeManagement Time;
+
#endif // #ifndef TIMEMAN_H_INCLUDED
#include "position.h"
#include "search.h"
#include "thread.h"
+#include "timeman.h"
#include "tt.h"
#include "uci.h"
<< "\n" << Options
<< "\nuciok" << sync_endl;
+ else if (token == "ucinewgame")
+ {
+ TT.clear();
+ Time.availableNodes = 0;
+ }
else if (token == "isready") sync_cout << "readyok" << sync_endl;
- else if (token == "ucinewgame") TT.clear();
else if (token == "go") go(pos, is);
else if (token == "position") position(pos, is);
else if (token == "setoption") setoption(is);
o["Move Overhead"] << Option(30, 0, 5000);
o["Minimum Thinking Time"] << Option(20, 0, 5000);
o["Slow Mover"] << Option(80, 10, 1000);
+ o["nodestime"] << Option(0, 0, 10000);
o["UCI_Chess960"] << Option(false);
o["SyzygyPath"] << Option("<empty>", on_tb_path);
o["SyzygyProbeDepth"] << Option(1, 1, 100);