Skat Engine und AI auf Haskell Basis
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

204 linhas
5.8KB

  1. module Operations where
  2. import Control.Monad.State
  3. import System.Random (newStdGen, randoms)
  4. import Data.List
  5. import Data.Ord
  6. import Card
  7. import Skat
  8. import Utils (shuffle)
  9. compareCards :: Colour
  10. -> Maybe Colour
  11. -> Card
  12. -> Card
  13. -> Ordering
  14. compareCards _ _ (Card Jack col1) (Card Jack col2) = compare col1 col2
  15. compareCards trumpCol turnCol c1@(Card tp1 col1) c2@(Card tp2 col2) =
  16. case compare trp1 trp2 of
  17. EQ ->
  18. case compare (col1 `equals` turnCol)
  19. (col2 `equals` turnCol) of
  20. EQ -> compare tp1 tp2
  21. v -> v
  22. v -> v
  23. where trp1 = isTrump trumpCol c1
  24. trp2 = isTrump trumpCol c2
  25. sortCards :: Colour -> Maybe Colour -> [Card] -> [Card]
  26. sortCards trumpCol turnCol cs = sortBy (compareCards trumpCol turnCol) cs
  27. compareRender :: Card -> Card -> Ordering
  28. compareRender (Card t1 c1) (Card t2 c2) = case compare c1 c2 of
  29. EQ -> compare t1 t2
  30. v -> v
  31. sortRender :: [Card] -> [Card]
  32. sortRender = sortBy compareRender
  33. -- | finishes the calculation of a match
  34. turning :: Index -> Skat (Int, Int)
  35. turning n = undefined
  36. turn2 :: Index -> Skat (Int, Int)
  37. turn2 n = do
  38. t <- table
  39. ps <- gets players
  40. let p = player ps n
  41. hand <- cardsAt (playerHand $ index p)
  42. if length hand == 0
  43. then countGame
  44. else case length t of
  45. 0 -> play p >> turn2 (next n)
  46. 1 -> do
  47. modify (setTurnColour . f . head $ t)
  48. play p
  49. turn2 (next n)
  50. 2 -> play p >> evaluateTable >>= turn2
  51. 3 -> evaluateTable >>= turn2
  52. where f (Card _ col) = Just col
  53. simulate :: Team -> Index -> Skat (Int, Int)
  54. simulate team n = do
  55. t <- table
  56. ps <- gets players
  57. let p = player ps n
  58. hand <- cardsAt (playerHand $ index p)
  59. if length hand == 0
  60. then countGame
  61. else case length t of
  62. 0 -> playOpen team p >> simulate team (next n)
  63. 1 -> do
  64. modify (setTurnColour . f . head $ t)
  65. playOpen team p
  66. simulate team (next n)
  67. 2 -> playOpen team p >> evaluateTable >>= simulate team
  68. 3 -> evaluateTable >>= simulate team
  69. where f (Card _ col) = Just col
  70. evaluateTable :: Skat Index
  71. evaluateTable = do
  72. trumpCol <- gets trumpColour
  73. turnCol <- gets turnColour
  74. t <- table
  75. ts <- tableS
  76. ps <- gets players
  77. let psOrdered = playersFromTable ps ts
  78. l = zip psOrdered t
  79. g a b = compareCards trumpCol turnCol (snd a) (snd b)
  80. (winner, _) = last (sortBy g l)
  81. pile = teamPile $ team winner
  82. forM t (\c -> move c pile)
  83. modify $ setTurnColour Nothing
  84. return $ index winner
  85. countGame :: Skat (Int, Int)
  86. countGame = do
  87. sgl <- count <$> cardsAt WonSingle
  88. tm <- count <$> cardsAt WonTeam
  89. return (sgl, tm)
  90. turn :: Index -> Skat Index
  91. turn n = do
  92. ps <- gets players
  93. let p1 = player ps n
  94. p2 = player ps (next n)
  95. p3 = player ps (next $ next n)
  96. c1@(Card _ col) <- play p1
  97. modify $ setTurnColour (Just col)
  98. c2 <- play p2
  99. c3 <- play p3
  100. trumpCol <- gets trumpColour
  101. turnCol <- gets turnColour
  102. let l = zip3 [p1, p2, p3] [c1, c2, c3] [n, next n, next $ next n]
  103. g a b = compareCards trumpCol turnCol (f a) (f b)
  104. (winner, _, idx) = last (sortBy g l)
  105. pile = teamPile $ team winner
  106. move c1 pile
  107. move c2 pile
  108. move c3 pile
  109. modify $ setTurnColour Nothing
  110. return idx
  111. where f (_, x, _) = x
  112. play :: Player -> Skat Card
  113. play p = do
  114. table <- table
  115. turnCol <- gets turnColour
  116. trump <- gets trumpColour
  117. hand <- cardsAt (playerHand $ index p)
  118. let card = playCard p table hand trump turnCol
  119. move card Table
  120. return card
  121. playOpen :: Team -> Player -> Skat Card
  122. playOpen team p = do
  123. card <- playCardOpenAI team p
  124. move card Table
  125. return card
  126. -- | cheating AI that knows all cards (open play)
  127. playCardOpenAI :: Team -> Player -> Skat Card
  128. playCardOpenAI team p = do
  129. table <- table
  130. turnCol <- gets turnColour
  131. trump <- gets trumpColour
  132. hand <- cardsAt (playerHand $ index p)
  133. let possible = filter (isAllowed trump turnCol hand) hand
  134. ownResult = if team == Single then fst else snd
  135. ownIdx = index p
  136. results <- forM possible (\card -> do
  137. move card Table
  138. val <- ownResult <$> simulate team ownIdx
  139. move card (playerHand $ index p)
  140. return (val, card))
  141. return $ snd $ maximumBy (comparing fst) results
  142. playCard :: Player
  143. -> [Card]
  144. -> [Card]
  145. -> Colour
  146. -> Maybe Colour
  147. -> Card
  148. playCard p table hand trump turnCol = head possible
  149. where possible = filter (isAllowed trump turnCol hand) hand
  150. runGame :: Skat (Int, Int)
  151. runGame = do
  152. foldM_ (\i _ -> turn i) One [1..10]
  153. sgl <- fmap count $ cardsAt WonSingle
  154. tm <- fmap count $ cardsAt WonTeam
  155. return (sgl, tm)
  156. shuffleCards :: IO [Card]
  157. shuffleCards = do
  158. gen <- newStdGen
  159. return $ shuffle gen allCards
  160. -- TESTING VARS
  161. env :: SkatEnv
  162. env = SkatEnv cards Nothing Spades playersExamp
  163. where hand1 = take 10 allCards
  164. hand2 = take 10 $ drop 10 allCards
  165. hand3 = take 10 $ drop 20 allCards
  166. skt = drop 30 allCards
  167. cards = map (putAt Hand1) hand1
  168. ++ map (putAt Hand2) hand2
  169. ++ map (putAt Hand3) hand3
  170. ++ map (putAt WonSingle) skt
  171. playersExamp :: Players
  172. playersExamp = Players (Player Team One) (Player Team Two) (Player Single Three)
  173. shuffledEnv :: IO SkatEnv
  174. shuffledEnv = do
  175. cards <- shuffleCards
  176. return $ SkatEnv (distribute cards) Nothing Spades playersExamp
  177. shuffledEnv2 :: IO SkatEnv
  178. shuffledEnv2 = do
  179. cards <- shuffleCards
  180. return $ SkatEnv (distributePutSkat cards) Nothing Spades playersExamp