From: Miguel Lahoz Date: Sat, 5 Jan 2019 20:53:21 +0000 (+0800) Subject: Introduce Multi-Cut X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=f69106f7bb82f97ba07fb06a31395039d08af9f4 Introduce Multi-Cut This was inspired after reading about [Multi-Cut](https://www.chessprogramming.org/Multi-Cut). We now do non-singular cut node pruning. The idea is to prune when we have a "backup plan" in case our expected fail high node does not fail high on the ttMove. For singular extensions, we do a search on all other moves but the ttMove. If this fails high on our original beta, this means that both the ttMove, as well as at least one other move was proven to fail high on a lower depth search. We then assume that one of these moves will work on a higher depth and prune. STC: LLR: 2.96 (-2.94,2.94) [0.50,4.50] Total: 72952 W: 16104 L: 15583 D: 41265 http://tests.stockfishchess.org/tests/view/5c3119640ebc596a450c0be5 LTC: LLR: 2.95 (-2.94,2.94) [0.00,3.50] Total: 27103 W: 4564 L: 4314 D: 18225 http://tests.stockfishchess.org/tests/view/5c3184c00ebc596a450c1662 Bench: 3145487 --- diff --git a/src/search.cpp b/src/search.cpp index fe9b446e..c8e6c8b6 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -943,13 +943,21 @@ moves_loop: // When in check, search starts from here && tte->depth() >= depth - 3 * ONE_PLY && pos.legal(move)) { - Value reducedBeta = std::max(ttValue - 2 * depth / ONE_PLY, -VALUE_MATE); + Value singularBeta = std::max(ttValue - 2 * depth / ONE_PLY, -VALUE_MATE); ss->excludedMove = move; - value = search(pos, ss, reducedBeta - 1, reducedBeta, depth / 2, cutNode); + value = search(pos, ss, singularBeta - 1, singularBeta, depth / 2, cutNode); ss->excludedMove = MOVE_NONE; - if (value < reducedBeta) + if (value < singularBeta) extension = ONE_PLY; + + // Multi-cut pruning + // Our ttMove is assumed to fail high, and now we failed high also on a reduced + // search without the ttMove. So we assume this expected Cut-node is not singular, + // that is multiple moves fail high, and we can prune the whole subtree by returning + // the hard beta bound. + else if (cutNode && singularBeta > beta) + return beta; } else if ( givesCheck // Check extension (~2 Elo) && pos.see_ge(move))