We describe the design of a computer player for 8×8 American checkers (English draughts) that, in practice, never loses: against any human opponent every game terminates in a draw or a win for the engine. We make precise what "unbeatable" can and cannot mean for this game, contrast it with the trivially solvable game of tic-tac-toe, and develop the algorithmic method actually implemented: a depth-limited negamax / alpha-beta search equipped with a heuristic evaluation function, a quiescence extension, iterative deepening, a bitboard move generator, multi-stage move ordering (MVV-LVA, killer moves, the history heuristic), a transposition table, and Principal Variation Search with aspiration windows. We then give the reasoning — partly a theorem, partly an empirical argument — for why the resulting program cannot be beaten by a human, and we stress that every one of the speed optimizations is value-invariant: it changes how fast the answer is found, never the answer.
This document is self-contained.
Checkers is a finite, deterministic, two-player, zero-sum game of perfect information. Two players, here called Black and White, alternate moves; Black moves first. The board is the 32 dark squares of an 8×8 grid. Each player starts with 12 men. Rules (American / English draughts):
- A man moves one square diagonally forward to an empty square.
- A king (a man that has reached the opponent's back rank, then promoted) moves one square diagonally in any direction.
- A capture ("jump") moves a piece diagonally over an adjacent enemy piece to the empty square beyond, removing the jumped piece. Captures are mandatory: if any capture is available, the moving player must capture.
- Within a turn, a jump must be continued as long as the same piece can jump again (a multi-jump). The whole chain counts as a single move.
- A man that reaches the last rank promotes to a king. If a man reaches the last rank as the landing square of a jump, its turn ends (it does not continue jumping as a king).
- A player who, on their turn, has no legal move (no pieces, or all pieces blocked) loses.
Because the game is finite and has perfect information, the theory of Zermelo
(1913) applies: from any position, with optimal play, the outcome is determined.
Each position
The central practical question is whether a program can compute, or closely
approximate, optimal play with respect to
Model the game as a tree. Nodes are positions; edges are legal moves; leaves are
terminal positions (won/lost/drawn). Assign a numeric utility to leaves from
Black's perspective, e.g.
where
Because the game is zero-sum, it is convenient to fold the two cases into one
using a side-relative utility
The sign flip
The minimax recurrence is exact but requires visiting the whole tree. Its cost is
governed by the state space and the branching factor
Tic-tac-toe. The board has 9 cells; an upper bound on configurations is
Checkers. The number of legal board positions is
and the number reachable by legal play is on the order of
Two facts rescue the project:
-
Checkers is a solved game. Schaeffer et al. (2007) proved, by a combination of endgame databases and search over roughly
$10^{14}$ positions, that with optimal play 8×8 checkers is a draw. Thus the best any opponent — human or machine — can force against perfect play is a draw. The ceiling for an "unbeatable" engine is exactly: never lose. -
The branching factor is small. Checkers' forced-capture rule keeps the effective branching factor near
$b \approx 3$ (and equal to$1$ whenever a single capture is forced), versus$\approx 35$ for chess. A search of fixed depth$d$ is dramatically cheaper here, which is what makes deep, human-surpassing search feasible on commodity hardware.
The engineering response, then, is not to solve the game, but to search deeply enough, and evaluate accurately enough, that no human can find a line the engine has not already refuted.
The program replaces the unreachable leaves of Section 2 with two devices: a
depth cutoff plus a heuristic evaluation
We search to a fixed depth
Let
Subtracting the ply
where
The evaluation is deliberately coarse. Its only job is to point search in the
right direction at the horizon; depth does the rest. A coarse-but-correct
Searching every node to depth
Soundness. Alpha-beta returns the minimax value whenever it is called with a
full window
Pruning changes which nodes are visited, never the value returned at the root. (This identity is exactly what the engine's test suite checks: alpha-beta is asserted equal to a separate, unpruned minimax on many positions.)
Speed. With perfect move ordering alpha-beta visits only
leaves — the square root of the full tree — effectively doubling the
reachable depth for the same work. For
Alpha-beta's
- Transposition-table move. The move that was best for this exact position at a shallower iteration (stored in the table, §4.7) is tried first. Combined with iterative deepening this is the single strongest ordering signal.
- Captures, by MVV-LVA. Captures come next, ordered most-valuable-victim, least-valuable-aggressor — here, longer jump chains and jumps that take kings first. These are also the sharpest, most forcing lines.
-
Killer moves. Two quiet moves per ply that recently produced a
$\beta$ -cutoff in a sibling node are tried early, since cutoff-causing moves tend to recur at the same depth. -
History heuristic. Remaining quiet moves are ordered by a table that
accumulates, for each
$(\text{from},\text{to})$ pair, the squared depth of every cutoff it has caused — a cheap, position-independent estimate of a move's usefulness.
These are purely ordering devices: they change the order in which moves are examined, never the value returned. Measured against ordering captures alone they cut the number of searched nodes by roughly a factor of three; because cost is exponential in depth, that is a real depth gain for the same time budget.
A fixed depth cutoff can stop the search one ply before a decisive capture,
making
Capture chains strictly reduce material, so this extension always terminates. It ensures the value returned reflects the settled position after forced exchanges, not a misleading snapshot mid-trade.
Rather than searching directly to depth
- It provides an anytime move: under a time budget, the engine plays the deepest completed iteration's move.
- Each iteration's results order the next, so the overhead of the shallow searches is more than repaid by sharper cutoffs deeper down.
A transposition table (a hash map from position to its previously computed
depth, value, and bound type) exploits the fact that the same position arises via
many move orders. A position already searched to sufficient depth is reused
instead of re-searched. Stored bounds (exact / lower / upper) are integrated into
the
Once ordering is good, the first move at almost every node is the best one, and
the remaining moves only need to be refuted, not valued exactly. Principal
Variation Search (a form of NegaScout) exploits this. It searches the first
move with the full window
Null-window searches cut off far more aggressively than full-window ones, and with good ordering the re-searches are rare, so PVS visits fewer nodes than plain alpha-beta. It returns the same value: the scout proves a bound, and any move that could actually change the result is re-searched exactly.
A position's value barely changes from one iterative-deepening iteration to the
next. So each new iteration starts with a narrow window
The techniques above shrink the number of nodes; the representation shrinks the cost per node. The 32 dark squares are encoded as the bits of 32-bit integers — three bitboards holding, respectively, the black pieces, the white pieces, and the kings. Then:
- Occupancy, emptiness, and "is this an enemy?" tests are single bitwise operations covering all squares at once.
- Non-capturing moves of every piece in a given diagonal direction are produced in parallel by one shift-and-mask: shifting the piece bitboard by a fixed amount — with precomputed masks for the board's staggered rows and its edges — yields all destination squares simultaneously, intersected with the empty-square bitboard.
- The search uses make/undo on a single board (toggling bits) instead of copying positions, writes generated moves into a preallocated buffer, and updates a Zobrist hash incrementally. With no per-node allocation, the compiled WebAssembly runs with no garbage collection at all.
None of this changes the value computed; it is a constant-factor accelerator that lets the exact search reach greater depth in the same wall-clock time.
"Unbeatable" is a strong word; we state precisely what holds.
By Schaeffer et al. (2007), the game-theoretic value of 8×8 checkers is a draw. Therefore:
- No player can force a win against optimal defense. An engine that "always wins" is impossible; the honest target is "never loses."
- A program that plays at least as well as optimal defense cannot be made to lose. Every game it plays is a draw or — when the opponent deviates into a losing line — a win for the engine.
So "unbeatable"
Three layered guarantees underwrite soundness:
-
The rules are implemented correctly. Move generation is validated by perft: counting the leaf nodes of the move tree to depth
$n$ from the initial position and matching the independently published English-draughts values $$ 7,;49,;302,;1469,;7361,;36768,;179740,;845931,;3963680,\dots $$ A single off-by-one in capture geometry, multi-jump chaining, promotion, or forced-capture logic perturbs these counts. Matching them through depth 9 ($3{,}963{,}680$ leaves) is strong evidence the engine plays the actual game, not a subtly different one. (A program that is "unbeatable" at the wrong rules is worthless; perft closes this gap.) -
The search returns the true minimax value of its tree. By §4.4, alpha-beta with the transposition table returns the same value as unpruned minimax — and this equality is asserted by the test suite over many positions. So within its search horizon the engine is not approximating: it plays the optimal move of the depth-$d$ game.
-
Every speed optimization is value-invariant. The transposition table (§4.7), the four-tier move ordering (§4.5), Principal Variation Search (§4.8), the aspiration windows (§4.9), and the bitboard representation (§4.10) change only which nodes are visited, in what order, and how cheaply each is processed — never the value produced at the root. This was checked directly: the fully optimized search returns exactly the same root value as plain, unordered minimax on every test position. Speed is therefore bought without surrendering a single point of strength, and the human-horizon argument below rests on the exact search, untouched by the optimizations.
A human, however expert, evaluates a bounded number of lines and looks a bounded
number of moves ahead, with fallible evaluation. The engine searches to a depth
Two measurements support the argument:
- No-loss harness. Across batches of games versus random and material-greedy opponents, the engine records zero losses (only wins and the occasional forced draw). Weak opponents cannot manufacture a win.
- Self-play draws. When the engine plays a copy of itself, the game is a draw. This is the signature of sound play: a sound player cannot be beaten into a loss even by an equally deep searcher, which is precisely the game-theoretic outcome (a draw). It is the same phenomenon as two perfect tic-tac-toe players always drawing.
The guarantee is "never loses to a human," not a mathematical proof of perfection. The distinction:
- The engine is perfect only within its search horizon. At the horizon it
trusts the heuristic
$h$ , which is not the true value function. A perfect oracle opponent could, in principle, steer toward a position where$h$ is wrong and the true value is a loss — but reaching such a position requires superhuman, in fact optimal, play, which is the very thing humans cannot do. - Closing even this theoretical gap is the provably-perfect path: attach
retrograde-analysis endgame databases (all positions with
$\le 8$ –$10$ pieces solved exactly by backward induction from terminal positions), so that once the piece count falls into the database the engine plays with the true value, not a heuristic. This is how the world-champion program Chinook played, and how the 2007 proof was completed. It is deliberately out of scope here — it is gigabytes of precomputed data, and it is unnecessary for the stated goal of beating humans.
In summary, the engine is ultra-strong in practice: it never loses to a human, draws sound opposition, and converts opponent mistakes into wins.
| Quantity | Tic-tac-toe | 8×8 Checkers |
|---|---|---|
| Reachable legal positions |
|
|
| Effective branching factor |
|
|
| Exhaustive minimax feasible? | Yes — game solved at the leaves |
No — |
| Generalized hardness | trivial | EXPTIME-complete (Robson 1984) |
| Game-theoretic value | Draw | Draw (Schaeffer et al. 2007) |
| Method used | full minimax to leaves | depth-limited alpha-beta + heuristic + quiescence |
| Full-width search cost | — | |
| Alpha-beta (best ordering) | — | |
| "Unbeatable" means | perfect; never loses | never loses to a human |
Two further levers act within these bounds without changing the value. Move
ordering (TT-move, MVV-LVA, killers, history) together with Principal
Variation Search and aspiration windows pushes alpha-beta toward its
- J. Schaeffer and R. Lake. Solving the Game of Checkers. University of Alberta. (Three levels of "solving"; Chinook's architecture: deep alpha-beta, evaluation, endgame databases, opening book.)
- J. Schaeffer, N. Burch, Y. Björnsson, A. Kishimoto, M. Müller, R. Lake, P. Lu, S. Sutphen. Checkers Is Solved. Science 317 (2007): 1518–1522. (8×8 checkers is a draw with optimal play.)
- J. M. Robson. N by N Checkers Is EXPTIME-Complete. SIAM J. Comput. 13(2), 1984. (Generalized checkers requires exponential time.)
- J. Bosboom, S. Congero, E. D. Demaine, M. L. Demaine, J. Lynch. Losing at Checkers Is Hard. (Complexity of checkers variants; context for why pruning and heuristics, not brute force, are required.)
- E. Zermelo. Über eine Anwendung der Mengenlehre auf die Theorie des Schachspiels. 1913. (Determinacy of finite perfect-information games.)
- D. E. Knuth and R. W. Moore. An Analysis of Alpha-Beta Pruning. Artificial
Intelligence 6(4), 1975. (The alpha-beta algorithm and its
$b^{d/2}$ bound.) - A. Reinefeld. An Improvement to the Scout Tree-Search Algorithm. ICCA Journal 6(4), 1983. (NegaScout / Principal Variation Search.)
- J. Schaeffer. The History Heuristic and Alpha-Beta Search Enhancements in Practice. IEEE TPAMI 11(11), 1989. (History heuristic, transposition tables, and move ordering in practice.)