function expectimax(node: Node, depth: number, chance: boolean): number {if (depth === 0 || node.isLeaf) return node.value;
if (chance) {let expected = 0;
for (const child of node.children) expected += child.probability * expectimax(child, depth - 1, false);
return expected;
}
let best = -Infinity;
for (const child of node.children) best = Math.max(best, expectimax(child, depth - 1, true));
return best;
}
MAX node at ply 0: pick the child with the highest expected value.
Understanding Expectimax
The idea
Minimax assumes the opponent always picks the move that hurts you most. When the 'opponent' is a die roll, a shuffled deck or a player known to move at random, that is too pessimistic: the right value of a chance node is the expected value, each outcome's value weighted by its probability.
Expectimax keeps MAX nodes as they are and replaces MIN nodes by chance nodes that average. The best line can differ from minimax's: a move with a great average but one bad outcome is chosen by expectimax and refused by minimax. The price is that alpha-beta pruning no longer applies in full, since an average can always be pulled up by an unseen child.
The four stages
Complexity
Versus its siblings
Pseudocode
EXPECTIMAX(node, depth, chance)
if depth = 0 or node is a leaf: return value(node)
if chance: return Σ probability(child) × EXPECTIMAX(child, depth − 1, false)
else: return max over children of EXPECTIMAX(child, depth − 1, true)
When to use
Pitfalls
History
Donald Michie described expectimax in 1966 while studying game learning; Bruce Ballard's *-minimax of 1983 brought partial pruning back by bounding the evaluation. Gerald Tesauro's TD-Gammon paired a two-ply expectimax with a learned evaluation to reach world-class backgammon in 1992.