Skat Engine und AI auf Haskell Basis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.6KB

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