-- -- 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 RobberSPMoveFun where import List ( minimumBy ) import Maybe ( mapMaybe ) import Syntax import CR import Graph import KnowledgeBase import Logging import Data.IORef ( newIORef, readIORef, writeIORef, IORef ) import System.IO.Unsafe ( unsafePerformIO ) import Control.Concurrent.MVar -- the state is the remaining path to go type State = Maybe GPath state :: IORef State state = unsafePerformIO (newIORef Nothing) {-# NOINLINE state #-} getState :: CR State getState = liftIO $ readIORef state setState :: State -> CR () setState s = do liftIO $ writeIORef state s moveFun :: CR Move moveFun = do kb <- getKB case kb_ownLoc kb of [(name,loc)] -> moveFun' name loc l -> fatal ("robber cannot be at " ++ show (length l) ++ " locations: " ++ show l) moveFun' :: Name -> GNode -> CR Move moveFun' name loc = do kb <- getKB state <- getState (next, newState) <- nextStep kb state info ("robber goes from " ++ show (kb_ownLoc kb) ++ " to " ++ show next ++ ", nextSteps: " ++ show newState) setState newState return $ Move (locOfNode next) Robber (kb_ownName kb) where bankWithMoney b | (bank_money b) > 0 = Just (bank_node b) | otherwise = Nothing sp :: GNode -> Graph -> GNode -> GSimplePath sp n1 g n2 = (gshortestpath n1 n2 g) cmpPath p1 p2 = length p1 `compare` length p2 nextStep :: KnowledgeBase -> State -> CR (GNode, State) nextStep kb Nothing = -- compute the shortest path to a bank which still has money let bankNodes = mapMaybe bankWithMoney (kb_banks kb) g = kb_footMap kb paths = map (sp loc g) bankNodes newState = if null paths then Nothing else Just (simplePath2path g $ minimumBy cmpPath paths) in do info ("all shortest paths: " ++ show paths ++ ", new goal path: " ++ show newState) case newState of Nothing -> do info ("no bank with money left, bank nodes: " ++ show bankNodes) return (loc, Nothing) Just l -> do nextStep kb newState nextStep kb (Just (n:[])) = return (n, Nothing) nextStep kb (Just (n:ns)) = return (n, Just ns) nextStep kb (Just []) = do warn "precomputed shortest path is empty" return (loc, Nothing)