Skip to content

Instantly share code, notes, and snippets.

@eriksvedang
Created November 29, 2016 10:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eriksvedang/553263d12bc00a4902b12a0dc289b725 to your computer and use it in GitHub Desktop.
Save eriksvedang/553263d12bc00a4902b12a0dc289b725 to your computer and use it in GitHub Desktop.
module Minimax2 where
type Player = Int
type Score = Int
data Solver s m = Solver { evalFn :: s -> Player -> Score
, branchFn :: s -> [m]
, moveFn :: s -> m -> s
, currentPlayerFn :: s -> Int
, getState :: s }
minimax :: Solver s m -> Player -> Int -> Score
minimax solver me depth = let state = getState solver in
case depth of
0 -> ((evalFn solver) state me)
_ -> let finder = if ((currentPlayerFn solver) state) == me then maximum else minimum
moves = ((branchFn solver) state)
in case moves of
[] -> ((evalFn solver) state me)
_ -> finder (map (\move -> minimax solver { getState = ((moveFn solver) state move) } me (depth - 1)) moves)
-- Nim
data Nim = Nim { nimTurn :: Int
, nimValue :: Int
, nimGoal :: Int } deriving (Show)
nimCurrentPlayer state = (nimTurn state) `mod` 2
nimEval state me = if (nimValue state) == (nimGoal state)
then if nimCurrentPlayer state == me
then 100
else -100
else 0
nimBranch state = case (nimGoal state) - (nimValue state) of
0 -> []
1 -> [1]
_ -> [1, 2]
nimMove state move = let newValue = (nimValue state) + move
in if newValue < (nimGoal state) then
state { nimTurn = (nimTurn state) + 1
, nimValue = newValue }
else
state { nimValue = newValue }
nim goal = Solver { evalFn = nimEval
, branchFn = nimBranch
, moveFn = nimMove
, currentPlayerFn = nimCurrentPlayer
, getState = Nim 0 0 goal }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment