-- -- Copyright (c) 2005 Don Stewart - http://www.cse.unsw.edu.au/~dons -- Sean Seefried -- Stefan Wehr -- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html) -- module RobberABMoveFun where import Prelude hiding ( catch ) import Syntax import CR import Graph import KnowledgeBase import qualified RobberHeuristic as RH import qualified RobberOneStepMoveFun as OneStep import AlphaBeta import Logging import Control.Exception import Control.Concurrent import Control.Concurrent.MVar import Data.IORef ( newIORef, readIORef, writeIORef, IORef ) import System.IO.Unsafe ( unsafePerformIO ) type State = (Maybe ThreadId, -- tid of the background thread MVar Move) -- container for the result of the background AB backgroundComp :: IORef State backgroundComp = unsafePerformIO $ do mvar <- newEmptyMVar newIORef (Nothing, mvar) {-# NOINLINE backgroundComp #-} getBackgroundResult :: IO (Maybe Move) getBackgroundResult = do (mtid, mvar) <- readIORef backgroundComp x <- tryTakeMVar mvar case x of Nothing -> -- mvar, background computation not finished do info "background computation not yet finished" case mtid of Just tid -> killThread tid `catch` (\e -> warn (show e)) Nothing -> return () mvar' <- newEmptyMVar writeIORef backgroundComp (Nothing, mvar') return Nothing Just move -> do mvar' <- newEmptyMVar writeIORef backgroundComp (Nothing, mvar') return $ Just move bgCutoff n | n < 2 = 14 | n < 4 = 15 | otherwise = 16 preFun :: CR () preFun = do (_, mvar) <- liftIO $ readIORef backgroundComp kb <- getKB info "forking new thread for precomputing next move" tid <- liftIO $ forkIO (doBg kb mvar) info $ "tid of thread running the pre-computation: " ++ show tid liftIO $ writeIORef backgroundComp (Just tid, mvar) where doBg kb mvar = time Info "background computation" $ do tid <- myThreadId --info ("now in the background") let cutoff = bgCutoff (kb_worldCount kb) info ("cutoff for background computation: " ++ show cutoff) let next = robberABSearch kb cutoff util --info ("result computed in the background: " ++ (show next)) next `seq` putMVar mvar (Move (locOfNode next) Robber (kb_ownName kb)) moveFun :: CR Move moveFun = do info ("checking if pre-computed result available") bgr <- liftIO $ getBackgroundResult case bgr of Just move -> do info ("using result computed in the background") return move Nothing -> do warn ("CANNOT USE RESULT COMPUTED IN THE BACKGROUND") watchdogCR directTimeout (moveFun' directCutoff) OneStep.moveFun -- timeout and cutoff for running AB-search inside the move function directTimeout = 4100 directCutoff = 6 util :: KnowledgeBase -> Int util kb = let loc = case kb_ownLoc kb of [(name,loc)] -> loc l -> niceError ("robber cannot be at " ++ show (length l) ++ " locations: " ++ show l) in floor $ RH.goodness kb loc 5 -- cop thresh dist 0.5 -- nearMoneyCoeff 1 -- haveMoneyCoeff 1000 -- smelledCoeff 500 -- copCoeff 100000 -- caughtCoeff moveFun' :: Int -> CR Move moveFun' cutoff = do kb <- getKB let next = robberABSearch kb cutoff util next `seq` return $ Move (locOfNode next) Robber (kb_ownName kb)