beta = std::min(mate_in(ss->ply+1), beta);
if (alpha >= beta)
return alpha;
+
+ // Check if there exists a move which draws by repetition, or an alternative
+ // earlier move to this position.
+ if ( pos.rule50_count() >= 3
+ && alpha < VALUE_DRAW
+ && pos.has_game_cycle(ss->ply))
+ {
+ alpha = VALUE_DRAW;
+ if (alpha >= beta)
+ return alpha;
+ }
}
assert(0 <= ss->ply && ss->ply < MAX_PLY);
}
}
- // Step 6. Evaluate the position statically
+ // Step 6. Static evaluation of the position
if (inCheck)
{
ss->staticEval = eval = VALUE_NONE;
improving = false;
- goto moves_loop;
+ goto moves_loop; // Skip early pruning when in check
}
else if (ttHit)
{
ss->staticEval, TT.generation());
}
- improving = ss->staticEval >= (ss-2)->staticEval
- ||(ss-2)->staticEval == VALUE_NONE;
-
- if (ss->excludedMove || !pos.non_pawn_material(pos.side_to_move()))
- goto moves_loop;
-
- // Step 7. Razoring (skipped when in check, ~2 Elo)
+ // Step 7. Razoring (~2 Elo)
if ( !PvNode
&& depth < 3 * ONE_PLY
&& eval <= alpha - RazorMargin[depth / ONE_PLY])
return v;
}
- // Step 8. Futility pruning: child node (skipped when in check, ~30 Elo)
+ improving = ss->staticEval >= (ss-2)->staticEval
+ || (ss-2)->staticEval == VALUE_NONE;
+
+ // Step 8. Futility pruning: child node (~30 Elo)
if ( !rootNode
&& depth < 7 * ONE_PLY
&& eval - futility_margin(depth, improving) >= beta
// Step 9. Null move search with verification search (~40 Elo)
if ( !PvNode
&& (ss-1)->currentMove != MOVE_NULL
- && (ss-1)->statScore < 30000
+ && (ss-1)->statScore < 22500
&& eval >= beta
&& ss->staticEval >= beta - 36 * depth / ONE_PLY + 225
+ && !excludedMove
+ && pos.non_pawn_material(pos.side_to_move())
&& (ss->ply >= thisThread->nmp_ply || ss->ply % 2 != thisThread->nmp_odd))
{
assert(eval - beta >= 0);
}
}
- // Step 10. ProbCut (skipped when in check, ~10 Elo)
+ // Step 10. ProbCut (~10 Elo)
// If we have a good enough capture and a reduced search returns a value
// much above beta, we can (almost) safely prune the previous move.
if ( !PvNode
}
}
- // Step 11. Internal iterative deepening (skipped when in check, ~2 Elo)
+ // Step 11. Internal iterative deepening (~2 Elo)
if ( depth >= 8 * ONE_PLY
&& !ttMove)
{
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY));
}
// Bonus for prior countermove that caused the fail low
- else if ( depth >= 3 * ONE_PLY
+ else if ( (depth >= 3 * ONE_PLY || PvNode)
&& !pos.captured_piece()
&& is_ok((ss-1)->currentMove))
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth));