module ALife.Creatur.Task
(
AgentProgram,
AgentsProgram,
withAgent,
withAgents,
runNoninteractingAgents,
runInteractingAgents,
simpleDaemon,
startupHandler,
shutdownHandler,
exceptionHandler,
noSummary
) where
import ALife.Creatur.Daemon (Daemon(..))
import ALife.Creatur.Universe (Universe, Agent, AgentProgram,
AgentsProgram, writeToLog, lineup, refresh, markDone, endOfRound,
withAgent, withAgents, incTime)
import Control.Conditional (whenM)
import Control.Exception (SomeException)
import Control.Monad.State (StateT, execStateT)
import Data.Serialize (Serialize)
simpleDaemon :: Universe u => Daemon u
simpleDaemon = Daemon
{
onStartup = startupHandler,
onShutdown = shutdownHandler,
onException = exceptionHandler,
task = undefined,
username = "",
sleepTime = 100
}
startupHandler :: Universe u => u -> IO u
startupHandler = execStateT (writeToLog $ "Starting")
shutdownHandler :: Universe u => u -> IO ()
shutdownHandler u = do
_ <- execStateT (writeToLog "Shutdown requested") u
return ()
exceptionHandler :: Universe u => u -> SomeException -> IO (Bool, u)
exceptionHandler u x = do
u' <- execStateT (writeToLog ("WARNING: " ++ show x)) u
return (True, u')
runNoninteractingAgents
:: (Universe u, Serialize (Agent u))
=> AgentProgram u -> SummaryProgram u -> StateT u IO Bool
runNoninteractingAgents agentProgram summaryProgram = do
atEndOfRound summaryProgram
as <- lineup
if null as
then return False
else do
let a = head as
markDone a
withAgent agentProgram a
return True
runInteractingAgents
:: (Universe u, Serialize (Agent u))
=> AgentsProgram u -> Int -> SummaryProgram u -> StateT u IO Bool
runInteractingAgents agentsProgram minAgents summaryProgram = do
atEndOfRound summaryProgram
as <- lineup
if length (take minAgents as) < minAgents
then do
writeToLog "Population too small"
summaryProgram
writeToLog "Requesting shutdown (population too small)"
return False
else do
markDone (head as)
withAgents agentsProgram as
return True
atEndOfRound
:: Universe u
=> SummaryProgram u -> StateT u IO ()
atEndOfRound summaryProgram = do
whenM endOfRound $ do
writeToLog "End of round"
summaryProgram
refresh
incTime
writeToLog "Beginning of round"
type SummaryProgram u = StateT u IO ()
noSummary :: SummaryProgram u
noSummary = return ()