From c172af1b6181b39288870689f912143c04a4040a Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Mon, 8 Dec 2008 10:46:52 +0100 Subject: [PATCH 1/1] 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 --- src/search.cpp | 60 +++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index ddcc851e..2a2e32f9 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -106,6 +106,9 @@ namespace { const bool UseIIDAtPVNodes = true; const bool UseIIDAtNonPVNodes = false; + // Use null move driven internal iterative deepening? + bool UseNullDrivenIID = true; + // 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. @@ -133,9 +136,6 @@ namespace { // evaluation of the position is more than NullMoveMargin below beta. 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 // understand their precise meaning. const bool PruneEscapeMoves = false; @@ -1127,13 +1127,13 @@ namespace { 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); } Value approximateEval = quick_evaluate(pos); bool mateThreat = false; - bool nullCapturePruning = false; + bool nullDrivenIID = false; bool isCheck = pos.is_check(); // Null move search @@ -1151,15 +1151,16 @@ namespace { 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 - // is above beta then mark the node as a suspicious failed low. We will verify - // later if we are really under threat. - if ( UseNullCapturePruning + // is above beta then there is a good possibility that this is a cut-node. + // We will do an IID later to find a ttMove. + if ( UseNullDrivenIID && nullValue < beta - && depth < 5 * OnePly + && depth > 6 * OnePly + && ttMove == MOVE_NONE && ss[ply + 1].currentMove != MOVE_NONE && pos.move_is_capture(ss[ply + 1].currentMove) - && pos.see(ss[ply + 1].currentMove) * PawnValueMidgame + nullValue > beta) - nullCapturePruning = true; + && pos.see(ss[ply + 1].currentMove) * PawnValueMidgame + nullValue > beta - IIDMargin) + nullDrivenIID = true; pos.undo_null_move(u); @@ -1180,33 +1181,15 @@ namespace { // 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 && connected_moves(pos, ss[ply - 1].currentMove, ss[ply].threatMove)) 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 @@ -1225,6 +1208,19 @@ namespace { 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 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 // to search all moves: -- 2.39.2