Minimax Search: Technical Game Development II
Minimax Search: Technical Game Development II
Minimax Search
Minimax is at the heart of almost every
computer board game
Applies to games where:
Players take turns
Have perfect information
Chess, Checkers, Tactics
Naive Approach
1. Exhaustively expand tree
Minimax Approach
assume both/all players play to the best of their
ability
define a scoring method (see next)
from the standpoint of a given player (lets call
him Max):
choose move which takes you to the next state with
highest expected score (from your point of view)
assuming the other player (lets call her Min-nie) will
on her move choose the next state with the lowest
score (from your point of view)
IMGD 4000 (D 10)
Naive Approach
1. Apply static evaluation to each next state
2. Choose move to highest scoring state
If static evaluation function were perfect, then
this is all you need to do
The solution?
Look ahead!
9
Max
Min
3 9
5 6 7
Max
Its Maxs turn at the start of the game (root of the tree)
There is only time to expand tree to 2nd ply
Maxs static evaluation function has been applied to all leaf states
Max would like to get to the 9 point state
But if Max chooses leftmost branch, Min will choose her move to get to 3
=> left branch has a value of 3
If Max chooses rightmost branch, Min can choose any one of 5, 6 or 7
(will choose 5, the minimum)
=> right branch has a value of 5
Right branch is largest (the maximum) so choose that move
10
11
Minimax Algorithm
def MinMax (board, player, depth, maxDepth)
if ( board.isGameOver() or depth == maxDepth )
return board.evaluate(player), null
bestMove = null
if ( board.currentPlayer() == player )
bestScore = -INFINITYNote: makeMove returns copy of board
else bestScore = +INFINITY
(can also move/unmove--but dont execute graphics!)
for move in board.getMoves()
newBoard = board.makeMove(move)
score = MinMax(newBoard, player, depth+1, maxDepth)
if ( board.currentPlayer() == player )
if ( score > bestScore ) # max
bestScore = score
bestMove = move
Note: test works for multiplayer
else
case also
if ( score < bestScore ) # min
bestScore = score
bestMove = move
return bestScore, bestMove
MinMax(board, player, 0, maxDepth)
12
Negamax Version
for common case of
two player
zero sum
13
Negamax Algorithm
def NegaMax (board, depth, maxDepth)
if ( board.isGameOver() or depth == maxDepth )
return board.evaluate(), null
bestMove = null
bestScore = -INFINITY
for move in board.getMoves()
newBoard = board.makeMove(move)
score = NegaMax(newBoard, depth+1, maxDepth)
score = -score
# alternates players
if ( score > bestScore )
bestScore = score
bestMove = move
return bestScore, bestMove
NegaMax(board, 0, maxDepth)
14
Pruning Approach
Minimax searches entire tree, even if in some cases it is clear that
parts of the tree can be ignored (pruned)
Example:
15
Pruning Approach
In general,
Stop processing branches at a node when you find a
branch worse than result you already know you can
achieve
This type of pruning saves processing time without
16
Pruning Example
17
Alpha-Beta Pruning
Keep track of two scores:
Alpha best score by any means
Anything less than this is no use (can be pruned) since we can
already get alpha
Minimum score Max will get
Initially, negative infinity
18
19
Move Order
20
10
Move Order
Can we improve branch (move) order?
apply static evaluation function at intermediate
nodes and check best first
logical idea
can improve pruning
but may effectively give up depth of search advantage (in
fixed time interval) due to high cost of function evalution
21
Chess Notes
Static evaluation function
typically use weighted function
c1*material + c2*mobility + c3*kingSafety + ...
22
11
Chess Notes
Chess has many forced tactical situations
e.g., exchanges of pieces
minimax may not find these
add cheap test at start of turn to check for
immediate captures
23
12