packages feed

nomyx-core-1.0.0: src/Nomyx/Core/Engine/Utils.hs

{-# LANGUAGE FlexibleInstances   #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE NamedFieldPuns      #-}
{-# LANGUAGE Rank2Types          #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- | additional tools for evaluation
module Nomyx.Core.Engine.Utils where

import           Control.Applicative
import           Control.Category
import           Control.Lens
import           Control.Monad
import           Control.Monad.Reader
import           Control.Monad.State
import           Data.List
import qualified Data.Text.IO as DT
import           Data.Maybe
import           Data.Typeable
import           Imprevu.Evaluation as Imp
import           Nomyx.Language.Types
import           Nomyx.Core.Engine.Types
import           Prelude                   hiding (log, (.))
import           Safe
import           Debug.Trace.Helpers    (traceM)
import           System.FilePath                 (dropFileName, (</>))
import           System.Directory (createDirectoryIfMissing)


log :: Maybe PlayerNumber -> String -> Evaluate ()
log mpn s = focusGame $ do
   time <- use currentTime
   void $ logs %= (Log mpn time s : )

focusGame :: State Game a -> Evaluate a
focusGame = lift . zoom (evalEnv . eGame)

accessGame :: Lens' Game a -> Evaluate (a, RuleNumber)
accessGame l = do
   a <- use (evalEnv . eGame . l)
   rn <- use (evalEnv . eRuleNumber)
   return (a, rn)

putGame :: Lens' Game a -> a -> Evaluate ()
putGame l a = do
   ruleActive <- evalRuleActive
   void $ (evalEnv . eGame . l) .= a --when ruleActive $

modifyGame :: Lens' Game a -> (a -> a) -> Evaluate ()
modifyGame l f = do
   ruleActive <- evalRuleActive
   void $ (evalEnv . eGame . l) %= f --when ruleActive $

evalRuleActive :: Evaluate Bool
evalRuleActive = do
   rn <- use (evalEnv . eRuleNumber)
   rs <- use (evalEnv . eGame . rules)
   return $ (rn == 0) ||
      case find (\r -> _rNumber r == rn) rs of
         Just r -> _rStatus r == Active
         Nothing -> True --TODO why should there be an evaluating rule not in the list?


--replace temporarily the rule number used for evaluation
withRN :: RuleNumber -> Evaluate a -> Evaluate a
withRN rn eval = do
   oldRn <- use (evalEnv . eRuleNumber)
   evalEnv . eRuleNumber .= rn
   a <- eval
   evalEnv . eRuleNumber .= oldRn
   return a

tracePN :: (Monad m) => Int -> String -> m ()
tracePN pn s = traceM $ "Player " ++ (show pn) ++ " " ++ s

mapStateIO :: Show s => State s a -> StateT s IO a
mapStateIO = mapStateT $ return . runIdentity

--TODO handle error cases
saveModule :: FilePath -> ModuleInfo -> IO (FilePath)
saveModule saveDir (ModuleInfo path content) = do
   let dest = saveDir </> path
   createDirectoryIfMissing True $ dropFileName dest
   DT.writeFile dest content
   return dest