module CCard where import Data.Word (Word64) import Data.Bits (clearBit, testBit, setBit, Bits) import System.Random (randomRIO) data Flower = Pine | Plum | Cherry | Wisteria | Iris | Peony | BushClover | SusukiGrass | Chrysanthemum | Maple | Willow | Paulownia deriving (Eq, Ord, Enum, Show) data Card = Pine0 | Pine1 | PinePoetry | Crane | Plum0 | Plum1 | PlumPoetry | BushWarbler | Cherry0 | Cherry1 | CherryPoetry | CampCurtain | Wisteria0 | Wisteria1 | WisteriaRed | Cuckoo | Iris0 | Iris1 | IrisRed | EightPlankBridge | Peony0 | Peony1 | PeonyBlue | Butterflies | BushClover0 | BushClover1 | BushCloverRed | Boar | SusukiGrass0 | SusukiGrass1 | Geese | FullMoon | Chrysanthemum0 | Chrysanthemum1 | ChrysanthemumBlue | SakeCup | Maple0 | Maple1 | MapleBlue | Deer | Lightning | WillowRed | Swallow | RainMan | Paulownia0 | Paulownia1 | Sand | Phoenix deriving (Eq, Ord, Enum, Show) flower :: Card -> Flower flower = toEnum . (`div` 4) . fromEnum type Pack = Word64 packOfCards :: [Card] -> Pack packOfCards = foldl setBit 0 . map fromEnum port :: (Bits a, Enum e) => (a -> Int -> b) -> a -> e -> b port f bits = f bits . fromEnum contains :: Pack -> Card -> Bool contains = port testBit add :: Pack -> Card -> Pack add = port setBit remove :: Pack -> Card -> Pack remove = port clearBit pair :: Card -> Card -> Bool pair card1 card2 = flower card1 == flower card2 cards :: [Card] cards = [Pine0 .. Phoenix] shuffle :: [a] -> IO [a] shuffle l = aux (length l) l where aux n [] = return [] aux n (h:t) = do cut <- randomRIO (0, n-1) shuffled <- shuffle t let (top, bottom) = splitAt cut shuffled return $ top ++ h : bottom