Reputation:
I'm trying to implement a tick event, and have a little test below that demonstrates that it doesn't work. I'd appreciate insight as to why it doesn't work.
gameloop :: TChan UAC ->
IO ()
gameloop commandChannel = do
(tickHandler, tickSink) <- newAddHandler
networkDescr <- compile $ makeNetworkDescription commandChannel tickHandler
actuate networkDescr
forkIO $ forever $ (timer 10) >>= tickSink
return ()
makeNetworkDescription :: forall t . Frameworks t =>
TChan UAC ->
AddHandler () ->
Moment t ()
makeNetworkDescription commandChannel tickHandler = do
eTick <- fromAddHandler tickHandler
bCChannel <- fromPoll $ grabCommands commandChannel
-- test fromPoll
test <- initial bCChannel
liftIO $ appendFile "testPoll.txt" $ show test
-- end fromPoll test
let eCChannel = bCChannel <@ eTick
liftIO $ print "hi there\n"
reactimate $ (\n -> appendFile "Commands.txt" (show n)) <$> eCChannel
grabCommands :: TChan UAC -> IO [UAC]
grabCommands unval = do
result <- (atomically $ readTChan unval) `untilM` (atomically $ isEmptyTChan unval)
liftIO $ print $ show result
return result
timer :: TimeOut -> IO ()
timer ms = do
threadDelay ms
Here's some test data.
main :: IO ()
main = do
commandChan <- atomically $ newTChan :: IO (TChan UAC)
forkIO $ gameloop commandChan
liftIO $ print "back from fork\n"
atomically $ populateCC commandChan playerCommands
return ()
populateCC :: TChan UAC -> [UAC] -> STM ()
populateCC pChannel pCommands = mapM_ (writeTChan pChannel) pCommands
playerCommands =
[UAC (PlayerCommand (CommandData (T.pack "1" :: AID) Look) (T.pack "1")),
UAC (PlayerCommand (CommandData (T.pack "2" :: AID) (Move Mongo)) (T.pack "2"))
]
when I execute the above Main
I get this output.
"back from fork\n"
"[UAC (PlayerCommand (CommandData \"1\" Look) \"1\"),UAC (PlayerCommand (CommandData \"2\" (Move Mongo)) \"2\")]"
"hi there\n"
The file Commands.txt
never comes into existence. I attribute this problem to a faulty tick event.
I got my idea for the timer implementation from this, but wonder if I'm thinking about this the wrong way. Any ideas?
Edit: I wanted some assurance fromPoll
was doing the right thing. I added the test above, and it is.
Upvotes: 4
Views: 220
Reputation: 11064
It appears to me that the problem is not with the tick event, but with the fact that you model the player commands as a Behavior
.
If you think denotationally and imagine that a behavior is a time-varying value Behavior a = Time -> a
, does it make sense to model player commands in this way? What is the player command in, say, the time frame between 3s
and 4s
? Does the argument you give to fromPoll
respect these semantics?
The thing is that grabCommands
has a serious side effect: calling it removes the commands from the channel, so it is not even idempotent. Also, it blocks when there is no command available. I think that this is ultimately the reason why the tick event doesn't work: the network is blocked trying to execute the fromPoll
action. However, the underlying problem is more profound: the right way to model player commands is to use an Event
, not a Behavior
.
Upvotes: 2