2 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3 Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4 Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5 Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
7 Stockfish is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Stockfish is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 TimeManagement Time; // Our global time management object
33 enum TimeType { OptimumTime, MaxTime };
35 int remaining(int myTime, int myInc, int moveOverhead,
36 int movesToGo, int ply, TimeType type) {
41 int moveNumber = (ply + 1) / 2;
42 double ratio; // Which ratio of myTime we are going to use. It is <= 1
45 // Usage of increment follows quadratic distribution with the maximum at move 25
46 double inc = myInc * std::max(55.0, 120.0 - 0.12 * (moveNumber - 25) * (moveNumber - 25));
48 // In moves-to-go we distribute time according to a quadratic function with
49 // the maximum around move 20 for 40 moves in y time case.
52 ratio = (type == OptimumTime ? 1.0 : 6.0) / std::min(50, movesToGo);
55 ratio *= 1.1 - 0.001 * (moveNumber - 20) * (moveNumber - 20);
59 // Otherwise we increase usage of remaining time as the game goes on
62 sd = 1 + 20 * moveNumber / (500.0 + moveNumber);
63 ratio = (type == OptimumTime ? 0.017 : 0.07) * sd;
66 ratio = std::min(1.0, ratio * (1 + inc / (myTime * sd)));
68 return int(ratio * std::max(0, myTime - moveOverhead));
74 /// init() is called at the beginning of the search and calculates the allowed
75 /// thinking time out of the time control and current game ply. We support four
76 /// different kinds of time controls, passed in 'limits':
78 /// inc == 0 && movestogo == 0 means: x basetime [sudden death!]
79 /// inc == 0 && movestogo != 0 means: x moves in y minutes
80 /// inc > 0 && movestogo == 0 means: x basetime + z increment
81 /// inc > 0 && movestogo != 0 means: x moves in y minutes + z increment
83 void TimeManagement::init(Search::LimitsType& limits, Color us, int ply)
85 int moveOverhead = Options["Move Overhead"];
86 int npmsec = Options["nodestime"];
88 // If we have to play in 'nodes as time' mode, then convert from time
89 // to nodes, and use resulting values in time management formulas.
90 // WARNING: Given npms (nodes per millisecond) must be much lower then
91 // the real engine speed to avoid time losses.
94 if (!availableNodes) // Only once at game start
95 availableNodes = npmsec * limits.time[us]; // Time is in msec
97 // Convert from millisecs to nodes
98 limits.time[us] = (int)availableNodes;
99 limits.inc[us] *= npmsec;
100 limits.npmsec = npmsec;
103 startTime = limits.startTime;
104 optimumTime = remaining(limits.time[us], limits.inc[us], moveOverhead, limits.movestogo, ply, OptimumTime);
105 maximumTime = remaining(limits.time[us], limits.inc[us], moveOverhead, limits.movestogo, ply, MaxTime);
107 if (Options["Ponder"])
108 optimumTime += optimumTime / 4;