|
{-# OPTIONS -Wall #-}
|
|
import Control.Applicative
|
|
import Datatypes.Game
|
|
import VM
|
|
|
|
|
|
|
|
data MonadicGameInternal = MonadicGameInternal { igame :: Game , inote :: Notes}
|
|
|
|
data MonadicGame a = MonadicAction {action :: (MonadicGameInternal -> (MonadicGameInternal, a))}
|
|
|
|
instance Functor MonadicGame where
|
|
fmap f (MonadicAction modifierFunction) = (MonadicAction newModifierFunction)
|
|
where
|
|
newModifierFunction = (\x -> ((fst . modifierFunction) x, (f . snd . modifierFunction) x))
|
|
|
|
|
|
instance Applicative MonadicGame where
|
|
(MonadicAction higherOrderModifierFunction) <*> (MonadicAction modifierFunction) = (MonadicAction newModifierFunction)
|
|
where
|
|
getGameFunction = fst . modifierFunction
|
|
getValueFunction = snd . modifierFunction
|
|
newGameState = fst . higherOrderModifierFunction . getGameFunction
|
|
functionToApply = snd . higherOrderModifierFunction . getGameFunction
|
|
newModifierFunction = (\x -> (newGameState x, (functionToApply x) (getValueFunction x)))
|
|
|
|
pure retData = MonadicAction (\x -> (x, retData))
|
|
|
|
|
|
instance Monad MonadicGame where
|
|
(MonadicAction modifierFunction) >>= f = (MonadicAction newModifierFunction)
|
|
where
|
|
getGameFunction = fst . modifierFunction
|
|
getValueFunction = snd . modifierFunction
|
|
getParametrizedModifierFunction = action . f . getValueFunction
|
|
newModifierFunction = (\x -> getParametrizedModifierFunction x (getGameFunction x))
|
|
|
|
return = pure
|
|
|
|
-- Private state modifiers --
|
|
|
|
modifyGame :: (a -> MonadicGameInternal -> (MonadicGameInternal, b)) -> a -> MonadicGame b
|
|
modifyGame accessorFunction param = (MonadicAction (accessorFunction param))
|
|
|
|
readGame :: (MonadicGameInternal -> a) -> MonadicGame a
|
|
readGame readFunction = modifyGame (\_ x -> (x, readFunction x)) ()
|
|
|
|
writeGame :: (a -> MonadicGameInternal -> MonadicGameInternal) -> a -> MonadicGame ()
|
|
writeGame writeFunction = modifyGame (\x y -> (writeFunction x y, ()))
|
|
|
|
------ Public Functions -----
|
|
|
|
|
|
-- Apply the monad to a Game
|
|
executeGame :: Game -> MonadicGame () -> ([Command], Int)
|
|
executeGame game (MonadicAction finalFunction) = (history executedGame, score executedGame)
|
|
where
|
|
executedGame = (igame . fst . finalFunction) (MonadicGameInternal{igame = game, inote = OK})
|
|
|
|
-- Execute a command
|
|
move :: Command -> MonadicGame ()
|
|
move command = writeGame applyMove command
|
|
where
|
|
applyMove param oldGameInternal = newInternals
|
|
where
|
|
newInternals = MonadicGameInternal {igame = newIgame, inote = newInote}
|
|
newIgame = fst $ step (igame oldGameInternal) param
|
|
newInote = snd $ step (igame oldGameInternal) param
|
|
|
|
-- Execute a list of commands
|
|
moves :: [Command] -> MonadicGame ()
|
|
moves commands = mapM_ move commands
|
|
|
|
-- Read actual score
|
|
readScore :: MonadicGame Int
|
|
readScore = readGame (score . igame)
|
|
|
|
-- Read actual note
|
|
readNote :: MonadicGame Notes
|
|
readNote = readGame inote
|
|
|
|
-----------------------------
|