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.

206 linhas
7.8KB

  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 hiding (Result)
  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. instance Communicator c => Bidder (PrepOnline c) where
  42. hand = prepHand
  43. askBid p against bid = do
  44. liftIO $ send (prepConnection p) (BS.unpack $ encode $ BidQuery against bid)
  45. r <- liftIO $ receive (prepConnection p)
  46. case decode (BS.pack r) of
  47. Just (BidResponse newBid) -> do
  48. if newBid > bid then return $ Just newBid else return Nothing
  49. Nothing -> askBid p against bid
  50. askResponse p bidder bid = do
  51. liftIO $ send (prepConnection p) (BS.unpack $ encode $ BidResponseQuery bidder bid)
  52. r <- liftIO $ receive (prepConnection p)
  53. case decode (BS.pack r) of
  54. Just (YesNo value) -> return value
  55. Nothing -> askResponse p bidder bid
  56. askGame p bid = do
  57. liftIO $ send (prepConnection p) (BS.unpack $ encode $ AskGameQuery bid)
  58. r <- liftIO $ receive (prepConnection p)
  59. case decode (BS.pack r) of
  60. Just (GameResponse game) -> return game
  61. Nothing -> askGame p bid
  62. askHand p bid = do
  63. liftIO $ send (prepConnection p) (BS.unpack $ encode $ AskHandQuery)
  64. r <- liftIO $ receive (prepConnection p)
  65. case decode (BS.pack r) of
  66. Just (YesNo value) -> return value
  67. Nothing -> askHand p bid
  68. askSkat p bid cards = do
  69. liftIO $ send (prepConnection p) (BS.unpack $ encode $ AskSkatQuery cards bid)
  70. r <- liftIO $ receive (prepConnection p)
  71. case decode (BS.pack r) of
  72. Just (ChosenCards cards) -> return cards
  73. Nothing -> askSkat p bid cards
  74. toPlayer p tm = PL $ OnlineEnv tm (prepHand p) (prepConnection p)
  75. onBid p mayBid reizer gereizter =
  76. liftIO $ send (prepConnection p) (BS.unpack $ encode $ BidEvent mayBid reizer gereizter)
  77. onResponse p response reizer gereizter =
  78. liftIO $ send (prepConnection p) (BS.unpack $ encode $ ResponseEvent response reizer gereizter)
  79. onStart p = do
  80. let cards = sortRender Jacks $ prepCards p
  81. liftIO $ send (prepConnection p) (BS.unpack $ encode $ CardsQuery cards)
  82. onResult p res =
  83. liftIO $ send (prepConnection p) (BS.unpack $ encode $ GameResultsQuery res)
  84. onGame p game sglPlayer = do
  85. liftIO $ send (prepConnection p) (BS.unpack $ encode $ GameStartQuery game sglPlayer)
  86. type Online a m = ReaderT (OnlineEnv a) m
  87. instance (Communicator c, MonadIO m) => MonadClient (Online c m) where
  88. query s = do
  89. conn <- asks connection
  90. liftIO $ send conn s
  91. response = do
  92. conn <- asks connection
  93. liftIO $ receive conn
  94. instance MonadPlayer m => MonadPlayer (Online a m) where
  95. trump = lift $ trump
  96. turnColour = lift $ turnColour
  97. showSkat = lift . showSkat
  98. choose :: HasCard a => (Communicator c, MonadPlayer m) => [CardS Played] -> [a] -> Online c m Card
  99. choose table hand' = do
  100. let hand = sortRender Jacks $ map toCard hand'
  101. query (BS.unpack $ encode $ ChooseQuery hand table)
  102. r <- response
  103. case decode (BS.pack r) of
  104. Just (ChosenResponse card) -> do
  105. allowed <- P.isAllowed hand card
  106. if card `elem` hand && allowed then return card else choose table hand'
  107. Nothing -> choose table hand'
  108. cardPlayed :: (Communicator c, MonadPlayer m) => CardS Played -> Online c m ()
  109. cardPlayed card = query (BS.unpack $ encode $ CardPlayedQuery card)
  110. -- | QUERIES AND RESPONSES
  111. data Query = ChooseQuery [Card] [CardS Played]
  112. | CardPlayedQuery (CardS Played)
  113. | GameResultsQuery Result
  114. | GameStartQuery Game Hand
  115. | BidQuery Hand Bid
  116. | BidResponseQuery Hand Bid
  117. | AskGameQuery Bid
  118. | AskHandQuery
  119. | AskSkatQuery [Card] Bid
  120. | CardsQuery [Card]
  121. | BidEvent (Maybe Bid) Hand Hand
  122. | ResponseEvent Bool Hand Hand
  123. newtype ChosenResponse = ChosenResponse Card
  124. newtype BidResponse = BidResponse Int
  125. newtype YesNo = YesNo Bool
  126. newtype GameResponse = GameResponse Game
  127. deriving Show
  128. newtype ChosenCards = ChosenCards [Card]
  129. instance ToJSON Query where
  130. toJSON (ChooseQuery hand table) =
  131. object ["query" .= ("choose_card" :: String), "hand" .= hand, "table" .= table]
  132. toJSON (CardPlayedQuery card) =
  133. object ["query" .= ("card_played" :: String), "card" .= card]
  134. toJSON (GameResultsQuery result) =
  135. object ["query" .= ("results" :: String), "result" .= result]
  136. toJSON (GameStartQuery game sglPlayer) =
  137. object [ "query" .= ("start_game" :: String)
  138. , "game" .= game
  139. , "single" .= toInt sglPlayer ]
  140. toJSON (BidQuery hand bid) =
  141. object ["query" .= ("bid" :: String), "whom" .= show hand, "current" .= bid]
  142. toJSON (BidResponseQuery hand bid) =
  143. object ["query" .= ("bid_response" :: String), "from" .= show hand, "bid" .= bid ]
  144. toJSON (AskHandQuery) =
  145. object ["query" .= ("play_hand" :: String)]
  146. toJSON (AskSkatQuery cards bid) =
  147. object ["query" .= ("skat" :: String), "cards" .= cards, "bid" .= bid ]
  148. toJSON (CardsQuery cards) =
  149. object ["query" .= ("cards" :: String), "cards" .= cards ]
  150. toJSON (AskGameQuery bid) =
  151. object ["query" .= ("ask_game" :: String), "bid" .= bid]
  152. toJSON (BidEvent (Just bid) reizer gereizter) =
  153. object ["query" .= ("bid_event" :: String), "bid" .= bid, "reizer" .= show reizer,
  154. "gereizter" .= show gereizter ]
  155. toJSON (BidEvent Nothing reizer gereizter) =
  156. object [ "query" .= ("bid_event" :: String)
  157. , "bid" .= ("weg" :: String)
  158. , "reizer" .= show reizer
  159. , "gereizter" .= show gereizter ]
  160. toJSON (ResponseEvent response reizer gereizter) =
  161. object [ "query" .= ("response_event" :: String)
  162. , "response" .= response
  163. , "reizer" .= show reizer
  164. , "gereizter" .= show gereizter ]
  165. instance FromJSON ChosenResponse where
  166. parseJSON = withObject "ChosenResponse" $ \v -> ChosenResponse
  167. <$> v .: "card"
  168. instance FromJSON BidResponse where
  169. parseJSON = withObject "BidResponse" $ \v -> BidResponse
  170. <$> v .: "bid"
  171. instance FromJSON YesNo where
  172. parseJSON = withObject "BidYesNo" $ \v -> YesNo
  173. <$> v .: "yesno"
  174. instance FromJSON GameResponse where
  175. parseJSON = withObject "GameResponse" $ \v -> GameResponse
  176. <$> v .: "game"
  177. instance FromJSON ChosenCards where
  178. parseJSON = withObject "ChosenCards" $ \v -> ChosenCards
  179. <$> v .: "cards"