const bool UseIIDAtPVNodes = true;
const bool UseIIDAtNonPVNodes = false;
- // Use null move driven internal iterative deepening?
- bool UseNullDrivenIID = false;
-
// Internal iterative deepening margin. At Non-PV moves, when
// UseIIDAtNonPVNodes is true, we do an internal iterative deepening search
// when the static evaluation is at most IIDMargin below beta.
// evaluation of the position is more than NullMoveMargin below beta.
const Value NullMoveMargin = Value(0x300);
- //Null move search refutes move when Nullvalue >= Beta - Delta. Index is depth
- //in full plies. Last index is 9+.
- const Value NullMoveDeltaMidgame[] =
- { Value(-8), Value( 6), Value(-15), Value( 9), Value(21),
- Value(34), Value(54), Value( 59), Value(61), Value(61) };
-
- const Value NullMoveDeltaEndgame[] =
- { Value( 6), Value( 0), Value(-13), Value(-9), Value(-35),
- Value(12), Value(24), Value( 9), Value( 5), Value( 5) };
-
// Pruning criterions. See the code and comments in ok_to_prune() to
// understand their precise meaning.
const bool PruneEscapeMoves = false;
if (UseLogFile)
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)");
UseFutilityPruning = get_option_value_bool("Futility Pruning (Main Search)");
Value approximateEval = quick_evaluate(pos);
bool mateThreat = false;
- bool nullDrivenIID = false;
bool isCheck = pos.is_check();
// Null move search
&& ok_to_do_nullmove(pos)
&& approximateEval >= beta - NullMoveMargin)
{
- //Calculate correct delta. Idea and tuning from Joona Kiiski.
- ScaleFactor factor[2] = { SCALE_FACTOR_NORMAL, SCALE_FACTOR_NORMAL };
- Phase phase = pos.game_phase();
- int i = Min(depth / OnePly, 9);
- Value delta = scale_by_game_phase(NullMoveDeltaMidgame[i], NullMoveDeltaEndgame[i], phase, factor);
-
ss[ply].currentMove = MOVE_NULL;
StateInfo st;
pos.do_null_move(st);
int R = (depth >= 4 * OnePly ? 4 : 3); // Null move dynamic reduction
- Value nullValue = -search(pos, ss, -(beta-delta-1), depth-R*OnePly, ply+1, false, threadID);
-
- // 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
- // later if we are really under threat.
- if ( UseNullDrivenIID
- && nullValue < beta
- && depth > 6 * OnePly
- &&!value_is_mate(nullValue)
- && ttMove == MOVE_NONE
- && ss[ply + 1].currentMove != MOVE_NONE
- && pos.move_is_capture(ss[ply + 1].currentMove)
- && pos.see(ss[ply + 1].currentMove) + nullValue >= beta)
- nullDrivenIID = true;
+ Value nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID);
pos.undo_null_move();
{
/* Do not return unproven mates */
}
- else if (nullValue >= beta - delta)
+ else if (nullValue >= beta)
{
if (depth < 6 * OnePly)
return beta;
// low score (which will cause the reduced move to fail high in the
// parent node, which will trigger a re-search with full depth).
if (nullValue == value_mated_in(ply + 2))
- {
mateThreat = true;
- nullDrivenIID = false;
- }
+
ss[ply].threatMove = ss[ply + 1].currentMove;
if ( depth < ThreatDepth
&& ss[ply - 1].reduction
search(pos, ss, beta, Min(depth/2, depth-2*OnePly), ply, false, threadID);
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 position should fail high. So do a normal search with a
- // reduced depth to get a good ttMove to use in the following full
- // depth search.
- Move tm = ss[ply].threatMove;
-
- assert(tm != MOVE_NONE);
- assert(ttMove == MOVE_NONE);
-
- search(pos, ss, beta, depth/2, ply, false, threadID);
- ttMove = ss[ply].pv[ply];
- ss[ply].threatMove = tm;
- }
// Initialize a MovePicker object for the current position, and prepare
// to search all moves: