Subversion Repositories Games.Chess Giants

Rev

Rev 96 | Rev 169 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  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-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
  6.  
  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.
  11.  
  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.
  16.  
  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/>.
  19. */
  20.  
  21. #include <algorithm>
  22. #include <cfloat>
  23. #include <cmath>
  24.  
  25. #include "search.h"
  26. #include "timeman.h"
  27. #include "uci.h"
  28.  
  29. TimeManagement Time; // Our global time management object
  30.  
  31. namespace {
  32.  
  33.   enum TimeType { OptimumTime, MaxTime };
  34.  
  35.   const int MoveHorizon   = 50;   // Plan time management at most this many moves ahead
  36.   const double MaxRatio   = 7.09; // When in trouble, we can step over reserved time with this ratio
  37.   const double StealRatio = 0.35; // However we must not steal time from remaining moves over this ratio
  38.  
  39.  
  40.   // move_importance() is a skew-logistic function based on naive statistical
  41.   // analysis of "how many games are still undecided after n half-moves". Game
  42.   // is considered "undecided" as long as neither side has >275cp advantage.
  43.   // Data was extracted from the CCRL game database with some simple filtering criteria.
  44.  
  45.   double move_importance(int ply) {
  46.  
  47.     const double XScale = 7.64;
  48.     const double XShift = 58.4;
  49.     const double Skew   = 0.183;
  50.  
  51.     return pow((1 + exp((ply - XShift) / XScale)), -Skew) + DBL_MIN; // Ensure non-zero
  52.   }
  53.  
  54.   template<TimeType T>
  55.   int remaining(int myTime, int movesToGo, int ply, int slowMover) {
  56.  
  57.     const double TMaxRatio   = (T == OptimumTime ? 1 : MaxRatio);
  58.     const double TStealRatio = (T == OptimumTime ? 0 : StealRatio);
  59.  
  60.     double moveImportance = (move_importance(ply) * slowMover) / 100;
  61.     double otherMovesImportance = 0;
  62.  
  63.     for (int i = 1; i < movesToGo; ++i)
  64.         otherMovesImportance += move_importance(ply + 2 * i);
  65.  
  66.     double ratio1 = (TMaxRatio * moveImportance) / (TMaxRatio * moveImportance + otherMovesImportance);
  67.     double ratio2 = (moveImportance + TStealRatio * otherMovesImportance) / (moveImportance + otherMovesImportance);
  68.  
  69.     return int(myTime * std::min(ratio1, ratio2)); // Intel C++ asks for an explicit cast
  70.   }
  71.  
  72. } // namespace
  73.  
  74.  
  75. /// init() is called at the beginning of the search and calculates the allowed
  76. /// thinking time out of the time control and current game ply. We support four
  77. /// different kinds of time controls, passed in 'limits':
  78. ///
  79. ///  inc == 0 && movestogo == 0 means: x basetime  [sudden death!]
  80. ///  inc == 0 && movestogo != 0 means: x moves in y minutes
  81. ///  inc >  0 && movestogo == 0 means: x basetime + z increment
  82. ///  inc >  0 && movestogo != 0 means: x moves in y minutes + z increment
  83.  
  84. void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
  85.  
  86.   int minThinkingTime = Options["Minimum Thinking Time"];
  87.   int moveOverhead    = Options["Move Overhead"];
  88.   int slowMover       = Options["Slow Mover"];
  89.   int npmsec          = Options["nodestime"];
  90.  
  91.   // If we have to play in 'nodes as time' mode, then convert from time
  92.   // to nodes, and use resulting values in time management formulas.
  93.   // WARNING: Given npms (nodes per millisecond) must be much lower then
  94.   // the real engine speed to avoid time losses.
  95.   if (npmsec)
  96.   {
  97.       if (!availableNodes) // Only once at game start
  98.           availableNodes = npmsec * limits.time[us]; // Time is in msec
  99.  
  100.       // Convert from millisecs to nodes
  101.       limits.time[us] = (int)availableNodes;
  102.       limits.inc[us] *= npmsec;
  103.       limits.npmsec = npmsec;
  104.   }
  105.  
  106.   startTime = limits.startTime;
  107.   optimumTime = maximumTime = std::max(limits.time[us], minThinkingTime);
  108.  
  109.   const int MaxMTG = limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon;
  110.  
  111.   // We calculate optimum time usage for different hypothetical "moves to go"-values
  112.   // and choose the minimum of calculated search time values. Usually the greatest
  113.   // hypMTG gives the minimum values.
  114.   for (int hypMTG = 1; hypMTG <= MaxMTG; ++hypMTG)
  115.   {
  116.       // Calculate thinking time for hypothetical "moves to go"-value
  117.       int hypMyTime =  limits.time[us]
  118.                      + limits.inc[us] * (hypMTG - 1)
  119.                      - moveOverhead * (2 + std::min(hypMTG, 40));
  120.  
  121.       hypMyTime = std::max(hypMyTime, 0);
  122.  
  123.       int t1 = minThinkingTime + remaining<OptimumTime>(hypMyTime, hypMTG, ply, slowMover);
  124.       int t2 = minThinkingTime + remaining<MaxTime    >(hypMyTime, hypMTG, ply, slowMover);
  125.  
  126.       optimumTime = std::min(t1, optimumTime);
  127.       maximumTime = std::min(t2, maximumTime);
  128.   }
  129.  
  130.   if (Options["Ponder"])
  131.       optimumTime += optimumTime / 4;
  132. }
  133.