Memra

Minimax for two-player games

◈ 3 cards

MAX and MIN alternate levels of a game tree; values back up to the root, giving the best outcome MAX can guarantee against optimal play.

The minimax procedure

For a two-person, zero-sum game (one player's gain is the other's loss), minimax assumes both sides play optimally. The two players are MAX, who tries to maximize the evaluation, and MIN, who tries to minimize it. Label the game tree with alternating MAX and MIN levels:

  • Leaf nodes get an actual or heuristic value (here: if MAX wins, if MIN wins, for a draw).
  • A MAX node takes the maximum of its children's backed-up values.
  • A MIN node takes the minimum of its children's backed-up values.

Values propagate up to the root. The root value is the best outcome MAX can guarantee, assuming MIN also plays optimally. That optimality assumption is both the strength (a rational guarantee) and the limit (an irrational opponent may behave differently) of minimax.

n-ply look-ahead and the horizon effect

Real games are too large to search to the end, so programs search n plies deep, apply a heuristic to the leaves, and back the values up. Deeper usually plays better — but not always, and a fixed depth creates the horizon effect: a disaster lurking one ply beyond the cutoff is invisible, so the program may walk into it (e.g. accept a piece that lures it into losing a bigger one). Quiescence / selective deepening (search a few extra plies for volatile positions) softens this but cannot remove it.

Worked example: tic-tac-toe

Encode the board as 9 cells; X is MAX, O is MIN. On a mid-game board where it is X's turn and taking the centre forces a win, minimax recurses to terminal positions, backs up , and returns best move (2,2), value +1 (X wins). On an empty board, optimal play by both sides is a draw, so the root value is — minimax correctly reports tic-tac-toe as a draw under perfect play. The chosen move is the child that achieves the backed-up root value.

X→(1,0)X→(1,1)X→(1,2)X→(2,1)X→(2,2)MAX (X to move)max = +1MIN−1MIN0MIN0MIN0MIN+1
The top ply of the worked position, with X to move. Every child is a MIN node and its plate is the value backed up from the whole subtree beneath it. MAX takes the <em>maximum</em>, so the root is +1 and the chosen move is the child that achieves it — (2,2). Note that only one move wins: (1,0) actually loses, and the other three are draws.
O→(1,0)O→(1,1)O→(1,2)O→(2,2)MIN (after X→(2,1))min = 0MAX+1MAX0MAX0MAX0
The full tree is 258 nodes, so this is a faithful sub-tree: the fourth root child above, expanded one ply. Each MAX node here is itself the root of a further subtree whose value has already been backed up. MIN takes the <em>minimum</em> of +1, 0, 0, 0 — and 0 is exactly the value this branch shows at the root. The next lesson prunes this very node.
NORMAL ~/memra/learn/comp-456/minimax-two-player-games utf-8 LF