⚙ Infographic Guide · Chess Programming

The Anatomy of a
Simple Modern Chess Engine

From 64-bit boards to billion-node searches — a visual map of how engines like Stockfish (in simplified form) turn a position into a best move.

📅 June 29, 2026 ⏱ 14 min read 🏷️ Engine Architecture
A chess engine is not one algorithm — it is a stack of tightly coupled systems. The board must be represented efficiently, legal moves generated fast, positions scored, millions of lines searched, and results delivered through a standard protocol (UCI). This guide maps each layer the way a modern engine is actually built.

Overview

The Engine Pipeline

🖥
GUI / Bot
Arena, Lichess, CuteChess
📡
UCI Layer
position · go · stop
🔍
Search
α-β · TT · QSearch
Best Move
e2e4 · score + PV
Search calls Move Gen + Make/Unmake thousands of times per second, backed by Bitboards, Attack Tables, and Evaluation at every leaf.
12Bitboards (6 piece types × 2 colors)
64Squares per board (a1 = 0 … h8 = 63)
~10⁷Nodes/sec (strong desktop engine)
UCIUniversal Chess Interface standard

Foundation

Bitboards: Chess on 64 Bits

White Knights bitboard

Each 1 bit = a square occupied by that piece type. Bitwise AND/OR/XOR updates the board in nanoseconds. Board shown rank 8 (top) to rank 1 (bottom), matching the a1=0 index used by the engine.

Why bitboards?
  • Generate knight moves with a few lookups + bitwise ops
  • Popcount finds how many pieces attack a square
  • Sliders use magic bitboards (see Layer 2)
  • Industry standard since the 2000s (Crafty → Stockfish lineage)

Deep Dive

Six Layers Inside the Engine

1
Board Representation Bitboards

Store the position as 12 × 64-bit integers — one bitboard per piece type per color — plus derived occupancy boards (all white, all black, all pieces), castling rights, en passant square, and side to move.

a1=0 little-endian rank-file indexing make/unmake incremental updates Zobrist hash XOR on every move
// 12 piece bitboards + derived state uint64_t bb[W_PAWN..B_KING]; uint64_t occ[W], occ[B], occ[ALL]; uint64_t zobristKey; // for TT + repetition
2
Attack Generation Magic Bitboards

Leapers (pawn, knight, king) use precomputed [64] attack tables. Sliders (bishop, rook, queen) use magic bitboards: multiply occupancy by a magic number, shift, index into a prebuilt attack table — O(1) sliding attacks.

Pawn separate tables per color Queen = rook | bishop attacks Fallback ray-scan without magics works too
// Magic bitboard lookup for a rook on `sq` blockers = occ[ALL] & rookMask[sq]; idx = (blockers * rookMagic[sq]) >> rookShift[sq]; attacks = rookAttackTable[sq][idx]; // precomputed, O(1)
3
Move Generation Legal Moves

Generate pseudo-legal moves (pushes, captures, promotions, castling, en passant), then filter illegal ones by making the move and checking if the king is in check. Must handle castling through attacked squares correctly.

Perft validates move gen before search Make/unmake faster than copy-make Startpos d5 = 4,865,609 nodes at depth 5
DepthNodes (perft)
120
2400
38,902
4197,281
54,865,609
6119,060,324

⚠ Golden rule

Never write search until perft matches known node counts from the standard starting position. Move-gen bugs corrupt every evaluation above them.

4
Evaluation Static Score

Score a position in centipawns without searching deeper. A simple modern engine uses material plus tapered piece-square tables (separate midgame/endgame tables blended by remaining material phase).

Pawn = 100 cp (typical) Queen = 900 cp Phase blends MG/EG PST scores
// Tapered eval sketch score = material + lerp(pstMG, pstEG, gamePhase); // Extensions: mobility, pawn structure, king safety…
5
Search Alpha-Beta

The brain. Iterative deepening drives negamax with alpha-beta pruning. At leaf nodes, quiescence search (captures only) prevents horizon effect. A transposition table caches scores; move ordering (TT move, MVV-LVA, killers, history) makes pruning effective.

PVS principal variation search Null-move pruning (with guards) LMR late move reductions
6
UCI Protocol Interface

Text commands on stdin/stdout. The GUI sends position and go; the engine searches on a background thread and replies with info lines (depth, score, PV, nps) and finally bestmove.

GUI
uci · isready · position startpos moves e2e4
GUI
go movetime 3000
Engine
info depth 12 score cp 34 pv e7e5 g1f3...
Engine
bestmove e7e5 ponder g1f3

Search Visualized

Alpha-Beta Prunes the Tree

Root (α=-∞ β=+∞) ├─ Move A score +0.4 → raises α ├─ Move B cutoff (β ≤ α) ✂ pruned subtree └─ Move C searched only if B fails high At depth 0 → Quiescence: capture moves until quiet TT hit? → reuse stored score (exact / lower / upper bound)

Practical Guide

Build Order (Don't Skip Steps)

1
Bitboard board
12 boards + occupancy + game state
2
Attack tables
Leaper lookups + magic (or ray) sliders
3
Move generation
Pseudo-legal → legal filter
4
Make/unmake + Zobrist
Incremental hash for TT & repetition
5
Perft test ✓
Match known node counts — mandatory gate
6
Evaluation
Material + tapered PST
7
Search core
ID + negamax αβ + QSearch + TT + ordering
8
Time management
Budget from wtime/btime/movetime
9
UCI loop
Threaded search + stop + bestmove

Reference

Layer Cheat Sheet

LayerInputOutputKey idea
BitboardsFEN / movesOccupancy masks64-bit sets, popcount, bitwise ops
AttacksSquare + occupancyAttack bitboardMagic multiply-shift-index
Move genPositionMove listPseudo-legal then king-safe filter
EvalPositionScore in cpMaterial + tapered PST
SearchPosition + depthBest move + PVαβ + TT + QSearch + ordering
UCIText commandsbestmove + infoStd protocol for all GUIs

Simple vs. superhuman

A simple modern engine implements every layer correctly but keeps evaluation and search extensions modest — architecturally identical to Stockfish, just smaller nets and fewer terms. Strength comes from better eval (often NNUE) and deeper search refinements built on this same skeleton.

Keep exploring chess tech

Pair engine architecture with tactics training and analysis tools on FujiBit.

Related: All Blogs · Chess Tools Hub · Magic of Chess Tactics