module GameEngine (
Symbol,
GameState(..),
Player(..),
Move(..),
GameActions(..),
GameEngine(..),
play
) where
type Symbol = Char
data GameState a = GameState a
data Player = Player Char
data Move a = Move a
data GameActions a b = GameActions {
getPlayer :: GameState a -> Player,
getMoves :: GameState a -> [Move b],
getResult :: GameState a -> Move b -> GameState a,
isTerminal :: GameState a -> Bool,
getScore :: GameState a -> Player -> Int
}
data GameEngine a b = GameEngine {
gameActions :: GameActions a b,
state :: GameState a
}
play :: GameEngine a b -> Int
play engine
| performWithState isTerminal engine = performWithState getScore engine $ performWithState getPlayer engine
| otherwise = play $ GameEngine (gameActions engine) (getNextState engine)
getNextState :: GameEngine a b -> GameState a
getNextState engine = performWithState getResult engine . head $ performWithState getMoves engine
performWithState :: (GameActions a b -> GameState a -> c) -> GameEngine a b -> c
performWithState f engine = f (gameActions engine) $ state engine