Skat Engine und AI auf Haskell Basis
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

109 行
3.1KB

  1. {-# LANGUAGE MultiParamTypeClasses #-}
  2. {-# LANGUAGE FlexibleInstances #-}
  3. module Pile where
  4. import Data.List
  5. import Card
  6. import Utils
  7. import Control.Exception
  8. data Team = Team | Single
  9. deriving (Show, Eq, Ord, Enum)
  10. data CardS p = CardS { getCard :: Card
  11. , getPile :: p }
  12. deriving (Show, Eq)
  13. instance Countable (CardS p) Int where
  14. count = count . getCard
  15. data Hand = Hand1 | Hand2 | Hand3
  16. deriving (Show, Eq, Ord)
  17. next :: Hand -> Hand
  18. next Hand1 = Hand2
  19. next Hand2 = Hand3
  20. next Hand3 = Hand1
  21. prev :: Hand -> Hand
  22. prev Hand1 = Hand3
  23. prev Hand2 = Hand1
  24. prev Hand3 = Hand2
  25. data Played = Table Hand
  26. | Won Hand Team
  27. deriving (Show, Eq)
  28. data SkatP = SkatP
  29. deriving (Show, Eq)
  30. data Piles = Piles { hands :: [CardS Hand]
  31. , played :: [CardS Played]
  32. , skat :: [CardS SkatP] }
  33. deriving (Show, Eq)
  34. instance Countable Piles (Int, Int) where
  35. count ps = (sgl, tm)
  36. where sgl = count (skatCards ps) + count (wonCards Single ps)
  37. tm = count (wonCards Team ps)
  38. origin :: CardS Played -> Hand
  39. origin (CardS _ (Table hand)) = hand
  40. origin (CardS _ (Won hand _)) = hand
  41. originOfCard :: Card -> Piles -> Maybe Hand
  42. originOfCard card (Piles _ pld _) = origin <$> find ((==card) . getCard) pld
  43. playCard :: Card -> Piles -> Piles
  44. playCard card (Piles hs pld skt) = Piles hs' (ca : pld) skt
  45. where (CardS _ hand, hs') = remove ((==card) . getCard) hs
  46. ca = CardS card (Table hand)
  47. winCard :: Team -> CardS Played -> CardS Played
  48. winCard team (CardS card (Table hand)) = CardS card (Won hand team)
  49. winCard team c = c
  50. wonCards :: Team -> Piles -> [Card]
  51. wonCards team (Piles _ pld _) = filterMap (f . getPile) getCard pld
  52. where f (Won _ tm) = tm == team
  53. f _ = False
  54. cleanTable :: Team -> Piles -> Piles
  55. cleanTable winner ps@(Piles hs pld skt) = Piles hs pld' skt
  56. where table = tableCards ps
  57. pld' = map (winCard winner) pld
  58. tableCards :: Piles -> [Card]
  59. tableCards (Piles _ pld _) = filterMap (f . getPile) getCard pld
  60. where f (Table _) = True
  61. f _ = False
  62. tableCardsS :: Piles -> [CardS Played]
  63. tableCardsS (Piles _ pld _) = filter (f . getPile) pld
  64. where f (Table _) = True
  65. f _ = False
  66. handCards :: Hand -> Piles -> [Card]
  67. handCards hand (Piles hs _ _) = filterMap ((==hand) . getPile) getCard hs
  68. skatCards :: Piles -> [Card]
  69. skatCards (Piles _ _ skat) = map getCard skat
  70. putAt :: p -> Card -> CardS p
  71. putAt = flip CardS
  72. distribute :: [Card] -> Piles
  73. distribute cards = Piles hands [] (map (putAt SkatP) skt)
  74. where round1 = chunksOf 3 (take 9 cards)
  75. skt = take 2 $ drop 9 cards
  76. round2 = chunksOf 4 (take 12 $ drop 11 cards)
  77. round3 = chunksOf 3 (take 9 $ drop 23 cards)
  78. hand1 = concatMap (!! 0) [round1, round2, round3]
  79. hand2 = concatMap (!! 1) [round1, round2, round3]
  80. hand3 = concatMap (!! 2) [round1, round2, round3]
  81. hands = map (putAt Hand1) hand1
  82. ++ map (putAt Hand2) hand2
  83. ++ map (putAt Hand3) hand3