summaryrefslogtreecommitdiff
path: root/Hsbot/Plugin
diff options
context:
space:
mode:
authorJulien Dessaux2011-05-11 00:29:19 +0200
committerJulien Dessaux2011-05-11 00:29:19 +0200
commita6ac073a6c5887fccbd75cb3a24e0b9cfd072cf0 (patch)
treec1b080a88fad0d62fb431be6cd31d48960916afa /Hsbot/Plugin
parentAdded a function to get the destination channel of a message. (diff)
downloadhsbot-a6ac073a6c5887fccbd75cb3a24e0b9cfd072cf0.tar.gz
hsbot-a6ac073a6c5887fccbd75cb3a24e0b9cfd072cf0.tar.bz2
hsbot-a6ac073a6c5887fccbd75cb3a24e0b9cfd072cf0.zip
Re-engineered and finished the duck spawning capability.
Diffstat (limited to '')
-rw-r--r--Hsbot/Plugin/Duck.hs84
1 files changed, 57 insertions, 27 deletions
diff --git a/Hsbot/Plugin/Duck.hs b/Hsbot/Plugin/Duck.hs
index 4a09d28..afc9fa3 100644
--- a/Hsbot/Plugin/Duck.hs
+++ b/Hsbot/Plugin/Duck.hs
@@ -19,44 +19,70 @@ import Hsbot.Utils
duck :: PluginId
duck = PluginId
{ pluginName = "duck"
- , pluginEp = theDuck "" 11 }
+ , pluginEp = theDuck "" 10 }
-- | An IRC plugin that generates and kills ducks
theDuck :: String -> Int -> Plugin (Env IO) ()
theDuck channel seconds = do
- env <- lift ask
- pEnv <- ask
- secondsMVar <- liftIO $ newMVar seconds
- killMVar <- liftIO newEmptyMVar
- (liftIO . forkIO $ runReaderT (runReaderT (duckSpawner channel secondsMVar killMVar) pEnv) env) >>= lift . addThreadIdToQuitMVar
- forever $ readMsg >>= eval
+ ducksMVar <- liftIO newEmptyMVar
+ duckSpawner channel seconds ducksMVar
+ forever $ readMsg >>= eval ducksMVar
where
- eval :: Message -> Plugin (Env IO) ()
- eval (IncomingMsg msg)
- | IRC.msg_command msg == "PRIVMSG" = answerMsg msg . isThereADuckToKillInThere . concat $ IRC.msg_params msg
+ eval :: MVar Int -> Message -> Plugin (Env IO) ()
+ eval ducksMVar (IncomingMsg msg)
+ | IRC.msg_command msg == "PRIVMSG" = do
+ -- First we kill the ducks that we find in the message
+ let kills = howManyDucksInThere . concat $ IRC.msg_params msg
+ when (kills /= "") $ answerMsg msg kills
+ -- Then we check if someone shot some duck
+ let shots = howManyBulletFiredInThere . concat $ IRC.msg_params msg
+ noDucksToShot <- liftIO $ isEmptyMVar ducksMVar
+ when (and [getDestination msg == channel, not noDucksToShot, shots > 0]) $ do
+ -- TODO: score dead ducks (with a min (ducksWaitingForDeath, shots))
+ ducksWaitingForDeath <- liftIO $ modifyMVar ducksMVar (\x -> return (x - shots, x))
+ when (shots >= ducksWaitingForDeath) $ do
+ _ <- liftIO $ takeMVar ducksMVar
+ duckSpawner channel seconds ducksMVar
+ -- TODO : score lost bullets and round
+ return ()
+ -- Finally we check if we received some command
+ cmdArgs <- lift $ getCommand msg
+ case cmdArgs of
+ --"ducks":"stats":args -> TODO
+ "ducks":_ -> answerMsg msg "Invalid duck command."
+ _ -> return ()
| otherwise = return ()
- eval _ = return ()
+ eval _ _ = return ()
-- | Regularly spawns ducks on a channel, just waiting to be shot
-duckSpawner :: String -> MVar Int -> MVar Int -> Plugin (Env IO) ()
-duckSpawner channel secondsMVar killMVar = forever $ do
- nbDucks <- liftIO . getStdRandom $ randomR (1,4)
- liftIO $ putMVar killMVar nbDucks
- thoseDucks <- liftIO $ someRandomDucks nbDucks ""
- writeMsg . OutgoingMsg $ IRC.Message Nothing "PRIVMSG" [channel, thoseDucks]
- secs <- liftIO $ readMVar secondsMVar
- liftIO $ threadDelay (3000000 * secs)
+duckSpawner :: String -> Int -> MVar Int -> Plugin (Env IO) ()
+duckSpawner channel secs ducksMVar = do
+ pEnv <- ask
+ lift ask >>= liftIO . forkIO . runReaderT (runReaderT trueSpawner pEnv) >>= lift . addThreadIdToQuitMVar
+ where
+ trueSpawner :: Plugin (Env IO) ()
+ trueSpawner = do
+ rsecs <- liftIO . getStdRandom $ randomR (1,secs)
+ liftIO $ threadDelay (1000000 * rsecs)
+ nbDucks <- liftIO . getStdRandom $ randomR (1,4)
+ thoseDucks <- liftIO $ replicateM nbDucks someRandomDuck
+ liftIO $ putMVar ducksMVar nbDucks
+ writeMsg . OutgoingMsg $ IRC.Message Nothing "PRIVMSG" [channel, concat thoseDucks]
+ liftIO myThreadId >>= lift . delThreadIdFromQuitMVar
-- | Shoot as many times are there are ducks in the initial string
-isThereADuckToKillInThere :: String -> String
-isThereADuckToKillInThere = concat . concatMap (\y -> map (\x -> if x `L.isInfixOf` y then "PAN! " else "") ducks) . words
+howManyBulletFiredInThere :: String -> Int
+howManyBulletFiredInThere = sum . concatMap (\y -> map (\x -> if x `L.isInfixOf` y then 1 else 0) bangs) . words
-someRandomDucks :: Int -> String -> IO String
-someRandomDucks 0 theDucks = return theDucks
-someRandomDucks nbDucks theDucks = do
- whatDuck <- getStdRandom $ randomR (1,length ducks)
- let thisDuck = ducks !! whatDuck
- someRandomDucks (nbDucks -1 ) $ concat [thisDuck, " ", theDucks]
+-- | Shoot as many times are there are ducks in the initial string
+howManyDucksInThere :: String -> String
+howManyDucksInThere = concat . concatMap (\y -> map (\x -> if x `L.isInfixOf` y then "PAN! " else "") ducks) . words
+
+-- | Output a string made of the specified number of random ducks
+someRandomDuck :: IO String
+someRandomDuck = do
+ whatDuck <- getStdRandom $ randomR (0,length ducks - 1)
+ return $ ducks !! whatDuck ++ " "
-- | There are many ways to hide as a duck, this function tries to cover most of them
ducks :: [String]
@@ -68,3 +94,7 @@ ducks = [ x : y : z | x <- nose, y <- face, z <- ["__/", "_/", "/"] ]
face :: String
face = "oO°@©®ð*òôóø"
+-- | Weapons can have different noises
+bangs :: [String]
+bangs = [ "PAN", "PAN!" ]
+