| @@ -1,88 +0,0 @@ | |||||
| module Operations where | |||||
| import Control.Monad.State | |||||
| import System.Random (newStdGen, randoms) | |||||
| import Data.List | |||||
| import Data.Ord | |||||
| import Card | |||||
| import Skat | |||||
| import Pile | |||||
| import Player (chooseCard, Players(..), Player(..), PL(..), | |||||
| updatePlayer, playersToList, player) | |||||
| import Utils (shuffle) | |||||
| compareRender :: Card -> Card -> Ordering | |||||
| compareRender (Card t1 c1) (Card t2 c2) = case compare c1 c2 of | |||||
| EQ -> compare t1 t2 | |||||
| v -> v | |||||
| sortRender :: [Card] -> [Card] | |||||
| sortRender = sortBy compareRender | |||||
| turnGeneric :: (PL -> Skat Card) | |||||
| -> Int | |||||
| -> Hand | |||||
| -> Skat (Int, Int) | |||||
| turnGeneric playFunc depth n = do | |||||
| table <- getp tableCards | |||||
| ps <- gets players | |||||
| let p = player ps n | |||||
| hand <- getp $ handCards n | |||||
| trCol <- gets trumpColour | |||||
| case length table of | |||||
| 0 -> playFunc p >> turnGeneric playFunc depth (next n) | |||||
| 1 -> do | |||||
| modify $ setTurnColour | |||||
| (Just $ effectiveColour trCol $ head table) | |||||
| playFunc p | |||||
| turnGeneric playFunc depth (next n) | |||||
| 2 -> playFunc p >> turnGeneric playFunc depth (next n) | |||||
| 3 -> do | |||||
| w <- evaluateTable | |||||
| if depth <= 1 || length hand == 0 | |||||
| then countGame | |||||
| else turnGeneric playFunc (depth - 1) w | |||||
| turn :: Hand -> Skat (Int, Int) | |||||
| turn n = turnGeneric play 10 n | |||||
| evaluateTable :: Skat Hand | |||||
| evaluateTable = do | |||||
| trumpCol <- gets trumpColour | |||||
| turnCol <- gets turnColour | |||||
| table <- getp tableCards | |||||
| ps <- gets players | |||||
| let winningCard = highestCard trumpCol turnCol table | |||||
| Just winnerHand <- getp $ originOfCard winningCard | |||||
| let winner = player ps winnerHand | |||||
| modifyp $ cleanTable (team winner) | |||||
| modify $ setTurnColour Nothing | |||||
| return $ hand winner | |||||
| countGame :: Skat (Int, Int) | |||||
| countGame = getp count | |||||
| play :: (Show p, Player p) => p -> Skat Card | |||||
| play p = do | |||||
| liftIO $ putStrLn "playing" | |||||
| table <- getp tableCardsS | |||||
| turnCol <- gets turnColour | |||||
| trump <- gets trumpColour | |||||
| hand <- getp $ handCards (hand p) | |||||
| fallen <- getp played | |||||
| (card, p') <- chooseCard p table fallen hand | |||||
| modifyPlayers $ updatePlayer p' | |||||
| modifyp $ playCard card | |||||
| ps <- fmap playersToList $ gets players | |||||
| table' <- getp tableCardsS | |||||
| ps' <- mapM (\p -> onCardPlayed p (head table')) ps | |||||
| mapM_ (modifyPlayers . updatePlayer) ps' | |||||
| return card | |||||
| playOpen :: (Show p, Player p) => p -> Skat Card | |||||
| playOpen p = do | |||||
| --liftIO $ putStrLn $ show (hand p) ++ " playing open" | |||||
| card <- chooseCardOpen p | |||||
| modifyp $ playCard card | |||||
| return card | |||||
| @@ -35,7 +35,8 @@ runAI = do | |||||
| if length trs >= 5 && any ((==32) . getID) cs | if length trs >= 5 && any ((==32) . getID) cs | ||||
| then do | then do | ||||
| pts <- fst <$> evalStateT (turn Hand1) env | pts <- fst <$> evalStateT (turn Hand1) env | ||||
| if pts > 60 then return 1 else return 0 | |||||
| -- if pts > 60 then return 1 else return 0 | |||||
| return pts | |||||
| else runAI | else runAI | ||||
| env :: SkatEnv | env :: SkatEnv | ||||
| @@ -4,7 +4,7 @@ cabal-version: 1.12 | |||||
| -- | -- | ||||
| -- see: https://github.com/sol/hpack | -- see: https://github.com/sol/hpack | ||||
| -- | -- | ||||
| -- hash: 0d6eafec0c3ba6bb4c0150a39f4dbab784c7a519ec911d0f0344edd1c5d916da | |||||
| name: skat | name: skat | ||||
| version: 0.1.0.1 | version: 0.1.0.1 | ||||
| @@ -34,6 +34,7 @@ library | |||||
| Skat.AI.Server | Skat.AI.Server | ||||
| Skat.AI.Stupid | Skat.AI.Stupid | ||||
| Skat.Card | Skat.Card | ||||
| Skat.Matches | |||||
| Skat.Operations | Skat.Operations | ||||
| Skat.Pile | Skat.Pile | ||||
| Skat.Player | Skat.Player | ||||
| @@ -33,6 +33,7 @@ instance Player OnlineEnv where | |||||
| chooseCard p table _ hand = runReaderT (choose table hand) p >>= \c -> return (c, p) | chooseCard p table _ hand = runReaderT (choose table hand) p >>= \c -> return (c, p) | ||||
| onCardPlayed p c = runReaderT (cardPlayed c) p >> return p | onCardPlayed p c = runReaderT (cardPlayed c) p >> return p | ||||
| onGameResults p res = runReaderT (onResults res) p | onGameResults p res = runReaderT (onResults res) p | ||||
| onGameStart p singlePlayer = runReaderT (onStart singlePlayer) p | |||||
| type Online m = ReaderT OnlineEnv m | type Online m = ReaderT OnlineEnv m | ||||
| @@ -65,23 +66,30 @@ cardPlayed card = query (BS.unpack $ encode $ CardPlayedQuery card) | |||||
| onResults :: MonadIO m => (Int, Int) -> Online m () | onResults :: MonadIO m => (Int, Int) -> Online m () | ||||
| onResults (sgl, tm) = query (BS.unpack $ encode $ GameResultsQuery sgl tm) | onResults (sgl, tm) = query (BS.unpack $ encode $ GameResultsQuery sgl tm) | ||||
| data ChooseQuery = ChooseQuery [Card] [CardS Played] | |||||
| data CardPlayedQuery = CardPlayedQuery (CardS Played) | |||||
| data GameResultsQuery = GameResultsQuery Int Int | |||||
| data ChosenResponse = ChosenResponse Card | |||||
| instance ToJSON ChooseQuery where | |||||
| 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) = | toJSON (ChooseQuery hand table) = | ||||
| object ["query" .= ("choose_card" :: String), "hand" .= hand, "table" .= table] | object ["query" .= ("choose_card" :: String), "hand" .= hand, "table" .= table] | ||||
| instance ToJSON CardPlayedQuery where | |||||
| toJSON (CardPlayedQuery card) = | toJSON (CardPlayedQuery card) = | ||||
| object ["query" .= ("card_played" :: String), "card" .= card] | object ["query" .= ("card_played" :: String), "card" .= card] | ||||
| instance ToJSON GameResultsQuery where | |||||
| toJSON (GameResultsQuery sgl tm) = | toJSON (GameResultsQuery sgl tm) = | ||||
| object ["query" .= ("results" :: String), "single" .= sgl, "team" .= 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 ChosenResponse where | |||||
| instance FromJSON Response where | |||||
| parseJSON = withObject "ChosenResponse" $ \v -> ChosenResponse | parseJSON = withObject "ChosenResponse" $ \v -> ChosenResponse | ||||
| <$> v .: "card" | <$> v .: "card" | ||||
| @@ -0,0 +1,25 @@ | |||||
| module Skat.Matches ( | |||||
| singleVsBots | |||||
| ) where | |||||
| import Control.Monad.State | |||||
| import Skat | |||||
| import Skat.Operations | |||||
| import Skat.Player | |||||
| import Skat.Pile | |||||
| import Skat.Card | |||||
| import Skat.AI.Rulebased | |||||
| import Skat.AI.Online | |||||
| import Skat.AI.Stupid | |||||
| singleVsBots :: (Team -> Hand -> OnlineEnv) -> IO () | |||||
| singleVsBots mkPlayer = do | |||||
| cards <- liftIO $ shuffleCards | |||||
| let ps = Players | |||||
| (PL $ mkPlayer Team Hand1) | |||||
| (PL $ Stupid Team Hand2) | |||||
| (PL $ mkAIEnv Single Hand3 10) | |||||
| env = SkatEnv (distribute cards) Nothing Spades ps | |||||
| liftIO $ evalStateT (turn Hand1 >>= publishGameResults) env | |||||
| @@ -1,4 +1,6 @@ | |||||
| module Skat.Operations where | |||||
| module Skat.Operations ( | |||||
| turn, turnGeneric, play, playOpen, publishGameResults | |||||
| ) where | |||||
| import Control.Monad.State | import Control.Monad.State | ||||
| import System.Random (newStdGen, randoms) | import System.Random (newStdGen, randoms) | ||||
| @@ -86,3 +88,8 @@ playOpen p = do | |||||
| card <- chooseCardOpen p | card <- chooseCardOpen p | ||||
| modifyp $ playCard card | modifyp $ playCard card | ||||
| return card | return card | ||||
| publishGameResults :: (Int, Int) -> Skat () | |||||
| publishGameResults res = do | |||||
| pls <- gets players | |||||
| mapM_ (\p -> onGameResults p res) (playersToList pls) | |||||
| @@ -28,6 +28,11 @@ instance ToJSON p => ToJSON (CardS p) where | |||||
| data Hand = Hand1 | Hand2 | Hand3 | data Hand = Hand1 | Hand2 | Hand3 | ||||
| deriving (Show, Eq, Ord) | deriving (Show, Eq, Ord) | ||||
| toInt :: Hand -> Int | |||||
| toInt Hand1 = 1 | |||||
| toInt Hand2 = 2 | |||||
| toInt Hand3 = 3 | |||||
| next :: Hand -> Hand | next :: Hand -> Hand | ||||
| next Hand1 = Hand2 | next Hand1 = Hand2 | ||||
| next Hand2 = Hand3 | next Hand2 = Hand3 | ||||
| @@ -43,6 +43,11 @@ class Player p where | |||||
| -> (Int, Int) | -> (Int, Int) | ||||
| -> m () | -> m () | ||||
| onGameResults _ _ = return () | onGameResults _ _ = return () | ||||
| onGameStart :: MonadPlayer m | |||||
| => p | |||||
| -> Hand | |||||
| -> m () | |||||
| onGameStart _ _ = return () | |||||
| data PL = forall p. (Show p, Player p) => PL p | data PL = forall p. (Show p, Player p) => PL p | ||||
| @@ -60,6 +65,7 @@ instance Player PL where | |||||
| return $ PL v | return $ PL v | ||||
| chooseCardOpen (PL p) = chooseCardOpen p | chooseCardOpen (PL p) = chooseCardOpen p | ||||
| onGameResults (PL p) res = onGameResults p res | onGameResults (PL p) res = onGameResults p res | ||||
| onGameStart (PL p) singlePlayer = onGameStart p singlePlayer | |||||
| data Players = Players PL PL PL | data Players = Players PL PL PL | ||||
| deriving Show | deriving Show | ||||