return Value((175 - 50 * improving) * d / ONE_PLY);
}
- // Futility and reductions lookup tables, initialized at startup
- int FutilityMoveCounts[2][16]; // [improving][depth]
- int Reductions[2][64][64]; // [improving][depth][moveNumber]
+ // Reductions lookup table, initialized at startup
+ int Reductions[64]; // [depth or moveNumber]
template <bool PvNode> Depth reduction(bool i, Depth d, int mn) {
- return (Reductions[i][std::min(d / ONE_PLY, 63)][std::min(mn, 63)] - PvNode) * ONE_PLY;
+ int r = Reductions[std::min(d / ONE_PLY, 63)] * Reductions[std::min(mn, 63)] / 1024;
+ return ((r + 512) / 1024 + (!i && r > 1024) - PvNode) * ONE_PLY;
+ }
+
+ constexpr int futility_move_count(bool improving, int depth) {
+ return (5 + depth * depth) * (1 + improving) / 2;
}
// History and stats update bonus, based on depth
void Search::init() {
- for (int imp = 0; imp <= 1; ++imp)
- for (int d = 1; d < 64; ++d)
- for (int mc = 1; mc < 64; ++mc)
- {
- double r = log(d) * log(mc) / 1.95;
-
- Reductions[imp][d][mc] = std::round(r);
-
- // Increase reduction for non-PV nodes when eval is not improving
- if (!imp && r > 1.0)
- Reductions[imp][d][mc]++;
- }
-
- for (int d = 0; d < 16; ++d)
- {
- FutilityMoveCounts[0][d] = int(2.4 + 0.74 * pow(d, 1.78));
- FutilityMoveCounts[1][d] = int(5.0 + 1.00 * pow(d, 2.00));
- }
+ for (int i = 1; i < 64; ++i)
+ Reductions[i] = int(1024 * std::log(i) / std::sqrt(1.95));
}
// Perform a preliminary qsearch to verify that the move holds
value = -qsearch<NonPV>(pos, ss+1, -raisedBeta, -raisedBeta+1);
- // If the qsearch held perform the regular search
+ // If the qsearch held, perform the regular search
if (value >= raisedBeta)
value = -search<NonPV>(pos, ss+1, -raisedBeta, -raisedBeta+1, depth - 4 * ONE_PLY, !cutNode);
&& move == ttMove
&& !rootNode
&& !excludedMove // Avoid recursive singular search
- && ttValue != VALUE_NONE
+ /* && ttValue != VALUE_NONE Already implicit in the next condition */
+ && abs(ttValue) < VALUE_KNOWN_WIN
&& (tte->bound() & BOUND_LOWER)
&& tte->depth() >= depth - 3 * ONE_PLY
&& pos.legal(move))
{
- Value singularBeta = std::max(ttValue - 2 * depth / ONE_PLY, -VALUE_MATE);
+ Value singularBeta = ttValue - 2 * depth / ONE_PLY;
ss->excludedMove = move;
value = search<NonPV>(pos, ss, singularBeta - 1, singularBeta, depth / 2, cutNode);
ss->excludedMove = MOVE_NONE;
&& bestValue > VALUE_MATED_IN_MAX_PLY)
{
// Skip quiet moves if movecount exceeds our FutilityMoveCount threshold
- moveCountPruning = depth < 16 * ONE_PLY
- && moveCount >= FutilityMoveCounts[improving][depth / ONE_PLY];
+ moveCountPruning = moveCount >= futility_move_count(improving,depth / ONE_PLY);
if ( !captureOrPromotion
&& !givesCheck