|
{-# OPTIONS -Wall #-}
|
|
module MonadicGame(executeGame, move, moves, readScore, readNote, getBestMovesFromHere, saveGame, loadGame, deleteSavedGame, deleteAllSaved, loadFromGame, executeStepCommands, retrieveGameData) where
|
|
|
|
import Control.Applicative
|
|
import qualified Data.HashMap as M
|
|
import Data.Maybe
|
|
import Datatypes.Game
|
|
import VM
|
|
|
|
data MonadicGameInternal = MonadicGameInternal { igame :: Game , inote :: Notes, isaves :: M.Map String (Game,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, return the list of command to execute and the score
|
|
executeGame :: Game -> MonadicGame () -> ([Command], Int)
|
|
executeGame game (MonadicAction actions) = (history executedGame, score executedGame)
|
|
where
|
|
executedGame = (igame . fst . actions) (MonadicGameInternal{igame = game, inote = OK, isaves = M.empty})
|
|
|
|
loadFromGame :: Game -> MonadicGameInternal
|
|
loadFromGame game = (MonadicGameInternal{igame = game, inote = OK, isaves = M.empty})
|
|
|
|
executeStepCommands :: MonadicGame () -> MonadicGameInternal -> MonadicGameInternal
|
|
executeStepCommands (MonadicAction actions) game = newGame
|
|
where
|
|
newGame = (fst . actions) game
|
|
|
|
retrieveGameData :: MonadicGameInternal -> ([Command],Int)
|
|
retrieveGameData game = bestData
|
|
where
|
|
bestData = M.fold findBestFun initData (isaves game)
|
|
initData = ((history . igame) game, (score . igame) game)
|
|
findBestFun procEl (bestHist,bestScore) = if bestScore > (score . fst) procEl
|
|
then (bestHist,bestScore)
|
|
else (bestHist,bestScore)
|
|
-- Execute a command
|
|
move :: Command -> MonadicGame ()
|
|
move command = writeGame applyMove command
|
|
where
|
|
applyMove param oldGameInternal = newInternals
|
|
where
|
|
newInternals = oldGameInternal{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
|
|
|
|
getBestMovesFromHere :: [MonadicGame ()] -> MonadicGame ()
|
|
getBestMovesFromHere [] = return ()
|
|
getBestMovesFromHere movesArr = writeGame bestGameFun movesArr
|
|
where
|
|
bestGameFun param oldGameInternal = bestBranch
|
|
where
|
|
bestBranch = foldl maxBranch oldGameInternal gameBranches
|
|
gameBranches = map (\x -> (fst . (action x)) oldGameInternal) param
|
|
maxBranch oldMax actualBranch = if (score . igame $ oldMax) > (score . igame $ actualBranch)
|
|
then oldMax
|
|
else actualBranch
|
|
|
|
saveGame :: String -> MonadicGame ()
|
|
saveGame saveStr = writeGame saveGameFun saveStr
|
|
where
|
|
saveGameFun param oldGameInternal = savedGameInternal
|
|
where
|
|
savedGameInternal = oldGameInternal{isaves = (M.insert param (actualIgame,actualNote) actualIsaves)}
|
|
actualIsaves = isaves oldGameInternal
|
|
actualIgame = igame oldGameInternal
|
|
actualNote = inote oldGameInternal
|
|
|
|
loadGame :: String -> MonadicGame Bool
|
|
loadGame loadStr = modifyGame loadGameFun loadStr
|
|
where
|
|
loadGameFun param oldGameInternal = (loadedGameInternal, loaded)
|
|
where
|
|
lookupResult = M.lookup param (isaves oldGameInternal)
|
|
(loadedGame, loadedNote, loaded) = if isJust lookupResult
|
|
then (fst $ fromJust lookupResult,snd $ fromJust lookupResult, True)
|
|
else (igame oldGameInternal, inote oldGameInternal, False)
|
|
loadedGameInternal = oldGameInternal{igame = loadedGame, inote = loadedNote}
|
|
|
|
|
|
deleteSavedGame :: String -> MonadicGame Bool
|
|
deleteSavedGame delStr = modifyGame deleteSavedGameFun delStr
|
|
where
|
|
deleteSavedGameFun param oldGameInternal = (deletedSavedGameInternal, deleted)
|
|
where
|
|
oldGameISaved = isaves oldGameInternal
|
|
deleted = M.member param oldGameISaved
|
|
deletedSavedGameInternal = if deleted
|
|
then oldGameInternal{isaves = (M.delete param oldGameISaved)}
|
|
else oldGameInternal
|
|
|
|
|
|
deleteAllSaved :: MonadicGame ()
|
|
deleteAllSaved = writeGame deleteAllSavedGameFun ()
|
|
where
|
|
deleteAllSavedGameFun _ oldGameInternal = deletedAllSavedGameInternal
|
|
where
|
|
deletedAllSavedGameInternal = oldGameInternal{isaves = M.empty}
|
|
|
|
-----------------------------
|