Question

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top