import Control.Applicative import Control.Lens hiding (has, indices, uses) import Control.Monad.State hiding (state) import Dominion import qualified Dominion.Cards as CA import Dominion.Internal import qualified Dominion.Types as T import Prelude hiding (log) import Test.Hspec -- | Use this to run a strategy once and inspect the gamestate. runOnce :: T.Player -> T.Strategy -> IO T.GameState runOnce player strategy = do state <- makeGameState [] [player] snd <$> runStateT (game [strategy]) state -- | Give a hand of cards and a function. You play one round -- with this given hand of cards. The function returns True or False. withHand :: [T.Card] -> [T.Option] -> (T.PlayerId -> T.Dominion Bool) -> IO Bool withHand hand options func = do let player = T.Player "testPlayer" (7 `cardsOf` CA.copper ++ 3 `cardsOf` CA.estate) [] hand 1 1 0 state <- makeGameState options [player] fst <$> runStateT (func 0) state bigMoney playerId = playerId `buysByPreference` [CA.province, CA.gold, CA.duchy, CA.silver, CA.copper] stupidStrategy playerId = playerId `buysByPreference` [CA.province, CA.gold] bigMoney2 playerId = do roundNum <- getRound if (roundNum < 6) then playerId `buysByPreference` [CA.province, CA.gold, CA.silver] else bigMoney playerId bigMoneySmithy playerId = do playerId `plays` CA.smithy roundNum <- getRound if (roundNum < 6) then playerId `buysByPreference` [CA.province, CA.gold, CA.smithy, CA.silver] else bigMoney playerId io = flip shouldReturn count x list = realToFrac . length $ filter (==x) list main = do hspec $ do describe "integration tests" $ do it "the stupid strategy of only buying provinces and golds should never win" $ do io True $ do winners <- map T.winner <$> dominion ["sherlock" `uses` bigMoney, "watson" `uses` stupidStrategy] return $ not ("watson" `elem` winners) it "bigMoney2 should win 1.4 times as often as bigMoney" $ do io True $ do winners <- map T.winner <$> dominion ["sherlock" `uses` bigMoney, "watson" `uses` bigMoney2] return $ (count "watson" winners) >= (1.4 * (count "sherlock" winners)) it "bigMoneySmithy should win more often than bigMoney2" $ do io True $ do winners <- map T.winner <$> dominionWithOpts [Cards [CA.smithy]] ["sherlock" `uses` bigMoneySmithy, "watson" `uses` bigMoney2] return $ (count "sherlock" winners) >= (count "watson" winners) -- silly spec, shows an example of how to use `withHand` it "market should add to the players cards, buys, money, and actions" $ do io True $ do withHand [CA.market, CA.copper, CA.copper, CA.estate, CA.estate] [] $ \playerId -> do playerId `plays` CA.market player <- getPlayer playerId return $ player ^. T.actions == 1 && player ^. T.extraMoney == 1 && player ^. T.buys == 2