Skip to content

Commit

Permalink
Fix sending of best move during an infinite search
Browse files Browse the repository at this point in the history
According to UCI standard once engine receives 'go infinite'
command it should search until the "stop" command and do not exit
the search without being told so, even if PLY_MAX has been reached.

Patch is quite invasive because it cleanups some hacks used
by fixed depth and fixed nodes modes, mainly during benchmarks.

Bug found by Pascal Georges.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
  • Loading branch information
mcostalba committed Jan 10, 2010
1 parent 968c3de commit 55745f4
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 53 deletions.
2 changes: 1 addition & 1 deletion src/benchmark.cpp
Expand Up @@ -155,7 +155,7 @@ void benchmark(const string& commandLine) {
cerr << "\nBench position: " << cnt << '/' << positions.size() << endl << endl; cerr << "\nBench position: " << cnt << '/' << positions.size() << endl << endl;
if (limitType == "perft") if (limitType == "perft")
totalNodes += perft(pos, maxDepth * OnePly); totalNodes += perft(pos, maxDepth * OnePly);
else if (!think(pos, true, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves)) else if (!think(pos, false, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves))
break; break;
totalNodes += nodes_searched(); totalNodes += nodes_searched();
} }
Expand Down
101 changes: 49 additions & 52 deletions src/search.cpp
Expand Up @@ -231,7 +231,7 @@ namespace {
int SearchStartTime; int SearchStartTime;
int MaxNodes, MaxDepth; int MaxNodes, MaxDepth;
int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime; int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime;
bool InfiniteSearch, PonderSearch, StopOnPonderhit; bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit;
bool AbortSearch, Quit; bool AbortSearch, Quit;
bool FailHigh, FailLow, Problem; bool FailHigh, FailLow, Problem;


Expand Down Expand Up @@ -373,8 +373,20 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
int time[], int increment[], int movesToGo, int maxDepth, int time[], int increment[], int movesToGo, int maxDepth,
int maxNodes, int maxTime, Move searchMoves[]) { int maxNodes, int maxTime, Move searchMoves[]) {


// Look for a book move // Initialize global search variables
if (!infinite && !ponder && get_option_value_bool("OwnBook")) Idle = StopOnPonderhit = AbortSearch = Quit = false;
FailHigh = FailLow = Problem = false;
NodesSincePoll = 0;
SearchStartTime = get_system_time();
ExactMaxTime = maxTime;
MaxDepth = maxDepth;
MaxNodes = maxNodes;
InfiniteSearch = infinite;
PonderSearch = ponder;
UseTimeManagement = !ExactMaxTime && !MaxDepth && !MaxNodes && !InfiniteSearch;

// Look for a book move, only during games, not tests
if (UseTimeManagement && !ponder && get_option_value_bool("OwnBook"))
{ {
Move bookMove; Move bookMove;
if (get_option_value_string("Book File") != OpeningBook.file_name()) if (get_option_value_string("Book File") != OpeningBook.file_name())
Expand All @@ -388,15 +400,6 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
} }
} }


// Initialize global search variables
Idle = StopOnPonderhit = AbortSearch = Quit = false;
FailHigh = FailLow = Problem = false;
SearchStartTime = get_system_time();
ExactMaxTime = maxTime;
NodesSincePoll = 0;
InfiniteSearch = infinite;
PonderSearch = ponder;

for (int i = 0; i < THREAD_MAX; i++) for (int i = 0; i < THREAD_MAX; i++)
{ {
Threads[i].nodes = 0ULL; Threads[i].nodes = 0ULL;
Expand Down Expand Up @@ -464,51 +467,45 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
// Set thinking time // Set thinking time
int myTime = time[side_to_move]; int myTime = time[side_to_move];
int myIncrement = increment[side_to_move]; int myIncrement = increment[side_to_move];

if (UseTimeManagement)
if (!movesToGo) // Sudden death time control
{ {
if (myIncrement) if (!movesToGo) // Sudden death time control
{
MaxSearchTime = myTime / 30 + myIncrement;
AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
}
else // Blitz game without increment
{ {
MaxSearchTime = myTime / 30; if (myIncrement)
AbsoluteMaxSearchTime = myTime / 8; {
MaxSearchTime = myTime / 30 + myIncrement;
AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
}
else // Blitz game without increment
{
MaxSearchTime = myTime / 30;
AbsoluteMaxSearchTime = myTime / 8;
}
} }
} else // (x moves) / (y minutes)
else // (x moves) / (y minutes)
{
if (movesToGo == 1)
{ {
MaxSearchTime = myTime / 2; if (movesToGo == 1)
AbsoluteMaxSearchTime = (myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4); {
MaxSearchTime = myTime / 2;
AbsoluteMaxSearchTime = (myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4);
}
else
{
MaxSearchTime = myTime / Min(movesToGo, 20);
AbsoluteMaxSearchTime = Min((4 * myTime) / movesToGo, myTime / 3);
}
} }
else
if (PonderingEnabled)
{ {
MaxSearchTime = myTime / Min(movesToGo, 20); MaxSearchTime += MaxSearchTime / 4;
AbsoluteMaxSearchTime = Min((4 * myTime) / movesToGo, myTime / 3); MaxSearchTime = Min(MaxSearchTime, AbsoluteMaxSearchTime);
} }
} }


if (PonderingEnabled) // Set best NodesBetweenPolls interval
{
MaxSearchTime += MaxSearchTime / 4;
MaxSearchTime = Min(MaxSearchTime, AbsoluteMaxSearchTime);
}

// Fixed depth or fixed number of nodes?
MaxDepth = maxDepth;
if (MaxDepth)
InfiniteSearch = true; // HACK

MaxNodes = maxNodes;
if (MaxNodes) if (MaxNodes)
{
NodesBetweenPolls = Min(MaxNodes, 30000); NodesBetweenPolls = Min(MaxNodes, 30000);
InfiniteSearch = true; // HACK
}
else if (myTime && myTime < 1000) else if (myTime && myTime < 1000)
NodesBetweenPolls = 1000; NodesBetweenPolls = 1000;
else if (myTime && myTime < 5000) else if (myTime && myTime < 5000)
Expand Down Expand Up @@ -791,7 +788,7 @@ namespace {


Problem = false; Problem = false;


if (!InfiniteSearch) if (UseTimeManagement)
{ {
// Time to stop? // Time to stop?
bool stopSearch = false; bool stopSearch = false;
Expand Down Expand Up @@ -845,9 +842,9 @@ namespace {


rml.sort(); rml.sort();


// If we are pondering, we shouldn't print the best move before we // If we are pondering or in infinite search, we shouldn't print the
// are told to do so // best move before we are told to do so.
if (PonderSearch) if (PonderSearch || InfiniteSearch)
wait_for_stop_or_ponderhit(); wait_for_stop_or_ponderhit();
else else
// Print final search statistics // Print final search statistics
Expand Down Expand Up @@ -2680,7 +2677,7 @@ namespace {
|| stillAtFirstMove //FIXME: We are not checking any problem flags, BUG? || stillAtFirstMove //FIXME: We are not checking any problem flags, BUG?
|| noProblemFound; || noProblemFound;


if ( (Iteration >= 3 && !InfiniteSearch && noMoreTime) if ( (Iteration >= 3 && UseTimeManagement && noMoreTime)
|| (ExactMaxTime && t >= ExactMaxTime) || (ExactMaxTime && t >= ExactMaxTime)
|| (Iteration >= 3 && MaxNodes && nodes_searched() >= MaxNodes)) || (Iteration >= 3 && MaxNodes && nodes_searched() >= MaxNodes))
AbortSearch = true; AbortSearch = true;
Expand Down Expand Up @@ -2710,7 +2707,7 @@ namespace {
|| stillAtFirstMove || stillAtFirstMove
|| noProblemFound; || noProblemFound;


if (Iteration >= 3 && !InfiniteSearch && (noMoreTime || StopOnPonderhit)) if (Iteration >= 3 && UseTimeManagement && (noMoreTime || StopOnPonderhit))
AbortSearch = true; AbortSearch = true;
} }


Expand Down

0 comments on commit 55745f4

Please sign in to comment.