Compare commits

..

3 Commits

Author SHA1 Message Date
Marco Costalba
235df6a887 Stockfish 1.1a
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-12-08 12:03:46 +01:00
Marco Costalba
8d86c87e1e Add "Null driven IID" UCI option (default true)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-12-08 10:57:40 +01:00
Marco Costalba
c172af1b61 Null move driven internal iterative deepening
When a null move fails low due to a capture, try
to detect if without the capture we are above beta,
in this case there is a good possibility this is
a cut-node and the capture is just a null move
artifact due to side to move change. So if we still
don't have a TT move it's a good time to start an IID.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-12-08 10:46:52 +01:00
3 changed files with 31 additions and 33 deletions

View File

@@ -37,7 +37,7 @@
/// Version number. If this is left empty, the current date (in the format /// Version number. If this is left empty, the current date (in the format
/// YYMMDD) is used as a version number. /// YYMMDD) is used as a version number.
const std::string EngineVersion = "1.1"; const std::string EngineVersion = "1.1a";
//// ////

View File

@@ -106,6 +106,9 @@ namespace {
const bool UseIIDAtPVNodes = true; const bool UseIIDAtPVNodes = true;
const bool UseIIDAtNonPVNodes = false; const bool UseIIDAtNonPVNodes = false;
// Use null move driven internal iterative deepening?
bool UseNullDrivenIID = true;
// Internal iterative deepening margin. At Non-PV moves, when // Internal iterative deepening margin. At Non-PV moves, when
// UseIIDAtNonPVNodes is true, we do an internal iterative deepening search // UseIIDAtNonPVNodes is true, we do an internal iterative deepening search
// when the static evaluation is at most IIDMargin below beta. // when the static evaluation is at most IIDMargin below beta.
@@ -133,9 +136,6 @@ namespace {
// evaluation of the position is more than NullMoveMargin below beta. // evaluation of the position is more than NullMoveMargin below beta.
const Value NullMoveMargin = Value(0x300); const Value NullMoveMargin = Value(0x300);
// Use null capture pruning?
const bool UseNullCapturePruning = false;
// Pruning criterions. See the code and comments in ok_to_prune() to // Pruning criterions. See the code and comments in ok_to_prune() to
// understand their precise meaning. // understand their precise meaning.
const bool PruneEscapeMoves = false; const bool PruneEscapeMoves = false;
@@ -393,6 +393,7 @@ void think(const Position &pos, bool infinite, bool ponder, int side_to_move,
if (UseLogFile) if (UseLogFile)
LogFile.open(get_option_value_string("Search Log Filename").c_str(), std::ios::out | std::ios::app); LogFile.open(get_option_value_string("Search Log Filename").c_str(), std::ios::out | std::ios::app);
UseNullDrivenIID = get_option_value_bool("Null driven IID");
UseQSearchFutilityPruning = get_option_value_bool("Futility Pruning (Quiescence Search)"); UseQSearchFutilityPruning = get_option_value_bool("Futility Pruning (Quiescence Search)");
UseFutilityPruning = get_option_value_bool("Futility Pruning (Main Search)"); UseFutilityPruning = get_option_value_bool("Futility Pruning (Main Search)");
@@ -1127,13 +1128,13 @@ namespace {
if (tte && ok_to_use_TT(tte, depth, beta, ply)) if (tte && ok_to_use_TT(tte, depth, beta, ply))
{ {
ss[ply].currentMove = ttMove; // can be MOVE_NONE ? ss[ply].currentMove = ttMove; // can be MOVE_NONE
return value_from_tt(tte->value(), ply); return value_from_tt(tte->value(), ply);
} }
Value approximateEval = quick_evaluate(pos); Value approximateEval = quick_evaluate(pos);
bool mateThreat = false; bool mateThreat = false;
bool nullCapturePruning = false; bool nullDrivenIID = false;
bool isCheck = pos.is_check(); bool isCheck = pos.is_check();
// Null move search // Null move search
@@ -1151,15 +1152,16 @@ namespace {
Value nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID); Value nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID);
// Check for a null capture artifact, if the value without the null capture // Check for a null capture artifact, if the value without the null capture
// is above beta then mark the node as a suspicious failed low. We will verify // is above beta then there is a good possibility that this is a cut-node.
// later if we are really under threat. // We will do an IID later to find a ttMove.
if ( UseNullCapturePruning if ( UseNullDrivenIID
&& nullValue < beta && nullValue < beta
&& depth < 5 * OnePly && depth > 6 * OnePly
&& ttMove == MOVE_NONE
&& ss[ply + 1].currentMove != MOVE_NONE && ss[ply + 1].currentMove != MOVE_NONE
&& pos.move_is_capture(ss[ply + 1].currentMove) && pos.move_is_capture(ss[ply + 1].currentMove)
&& pos.see(ss[ply + 1].currentMove) * PawnValueMidgame + nullValue > beta) && pos.see(ss[ply + 1].currentMove) * PawnValueMidgame + nullValue > beta - IIDMargin)
nullCapturePruning = true; nullDrivenIID = true;
pos.undo_null_move(u); pos.undo_null_move(u);
@@ -1180,33 +1182,15 @@ namespace {
// low score (which will cause the reduced move to fail high in the // low score (which will cause the reduced move to fail high in the
// parent node, which will trigger a re-search with full depth). // parent node, which will trigger a re-search with full depth).
if (nullValue == value_mated_in(ply + 2)) if (nullValue == value_mated_in(ply + 2))
{
mateThreat = true; mateThreat = true;
nullDrivenIID = false;
}
ss[ply].threatMove = ss[ply + 1].currentMove; ss[ply].threatMove = ss[ply + 1].currentMove;
if ( depth < ThreatDepth if ( depth < ThreatDepth
&& ss[ply - 1].reduction && ss[ply - 1].reduction
&& connected_moves(pos, ss[ply - 1].currentMove, ss[ply].threatMove)) && connected_moves(pos, ss[ply - 1].currentMove, ss[ply].threatMove))
return beta - 1; return beta - 1;
if (nullCapturePruning && !mateThreat)
{
// The null move failed low due to a suspicious capture. Verify if
// position is really dangerous or we are facing a null capture
// artifact due to the side to move change. So search this
// position with a reduced depth and see if we still fail low.
Move tm = ss[ply].threatMove;
assert(tm != MOVE_NONE);
Value v = search(pos, ss, beta, depth-3*OnePly, ply, false, threadID);
if (v >= beta)
return beta;
// Restore stack and update ttMove if was empty
ss[ply].threatMove = tm;
if (ttMove == MOVE_NONE)
ttMove = ss[ply].pv[ply];
}
} }
} }
// Null move search not allowed, try razoring // Null move search not allowed, try razoring
@@ -1225,6 +1209,19 @@ namespace {
search(pos, ss, beta, Min(depth/2, depth-2*OnePly), ply, false, threadID); search(pos, ss, beta, Min(depth/2, depth-2*OnePly), ply, false, threadID);
ttMove = ss[ply].pv[ply]; ttMove = ss[ply].pv[ply];
} }
else if (nullDrivenIID)
{
// The null move failed low due to a suspicious capture. Perhaps we
// are facing a null capture artifact due to the side to move change
// and this is a cut-node. So it's a good time to search for a ttMove.
Move tm = ss[ply].threatMove;
assert(tm != MOVE_NONE);
search(pos, ss, beta, Min(depth/2, depth-3*OnePly), ply, false, threadID);
ttMove = ss[ply].pv[ply];
ss[ply].threatMove = tm;
}
// Initialize a MovePicker object for the current position, and prepare // Initialize a MovePicker object for the current position, and prepare
// to search all moves: // to search all moves:

View File

@@ -120,6 +120,7 @@ namespace {
o.push_back(Option("Full Depth Moves (non-PV nodes)", 3, 1, 100)); o.push_back(Option("Full Depth Moves (non-PV nodes)", 3, 1, 100));
o.push_back(Option("Threat Depth", 5, 0, 100)); o.push_back(Option("Threat Depth", 5, 0, 100));
o.push_back(Option("Selective Plies", 7, 0, 10)); o.push_back(Option("Selective Plies", 7, 0, 10));
o.push_back(Option("Null driven IID", true));
o.push_back(Option("Futility Pruning (Main Search)", true)); o.push_back(Option("Futility Pruning (Main Search)", true));
o.push_back(Option("Futility Pruning (Quiescence Search)", true)); o.push_back(Option("Futility Pruning (Quiescence Search)", true));
o.push_back(Option("Futility Margin 0", 50, 0, 1000)); o.push_back(Option("Futility Margin 0", 50, 0, 1000));