-- -- A cop that walks around randomly -- module CopRandomStrategy where import Logging import CR import Syntax import KnowledgeBase import Graph import Utils import qualified Data.Map as M import Data.Maybe import Data.List ((\\)) import System.IO.Unsafe import Control.Concurrent.MVar import Control.Monad import System.IO -- evil name to see if we can break other people's parsers copName = "78094" copCRState = CRState { crCopStrat = niceError "no cop strategy", crRobberStrat = niceError "no robber strategy defined", crKB = Nothing } {- -- He will conduct a random walk randomCopStrategy = CopStrategy { csMkRegisterMsg = \ name -> return $ Register name CopFoot , csStoreWorldSkel = \wks -> do setKB $ mkInitialKnowledge wks kbCopCfg , csStoreWorld = \w -> do kb <- getKB setKB (updateKnowledge kb w) updateCopVisited -- pick a random bank and compute the shortest path p <- liftIO getPathToBank when (isNothing p) $ do kb <- getKB bank <- liftIO $ stdGetRandItem (kb_bankNodes kb) let here = kb_ownLoc kb g = kb_footMap kb path = gshortestpath' here bank g liftIO $ setPathToBank path , csMkInformMsg = dummyInformMsg , csMkPlanMsg = \_ -> dummyPlanMsg , csMkVoteMsg = \_ -> dummyVoteMsg , csMkMoveMsg = \_ -> moveToBank >>= \m -> return (m, NotDirty) } ------------------------------------------------------------------------ -- Add current positions of all cops to list of visited nodes -- updateCopVisited = do kb <- getKB let cops = kb_cops kb mapM_ (liftIO . setVisited) (map cop_node cops) ------------------------------------------------------------------------ -- -- A better strategy. Perform a random walk until we smell the robber. randomUntilSmell = do kb <- getKB case kb_smell kb of Nothing -> randomMove Just i -> stayStill -- A random walk randomMove = do kb <- getKB let here = kb_ownLoc kb g = kb_footMap kb nexts = gsucc g here next <- liftIO $ stdGetRandItem nexts return $ CopMove Straight (MoveBlock [Move (locOfNode next) CopFoot (kb_ownName kb)]) (AccuseBlock []) -- A random walk, where we don't go where we've been before. randomNewMove = do kb <- getKB let here = kb_ownLoc kb g = kb_footMap kb nexts = gsucc g here nexts' <- liftIO $ filterM (\b -> isVisited b >>= return . not) nexts next <- liftIO $ stdGetRandItem (if null nexts' then nexts else nexts') liftIO $ setVisited next return $ CopMove Straight (MoveBlock [Move (locOfNode next) CopFoot (kb_ownName kb)]) (AccuseBlock []) -- Shortest path to bank moveToBank = do kb <- getKB mp <- liftIO getPathToBank let p = fromJust mp -- should only be Nothing at the start... if null p then randomNewMove else case p of (a:xs) -> do liftIO $ setPathToBank xs liftIO $ setVisited a return $ CopMove Straight (MoveBlock [Move (locOfNode a) CopFoot (kb_ownName kb)]) (AccuseBlock []) ------------------------------------------------------------------------ visitedNodes :: MVar (M.Map GNode ()) visitedNodes = unsafePerformIO $ newMVar M.empty {-# NOINLINE visitedNodes #-} isVisited :: GNode -> IO Bool isVisited g = withMVar visitedNodes $ \m -> return $ case M.lookup g m of Nothing -> False Just _ -> True setVisited :: GNode -> IO () setVisited g = modifyMVar_ visitedNodes $ \m -> return $ M.insert g () m ------------------------------------------------------------------------ bankPath :: MVar (Maybe GPath) bankPath = unsafePerformIO $ newMVar Nothing {-# NOINLINE bankPath #-} setPathToBank :: GPath -> IO () setPathToBank p = modifyMVar_ bankPath $ \_ -> return (Just p) getPathToBank :: IO (Maybe GPath) getPathToBank = readMVar bankPath ------------------------------------------------------------------------ -- Stay where we are stayStill = do kb <- getKB return $ CopMove Straight (MoveBlock [Move (locOfNode (kb_ownLoc kb)) CopFoot (kb_ownName kb)]) (AccuseBlock []) ------------------------------------------------------------------------ -- Simple inform. Just guess that the robber is where they started. dummyInformMsg = do kb <- getKB return $ InformMsg [Inform (kb_robberName kb) (locOfNode $ kb_robberStart kb) Robber (kb_worldCount kb) (-90) ] -- A random plan dummyPlanMsg = do kb <- getKB let foot = kb_footMap kb car = kb_carMap kb cops = kb_cops kb nexts <- sequence [ do let ns = gsucc (if ty == ByFoot then foot else car) here liftIO $ stdGetRandItem ns | (Cop _ here ty) <- cops ] return $ PlanMsg [ Plan nm (locOfNode node) (cop2Player typ) (kb_worldCount kb) | (node, (Cop nm _ typ)) <- zip nexts cops ] {- -- Ignore all informs. Suggest our own plan. dummyPlanMsg = do kb <- getKB return $ PlanMsg [ Plan nm dummyLoc (cop2Player typ) (kb_worldCount kb) | (Cop nm _ typ) <- kb_cops kb ] where dummyLoc = "55-and-university" -} -- Vote for our own plan dummyVoteMsg = do kb <- getKB let me = kb_ownName kb return $ VoteMsg $ (kb_ownName kb) : (kb_copNames kb \\ [me]) -}