packages feed

general-games-0.3.0: test/Spec.hs

import Control.Monad.Random
import Test.Hspec
import Game.Game.Poker
import Game.Implement.Card
import Game.Implement.Card.Standard

allHandsCount :: Int
allHandsCount = length allPossibleHands
allHandsCountExpected :: Int
allHandsCountExpected = 2598960
allRoyalFlushCountExpected :: Int
allRoyalFlushCountExpected = 4
allStraightFlushCountExpected :: Int
allStraightFlushCountExpected = 36
allFourOfAKindCountExpected :: Int
allFourOfAKindCountExpected = 624
allFullHouseCountExpected :: Int
allFullHouseCountExpected = 3744
allFlushCountExpected :: Int
allFlushCountExpected = 5108
allStraightCountExpected :: Int
allStraightCountExpected = 10200
allThreeOfAKindCountExpected :: Int
allThreeOfAKindCountExpected = 54912
allTwoPairCountExpected :: Int
allTwoPairCountExpected = 123552
allPairCountExpected :: Int
allPairCountExpected = 1098240
allHighCardCountExpected :: Int
allHighCardCountExpected = 1302540

royalFlush :: [PlayingCard]
royalFlush =
  [PlayingCard Ace Hearts,
   PlayingCard Queen Hearts,
   PlayingCard King Hearts,
   PlayingCard Jack Hearts,
   PlayingCard Ten Hearts]

royalFlushNot :: [PlayingCard]
royalFlushNot =
  [PlayingCard Ace Hearts,
   PlayingCard Queen Hearts,
   PlayingCard Eight Hearts,
   PlayingCard Jack Hearts,
   PlayingCard Ten Hearts]

drawDeck :: [PlayingCard]
drawDeck =
  [PlayingCard Five Diamonds,
   PlayingCard Seven Clubs,
   PlayingCard Two Spades,
   PlayingCard King Spades,
   PlayingCard King Hearts,
   PlayingCard Ace Diamonds,
   PlayingCard Seven Diamonds,
   PlayingCard Three Clubs,
   PlayingCard Four Clubs]


drawDeckSizes :: [Int]
drawDeckSizes = [1,4,2]

drawDeckSizesFail :: [Int]
drawDeckSizesFail = [5,9]

drawDeckSizesFailNeg :: [Int]
drawDeckSizesFailNeg = [-3,4]


drawDeckExpectedOutput :: Maybe ([[PlayingCard]],[PlayingCard])
drawDeckExpectedOutput = Just
  ([[PlayingCard Five Diamonds],
   [PlayingCard Seven Clubs,
   PlayingCard Two Spades,
   PlayingCard King Spades,
   PlayingCard King Hearts],
   [PlayingCard Ace Diamonds,
   PlayingCard Seven Diamonds]],
   [PlayingCard Three Clubs,
   PlayingCard Four Clubs])

confirmDisjoint :: (Int, Bool)
confirmDisjoint =
  let mfunc1 hand = [mkRoyalFlush hand,
                     mkStraightFlush hand,
                     mkFourOfAKind hand,
                     mkFullHouse hand,
                     mkFlush hand,
                     mkStraight hand,
                     mkThreeOfAKind hand,
                     mkTwoPair hand,
                     mkPair hand,
                     mkHighCard hand]
      maybem (Just _) = 1
      maybem Nothing = 0
      countJust hand = sum $ map maybem $ mfunc1 hand
      allSums = map countJust allPossibleHands
      collect _  (outsum, False) = (outsum, False)
      collect (x:xs) (outsum, _) =
        collect xs (x+outsum, if x==0 || x==1 then True else False)
      collect [] output = output 
  in
    collect allSums (0, True)

isUnique :: Eq a => [a] -> Bool
isUnique lst = f lst True where
  f _ False = False
  f [] result = result
  f (x:xs) _ = if x `elem` xs then f xs False else f xs True

shuffledDeck :: RandomGen g => Rand g [PlayingCard]
shuffledDeck = shuffle $ fullDeck

main :: IO ()
main =
  do
    randdecks <- evalRandIO $ replicateM 10000 shuffledDeck;

    hspec $ do
      describe "Game.Implement.Card.draw (PlayingCard)" $ do
        it "returns drawn hands from a deck, plus the remaining deck" $ do
          (draw drawDeckSizes drawDeck) `shouldBe` drawDeckExpectedOutput
        it "returns Nothing when trying to return more cards than in deck" $ do
          (draw drawDeckSizesFail drawDeck) `shouldBe` Nothing
        it "returns Nothing when trying to return negative cards" $ do
          (draw drawDeckSizesFailNeg drawDeck) `shouldBe` Nothing

      describe "Game.Implement.Card.fullDeck (PlayingCard)" $ do
        it "returns 52 cards" $ do
          length (fullDeck :: [PlayingCard]) `shouldBe` 52
        it "returns unique cards" $ do
          isUnique (fullDeck :: [PlayingCard]) `shouldBe` True

      describe "Game.Implement.Card.shuffle (PlayingCard)" $ do
        it "returns 10000 different fullDeck shuffles using the global random generator" $ do
          (isUnique randdecks) `shouldBe` True
  
      describe "Game.Implement.Card.Standard.Poker.isRoyalFlush" $ do
        it "confirms that [AH, QH, KH, JH, TH] is a Royal Flush" $ do
          (isRoyalFlush royalFlush) `shouldBe` True
        it "confirms that [AH, QH, 8H, JH, TH] is not a Royal Flush" $ do
          (isRoyalFlush royalFlushNot) `shouldBe` False
      describe "Game.Implement.Card.Standard.Poker allPossibleHands / mkHand / isHand functions" $ do
        it "confirms that sets of each hand are disjoint and that total count correct" $ do
          confirmDisjoint `shouldBe` (allHandsCountExpected, True)
        it "confirms the total number of poker hands" $ do
          allHandsCount `shouldBe` allHandsCountExpected
        it "confirms the total number of royal flushes" $ do
          (length allRoyalFlush) `shouldBe` allRoyalFlushCountExpected
        it "confirms the total number of straight flushes" $ do
          (length allStraightFlush) `shouldBe` allStraightFlushCountExpected
        it "confirms the total number of four-of-a-kinds" $ do
          (length allFourOfAKind) `shouldBe` allFourOfAKindCountExpected
        it "confirms the total number of full houses" $ do
          (length allFullHouse) `shouldBe` allFullHouseCountExpected
        it "confirms the total number of flushes" $ do
          (length allFlush) `shouldBe` allFlushCountExpected
        it "confirms the total number of straights" $ do
          (length allStraight) `shouldBe` allStraightCountExpected
        it "confirms the total number of three-of-a-kinds" $ do
          (length allThreeOfAKind) `shouldBe` allThreeOfAKindCountExpected
        it "confirms the total number of two-pairs" $ do
          (length allTwoPair) `shouldBe` allTwoPairCountExpected
        it "confirms the total number of pairs" $ do
          (length allPair) `shouldBe` allPairCountExpected
        it "confirms the total number of high card hands" $ do
          (length allHighCard) `shouldBe` allHighCardCountExpected