signature GAME = sig datatype player = Player | Opponent type board val initialBoard : board val moves : player -> board -> board list (* no moves means player loses *) val evaluate : player -> board -> real (* approximate, between -1 and 1 *) val toString : board -> string end; signature PLAY = sig structure Game : GAME (* parameter *) val play : int -> Game.player -> Game.board -> (Game.board option * real) end; functor Play1 (structure Game : GAME) :> PLAY = struct structure Game = Game structure G = Game (* abbreviation *) fun maxVal (l) = foldr Real.max ~1.0 l fun minVal (l) = foldr Real.min 1.0 l (* val eval : G.player -> int -> G.board -> real *) (* d >= 0 search to depth d, d < 0 searches whole tree *) fun eval p 0 board = G.evaluate p board | eval G.Player d board = maxVal (map (eval G.Opponent (d-1)) (G.moves G.Player board)) | eval G.Opponent d board = minVal (map (eval G.Player (d-1)) (G.moves G.Opponent board)) (* val pick : real -> real list -> G.board list -> G.board option *) (* pick v vs ms where |vs| = |ms| *) fun pick v (nil) (nil) = NONE | pick v (v'::vs) (m::ms) = if v = v' then SOME(m) else pick v vs ms (* val play : int -> G.player -> G.board -> (G.board option * real) *) (* play d player b where d > 0 searches to depth d *) (* d = 0 searches to arbitrary depth *) fun play d G.Player board = let val moves = G.moves G.Player board val values = map (eval G.Opponent (d-1)) moves val maxv = maxVal values in (pick maxv values moves, maxv) end | play d G.Opponent board = let val moves = G.moves G.Opponent board val values = map (eval G.Player (d-1)) moves val minv = minVal values in (pick minv values moves, minv) end end;