/* finin@Umbc.edu, 2001, 2006 http://umbc.edu/~finin/ a simple minimax algorithm for playing two person games. To define the game, provide definitions for a state is like s(N,B) where N is the player number (e.g., 1,2) and B is the board position. player(N,Depth,Eval) -- Player N does lookahead to depth Depth and uses the static evaluation predicate Eval. Eval/2 takes two arguments (+S,-V) and is true if state S has static value V. start(S) -- true if S is the initial game state. move(S1,S2) - true if there is a legal move from state S1 to S2. win(P,S) -- true if state S is a win for player P. draw(S) -- true of state S is a draw printBoard(S) -- prints the curent board We assume that a state is of the form s(P,B) where P is the player whose turn is next (1 or 2) and B represents the "board position". */ % mm(+N,+S1,-S2,-Value) does the minimax algorithm with a lookahead % depth of N and a static evaluation function Eval starting in state % S1. The best next move is the one which results in state S2 and the % value backed up for this position is V. % stop recursing if N=0, figure out which player is to move and get % her static evaluation predicate mm(0,Eval,S,S,Value) :- !, call(Eval,S,Value). % stop recursing if if one of the players has won or if it's a draw. mm(_,Eval,S,S,9999) :- win(1,S). mm(_,Eval,S,S,-9999) :- win(2,S). mm(_,_,S,S,0) :- draw(S). mm(N,Eval,S1,S2,Value) :- N2 is N-1, % find all of the legal moves and their minimax values. findall(V-S, (move(S1,S), mm(N2,Eval,S,_,V)), Moves), % sort them from lowest to highest. keysort(Moves,SortedMoves), % select which of SortedMoves is the best for this player selectMove(S,Eval,SortedMoves,S2,Value), !. % selectMove(+State,+ListOfSortedMoves,-BestMove,-ValueOfBestMove) % % selects the best move for the state, depending on which player's turn % % it is (e.g., min or max). % If there are no moves, just run the static evaluator on this state. selectMove(S,Eval,[],S,Value) :- call(Eval,S,Value). % If it's player 1's turn, choose the max (last value). selectMove(s(1,_),_,SortedMoves,S2,Value) :- last(SortedMoves,Value-S2). % If it's player 2's turn, choose the min (first value). selectMove(s(2,_),_,[S2-Value | _],S2,Value).