Skip to content

Commit 369da0e

Browse files
luccabbclaude
andcommitted
[8/9] Add futility pruning
Implements futility pruning to skip quiet moves that can't improve alpha: **Futility Pruning:** - At low depths (1-2), compute static evaluation - If eval + margin < alpha, quiet moves can't help - Skip quiet moves (no capture, check, or promotion) - Never prune the first move (might be the only good one) **Margin Calculation:** - Depth 1: 100 centipawns margin - Depth 2: 200 centipawns margin - Larger margin at deeper depths allows for more potential improvement **Conditions for pruning:** - Depth <= 2 - Not in check (check positions are critical) - Static eval + margin < alpha - Move is quiet (not capture/check/promotion) - Not the first move in the list This is a forward pruning technique that can miss some moves, but the marginsare conservative enough to rarely affect results while significantly reducing nodes searched. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent bd310e6 commit 369da0e

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

moonfish/engines/alpha_beta.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,32 @@ def negamax(
302302

303303
in_check = board.is_check()
304304

305+
# Futility pruning: if static eval is far below alpha, quiet moves won't help
306+
# Only compute if we might use it (low depth, not in check)
307+
futility_margin = 0
308+
can_futility_prune = False
309+
if depth <= 2 and not in_check:
310+
static_eval = self.eval_board(board)
311+
# Margin increases with depth: depth 1 = 100cp, depth 2 = 200cp
312+
futility_margin = 100 * depth
313+
can_futility_prune = static_eval + futility_margin < alpha
314+
305315
for move_index, move in enumerate(moves):
306316
is_capture = board.is_capture(move)
307317
gives_check = board.gives_check(move)
308318
is_promotion = move.promotion is not None
309319

320+
# Futility pruning: skip quiet moves that can't raise alpha
321+
# Conditions: low depth, not PV move, quiet move, not in check
322+
if (
323+
can_futility_prune
324+
and move_index > 0 # Don't prune first move
325+
and not is_capture
326+
and not gives_check
327+
and not is_promotion
328+
):
329+
continue
330+
310331
# make the move
311332
board.push(move)
312333

0 commit comments

Comments
 (0)