// better than the second best move.
const Value EasyMoveMargin = Value(0x200);
- // Problem margin. If the score of the first move at iteration N+1 has
- // dropped by more than this since iteration N, the boolean variable
- // "Problem" is set to true, which will make the program spend some extra
- // time looking for a better move.
- const Value ProblemMargin = Value(0x28);
-
- // No problem margin. If the boolean "Problem" is true, and a new move
- // is found at the root which is less than NoProblemMargin worse than the
- // best move from the previous iteration, Problem is set back to false.
- const Value NoProblemMargin = Value(0x14);
-
// Null move margin. A null move search will not be done if the static
// evaluation of the position is more than NullMoveMargin below beta.
const Value NullMoveMargin = Value(0x200);
int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime;
bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit;
bool AbortSearch, Quit;
- bool FailHigh, FailLow, Problem;
+ bool FailLow;
// Show current line?
bool ShowCurrentLine;
void update_killers(Move m, SearchStack& ss);
void update_gains(const Position& pos, Move move, Value before, Value after);
- bool fail_high_ply_1();
int current_search_time();
int nps();
void poll();
// Initialize global search variables
Idle = StopOnPonderhit = AbortSearch = Quit = false;
- FailHigh = FailLow = Problem = false;
+ FailLow = false;
NodesSincePoll = 0;
SearchStartTime = get_system_time();
ExactMaxTime = maxTime;
for (int i = 0; i < THREAD_MAX; i++)
{
Threads[i].nodes = 0ULL;
- Threads[i].failHighPly1 = false;
}
if (button_was_pressed("New Game"))
if (ss[0].pv[0] != EasyMove)
EasyMove = MOVE_NONE;
- Problem = false;
-
if (UseTimeManagement)
{
// Time to stop?
}
RootMoveNumber = i + 1;
- FailHigh = false;
// Save the current node count before the move is searched
nodes = nodes_searched();
alpha = -VALUE_INFINITE;
value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
-
- // If the value has dropped a lot compared to the last iteration,
- // set the boolean variable Problem to true. This variable is used
- // for time managment: When Problem is true, we try to complete the
- // current iteration before playing a move.
- Problem = ( Iteration >= 2
- && value <= ValueByIteration[Iteration - 1] - ProblemMargin);
-
- if (Problem && StopOnPonderhit)
- StopOnPonderhit = false;
}
else
{
value = -search(pos, ss, -alpha, newDepth, 1, true, 0);
if (value > alpha)
- {
- // Fail high! Set the boolean variable FailHigh to true, and
- // re-search the move using a PV search. The variable FailHigh
- // is used for time managment: We try to avoid aborting the
- // search prematurely during a fail high research.
- FailHigh = true;
value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
- }
}
}
}
if (value > alpha)
alpha = value;
-
- // Reset the global variable Problem to false if the value isn't too
- // far below the final value from the last iteration.
- if (value > ValueByIteration[Iteration - 1] - NoProblemMargin)
- Problem = false;
}
else // MultiPV > 1
{
assert(alpha >= oldAlpha);
FailLow = (alpha == oldAlpha);
+
+ if (FailLow && StopOnPonderhit)
+ StopOnPonderhit = false;
}
// Can we exit fail low loop ?
ss[ply].reduction = Depth(0);
value = -search(pos, ss, -alpha, newDepth, ply+1, true, threadID);
if (value > alpha && value < beta)
- {
- // When the search fails high at ply 1 while searching the first
- // move at the root, set the flag failHighPly1. This is used for
- // time managment: We don't want to stop the search early in
- // such cases, because resolving the fail high at ply 1 could
- // result in a big drop in score at the root.
- if (ply == 1 && RootMoveNumber == 1)
- Threads[threadID].failHighPly1 = true;
-
- // A fail high occurred. Re-search at full window (pv search)
value = -search_pv(pos, ss, -beta, -alpha, newDepth, ply+1, threadID);
- Threads[threadID].failHighPly1 = false;
- }
}
}
pos.undo_move(move);
if (value == value_mate_in(ply + 1))
ss[ply].mateKiller = move;
}
- // If we are at ply 1, and we are searching the first root move at
- // ply 0, set the 'Problem' variable if the score has dropped a lot
- // (from the computer's point of view) since the previous iteration.
- if ( ply == 1
- && Iteration >= 2
- && -value <= ValueByIteration[Iteration-1] - ProblemMargin)
- Problem = true;
}
// Split?
if (value > localAlpha && value < sp->beta)
{
- // When the search fails high at ply 1 while searching the first
- // move at the root, set the flag failHighPly1. This is used for
- // time managment: We don't want to stop the search early in
- // such cases, because resolving the fail high at ply 1 could
- // result in a big drop in score at the root.
- if (sp->ply == 1 && RootMoveNumber == 1)
- Threads[threadID].failHighPly1 = true;
-
// If another thread has failed high then sp->alpha has been increased
// to be higher or equal then beta, if so, avoid to start a PV search.
localAlpha = sp->alpha;
value = -search_pv(pos, ss, -sp->beta, -localAlpha, newDepth, sp->ply+1, threadID);
else
assert(thread_should_stop(threadID));
-
- Threads[threadID].failHighPly1 = false;
}
}
pos.undo_move(move);
if (value == value_mate_in(sp->ply + 1))
ss[sp->ply].mateKiller = move;
}
- // If we are at ply 1, and we are searching the first root move at
- // ply 0, set the 'Problem' variable if the score has dropped a lot
- // (from the computer's point of view) since the previous iteration.
- if ( sp->ply == 1
- && Iteration >= 2
- && -value <= ValueByIteration[Iteration-1] - ProblemMargin)
- Problem = true;
}
lock_release(&(sp->lock));
}
}
- // fail_high_ply_1() checks if some thread is currently resolving a fail
- // high at ply 1 at the node below the first root node. This information
- // is used for time management.
-
- bool fail_high_ply_1() {
-
- for (int i = 0; i < ActiveThreads; i++)
- if (Threads[i].failHighPly1)
- return true;
-
- return false;
- }
-
-
// current_search_time() returns the number of milliseconds which have passed
// since the beginning of the current search.