🔍 Infographic · Engine Search

Explain Chess Engine
Search Algorithm

Evaluation tells you who is ahead. Search asks “what happens next?” — exploring millions of lines with alpha-beta, transposition tables, and quiescence.

📅 June 29, 2026 ⏱ 13 min read 🏷️ Alpha-Beta · TT · QSearch
A chess game tree grows exponentially — ~30 legal moves per position, billions of nodes within a few plies. Engines cannot brute-force it. They use negamax with alpha-beta pruning to ignore provably bad branches, plus iterative deepening, transposition tables, and quiescence search to go deep where it matters.

Evolution

From Minimax to Modern Search

Minimax
explore all
Alpha-Beta
prune branches
Negamax + PVS
one recursive fn
+ TT + QSearch
+ ordering + ID
α βAlpha-beta window bounds best/worst
TTTransposition table caches positions
QSearchCaptures-only at leaf depth
IDIterative deepening rebuilds PV each ply

Core pruning

Alpha-Beta: Cut What Cannot Win

Window at each node: keep score between α (best for side) and β (opponent's bound)
α bound
[ α … β ]
β bound

If a move makes β ≤ α, the opponent already has a refutation — cut off remaining siblings without searching them.

Root depth 3 [α=-∞ β=+∞] ├─ 1. e4 score +0.3 → raises α ├─ 2. d4 β ≤ α ✂ cutoff — rest of d4 subtree skipped └─ 3. Nf3 searched only if still in window At depth 0 → enter Quiescence (captures/promotions until quiet) Best line stored as PV: e4 e5 Nf3 Nc6 ...

Techniques

Layers of a Modern Search

±
Negamax

One recursive function for both sides: score = −search(−α, −β). Maximizing and minimizing collapse into a single loop — simpler code, same result as minimax.

int negamax(depth, alpha, beta) { if (depth == 0) return quiescence(alpha, beta); // try moves, recurse with −beta, −alpha }
ID
Iterative Deepening

Search depth 1, then 2, then 3… Each pass fills the transposition table and produces a principal variation (PV) used to order moves at the next depth. Stoppable anytime — always have a best move ready.

d=1
quick PV
d=2
better order
d=3
deeper…
d=N
time up → stop
PVS
Principal Variation Search

First move at each node gets a full [α, β] window. Later moves use a zero-width scout (−α−1, −α). If a move fails high, re-search with full window. Assumes first move is best (thanks to ordering) — huge speedup.

1st move full window rest null-window scout fail-high → re-search
Q
Quiescence Search

Static eval at depth 0 is blind to hanging pieces (horizon effect). QSearch extends with captures (and often promotions/checks) until the position is “quiet,” then evaluates. Stand-pat: if eval ≥ α, skip captures.

Stand-pat cutoff in eval Delta pruning skip hopeless captures
TT
Transposition Table

Same position reached by different move orders shares one Zobrist hash key. Store depth, score, flag (exact / lower / upper bound), and best move. Depth-preferred replacement — skip re-searching known subtrees.

keyZobrist hash
depthstored ply
scorecp or mate
flagEXACT α β
moveTT best move
Advanced Pruning

Null-move pruning: if giving a free pass still fails high, cut (not in check, enough material). LMR: reduce depth for late, quiet moves. Aspiration windows: narrow [α, β] around last iteration's score. All guarded — wrong guards cause tactical blindness.

Move Ordering (makes pruning work)

Alpha-beta efficiency depends on trying the best move first. Bad ordering = almost no cutoffs.

  1. Transposition table best move
  2. Captures ordered by MVV-LVA (Most Valuable Victim — Least Valuable Aggressor)
  3. Killer moves (quiet moves that caused cutoffs at this depth)
  4. History heuristic (quiet moves that caused cutoffs anywhere)
  5. Remaining quiet moves

Output

What the GUI Sees During Search

UCI info lines (each iterative deepening pass)

Engine reports depth, score in centipawns (or mate in N), nodes searched, nodes/sec, and principal variation — the expected best line.

info depth 14 seldepth 22 score cp 34 nodes 823401 nps 4120000
pv e2e4 e7e5 g1f3 b8c6 f1b5 a7a6
bestmove e2e4 ponder e7e5

Reference

Search Stack Cheat Sheet

TechniquePurposeWhen skipped / guarded
NegamaxUnified max/min recursion
Alpha-betaPrune losing branches
Iterative deepeningProgressive depth + PV for orderingStopped by time / stop
PVSFast re-search on fail-high
QuiescenceFix horizon at leafDelta / depth limit in QSearch
Transposition tableCache sub-tree scoresInsufficient stored depth
Null-moveCut if position still good after passIn check, endgame, shallow
LMRShallow search for unlikely movesCaptures, checks, PV moves
Move orderingMaximize cutoffs

Search depends on everything below it

Move generation must be perft-correct. Evaluation must be consistent (same sign for both sides). Magic bitboards and make/unmake must be fast — search calls them billions of times per move. Build the foundation first, then stack search on top.

Complete the engine series

Search sits on move gen, attacks, and eval — explore the full stack on FujiBit.

Related: Magic Bitboards · Engine Anatomy · All Blogs