{-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} module Skat.AI.Online where import Control.Monad.Reader import Network.WebSockets (Connection, sendTextData, receiveData) import Data.Aeson import qualified Data.ByteString.Lazy.Char8 as BS import Skat.Player import qualified Skat.Player.Utils as P import Skat.Pile import Skat.Card import Skat.Render class Monad m => MonadClient m where query :: String -> m () response :: m String data OnlineEnv = OnlineEnv { getTeam :: Team , getHand :: Hand , connection :: Connection } deriving Show instance Show Connection where show _ = "A connection" instance Player OnlineEnv where team = getTeam hand = getHand chooseCard p table _ hand = runReaderT (choose table hand) p >>= \c -> return (c, p) onCardPlayed p c = runReaderT (cardPlayed c) p >> return p onGameResults p res = runReaderT (onResults res) p onGameStart p singlePlayer = runReaderT (onStart singlePlayer) p type Online m = ReaderT OnlineEnv m instance MonadIO m => MonadClient (Online m) where query s = do conn <- asks connection liftIO $ sendTextData conn (BS.pack s) response = do conn <- asks connection liftIO $ BS.unpack <$> receiveData conn instance MonadPlayer m => MonadPlayer (Online m) where trumpColour = lift $ trumpColour turnColour = lift $ turnColour showSkat = lift . showSkat choose :: MonadPlayer m => [CardS Played] -> [Card] -> Online m Card choose table hand = do query (BS.unpack $ encode $ ChooseQuery hand table) r <- response case decode (BS.pack r) of Just (ChosenResponse card) -> do allowed <- P.isAllowed hand card if card `elem` hand && allowed then return card else choose table hand Nothing -> choose table hand cardPlayed :: MonadPlayer m => CardS Played -> Online m () cardPlayed card = query (BS.unpack $ encode $ CardPlayedQuery card) onResults :: MonadIO m => (Int, Int) -> Online m () onResults (sgl, tm) = query (BS.unpack $ encode $ GameResultsQuery sgl tm) onStart :: MonadPlayer m => Hand -> Online m () onStart singlePlayer = do trCol <- trumpColour ownHand <- asks getHand query (BS.unpack $ encode $ GameStartQuery trCol ownHand singlePlayer) data Query = ChooseQuery [Card] [CardS Played] | CardPlayedQuery (CardS Played) | GameResultsQuery Int Int | GameStartQuery Colour Hand Hand data Response = ChosenResponse Card instance ToJSON Query where toJSON (ChooseQuery hand table) = object ["query" .= ("choose_card" :: String), "hand" .= hand, "table" .= table] toJSON (CardPlayedQuery card) = object ["query" .= ("card_played" :: String), "card" .= card] toJSON (GameResultsQuery sgl tm) = object ["query" .= ("results" :: String), "single" .= sgl, "team" .= tm] toJSON (GameStartQuery trumps handNo sglPlayer) = object ["query" .= ("start_game" :: String), "trumps" .= show trumps, "hand" .= toInt handNo, "single" .= toInt sglPlayer] instance FromJSON Response where parseJSON = withObject "ChosenResponse" $ \v -> ChosenResponse <$> v .: "card"