Alpha-beta prunes when move #2 refutes move #1. The refuting move is often a quiet move (not in the TT for this position).
The killer heuristic stores such moves per search ply — not per position hash.
At the same remaining depth elsewhere, try killer moves right after TT move and before captures/history.
Storage
Killer Slots Per Ply
Ply
Killer 1
Killer 2
1
Nf3→g5
—
2
Bb5
Qd2
3
Rfe1
h3
…
max depth slots
2 typical
Array: killers[depth][0..1]. Cleared or aged each root search. Same move at same ply in different branches gets priority.
Ordering
Where Killers Rank
1 TT best move (if hash matches)
2 Killer moves at this ply (if legal here)
3 Captures (MVV-LVA)
4 History heuristic scores
5 Remaining quiet moves
if (score >= beta) { // beta cutoff
if (!isCapture(move) && !isPromotion(move))
storeKiller(ply, move);
return beta;
}
Notes
- Only store non-captures — captures already ordered by MVV-LVA
- Don't store if move equals current killers (shift slot 2 ← slot 1)
- Works because tactical motifs repeat at same distance to leaf
- Pairs with countermove heuristic (previous move → refutation)
- Modern engines also use history tables; killers remain cheap baseline
Related: Late Move Reduction · Iterative Deepening · All Blogs