along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "search.h"
+
#include <algorithm>
+#include <array>
+#include <atomic>
#include <cassert>
#include <cmath>
-#include <cstring> // For std::memset
+#include <cstdlib>
+#include <cstring>
+#include <initializer_list>
#include <iostream>
#include <sstream>
+#include <string>
+#include <utility>
+#include "bitboard.h"
#include "evaluate.h"
#include "misc.h"
#include "movegen.h"
#include "movepick.h"
+#include "nnue/evaluate_nnue.h"
+#include "nnue/nnue_common.h"
#include "position.h"
-#include "search.h"
+#include "syzygy/tbprobe.h"
#include "thread.h"
#include "timeman.h"
#include "tt.h"
#include "uci.h"
-#include "syzygy/tbprobe.h"
-#include "nnue/evaluate_nnue.h"
namespace Stockfish {
int Reductions[MAX_MOVES]; // [depth or moveNumber]
Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) {
- int r = Reductions[d] * Reductions[mn];
- return (r + 1372 - int(delta) * 1073 / int(rootDelta)) / 1024 + (!i && r > 936);
+ int reductionScale = Reductions[d] * Reductions[mn];
+ return (reductionScale + 1372 - int(delta) * 1073 / int(rootDelta)) / 1024
+ + (!i && reductionScale > 936);
}
constexpr int futility_move_count(bool improving, Depth depth) {
// Check if we have an upcoming move that draws by repetition, or
// if the opponent had an alternative move earlier to this position.
if ( !rootNode
- && pos.rule50_count() >= 3
&& alpha < VALUE_DRAW
&& pos.has_game_cycle(ss->ply))
{
// Decrease further on cutNodes. (~1 Elo)
if ( ss->ttPv
&& !likelyFailLow)
- r -= cutNode && tte->depth() >= depth + 3 ? 3 : 2;
+ r -= cutNode && tte->depth() >= depth ? 3 : 2;
// Decrease reduction if opponent's move count is high (~1 Elo)
if ((ss-1)->moveCount > 8)
// Decrease reduction if ttMove has been singularly extended (~1 Elo)
if (singularQuietLMR)
r--;
-
+
// Increase reduction on repetition (~1 Elo)
if ( move == (ss-4)->currentMove
&& pos.has_repeated())
// Check if we have an upcoming move that draws by repetition, or
// if the opponent had an alternative move earlier to this position.
if ( depth < 0
- && pos.rule50_count() >= 3
&& alpha < VALUE_DRAW
&& pos.has_game_cycle(ss->ply))
{
futilityValue = futilityBase + PieceValue[pos.piece_on(to_sq(move))];
+ // If static eval + value of piece we are going to capture is much lower
+ // than alpha we can prune this move
if (futilityValue <= alpha)
{
bestValue = std::max(bestValue, futilityValue);
continue;
}
+ // If static eval is much lower than alpha and move is not winning material
+ // we can prune this move
if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1))
{
bestValue = std::max(bestValue, futilityBase);
continue;
}
+
+ // If static exchange evaluation is much worse than what is needed to not
+ // fall below alpha we can prune this move
+ if (futilityBase > alpha && !pos.see_ge(move, (alpha - futilityBase) * 4))
+ {
+ bestValue = alpha;
+ continue;
+ }
}
// We prune after the second quiet check evasion move, where being 'in check' is