1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-07-12 03:59:15 +00:00

Introduce and use SearchLimits

Pack a bit of global variables related to search limits in
a single struct.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba 2011-04-22 15:52:03 +02:00
parent bbfe452f85
commit 1d368bbbdc
6 changed files with 112 additions and 119 deletions

View file

@ -73,7 +73,7 @@ void benchmark(int argc, char* argv[]) {
vector<string> positions; vector<string> positions;
string ttSize, threads, valStr, posFile, valType; string ttSize, threads, valStr, posFile, valType;
int val, secsPerPos, maxDepth, maxNodes; int val, maxTime, maxDepth, maxNodes;
ttSize = argc > 2 ? argv[2] : "128"; ttSize = argc > 2 ? argv[2] : "128";
threads = argc > 3 ? argv[3] : "1"; threads = argc > 3 ? argv[3] : "1";
@ -87,13 +87,13 @@ void benchmark(int argc, char* argv[]) {
Options["Use Search Log"].set_value("true"); Options["Use Search Log"].set_value("true");
Options["Search Log Filename"].set_value("bench.txt"); Options["Search Log Filename"].set_value("bench.txt");
secsPerPos = maxDepth = maxNodes = 0; maxTime = maxDepth = maxNodes = 0;
val = atoi(valStr.c_str()); val = atoi(valStr.c_str());
if (valType == "depth" || valType == "perft") if (valType == "depth" || valType == "perft")
maxDepth = val; maxDepth = val;
else if (valType == "time") else if (valType == "time")
secsPerPos = val * 1000; maxTime = val * 1000;
else else
maxNodes = val; maxNodes = val;
@ -124,8 +124,7 @@ void benchmark(int argc, char* argv[]) {
for (it = positions.begin(); it != positions.end(); ++it, ++cnt) for (it = positions.begin(); it != positions.end(); ++it, ++cnt)
{ {
Move moves[1] = { MOVE_NONE }; Move moves[] = { MOVE_NONE };
int dummy[2] = { 0, 0 };
Position pos(*it, false, 0); Position pos(*it, false, 0);
cerr << "\nBench position: " << cnt << '/' << positions.size() << endl << endl; cerr << "\nBench position: " << cnt << '/' << positions.size() << endl << endl;
if (valType == "perft") if (valType == "perft")
@ -134,7 +133,7 @@ void benchmark(int argc, char* argv[]) {
cerr << "\nPerft " << maxDepth << " result (nodes searched): " << perftCnt << endl << endl; cerr << "\nPerft " << maxDepth << " result (nodes searched): " << perftCnt << endl << endl;
totalNodes += perftCnt; totalNodes += perftCnt;
} else { } else {
if (!think(pos, false, false, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves)) if (!think(pos, SearchLimits(0, 0, 0, maxTime, maxDepth, maxNodes, false, false), moves))
break; break;
totalNodes += pos.nodes_searched(); totalNodes += pos.nodes_searched();
} }

View file

@ -116,8 +116,8 @@ namespace {
void extract_pv_from_tt(Position& pos); void extract_pv_from_tt(Position& pos);
void insert_pv_in_tt(Position& pos); void insert_pv_in_tt(Position& pos);
std::string pv_info_to_uci(Position& pos, int depth, int selDepth, Value alpha, Value beta, int pvIdx); std::string pv_info_to_uci(Position& pos, int depth, int selDepth,
Value alpha, Value beta, int pvIdx);
int64_t nodes; int64_t nodes;
Value pv_score; Value pv_score;
Value non_pv_score; Value non_pv_score;
@ -125,7 +125,7 @@ namespace {
}; };
// RootMoveList struct is just a std::vector<> of RootMove objects, // RootMoveList struct is just a vector of RootMove objects,
// with an handful of methods above the standard ones. // with an handful of methods above the standard ones.
struct RootMoveList : public std::vector<RootMove> { struct RootMoveList : public std::vector<RootMove> {
@ -188,8 +188,8 @@ namespace {
// Step 11. Decide the new search depth // Step 11. Decide the new search depth
// Extensions. Configurable UCI options // Extensions. Configurable UCI options. Array index 0 is used at
// Array index 0 is used at non-PV nodes, index 1 at PV nodes. // non-PV nodes, index 1 at PV nodes.
Depth CheckExtension[2], PawnPushTo7thExtension[2]; Depth CheckExtension[2], PawnPushTo7thExtension[2];
Depth PassedPawnExtension[2], PawnEndgameExtension[2]; Depth PassedPawnExtension[2], PawnEndgameExtension[2];
@ -210,7 +210,7 @@ namespace {
// Step 14. Reduced search // Step 14. Reduced search
// Reduction lookup tables (initialized at startup) and their getter functions // Reduction lookup tables (initialized at startup) and their access function
int8_t ReductionMatrix[2][64][64]; // [pv][depth][moveNumber] int8_t ReductionMatrix[2][64][64]; // [pv][depth][moveNumber]
template <NodeType PV> template <NodeType PV>
@ -233,10 +233,9 @@ namespace {
int MultiPV, UCIMultiPV; int MultiPV, UCIMultiPV;
// Time management variables // Time management variables
int MaxNodes, MaxDepth, ExactMaxTime; bool StopOnPonderhit, FirstRootMove, StopRequest, QuitRequest, AspirationFailLow;
bool UseTimeManagement, InfiniteSearch, Pondering, StopOnPonderhit;
bool FirstRootMove, StopRequest, QuitRequest, AspirationFailLow;
TimeManager TimeMgr; TimeManager TimeMgr;
SearchLimits Limits;
// Log file // Log file
bool UseLogFile; bool UseLogFile;
@ -304,7 +303,7 @@ namespace {
#endif #endif
// MovePickerExt is an extended MovePicker used to choose at compile time // MovePickerExt is an extended MovePicker class used to choose at compile time
// the proper move source according to the type of node. // the proper move source according to the type of node.
template<bool SpNode, bool Root> struct MovePickerExt; template<bool SpNode, bool Root> struct MovePickerExt;
@ -439,25 +438,30 @@ int64_t perft(Position& pos, Depth depth) {
/// think() is the external interface to Stockfish's search, and is called when /// think() is the external interface to Stockfish's search, and is called when
/// the program receives the UCI 'go' command. It initializes various global /// the program receives the UCI 'go' command. It initializes various global
/// variables, and calls id_loop(). It returns false when a quit command is /// variables, and calls id_loop(). It returns false when a "quit" command is
/// received during the search. /// received during the search.
bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[], bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
int movesToGo, int maxDepth, int maxNodes, int maxTime, Move searchMoves[]) {
// Initialize global search-related variables // Initialize global search-related variables
StopOnPonderhit = StopRequest = QuitRequest = AspirationFailLow = SendSearchedNodes = false; StopOnPonderhit = StopRequest = QuitRequest = AspirationFailLow = SendSearchedNodes = false;
NodesSincePoll = 0; NodesSincePoll = 0;
current_search_time(get_system_time()); current_search_time(get_system_time());
ExactMaxTime = maxTime; Limits = limits;
MaxDepth = maxDepth; TimeMgr.init(Limits, pos.startpos_ply_counter());
MaxNodes = maxNodes;
InfiniteSearch = infinite; // Set best NodesBetweenPolls interval to avoid lagging under time pressure
Pondering = ponder; if (Limits.maxNodes)
UseTimeManagement = !ExactMaxTime && !MaxDepth && !MaxNodes && !InfiniteSearch; NodesBetweenPolls = Min(Limits.maxNodes, 30000);
else if (Limits.time && Limits.time < 1000)
NodesBetweenPolls = 1000;
else if (Limits.time && Limits.time < 5000)
NodesBetweenPolls = 5000;
else
NodesBetweenPolls = 30000;
// Look for a book move, only during games, not tests // Look for a book move, only during games, not tests
if (UseTimeManagement && Options["OwnBook"].value<bool>()) if (Limits.useTimeManagement() && Options["OwnBook"].value<bool>())
{ {
if (Options["Book File"].value<std::string>() != OpeningBook.name()) if (Options["Book File"].value<std::string>() != OpeningBook.name())
OpeningBook.open(Options["Book File"].value<std::string>()); OpeningBook.open(Options["Book File"].value<std::string>());
@ -465,7 +469,7 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[
Move bookMove = OpeningBook.get_move(pos, Options["Best Book Move"].value<bool>()); Move bookMove = OpeningBook.get_move(pos, Options["Best Book Move"].value<bool>());
if (bookMove != MOVE_NONE) if (bookMove != MOVE_NONE)
{ {
if (Pondering) if (Limits.ponder)
wait_for_stop_or_ponderhit(); wait_for_stop_or_ponderhit();
cout << "bestmove " << bookMove << endl; cout << "bestmove " << bookMove << endl;
@ -511,34 +515,18 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[
ThreadsMgr[i].maxPly = 0; ThreadsMgr[i].maxPly = 0;
} }
// Set thinking time // Write to log file and keep it open to be accessed during the search
int myTime = time[pos.side_to_move()];
int myIncrement = increment[pos.side_to_move()];
if (UseTimeManagement)
TimeMgr.init(myTime, myIncrement, movesToGo, pos.startpos_ply_counter());
// Set best NodesBetweenPolls interval to avoid lagging under time pressure
if (MaxNodes)
NodesBetweenPolls = Min(MaxNodes, 30000);
else if (myTime && myTime < 1000)
NodesBetweenPolls = 1000;
else if (myTime && myTime < 5000)
NodesBetweenPolls = 5000;
else
NodesBetweenPolls = 30000;
// Write search information to log file
if (UseLogFile) if (UseLogFile)
{ {
std::string name = Options["Search Log Filename"].value<std::string>(); std::string name = Options["Search Log Filename"].value<std::string>();
LogFile.open(name.c_str(), std::ios::out | std::ios::app); LogFile.open(name.c_str(), std::ios::out | std::ios::app);
LogFile << "\nSearching: " << pos.to_fen() LogFile << "\nSearching: " << pos.to_fen()
<< "\ninfinite: " << infinite << "\ninfinite: " << Limits.infinite
<< " ponder: " << ponder << " ponder: " << Limits.ponder
<< " time: " << myTime << " time: " << Limits.time
<< " increment: " << myIncrement << " increment: " << Limits.increment
<< " moves to go: " << movesToGo << " moves to go: " << Limits.movesToGo
<< endl; << endl;
} }
@ -546,15 +534,15 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[
Move ponderMove = MOVE_NONE; Move ponderMove = MOVE_NONE;
Move bestMove = id_loop(pos, searchMoves, &ponderMove); Move bestMove = id_loop(pos, searchMoves, &ponderMove);
// Print final search statistics
cout << "info" << speed_to_uci(pos.nodes_searched()) << endl; cout << "info" << speed_to_uci(pos.nodes_searched()) << endl;
// Write final search statistics and close log file
if (UseLogFile) if (UseLogFile)
{ {
int t = current_search_time(); int t = current_search_time();
LogFile << "Nodes: " << pos.nodes_searched() LogFile << "Nodes: " << pos.nodes_searched()
<< "\nNodes/second: " << (t > 0 ? int(pos.nodes_searched() * 1000 / t) : 0) << "\nNodes/second: " << (t > 0 ? pos.nodes_searched() * 1000 / t : 0)
<< "\nBest move: " << move_to_san(pos, bestMove); << "\nBest move: " << move_to_san(pos, bestMove);
StateInfo st; StateInfo st;
@ -569,7 +557,7 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[
// If we are pondering or in infinite search, we shouldn't print the // If we are pondering or in infinite search, we shouldn't print the
// best move before we are told to do so. // best move before we are told to do so.
if (!StopRequest && (Pondering || InfiniteSearch)) if (!StopRequest && (Limits.ponder || Limits.infinite))
wait_for_stop_or_ponderhit(); wait_for_stop_or_ponderhit();
// Could be MOVE_NONE when searching on a stalemate position // Could be MOVE_NONE when searching on a stalemate position
@ -624,7 +612,7 @@ namespace {
} }
// Iterative deepening loop // Iterative deepening loop
while (++depth <= PLY_MAX && (!MaxDepth || depth <= MaxDepth) && !StopRequest) while (++depth <= PLY_MAX && (!Limits.maxDepth || depth <= Limits.maxDepth) && !StopRequest)
{ {
Rml.bestMoveChanges = 0; Rml.bestMoveChanges = 0;
cout << set960(pos.is_chess960()) << "info depth " << depth << endl; cout << set960(pos.is_chess960()) << "info depth " << depth << endl;
@ -708,7 +696,7 @@ namespace {
else if (bestMove != easyMove) else if (bestMove != easyMove)
easyMove = MOVE_NONE; easyMove = MOVE_NONE;
if (UseTimeManagement && !StopRequest) if (Limits.useTimeManagement() && !StopRequest)
{ {
// Time to stop? // Time to stop?
bool noMoreTime = false; bool noMoreTime = false;
@ -743,7 +731,7 @@ namespace {
if (noMoreTime) if (noMoreTime)
{ {
if (Pondering) if (Limits.ponder)
StopOnPonderhit = true; StopOnPonderhit = true;
else else
break; break;
@ -1907,7 +1895,7 @@ split_point_start: // At split points actual search starts from here
if (!std::getline(std::cin, command) || command == "quit") if (!std::getline(std::cin, command) || command == "quit")
{ {
// Quit the program as soon as possible // Quit the program as soon as possible
Pondering = false; Limits.ponder = false;
QuitRequest = StopRequest = true; QuitRequest = StopRequest = true;
return; return;
} }
@ -1915,7 +1903,7 @@ split_point_start: // At split points actual search starts from here
{ {
// Stop calculating as soon as possible, but still send the "bestmove" // Stop calculating as soon as possible, but still send the "bestmove"
// and possibly the "ponder" token when finishing the search. // and possibly the "ponder" token when finishing the search.
Pondering = false; Limits.ponder = false;
StopRequest = true; StopRequest = true;
} }
else if (command == "ponderhit") else if (command == "ponderhit")
@ -1923,7 +1911,7 @@ split_point_start: // At split points actual search starts from here
// The opponent has played the expected move. GUI sends "ponderhit" if // The opponent has played the expected move. GUI sends "ponderhit" if
// we were told to ponder on the same move the opponent has played. We // we were told to ponder on the same move the opponent has played. We
// should continue searching but switching from pondering to normal search. // should continue searching but switching from pondering to normal search.
Pondering = false; Limits.ponder = false;
if (StopOnPonderhit) if (StopOnPonderhit)
StopRequest = true; StopRequest = true;
@ -1951,7 +1939,7 @@ split_point_start: // At split points actual search starts from here
} }
// Should we stop the search? // Should we stop the search?
if (Pondering) if (Limits.ponder)
return; return;
bool stillAtFirstMove = FirstRootMove bool stillAtFirstMove = FirstRootMove
@ -1961,9 +1949,9 @@ split_point_start: // At split points actual search starts from here
bool noMoreTime = t > TimeMgr.maximum_time() bool noMoreTime = t > TimeMgr.maximum_time()
|| stillAtFirstMove; || stillAtFirstMove;
if ( (UseTimeManagement && noMoreTime) if ( (Limits.useTimeManagement() && noMoreTime)
|| (ExactMaxTime && t >= ExactMaxTime) || (Limits.maxTime && t >= Limits.maxTime)
|| (MaxNodes && pos.nodes_searched() >= MaxNodes)) // FIXME || (Limits.maxNodes && pos.nodes_searched() >= Limits.maxNodes)) // FIXME
StopRequest = true; StopRequest = true;
} }

View file

@ -23,13 +23,13 @@
#include "move.h" #include "move.h"
#include "types.h" #include "types.h"
class Position;
struct SplitPoint;
/// The SearchStack struct keeps track of the information we need to remember /// The SearchStack struct keeps track of the information we need to remember
/// from nodes shallower and deeper in the tree during the search. Each /// from nodes shallower and deeper in the tree during the search. Each
/// search thread has its own array of SearchStack objects, indexed by the /// search thread has its own array of SearchStack objects, indexed by the
/// current ply. /// current ply.
struct EvalInfo;
struct SplitPoint;
struct SearchStack { struct SearchStack {
int ply; int ply;
@ -45,12 +45,27 @@ struct SearchStack {
SplitPoint* sp; SplitPoint* sp;
}; };
class Position;
/// The SearchLimits struct stores information sent by GUI about available time
/// to search the current move, maximum depth/time, if we are in analysis mode
/// or if we have to ponder while is our opponent's side to move.
struct SearchLimits {
SearchLimits() {}
SearchLimits(int t, int i, int mtg, int mt, int md, int mn, bool inf, bool pon)
: time(t), increment(i), movesToGo(mtg), maxTime(mt), maxDepth(md),
maxNodes(mn), infinite(inf), ponder(pon) {}
bool useTimeManagement() const { return !(maxTime | maxDepth | maxNodes | int(infinite)); }
int time, increment, movesToGo, maxTime, maxDepth, maxNodes;
bool infinite, ponder;
};
extern void init_threads(); extern void init_threads();
extern void exit_threads(); extern void exit_threads();
extern int64_t perft(Position& pos, Depth depth); extern int64_t perft(Position& pos, Depth depth);
extern bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[], extern bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]);
int movesToGo, int maxDepth, int maxNodes, int maxTime, Move searchMoves[]);
#endif // !defined(SEARCH_H_INCLUDED) #endif // !defined(SEARCH_H_INCLUDED)

View file

@ -17,21 +17,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
////
//// Includes
////
#include <cmath> #include <cmath>
#include "misc.h" #include "misc.h"
#include "search.h"
#include "timeman.h" #include "timeman.h"
#include "ucioption.h" #include "ucioption.h"
////
//// Local definitions
////
namespace { namespace {
/// Constants /// Constants
@ -84,24 +76,21 @@ namespace {
} }
////
//// Functions
////
void TimeManager::pv_instability(int curChanges, int prevChanges) { void TimeManager::pv_instability(int curChanges, int prevChanges) {
unstablePVExtraTime = curChanges * (optimumSearchTime / 2) unstablePVExtraTime = curChanges * (optimumSearchTime / 2)
+ prevChanges * (optimumSearchTime / 3); + prevChanges * (optimumSearchTime / 3);
} }
void TimeManager::init(int myTime, int myInc, int movesToGo, int currentPly)
void TimeManager::init(const SearchLimits& limits, int currentPly)
{ {
/* We support four different kind of time controls: /* We support four different kind of time controls:
Inc == 0 && movesToGo == 0 means: x basetime [sudden death!] increment == 0 && movesToGo == 0 means: x basetime [sudden death!]
Inc == 0 && movesToGo != 0 means: (x moves) / (y minutes) increment == 0 && movesToGo != 0 means: x moves in y minutes
Inc > 0 && movesToGo == 0 means: x basetime + z inc. increment > 0 && movesToGo == 0 means: x basetime + z increment
Inc > 0 && movesToGo != 0 means: (x moves) / (y minutes) + z inc increment > 0 && movesToGo != 0 means: x moves in y minutes + z increment
Time management is adjusted by following UCI parameters: Time management is adjusted by following UCI parameters:
@ -121,14 +110,19 @@ void TimeManager::init(int myTime, int myInc, int movesToGo, int currentPly)
// Initialize to maximum values but unstablePVExtraTime that is reset // Initialize to maximum values but unstablePVExtraTime that is reset
unstablePVExtraTime = 0; unstablePVExtraTime = 0;
optimumSearchTime = maximumSearchTime = myTime; optimumSearchTime = maximumSearchTime = limits.time;
// We calculate optimum time usage for different hypothetic "moves to go"-values and choose the // We calculate optimum time usage for different hypothetic "moves to go"-values and choose the
// minimum of calculated search time values. Usually the greatest hypMTG gives the minimum values. // minimum of calculated search time values. Usually the greatest hypMTG gives the minimum values.
for (hypMTG = 1; hypMTG <= (movesToGo ? Min(movesToGo, MoveHorizon) : MoveHorizon); hypMTG++) for (hypMTG = 1; hypMTG <= (limits.movesToGo ? Min(limits.movesToGo, MoveHorizon) : MoveHorizon); hypMTG++)
{ {
// Calculate thinking time for hypothetic "moves to go"-value // Calculate thinking time for hypothetic "moves to go"-value
hypMyTime = Max(myTime + (hypMTG - 1) * myInc - emergencyBaseTime - Min(hypMTG, emergencyMoveHorizon) * emergencyMoveTime, 0); hypMyTime = limits.time
+ limits.increment * (hypMTG - 1)
- emergencyBaseTime
- emergencyMoveTime * Min(hypMTG, emergencyMoveHorizon);
hypMyTime = Max(hypMyTime, 0);
t1 = minThinkingTime + remaining<OptimumTime>(hypMyTime, hypMTG, currentPly); t1 = minThinkingTime + remaining<OptimumTime>(hypMyTime, hypMTG, currentPly);
t2 = minThinkingTime + remaining<MaxTime>(hypMyTime, hypMTG, currentPly); t2 = minThinkingTime + remaining<MaxTime>(hypMyTime, hypMTG, currentPly);
@ -144,9 +138,6 @@ void TimeManager::init(int myTime, int myInc, int movesToGo, int currentPly)
optimumSearchTime = Min(optimumSearchTime, maximumSearchTime); optimumSearchTime = Min(optimumSearchTime, maximumSearchTime);
} }
////
//// Local functions
////
namespace { namespace {

View file

@ -20,10 +20,12 @@
#if !defined(TIMEMAN_H_INCLUDED) #if !defined(TIMEMAN_H_INCLUDED)
#define TIMEMAN_H_INCLUDED #define TIMEMAN_H_INCLUDED
struct SearchLimits;
class TimeManager { class TimeManager {
public: public:
void init(int myTime, int myInc, int movesToGo, int currentPly); void init(const SearchLimits& limits, int currentPly);
void pv_instability(int curChanges, int prevChanges); void pv_instability(int curChanges, int prevChanges);
int available_time() const { return optimumSearchTime + unstablePVExtraTime; } int available_time() const { return optimumSearchTime + unstablePVExtraTime; }
int maximum_time() const { return maximumSearchTime; } int maximum_time() const { return maximumSearchTime; }

View file

@ -203,50 +203,48 @@ namespace {
bool go(Position& pos, UCIParser& up) { bool go(Position& pos, UCIParser& up) {
string token; string token;
Move searchMoves[MOVES_MAX]; int time[] = { 0, 0 }, inc[] = { 0, 0 };
int movesToGo, depth, nodes, moveTime, numOfMoves; SearchLimits limits(0, 0, 0, 0, 0, 0, false, false);
bool infinite, ponder; Move searchMoves[MOVES_MAX] = { MOVE_NONE };
int time[2] = {0, 0}, inc[2] = {0, 0}; Move* cur = searchMoves;
searchMoves[0] = MOVE_NONE;
infinite = ponder = false;
movesToGo = depth = nodes = moveTime = numOfMoves = 0;
while (up >> token) while (up >> token)
{ {
if (token == "infinite") if (token == "infinite")
infinite = true; limits.infinite = true;
else if (token == "ponder") else if (token == "ponder")
ponder = true; limits.ponder = true;
else if (token == "wtime") else if (token == "wtime")
up >> time[0]; up >> time[WHITE];
else if (token == "btime") else if (token == "btime")
up >> time[1]; up >> time[BLACK];
else if (token == "winc") else if (token == "winc")
up >> inc[0]; up >> inc[WHITE];
else if (token == "binc") else if (token == "binc")
up >> inc[1]; up >> inc[BLACK];
else if (token == "movestogo") else if (token == "movestogo")
up >> movesToGo; up >> limits.movesToGo;
else if (token == "depth") else if (token == "depth")
up >> depth; up >> limits.maxDepth;
else if (token == "nodes") else if (token == "nodes")
up >> nodes; up >> limits.maxNodes;
else if (token == "movetime") else if (token == "movetime")
up >> moveTime; up >> limits.maxTime;
else if (token == "searchmoves") else if (token == "searchmoves")
{ {
while (up >> token) while (up >> token)
searchMoves[numOfMoves++] = move_from_uci(pos, token); *cur++ = move_from_uci(pos, token);
searchMoves[numOfMoves] = MOVE_NONE; *cur = MOVE_NONE;
} }
} }
assert(pos.is_ok()); assert(pos.is_ok());
return think(pos, infinite, ponder, time, inc, movesToGo, limits.time = time[pos.side_to_move()];
depth, nodes, moveTime, searchMoves); limits.increment = inc[pos.side_to_move()];
return think(pos, limits, searchMoves);
} }
void perft(Position& pos, UCIParser& up) { void perft(Position& pos, UCIParser& up) {