From 76e60894cd5d9fc25009821409df6ae9b518a0fd Mon Sep 17 00:00:00 2001 From: Barak Michener Date: Thu, 13 Nov 2014 16:50:33 -0500 Subject: [PATCH] Add players and strategies --- ZombieDice.hs | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/ZombieDice.hs b/ZombieDice.hs index 2e59db6..42d60ef 100644 --- a/ZombieDice.hs +++ b/ZombieDice.hs @@ -4,6 +4,9 @@ import Control.Monad import Control.Monad.Trans.Maybe import Data.List import Data.Maybe +import Data.Ord +import System.IO.Unsafe + data Cup = Cup { green :: Int, @@ -131,8 +134,83 @@ playRound (Just player) = do {-outcome <- rollHand playerWithHand-} {-return $ acceptOutcome playerWithHand outcome-} +type StratFunction = Int -> [Int] -> PlayerState -> IO Bool +maxi xs = maximumBy (comparing fst) (zip xs [0..]) +replace pos newVal list = take pos list ++ newVal : drop (pos+1) list + +playZombieRound strat playerIndex scores = playZombieRound' strat playerIndex scores defaultPlayer + + +playZombieRound' :: (RandomGen g) => StratFunction -> Int -> [Int] -> PlayerState -> Rand g Int +playZombieRound' strat index scores state = do + if continue + then do + newState <- playRound (Just state) + if (isNothing newState) + then return (scores !! index) + else playZombieRound' strat index scores (fromJust newState) + else + return $ (scores !! index) + (brains state) + where continue = unsafePerformIO $ strat index scores state + + +playZombieDice playerStrats = evalRandIO $ playZombieDice' playerStrats 0 (-1) $ take (length playerStrats) $ repeat 0 + +playZombieDice' playerStrats playerIndex final scores = + if playerIndex == nPlayers + then playZombieDice' playerStrats 0 final scores + else if final == playerIndex then return $ snd $ maxi scores + else if (foldl max 0 scores) >= 13 && final == -1 + then playZombieDice' playerStrats playerIndex newFinal scores + else do + newscore <- playZombieRound (playerStrats !! playerIndex) playerIndex scores + let newscores = replace playerIndex newscore scores in + playZombieDice' playerStrats (playerIndex + 1) final newscores + where nPlayers = length scores + newFinal = if (playerIndex == 0) then (nPlayers - 1) else (playerIndex - 1) + +humanPlayer index scores state = do + putStrLn "\n" + putStrLn $ "Your Score: " ++ show (scores !! index) + putStrLn $ "Scores: " ++ show (scores) ++ " Index " ++ show index + putStrLn $ "Your State:" + print state + putStrLn "Continue?" + response <- getLine + if response == "y" then return True else return False + +getNPlayer :: Int -> StratFunction +getNPlayer n index scores state = do + if (brains state) < n then return True else return False + +getFourPlayer = getNPlayer 4 +getFivePlayer = getNPlayer 5 + +fiftyFiftyPlayer :: Int -> StratFunction +fiftyFiftyPlayer n index scores state = + if brains state == 0 then return True else do + outcomeStates <- replicateM n (evalRandIO $ playNRounds 1 state) + if length (filter isJust outcomeStates) > ((3 * (quot n 4)) - (quot n 7)) then return True else return False + +expectimaxPlayer :: Int -> Float -> StratFunction +expectimaxPlayer n limit index scores state = do + outcomeStates <- replicateM n (evalRandIO $ playNRounds 1 state) + let scoretotal = sum $ map (\x -> x - (brains state)) $ map brains $ catMaybes outcomeStates in + let badscore = failScore * (length $ filter isNothing outcomeStates) in + let expectedValue = (fromIntegral (scoretotal + badscore)) / (fromIntegral n) in do + {-print state-} + {-print expectedValue -} + if expectedValue > limit then return True else return False + where failScore = 0 - (brains state) + + + main = mainN 8 100000 +playAndReport strats x = do + out <- replicateM x (playZombieDice strats) + print $ report out + mainN n x = do outcomeStates <- replicateM x (evalRandIO $ playNRounds n defaultPlayer) print "brains"