Negamax: a compact minimax variant for chess engines
Negamax
Definition
Negamax is a streamlined formulation of the minimax algorithm tailored for two-player zero-sum games like chess. It relies on the identity max(a, b) = −min(−a, −b), allowing a single “maximize” routine to handle both sides by flipping the sign of returned scores at each ply. Scores are interpreted from the perspective of the side to move: positive is good for the player to move, negative is good for the opponent.
How it works (core idea)
- Zero-sum symmetry: the value of a position for one player is the negative of the value for the other.
- Single recursion: instead of separate “min” and “max” levels, negamax always chooses the move with the highest score; child scores are negated to reflect the opponent’s turn.
- Alpha–beta in negamax: a standard call looks like score = −search(child, −beta, −alpha, depth−1). The window and result are negated and swapped.
- Terminal handling: checkmate is scored with large magnitudes (e.g., ±Mate), typically adjusted by ply to prefer faster mates and longer defenses. A node where the side to move is checkmated returns a large negative value; its parent (who delivered mate) sees the negated large positive value.
Usage in chess
Negamax underpins most classical chess engines that use alpha–beta pruning. It is typically embedded in a larger search framework:
- Move ordering (e.g., hash move, captures, killers, history) to maximize alpha–beta cutoffs.
- Transposition tables to store bounds and exact scores, avoiding re-searching repeated positions.
- Iterative deepening with aspiration windows (small alpha–beta windows around the previous iteration’s score).
- Quiescence search at leaf nodes to resolve volatile tactical positions by exploring checks and captures.
- Extensions and reductions (late move reductions, check extensions, singular extensions) to intelligently vary search depth.
In practice, engines evaluate a position either:
- From White’s viewpoint (then multiply by +1/−1 depending on who moves), or
- Directly from the side to move (most convenient for negamax), ensuring sign consistency throughout the tree.
Numerical toy example
Imagine a position with White to move. White considers two moves, A and B. After A, Black has two replies, a1 and a2; after B, Black has b1 and b2. Leaf evaluations (in centipawns, from the side to move at those leaf nodes):
- A → a1: leaf returns +120 (side to move is better by a pawn+); A → a2: leaf returns −50.
- B → b1: leaf returns +20; B → b2: leaf returns +10.
Working bottom-up with negamax:
- At Black’s reply after A, the child scores (from Black’s perspective) are +120 and −50; White’s parent node negates them to −120 and +50, so Black would choose a2 (the child White sees as +50 for Black), leaving White with −50 at A after re-negation. In plain terms: Black steers to White’s worst line after A.
- After B, the worst White can be forced to is +10 (since Black chooses the line that minimizes White’s eventual outcome).
- White picks the move with the higher resulting score: max(−50, +10) = +10, so White chooses B.
On-the-board example (mate demonstration)
Consider the quick mating pattern known as Fool’s Mate in a slightly different move order:
1. f3 e5 2. g4 Qh4#
Visualization: White’s king sits on e1; the f-pawn has moved to f3 (vacating f2), and the g-pawn advances to g4 (vacating g3). Black’s queen reaches h4 and mates along the cleared diagonal h4–e1 (through g3 and f2). In negamax terms, the terminal child node (with White to move and checkmated) returns a large negative value; the caller (Black’s move delivering mate) negates it to a large positive value, making Qh4# the engine’s immediate top choice.
Strategic and historical significance
Negamax is not a different strategy from minimax; it is a representation that exploits zero-sum symmetry to simplify code and reasoning. This simplification made it the de facto standard for implementing alpha–beta search in early and modern chess programs. The conceptual roots are in von Neumann’s minimax theorem; negamax’s compact formulation became popular in computer chess literature and practice as programmers recognized the convenience of a single, uniform “maximize with sign flip” routine.
Implementation tips and common pitfalls
- Alpha–beta window flipping: always call child searches with (−beta, −alpha) and negate the returned score.
- Mate distances: adjust mate scores by ply so the engine prefers faster mates and delays being mated (e.g., +Mate−ply, −Mate+ply).
- Consistency in evaluation: if eval is White-centric, multiply by sideToMove; if it’s side-to-move-centric, keep it consistent everywhere (including quiescence).
- Transposition tables: store whether a score is exact, a lower bound (alpha-raise), or an upper bound (beta-cutoff) and remember that the bounds are from the viewpoint at that node.
- Fail-soft vs fail-hard: fail-soft returns the best value outside the window on cutoffs (often more informative for move ordering); fail-hard returns alpha or beta exactly.
Interesting facts
- Despite its name, negamax isn’t a new algorithm—just a re-expression of minimax that enables clean, symmetric code.
- Most alpha–beta engines (including leading open-source engines) adopt a negamax-style core with numerous refinements like Principal Variation Search (also called “Negascout”), null-window probes, and aspiration windows.
- A basic negamax with alpha–beta, decent move ordering, and quiescence can play surprisingly strong chess relative to its simplicity.
Related terms
- minimax
- alpha-beta pruning
- evaluation function
- quiescence search
- principal variation
- transposition table
- Principal Variation Search (Negascout)