1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-29 16:23:09 +00:00

Rewrite early stop logic

In the "easy move" paradigm we verify if the best move has
ever changed over a good number of iterations and if the
biggest part of the searched nodes are consumed on it.
This is a kind of hacky ad indirect heuristic to deduce
if one move is much better than others.

Rewrite the early stop condition to verify directly if one
move is much better than others performing an exclusion
search.

Idea to use exclusion search for time management if form Critter.

After 12245 games at 30"+0.1
Mod vs Orig 1776 - 1775 - 8694 ELO +0 (+-3.4)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba 2011-10-08 13:01:18 +01:00
parent b56a098cfb
commit 35fa4fc71f

View file

@ -150,7 +150,7 @@ namespace {
// Easy move margin. An easy move candidate must be at least this much
// better than the second best move.
const Value EasyMoveMargin = Value(0x200);
const Value EasyMoveMargin = Value(0x150);
/// Namespace variables
@ -497,13 +497,14 @@ namespace {
int bestMoveChanges[PLY_MAX_PLUS_2];
int depth, aspirationDelta;
Value bestValue, alpha, beta;
Move bestMove, easyMove, skillBest, skillPonder;
Move bestMove, skillBest, skillPonder;
bool bestMoveNeverChanged = true;
// Initialize stuff before a new search
memset(ss, 0, 4 * sizeof(SearchStack));
TT.new_search();
H.clear();
*ponderMove = bestMove = easyMove = skillBest = skillPonder = MOVE_NONE;
*ponderMove = bestMove = skillBest = skillPonder = MOVE_NONE;
depth = aspirationDelta = 0;
bestValue = alpha = -VALUE_INFINITE, beta = VALUE_INFINITE;
ss->currentMove = MOVE_NULL; // Hack to skip update gains
@ -643,25 +644,16 @@ namespace {
log << pretty_pv(pos, depth, bestValue, elapsed_search_time(), &Rml[0].pv[0]) << endl;
}
// Init easyMove at first iteration or drop it if differs from the best move
if (depth == 1 && (Rml.size() == 1 || Rml[0].score > Rml[1].score + EasyMoveMargin))
easyMove = bestMove;
else if (bestMove != easyMove)
easyMove = MOVE_NONE;
// Filter out startup noise when monitoring best move stability
if (depth > 2 && bestMoveChanges[depth])
bestMoveNeverChanged = false;
// Check for some early stop condition
if (!StopRequest && Limits.useTimeManagement())
{
// Easy move: Stop search early if one move seems to be much better
// than the others or if there is only a single legal move. Also in
// the latter case search to some depth anyway to get a proper score.
if ( depth >= 7
&& easyMove == bestMove
&& ( Rml.size() == 1
||( Rml[0].nodes > (pos.nodes_searched() * 85) / 100
&& elapsed_search_time() > TimeMgr.available_time() / 16)
||( Rml[0].nodes > (pos.nodes_searched() * 98) / 100
&& elapsed_search_time() > TimeMgr.available_time() / 32)))
// Stop search early if there is only a single legal move. Search to
// some depth anyway to get a proper score.
if (Rml.size() == 1 && depth >= 7)
StopRequest = true;
// Take in account some extra time if the best move has changed
@ -673,6 +665,23 @@ namespace {
if (elapsed_search_time() > (TimeMgr.available_time() * 62) / 100)
StopRequest = true;
// Stop search early if one move seems to be much better than others
if ( depth >= 10
&& !StopRequest
&& ( bestMoveNeverChanged
|| elapsed_search_time() > (TimeMgr.available_time() * 40) / 100))
{
Value rBeta = bestValue - EasyMoveMargin;
(ss+1)->excludedMove = bestMove;
(ss+1)->skipNullMove = true;
Value v = search<NonPV>(pos, ss+1, rBeta - 1, rBeta, (depth * ONE_PLY) / 2);
(ss+1)->skipNullMove = false;
(ss+1)->excludedMove = MOVE_NONE;
if (v < rBeta)
StopRequest = true;
}
// If we are allowed to ponder do not stop the search now but keep pondering
if (StopRequest && Limits.ponder)
{
@ -1027,8 +1036,7 @@ split_point_start: // At split points actual search starts from here
<< " currmovenumber " << moveCount + MultiPVIdx << endl;
}
// At Root and at first iteration do a PV search on all the moves to score root moves
isPvMove = (PvNode && moveCount <= (RootNode && depth <= ONE_PLY ? MAX_MOVES : 1));
isPvMove = (PvNode && moveCount <= 1);
givesCheck = pos.move_gives_check(move, ci);
captureOrPromotion = pos.is_capture_or_promotion(move);