Skat Engine und AI auf Haskell Basis
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

190 wiersze
6.9KB

  1. {-# LANGUAGE TypeSynonymInstances #-}
  2. {-# LANGUAGE FlexibleInstances #-}
  3. {-# LANGUAGE OverloadedStrings #-}
  4. module Skat.AI.Online where
  5. import Control.Monad.Reader
  6. import Control.Concurrent.Chan
  7. import Data.Aeson
  8. import Data.Maybe
  9. import qualified Data.ByteString.Lazy.Char8 as BS
  10. import Skat.Player
  11. import qualified Skat.Player.Utils as P
  12. import Skat.Pile
  13. import Skat.Card
  14. import Skat.Render
  15. import Skat.Preperation
  16. import Skat.Bidding
  17. class Communicator a where
  18. send :: a -> String -> IO ()
  19. receive :: a -> IO String
  20. instance Communicator (Chan String) where
  21. send = writeChan
  22. receive = readChan
  23. class Monad m => MonadClient m where
  24. query :: String -> m ()
  25. response :: m String
  26. data OnlineEnv c = OnlineEnv { getTeam :: Team
  27. , getHand :: Hand
  28. , connection :: c }
  29. data PrepOnline c = PrepOnline { prepHand :: Hand
  30. , prepConnection :: c
  31. , prepCards :: [Card] }
  32. instance Show (OnlineEnv c) where
  33. show _ = "An online env"
  34. instance Show (PrepOnline c) where
  35. show _ = "An online prep env"
  36. instance Communicator c => Player (OnlineEnv c) where
  37. team = getTeam
  38. hand = getHand
  39. chooseCard p table _ hand = runReaderT (choose table hand) p >>= \c -> return (c, p)
  40. onCardPlayed p c = runReaderT (cardPlayed c) p >> return p
  41. onGameResults p res = runReaderT (onResults res) p
  42. onGameStart p singlePlayer = runReaderT (onStartOnline singlePlayer) p
  43. instance Communicator c => Bidder (PrepOnline c) where
  44. hand = prepHand
  45. askBid p against bid = do
  46. liftIO $ send (prepConnection p) (BS.unpack $ encode $ BidQuery against bid)
  47. r <- liftIO $ receive (prepConnection p)
  48. case decode (BS.pack r) of
  49. Just (BidResponse newBid) -> do
  50. if newBid > bid then return $ Just newBid else return Nothing
  51. Nothing -> askBid p against bid
  52. askResponse p bidder bid = do
  53. liftIO $ send (prepConnection p) (BS.unpack $ encode $ BidResponseQuery bidder bid)
  54. r <- liftIO $ receive (prepConnection p)
  55. case decode (BS.pack r) of
  56. Just (YesNo value) -> return value
  57. Nothing -> askResponse p bidder bid
  58. askGame p bid = do
  59. liftIO $ send (prepConnection p) (BS.unpack $ encode $ AskGameQuery bid)
  60. r <- liftIO $ receive (prepConnection p)
  61. case decode (BS.pack r) of
  62. Just (GameResponse game) -> return game
  63. Nothing -> askGame p bid
  64. askHand p bid = do
  65. liftIO $ send (prepConnection p) (BS.unpack $ encode $ AskHandQuery)
  66. r <- liftIO $ receive (prepConnection p)
  67. case decode (BS.pack r) of
  68. Just (YesNo value) -> return value
  69. Nothing -> askHand p bid
  70. askSkat p bid cards = do
  71. liftIO $ send (prepConnection p) (BS.unpack $ encode $ AskSkatQuery cards bid)
  72. r <- liftIO $ receive (prepConnection p)
  73. case decode (BS.pack r) of
  74. Just (ChosenCards cards) -> return cards
  75. Nothing -> askSkat p bid cards
  76. toPlayer p tm = PL $ OnlineEnv tm (prepHand p) (prepConnection p)
  77. onStart p = do
  78. let cards = prepCards p
  79. liftIO $ send (prepConnection p) (BS.unpack $ encode $ CardsQuery cards)
  80. type Online a m = ReaderT (OnlineEnv a) m
  81. instance (Communicator c, MonadIO m) => MonadClient (Online c m) where
  82. query s = do
  83. conn <- asks connection
  84. liftIO $ send conn s
  85. response = do
  86. conn <- asks connection
  87. liftIO $ receive conn
  88. instance MonadPlayer m => MonadPlayer (Online a m) where
  89. trumpColour = lift $ trumpColour
  90. turnColour = lift $ turnColour
  91. showSkat = lift . showSkat
  92. choose :: HasCard a => (Communicator c, MonadPlayer m) => [CardS Played] -> [a] -> Online c m Card
  93. choose table hand' = do
  94. let hand = map toCard hand'
  95. query (BS.unpack $ encode $ ChooseQuery hand table)
  96. r <- response
  97. case decode (BS.pack r) of
  98. Just (ChosenResponse card) -> do
  99. allowed <- P.isAllowed hand card
  100. if card `elem` hand && allowed then return card else choose table hand'
  101. Nothing -> choose table hand'
  102. cardPlayed :: (Communicator c, MonadPlayer m) => CardS Played -> Online c m ()
  103. cardPlayed card = query (BS.unpack $ encode $ CardPlayedQuery card)
  104. onResults :: (Communicator c, MonadIO m) => (Int, Int) -> Online c m ()
  105. onResults (sgl, tm) = query (BS.unpack $ encode $ GameResultsQuery sgl tm)
  106. onStartOnline :: (Communicator c, MonadPlayer m) => Hand -> Online c m ()
  107. onStartOnline singlePlayer = do
  108. trCol <- trumpColour
  109. ownHand <- asks getHand
  110. query (BS.unpack $ encode $ GameStartQuery trCol ownHand singlePlayer)
  111. -- | QUERIES AND RESPONSES
  112. data Query = ChooseQuery [Card] [CardS Played]
  113. | CardPlayedQuery (CardS Played)
  114. | GameResultsQuery Int Int
  115. | GameStartQuery Colour Hand Hand
  116. | BidQuery Hand Bid
  117. | BidResponseQuery Hand Bid
  118. | AskGameQuery Bid
  119. | AskHandQuery
  120. | AskSkatQuery [Card] Bid
  121. | CardsQuery [Card]
  122. newtype ChosenResponse = ChosenResponse Card
  123. newtype BidResponse = BidResponse Int
  124. newtype YesNo = YesNo Bool
  125. newtype GameResponse = GameResponse Game
  126. newtype ChosenCards = ChosenCards [Card]
  127. instance ToJSON Query where
  128. toJSON (ChooseQuery hand table) =
  129. object ["query" .= ("choose_card" :: String), "hand" .= hand, "table" .= table]
  130. toJSON (CardPlayedQuery card) =
  131. object ["query" .= ("card_played" :: String), "card" .= card]
  132. toJSON (GameResultsQuery sgl tm) =
  133. object ["query" .= ("results" :: String), "single" .= sgl, "team" .= tm]
  134. toJSON (GameStartQuery trumps handNo sglPlayer) =
  135. object ["query" .= ("start_game" :: String), "trumps" .= show trumps,
  136. "hand" .= toInt handNo, "single" .= toInt sglPlayer ]
  137. toJSON (BidQuery hand bid) =
  138. object ["query" .= ("bid" :: String), "whom" .= show hand ]
  139. toJSON (BidResponseQuery hand bid) =
  140. object ["query" .= ("bid_response" :: String), "from" .= show hand ]
  141. toJSON (AskHandQuery) =
  142. object ["query" .= ("play_hand" :: String)]
  143. toJSON (AskSkatQuery cards bid) =
  144. object ["query" .= ("skat" :: String), "cards" .= cards, "bid" .= bid ]
  145. toJSON (CardsQuery cards) =
  146. object ["query" .= ("cards" :: String), "cards" .= cards ]
  147. instance FromJSON ChosenResponse where
  148. parseJSON = withObject "ChosenResponse" $ \v -> ChosenResponse
  149. <$> v .: "card"
  150. instance FromJSON BidResponse where
  151. parseJSON = withObject "BidResponse" $ \v -> BidResponse
  152. <$> v .: "bid"
  153. instance FromJSON YesNo where
  154. parseJSON = withObject "BidYesNo" $ \v -> YesNo
  155. <$> v .: "yesno"
  156. instance FromJSON GameResponse where
  157. parseJSON = withObject "GameResponse" $ \v -> GameResponse
  158. <$> v .: "game"
  159. instance FromJSON ChosenCards where
  160. parseJSON = withObject "ChosenCards" $ \v -> ChosenCards
  161. <$> v .: "cards"