Agent moves first
- Agent
- 0
- Draw
- 0
- You
- 0
CS 440 · Adversarial search · Lecture 5
Minimax solves tic-tac-toe by expanding half a million positions. Alpha–beta returns the identical answer after examining a small fraction of them — not by guessing, and not by approximating, but by proving that the rest cannot matter.
Alpha–beta never asks “does this subtree exist?”
It asks
“can anything in this subtree still change my decision?”
Where we left off
It searches to the end of the game before every move, so nothing surprises it. Watch the position count under each board — that is the price of certainty, and the rest of this page is about how to stop paying it.
01
Nine choices, then eight, then seven. Each one is unremarkable. Multiply them and the futures run away from you. Add one turn at a time and watch.
No, and it is bigger than that. 9! counts the orderings of nine moves, which is roughly the number of leaves in a tree where nobody ever wins early. The game tree also contains every prefix: the root, the 9 positions after one move, the 72 after two, and so on. Internal nodes are nodes too.
Pushing in the other direction, games that end in a win have no children, which removes whole branches. Both effects are real. The exact answer is below, and the exact answer is not the point — the point is that a handful of choices per turn produces a number you cannot enumerate by hand.
02
Before any search, a modelling decision: MAX tries to push the final number up, MIN tries to push it down, and one player's gain is exactly the other's loss. Minimax then assumes MIN plays perfectly. Not probably-well — perfectly. Everything the algorithm proves is conditional on that.
| Outcome | MAX utility | MIN utility |
|---|---|---|
| MAX wins | +1 | −1 |
| Draw | 0 | 0 |
| MIN wins | −1 | +1 |
No. What matters is that the players' preferences are exactly opposed. Two players splitting a fixed £100 get (k, 100 − k) — the total is always 100, a constant-sum game.
Subtract 50 from each and you get (k − 50, 50 − k), which sums to zero. Nothing about anyone's strategy changed; the numbers were relabelled. So “zero-sum” is a statement about opposed preferences, not about arithmetic. Minimax works on any constant-sum game.
Where it genuinely breaks is games that are neither — where both players can be made better off at once. Then “the opponent minimises my score” is simply false, and you need different machinery.
03
Small enough to do in your head. MAX moves first and picks a branch; MIN then picks a leaf. The leaf numbers are MAX's payoff.
Work the left branch first: MIN picks min(3, 5) = 3, so MAX can guarantee 3 by going left.
Now the right branch. Its first leaf is 2. MIN is choosing here, and MIN already has a 2 available — so the right branch is worth at most 2, whatever the fourth leaf says. MAX has 3 elsewhere. The fourth leaf cannot change the decision, so it never needs to be read.
That is the entire algorithm. Everything from here is bookkeeping for that one argument.
04
The same reasoning on a tree where the saving is worth having. Step through it and decide for yourself when to stop — no Greek letters until the end.
Your call: does MAX need to see B's last two leaves?
MIN can already hold branch B to 3. MAX can already get 5 elsewhere. So MAX will never walk into B — and what is underneath it stops being a question.
05
Those two facts — what MAX can already guarantee and what MIN can already hold MAX to — get carried down the tree as a pair of numbers. That is all α and β are. They are not the algorithm; they are a compact record of what has already been proved.
MAX has found lines worth 3, then 5, then 4, then 7, then 6. Its guarantee is the best so far — it would never trade a guaranteed 5 back for a 4.
MIN has found replies holding MAX to 9, then 7, then 8, then 4, then 6. Its ceiling is the tightest so far, by exactly the same argument.
Unpack both sides into English. α says MAX can already guarantee at least α somewhere else. β says MIN can already hold this branch to at most β.
If α ≥ β, then the most this branch could ever deliver is no better than something MAX already has in hand. MAX is the one choosing whether to come here, and MAX has no reason to. The inequality is not the reason — it is the receipt.
06
Tic-tac-toe, searched to the end. Nodes appear only as the search reaches them, because a pruned subtree is never built — though the positions in it exist in the game all the same. Turn on Ask me before each decision and the search will stop and make you call it.
Because it stopped early, on purpose. A MIN node that cut off has seen some of its children and knows its value is no higher than the best it found. The unseen children could only push it lower. So what comes back is a bound, not a value.
In the first position on this page, one node reports v ≤ 0 while its true minimax value is +1. That is not a bug — it is the algorithm declining to buy information it does not need.
Which gives a sharper description of what alpha–beta is: not a search for values, but a search that propagates bounds on values, and stops as soon as the bounds are tight enough to decide. Only the root, and the nodes along the line actually chosen, come back exact.
A theorem. Alpha–beta always returns the minimax value of the root. The proof is the cutoff rule: a branch is abandoned only after showing that its value cannot reach the root, so abandoning it cannot change the root.
The value is guaranteed identical. The move is not always: when several moves tie, the two searches may report different members of the tie. Equally good, not identical.
07
Cutoffs need something to cut against, and α and β only get strong when a good move is examined early. Search the best move first and each sibling is refuted by one child. Search it last and you have paid for the whole tree before learning anything.
The first two positions in the stepper are nearly the same size and prune completely differently. Here is the same effect on the whole game.
| Whole game, X to move first | Nodes built | vs. minimax |
|---|---|---|
| Full minimax — no pruning | — | — |
| Alpha–beta, cells in order 1…9 | — | — |
| Alpha–beta, centre then corners then edges | — | — |
| Alpha–beta, moves shuffled | — | — |
08
A uniform tree with random leaf values, so you can change one thing at a time. The best ordering is an oracle — it already knows which child is best, which no real program does. It is here to show the ceiling.
| Reference | Nodes |
|---|---|
| Minimax, no pruning — bd leaves | — |
| Alpha–beta, this ordering | — |
| Perfect-ordering ideal — about 2bd/2 leaves | — |
Follow the best line of play down the tree. A node on that line must still examine all its children — it has to prove the best one really is best. But each of those children is a node whose first child is already its best, and that single child immediately produces a bound tight enough to refute all of its siblings.
So the tree branches fully on one level and by one on the next, alternating: b × 1 × b × 1 … across d levels, which is bd/2. Half the levels are free. In a fixed time budget that is roughly twice the depth — which in chess is the difference between a club player and a strong one.
09
If searching during the game is so expensive, why search at all? Solve every position once, store the best move for each, and at play time just look it up.
This is not a naive idea — it is exactly what we do when we can. Tic-tac-toe has 5,478 reachable positions; you could put the whole solution in a spreadsheet. The question is where that stops working, and the answer arrives faster than most people expect.
| Game | Distinct positions | Possible games | Solved? |
|---|---|---|---|
| Tic-tac-toe | 5,478 | ~105 | yes — draw |
| Connect Four | 4.5 × 1012 | ~1021 | yes, 1988 — first player wins |
| Checkers | 5 × 1020 | ~1031 | yes, 2007 — draw |
| Chess | ~1044 | ~10120 | no |
| Go, 19×19 | 2.1 × 10170 | ~10360 | no |
Read the checkers row again. Five hundred million million million positions. At one byte each that is 500 exabytes, and a byte is not enough to store a move. Checkers was solved — it took eighteen years — but not by tabulating that. Chinook computed perfect endgame databases for every position with ten pieces or fewer, then searched the gap between the opening and those databases. Even the games we have solved were solved by search plus storage, never storage alone.
Chess makes the point sharper. We really do precompute chess endings: the seven-piece tablebases hold about 423 trillion positions and take roughly 18 terabytes compressed. That is a colossal engineering achievement, and it covers about 10−30 of the game. The tail of chess, and not one percent of one percent of anything.
And Go has more legal positions than there are atoms in the observable universe — not a few times more, about 1090 times more. There is no table. There will not be a table.
Don't solve every position that could ever exist. Solve the tiny region of the tree that the
position in front of you can actually reach.
Search narrows what we consider. Alpha–beta narrows how much of that search we have to
perform.
Because 4.5 TB was not one disk in 1988, and more importantly because you cannot write down the answer without first computing it. Filling the table means evaluating every entry, which is the whole search you were trying to avoid — you have moved the cost, not removed it.
Offline solving pays off only when the answer will be reused enough times to amortise that one-off cost, which is exactly why it is worth doing for endgames: a few hundred distinct piece combinations, reached over and over, in every game ever played afterwards. It is not worth doing for openings, where the tree below each entry is astronomically larger and the position may never recur.
The general lesson is not about board games. Precompute what is small and heavily reused; search what is enormous and specific to the case in front of you.
10
Alpha–beta works best when you search the best move first. But finding the best move is what you are searching for. That looks like a dead end, and the escape routes are some of the most-used ideas in game programming:
Two facts collide in a useful way. First, the cost of a tree is dominated by its last level: searching to depth d−1 is a small fraction of searching to d, so the repeated work is cheaper than it sounds.
Second, and this is the real payoff, the depth-d−1 search returns a ranking of the moves. Feed that ranking in as the move order for depth d and you are much closer to the best-first ordering whose ceiling is bd/2. The shallow searches are not overhead; they are how you buy ordering.
So the extra passes pay for themselves, and you get an anytime algorithm for free: interrupt it at any moment and a complete, usable answer from the last finished depth is already in hand.
11
The pruning rule is settled. It is provably correct, it has been understood for seventy years, and nobody is going to improve it — there is nothing to improve, because it already skips exactly what cannot matter and nothing that can.
But “search enormous game spaces well” is not settled at all. Alpha–beta turns out to be the small, stable core of a large system, and almost every part of that system is still an open engineering and research problem.
Each box is a live question, and most of them have no settled answer:
The pruning rule is solved.
Efficient game-tree search is not.
No — and what actually happened is more interesting. AlphaZero replaced two things at once: it swapped alpha–beta for Monte Carlo tree search, and it swapped a hand-written evaluation function for a neural network. It was easy to read that result as “tree search lost”.
Then Stockfish adopted a small neural evaluation of its own, kept its alpha–beta search, and went back to being at least as strong. Which isolates the variable: the bottleneck was the evaluation, not the search discipline. Today's strongest engines include both kinds, and each has borrowed from the other.
The honest summary is that alpha–beta and MCTS make different bets about where to spend effort — alpha–beta proves things about a narrow, deep slice of the tree; MCTS samples widely and averages. Which bet wins depends on the branching factor, the sharpness of the game, and how good your evaluation is. In Go, with a branching factor near 250, the second bet was better. In chess it was not, and that is still true.
12
You were asked why the agent favours some opening cells over others. Now we can just compute it: every first move, solved to the end.
Press solve to fill this in.
With perfect play from both sides, all nine first moves lead to a draw. So the agent is not choosing between winning and losing openings. It is choosing between openings that give a fallible opponent more ways to go wrong — a different question, and not one minimax asks.
13
Because MIN is the one choosing there. MIN has already found a reply that holds this branch to 5, and MIN will not volunteer anything better. So the branch is worth at most 5, no matter what those 10,000 positions contain — one of them could be a forced win for MAX and it would still be unreachable, because MIN simply plays the reply worth 5 instead.
MAX, meanwhile, can already get 8 somewhere else. A branch capped at 5 cannot beat a guarantee of 8. So MAX's decision is settled, and 10,000 positions become irrelevant — not unimportant, not approximated, irrelevant.
If you can say that, you understand alpha–beta. α ≥ β is just the two-symbol shorthand for the paragraph you have written.
Go deeper
Roughly in order of depth. The first two levels are examinable; the rest is where the subject actually lives.
Use as few words as possible.
Play the agent as often as you like. It never loses. Why?
Can we call this agent intelligent? Recall the first lecture on definitions of intelligence.
State the pruning argument without using α or β, and say explicitly where the opponent's freedom to choose enters it.
A finished node reports v ≤ 3. What is known about its true minimax value, what is not, and why was it not worth finding out?
Describe the property a move ordering needs for cutoffs to fire — without using the word “best”.
Two orderings, same position, two different moves returned. Has something gone wrong? Justify either answer.
Iterative deepening does strictly more searching and finishes sooner. Explain the apparent contradiction.