| @@ -47,11 +47,11 @@ runAI = do | |||||
| else runAI | else runAI | ||||
| env :: SkatEnv | env :: SkatEnv | ||||
| env = SkatEnv piles Nothing (Colour Spades Einfach) playersExamp Hand1 | |||||
| env = SkatEnv piles Nothing (Colour Spades Einfach) playersExamp Hand1 Hand3 | |||||
| where piles = distribute allCards | where piles = distribute allCards | ||||
| envStupid :: SkatEnv | envStupid :: SkatEnv | ||||
| envStupid = SkatEnv piles Nothing (Colour Spades Einfach) pls2 Hand1 | |||||
| envStupid = SkatEnv piles Nothing (Colour Spades Einfach) pls2 Hand1 Hand3 | |||||
| where piles = distribute allCards | where piles = distribute allCards | ||||
| playersExamp :: Players | playersExamp :: Players | ||||
| @@ -69,22 +69,22 @@ pls2 = Players | |||||
| shuffledEnv :: IO SkatEnv | shuffledEnv :: IO SkatEnv | ||||
| shuffledEnv = do | shuffledEnv = do | ||||
| cards <- shuffleCards | cards <- shuffleCards | ||||
| return $ SkatEnv (distribute cards) Nothing (Colour Spades Einfach) playersExamp Hand1 | |||||
| return $ SkatEnv (distribute cards) Nothing (Colour Spades Einfach) playersExamp Hand1 Hand3 | |||||
| shuffledEnv2 :: IO SkatEnv | shuffledEnv2 :: IO SkatEnv | ||||
| shuffledEnv2 = do | shuffledEnv2 = do | ||||
| cards <- shuffleCards | cards <- shuffleCards | ||||
| return $ SkatEnv (distribute cards) Nothing (Colour Spades Einfach) pls2 Hand1 | |||||
| return $ SkatEnv (distribute cards) Nothing (Colour Spades Einfach) pls2 Hand1 Hand3 | |||||
| env2 :: SkatEnv | env2 :: SkatEnv | ||||
| env2 = SkatEnv piles Nothing (Colour Hearts Einfach) playersExamp Hand2 | |||||
| env2 = SkatEnv piles Nothing (Colour Hearts Einfach) playersExamp Hand2 Hand3 | |||||
| where hand1 = [Card Eight Hearts, Card Queen Hearts, Card Ace Clubs, Card Queen Diamonds] | where hand1 = [Card Eight Hearts, Card Queen Hearts, Card Ace Clubs, Card Queen Diamonds] | ||||
| hand2 = [Card Seven Hearts, Card King Hearts, Card Ten Hearts, Card Queen Spades] | hand2 = [Card Seven Hearts, Card King Hearts, Card Ten Hearts, Card Queen Spades] | ||||
| hand3 = [Card Seven Spades, Card King Spades, Card Ace Spades, Card Queen Clubs] | hand3 = [Card Seven Spades, Card King Spades, Card Ace Spades, Card Queen Clubs] | ||||
| piles = emptyPiles hand1 hand2 hand3 [] | piles = emptyPiles hand1 hand2 hand3 [] | ||||
| env3 :: SkatEnv | env3 :: SkatEnv | ||||
| env3 = SkatEnv piles Nothing (Colour Diamonds Einfach) pls2 Hand3 | |||||
| env3 = SkatEnv piles Nothing (Colour Diamonds Einfach) pls2 Hand3 Hand3 | |||||
| where hand1 = [ Card Jack Diamonds, Card Jack Clubs, Card Nine Spades, Card King Spades | where hand1 = [ Card Jack Diamonds, Card Jack Clubs, Card Nine Spades, Card King Spades | ||||
| , Card Seven Diamonds, Card Nine Diamonds, Card Seven Clubs, Card Eight Clubs | , Card Seven Diamonds, Card Nine Diamonds, Card Seven Clubs, Card Eight Clubs | ||||
| , Card Ten Clubs, Card Eight Hearts ] | , Card Ten Clubs, Card Eight Hearts ] | ||||
| @@ -14,7 +14,7 @@ pls2 = Players | |||||
| (PL $ Stupid Single Hand3) | (PL $ Stupid Single Hand3) | ||||
| env3 :: SkatEnv | env3 :: SkatEnv | ||||
| env3 = SkatEnv piles Nothing (Colour Diamonds Einfach) pls2 Hand3 | |||||
| env3 = SkatEnv piles Nothing (Colour Diamonds Einfach) pls2 Hand3 Hand3 | |||||
| where hand1 = [ Card Jack Diamonds, Card Jack Clubs, Card Nine Spades, Card King Spades | where hand1 = [ Card Jack Diamonds, Card Jack Clubs, Card Nine Spades, Card King Spades | ||||
| , Card Seven Diamonds, Card Nine Diamonds, Card Seven Clubs, Card Eight Clubs | , Card Seven Diamonds, Card Nine Diamonds, Card Seven Clubs, Card Eight Clubs | ||||
| , Card Ten Clubs, Card Eight Hearts ] | , Card Ten Clubs, Card Eight Hearts ] | ||||
| @@ -29,4 +29,4 @@ env3 = SkatEnv piles Nothing (Colour Diamonds Einfach) pls2 Hand3 | |||||
| shuffledEnv2 :: IO SkatEnv | shuffledEnv2 :: IO SkatEnv | ||||
| shuffledEnv2 = do | shuffledEnv2 = do | ||||
| cards <- shuffleCards | cards <- shuffleCards | ||||
| return $ SkatEnv (distribute cards) Nothing (Colour Spades Einfach) pls2 Hand1 | |||||
| return $ SkatEnv (distribute cards) Nothing (Colour Spades Einfach) pls2 Hand1 Hand3 | |||||
| @@ -35,6 +35,7 @@ dependencies: | |||||
| - case-insensitive | - case-insensitive | ||||
| - vector | - vector | ||||
| - transformers | - transformers | ||||
| - exceptions | |||||
| library: | library: | ||||
| source-dirs: src | source-dirs: src | ||||
| @@ -4,7 +4,7 @@ cabal-version: 1.12 | |||||
| -- | -- | ||||
| -- see: https://github.com/sol/hpack | -- see: https://github.com/sol/hpack | ||||
| -- | -- | ||||
| -- hash: f2e3dd604c5fb3558a0a89d7551927574fb21db0892d1c2d70d401dd30807071 | |||||
| name: skat | name: skat | ||||
| version: 0.1.0.7 | version: 0.1.0.7 | ||||
| @@ -56,6 +56,7 @@ library | |||||
| , case-insensitive | , case-insensitive | ||||
| , containers | , containers | ||||
| , deepseq | , deepseq | ||||
| , exceptions | |||||
| , mtl | , mtl | ||||
| , network | , network | ||||
| , parallel | , parallel | ||||
| @@ -82,6 +83,7 @@ executable skat-exe | |||||
| , case-insensitive | , case-insensitive | ||||
| , containers | , containers | ||||
| , deepseq | , deepseq | ||||
| , exceptions | |||||
| , mtl | , mtl | ||||
| , network | , network | ||||
| , parallel | , parallel | ||||
| @@ -109,6 +111,7 @@ test-suite skat-test | |||||
| , case-insensitive | , case-insensitive | ||||
| , containers | , containers | ||||
| , deepseq | , deepseq | ||||
| , exceptions | |||||
| , mtl | , mtl | ||||
| , network | , network | ||||
| , parallel | , parallel | ||||
| @@ -18,9 +18,10 @@ import qualified Skat.Player as P | |||||
| data SkatEnv = SkatEnv { piles :: Piles | data SkatEnv = SkatEnv { piles :: Piles | ||||
| , turnColour :: Maybe TurnColour | , turnColour :: Maybe TurnColour | ||||
| , game :: Game | |||||
| , skatGame :: Game | |||||
| , players :: Players | , players :: Players | ||||
| , currentHand :: Hand } | |||||
| , currentHand :: Hand | |||||
| , skatSinglePlayer :: Hand } | |||||
| deriving Show | deriving Show | ||||
| type Skat = StateT SkatEnv (WriterT [Trick] IO) | type Skat = StateT SkatEnv (WriterT [Trick] IO) | ||||
| @@ -37,11 +38,13 @@ execSkat :: Skat a -> SkatEnv -> IO SkatEnv | |||||
| execSkat action = (fmap fst) . runWriterT . execStateT action | execSkat action = (fmap fst) . runWriterT . execStateT action | ||||
| instance P.MonadPlayer Skat where | instance P.MonadPlayer Skat where | ||||
| trump = gets $ getTrump . game | |||||
| trump = getTrump <$> P.game | |||||
| turnColour = gets turnColour | turnColour = gets turnColour | ||||
| showSkat p = case P.team p of | showSkat p = case P.team p of | ||||
| Single -> fmap (Just . skatCards) $ gets piles | Single -> fmap (Just . skatCards) $ gets piles | ||||
| Team -> return Nothing | Team -> return Nothing | ||||
| singlePlayer = gets skatSinglePlayer | |||||
| game = gets skatGame | |||||
| instance P.MonadPlayerOpen Skat where | instance P.MonadPlayerOpen Skat where | ||||
| showPiles = gets piles | showPiles = gets piles | ||||
| @@ -63,7 +66,7 @@ setTurnColour col sk = sk { turnColour = col } | |||||
| setCurrentHand :: Hand -> SkatEnv -> SkatEnv | setCurrentHand :: Hand -> SkatEnv -> SkatEnv | ||||
| setCurrentHand hand sk = sk { currentHand = hand } | setCurrentHand hand sk = sk { currentHand = hand } | ||||
| mkSkatEnv :: Piles -> Maybe TurnColour -> Game -> Players -> Hand -> SkatEnv | |||||
| mkSkatEnv :: Piles -> Maybe TurnColour -> Game -> Players -> Hand -> Hand -> SkatEnv | |||||
| mkSkatEnv = SkatEnv | mkSkatEnv = SkatEnv | ||||
| allowedCards :: Skat [CardS Owner] | allowedCards :: Skat [CardS Owner] | ||||
| @@ -15,7 +15,7 @@ data Human = Human { getTeam :: Team | |||||
| instance Player Human where | instance Player Human where | ||||
| team = getTeam | team = getTeam | ||||
| hand = getHand | hand = getHand | ||||
| chooseCard p table _ hand = do | |||||
| chooseCard p table _ _ hand = do | |||||
| trumpCol <- trump | trumpCol <- trump | ||||
| turnCol <- turnColour | turnCol <- turnColour | ||||
| let possible = filter (isAllowed trumpCol turnCol hand) hand | let possible = filter (isAllowed trumpCol turnCol hand) hand | ||||
| @@ -47,7 +47,7 @@ instance Show (PrepOnline c) where | |||||
| instance Communicator c => Player (OnlineEnv c) where | instance Communicator c => Player (OnlineEnv c) where | ||||
| team = getTeam | team = getTeam | ||||
| hand = getHand | hand = getHand | ||||
| chooseCard p table _ hand = runReaderT (choose table hand) p >>= \c -> return (c, p) | |||||
| chooseCard p table _ mayOuvert hand = runReaderT (choose table mayOuvert hand) p >>= \c -> return (c, p) | |||||
| onCardPlayed p c = runReaderT (cardPlayed c) p >> return p | onCardPlayed p c = runReaderT (cardPlayed c) p >> return p | ||||
| instance Communicator c => Bidder (PrepOnline c) where | instance Communicator c => Bidder (PrepOnline c) where | ||||
| @@ -112,24 +112,26 @@ instance MonadPlayer m => MonadPlayer (Online a m) where | |||||
| trump = lift $ trump | trump = lift $ trump | ||||
| turnColour = lift $ turnColour | turnColour = lift $ turnColour | ||||
| showSkat = lift . showSkat | showSkat = lift . showSkat | ||||
| singlePlayer = lift singlePlayer | |||||
| game = lift game | |||||
| choose :: HasCard a => (Communicator c, MonadPlayer m) => [CardS Played] -> [a] -> Online c m Card | |||||
| choose table hand' = do | |||||
| choose :: (HasCard b, HasCard a) => (Communicator c, MonadPlayer m) => [CardS Played] -> Maybe [b] -> [a] -> Online c m Card | |||||
| choose table mayOuvert hand' = do | |||||
| let hand = sortRender Jacks $ map toCard hand' | let hand = sortRender Jacks $ map toCard hand' | ||||
| query (BS.unpack $ encode $ ChooseQuery hand table) | |||||
| query (BS.unpack $ encode $ ChooseQuery hand table $ fmap (map toCard) mayOuvert) | |||||
| r <- response | r <- response | ||||
| case decode (BS.pack r) of | case decode (BS.pack r) of | ||||
| Just (ChosenResponse card) -> do | Just (ChosenResponse card) -> do | ||||
| allowed <- P.isAllowed hand card | allowed <- P.isAllowed hand card | ||||
| if card `elem` hand && allowed then return card else choose table hand' | |||||
| Nothing -> choose table hand' | |||||
| if card `elem` hand && allowed then return card else choose table mayOuvert hand' | |||||
| Nothing -> choose table mayOuvert hand' | |||||
| cardPlayed :: (Communicator c, MonadPlayer m) => CardS Played -> Online c m () | cardPlayed :: (Communicator c, MonadPlayer m) => CardS Played -> Online c m () | ||||
| cardPlayed card = query (BS.unpack $ encode $ CardPlayedQuery card) | cardPlayed card = query (BS.unpack $ encode $ CardPlayedQuery card) | ||||
| -- | QUERIES AND RESPONSES | -- | QUERIES AND RESPONSES | ||||
| data Query = ChooseQuery [Card] [CardS Played] | |||||
| data Query = ChooseQuery [Card] [CardS Played] (Maybe [Card]) | |||||
| | CardPlayedQuery (CardS Played) | | CardPlayedQuery (CardS Played) | ||||
| | GameResultsQuery Result | | GameResultsQuery Result | ||||
| | GameStartQuery Game Hand | | GameStartQuery Game Hand | ||||
| @@ -151,8 +153,9 @@ newtype GameResponse = GameResponse Game | |||||
| newtype ChosenCards = ChosenCards [Card] | newtype ChosenCards = ChosenCards [Card] | ||||
| instance ToJSON Query where | instance ToJSON Query where | ||||
| toJSON (ChooseQuery hand table) = | |||||
| object ["query" .= ("choose_card" :: String), "hand" .= hand, "table" .= table] | |||||
| toJSON (ChooseQuery hand table mayOuvert) = | |||||
| object [ "query" .= ("choose_card" :: String), "hand" .= hand, "table" .= table | |||||
| , "single_hand" .= mayOuvert] | |||||
| toJSON (CardPlayedQuery card) = | toJSON (CardPlayedQuery card) = | ||||
| object ["query" .= ("card_played" :: String), "card" .= card] | object ["query" .= ("card_played" :: String), "card" .= card] | ||||
| toJSON (GameResultsQuery result) = | toJSON (GameResultsQuery result) = | ||||
| @@ -160,7 +163,7 @@ instance ToJSON Query where | |||||
| toJSON (GameStartQuery game sglPlayer) = | toJSON (GameStartQuery game sglPlayer) = | ||||
| object [ "query" .= ("start_game" :: String) | object [ "query" .= ("start_game" :: String) | ||||
| , "game" .= game | , "game" .= game | ||||
| , "single" .= toInt sglPlayer ] | |||||
| , "single" .= show sglPlayer ] | |||||
| toJSON (BidQuery hand bid) = | toJSON (BidQuery hand bid) = | ||||
| object ["query" .= ("bid" :: String), "whom" .= show hand, "current" .= bid] | object ["query" .= ("bid" :: String), "whom" .= show hand, "current" .= bid] | ||||
| toJSON (BidResponseQuery hand bid) = | toJSON (BidResponseQuery hand bid) = | ||||
| @@ -80,7 +80,7 @@ runWithPiles ps sim = runReaderT sim ps | |||||
| instance Player AIEnv where | instance Player AIEnv where | ||||
| team = getTeam | team = getTeam | ||||
| hand = getHand | hand = getHand | ||||
| chooseCard p table fallen hand = runStateT (do | |||||
| chooseCard p table fallen _ hand = runStateT (do | |||||
| modify $ setTable table | modify $ setTable table | ||||
| modify $ setHand (map toCard hand) | modify $ setHand (map toCard hand) | ||||
| modify $ setFallen fallen | modify $ setFallen fallen | ||||
| @@ -316,7 +316,7 @@ chooseSimulating = do | |||||
| (PL $ Stupid.Stupid Team Hand2) | (PL $ Stupid.Stupid Team Hand2) | ||||
| (PL $ Stupid.Stupid Single Hand3) | (PL $ Stupid.Stupid Single Hand3) | ||||
| -- TODO: fix | -- TODO: fix | ||||
| env = mkSkatEnv piles turnCol undefined ps myHand | |||||
| env = mkSkatEnv piles turnCol undefined ps myHand undefined | |||||
| liftIO $ evalSkat (toCard <$> (Minmax.choose depth :: Skat (CardS Owner))) env | liftIO $ evalSkat (toCard <$> (Minmax.choose depth :: Skat (CardS Owner))) env | ||||
| simulate :: (MonadState AIEnv m, MonadPlayerOpen m) | simulate :: (MonadState AIEnv m, MonadPlayerOpen m) | ||||
| @@ -337,7 +337,7 @@ simulate card = do | |||||
| (PL $ mkAIEnv Team Hand2 newDepth) | (PL $ mkAIEnv Team Hand2 newDepth) | ||||
| (PL $ mkAIEnv Single Hand3 newDepth) | (PL $ mkAIEnv Single Hand3 newDepth) | ||||
| -- TODO: fix | -- TODO: fix | ||||
| env = mkSkatEnv piles turnCol undefined ps (next myHand) | |||||
| env = mkSkatEnv piles turnCol undefined ps (next myHand) undefined | |||||
| -- simulate the game after playing the given card | -- simulate the game after playing the given card | ||||
| (sgl, tm) <- liftIO $ evalSkat (do | (sgl, tm) <- liftIO $ evalSkat (do | ||||
| modifyp $ playCard myHand card | modifyp $ playCard myHand card | ||||
| @@ -16,7 +16,7 @@ data Stupid = Stupid { getTeam :: Team | |||||
| instance Player Stupid where | instance Player Stupid where | ||||
| team = getTeam | team = getTeam | ||||
| hand = getHand | hand = getHand | ||||
| chooseCard p _ _ hand = do | |||||
| chooseCard p _ _ _ hand = do | |||||
| trumpCol <- trump | trumpCol <- trump | ||||
| turnCol <- turnColour | turnCol <- turnColour | ||||
| liftIO $ threadDelay 1000000 | liftIO $ threadDelay 1000000 | ||||
| @@ -2,7 +2,7 @@ | |||||
| module Skat.Bidding ( | module Skat.Bidding ( | ||||
| biddingScore, Game(..), Modifier(..), isHand, getTrump, Result(..), | biddingScore, Game(..), Modifier(..), isHand, getTrump, Result(..), | ||||
| getResults | |||||
| getResults, isOuvert, isSchwarz | |||||
| ) where | ) where | ||||
| import Data.Aeson hiding (Null, Result) | import Data.Aeson hiding (Null, Result) | ||||
| @@ -82,6 +82,13 @@ isHand Schneider = False | |||||
| isHand Schwarz = False | isHand Schwarz = False | ||||
| isHand _ = True | isHand _ = True | ||||
| isOuvert :: Game -> Bool | |||||
| isOuvert NullOuvert = True | |||||
| isOuvert NullOuvertHand = True | |||||
| isOuvert (Grand Ouvert) = True | |||||
| isOuvert (Colour _ Ouvert) = True | |||||
| isOuvert _ = False | |||||
| -- | calculate the value of a game with given cards | -- | calculate the value of a game with given cards | ||||
| biddingScore :: HasCard c => Game -> [c] -> Int | biddingScore :: HasCard c => Game -> [c] -> Int | ||||
| biddingScore game@(Grand mod) cards = (spitzen game cards + modifierFactor mod) * 24 | biddingScore game@(Grand mod) cards = (spitzen game cards + modifierFactor mod) * 24 | ||||
| @@ -1,5 +1,5 @@ | |||||
| module Skat.Matches ( | module Skat.Matches ( | ||||
| singleVsBots, pvp, singleWithBidding, Match(..) | |||||
| singleVsBots, pvp, singleWithBidding, Match(..), Unfinished(..), continue | |||||
| ) where | ) where | ||||
| import Control.Monad.State | import Control.Monad.State | ||||
| @@ -8,7 +8,7 @@ import System.Random (mkStdGen) | |||||
| import Skat | import Skat | ||||
| import Skat.Operations | import Skat.Operations | ||||
| import Skat.Player | |||||
| import Skat.Player as P | |||||
| import Skat.Pile | import Skat.Pile | ||||
| import Skat.Card | import Skat.Card | ||||
| import Skat.Preperation | import Skat.Preperation | ||||
| @@ -24,20 +24,59 @@ data Match = Match { matchPiles :: Piles | |||||
| , matchSingle :: Hand } | , matchSingle :: Hand } | ||||
| deriving Show | deriving Show | ||||
| match :: PrepEnv -> IO (Maybe Match) | |||||
| data Unfinished = UnfinishedGame { unfinishedGame :: SkatEnv | |||||
| , unfinishedPrep :: PrepEnv | |||||
| , unfinishedTricks :: [Trick] } | |||||
| | UnfinishedPrep { unfinishedPrep :: PrepEnv } | |||||
| deriving Show | |||||
| continue :: Communicator c => Unfinished -> c -> c -> c -> IO (Either Unfinished (Maybe Match)) | |||||
| continue (UnfinishedGame skatEnv prepEnv tricks) comm1 comm2 comm3 = do | |||||
| let ps = players skatEnv | |||||
| ps' = Players | |||||
| (PL $ OnlineEnv (P.team $ player ps Hand1) (P.hand $ player ps Hand1) comm1) | |||||
| (PL $ OnlineEnv (P.team $ player ps Hand2) (P.hand $ player ps Hand2) comm2) | |||||
| (PL $ OnlineEnv (P.team $ player ps Hand3) (P.hand $ player ps Hand3) comm3) | |||||
| bs = bidders prepEnv | |||||
| bs' = Bidders | |||||
| (BD $ PrepOnline (Skat.Preperation.hand $ bidder bs Hand1) comm1 []) | |||||
| (BD $ PrepOnline (Skat.Preperation.hand $ bidder bs Hand2) comm2 []) | |||||
| (BD $ PrepOnline (Skat.Preperation.hand $ bidder bs Hand3) comm3 []) | |||||
| skatEnv' = skatEnv { players = ps' } | |||||
| prepEnv' = prepEnv { bidders = bs' } | |||||
| runGame prepEnv' skatEnv' | |||||
| match :: PrepEnv -> IO (Either Unfinished (Maybe Match)) | |||||
| match prepEnv = do | match prepEnv = do | ||||
| maySkatEnv <- runReaderT runPreperation prepEnv | maySkatEnv <- runReaderT runPreperation prepEnv | ||||
| case maySkatEnv of | case maySkatEnv of | ||||
| Just (sglPlayer, skatEnv) -> do | |||||
| (_, finished, tricks) <- runSkat turn skatEnv | |||||
| let res = getResults | |||||
| (game skatEnv) | |||||
| sglPlayer | |||||
| (Skat.Preperation.piles prepEnv) | |||||
| (Skat.piles finished) | |||||
| publishGameResults res (bidders prepEnv) | |||||
| return $ Just $ Match (Skat.Preperation.piles prepEnv) res tricks sglPlayer | |||||
| Nothing -> putStrLn "no one wanted to play" >> return Nothing | |||||
| Just skatEnv -> runGame prepEnv skatEnv | |||||
| Nothing -> putStrLn "no one wanted to play" >> return (Right Nothing) | |||||
| runGame :: PrepEnv -> SkatEnv -> IO (Either Unfinished (Maybe Match)) | |||||
| runGame prepEnv skatEnv = do | |||||
| (isFinished, finalEnv, tricks) <- (flip runSkat) skatEnv $ do | |||||
| -- send current table cards to clients | |||||
| -- only relevant if this is a continued game | |||||
| -- otherwise table is empty | |||||
| table <- getp tableCards | |||||
| ps <- playersToList <$> gets players | |||||
| mapM_ (\card -> mapM_ (\p -> onCardPlayed p card) ps) (reverse table) | |||||
| -- run game | |||||
| turn | |||||
| -- return if game has finished | |||||
| gameOver | |||||
| if isFinished then do | |||||
| let res = getResults | |||||
| (skatGame skatEnv) | |||||
| (skatSinglePlayer skatEnv) | |||||
| (Skat.Preperation.piles prepEnv) | |||||
| (Skat.piles finalEnv) | |||||
| publishGameResults res (bidders prepEnv) | |||||
| return $ Right $ Just $ | |||||
| Match (Skat.Preperation.piles prepEnv) res tricks (skatSinglePlayer skatEnv) | |||||
| else do -- if not finished an error has occured, thus returning unfinished game state | |||||
| return $ Left $ UnfinishedGame finalEnv prepEnv tricks | |||||
| -- | predefined card distribution for testing purposes | -- | predefined card distribution for testing purposes | ||||
| cardDistr :: Piles | cardDistr :: Piles | ||||
| @@ -60,7 +99,7 @@ singleVsBots comm = do | |||||
| (PL $ OnlineEnv Team Hand1 comm) | (PL $ OnlineEnv Team Hand1 comm) | ||||
| (PL $ Stupid Team Hand2) | (PL $ Stupid Team Hand2) | ||||
| (PL $ mkAIEnv Single Hand3 10) | (PL $ mkAIEnv Single Hand3 10) | ||||
| env = SkatEnv (distribute cards) Nothing (Colour Spades Einfach) ps Hand1 | |||||
| env = SkatEnv (distribute cards) Nothing (Colour Spades Einfach) ps Hand1 Hand3 | |||||
| void $ evalSkat turn env | void $ evalSkat turn env | ||||
| singleWithBidding :: Communicator c => c -> IO () | singleWithBidding :: Communicator c => c -> IO () | ||||
| @@ -75,7 +114,7 @@ singleWithBidding comm = do | |||||
| env = PrepEnv ps bs | env = PrepEnv ps bs | ||||
| void $ match env | void $ match env | ||||
| pvp :: Communicator c => c -> c -> c -> IO (Maybe Match) | |||||
| pvp :: Communicator c => c -> c -> c -> IO (Either Unfinished (Maybe Match)) | |||||
| pvp comm1 comm2 comm3 = do | pvp comm1 comm2 comm3 = do | ||||
| cards <- shuffleCards | cards <- shuffleCards | ||||
| let ps = distribute cards | let ps = distribute cards | ||||
| @@ -1,9 +1,11 @@ | |||||
| module Skat.Operations ( | module Skat.Operations ( | ||||
| turn, turnGeneric, play, playOpen, | turn, turnGeneric, play, playOpen, | ||||
| play_, sortRender, undo_ | |||||
| play_, sortRender, undo_, gameOver | |||||
| ) where | ) where | ||||
| import Control.Monad.State | import Control.Monad.State | ||||
| import Control.Monad.Catch | |||||
| import Control.Exception hiding (catch, bracketOnError) | |||||
| import Control.Monad.Writer (tell) | import Control.Monad.Writer (tell) | ||||
| import System.Random (newStdGen, randoms) | import System.Random (newStdGen, randoms) | ||||
| import Data.List | import Data.List | ||||
| @@ -14,8 +16,10 @@ import Skat | |||||
| import Skat.Card | import Skat.Card | ||||
| import Skat.Pile | import Skat.Pile | ||||
| import Skat.Player (chooseCard, Players(..), Player(..), PL(..), | import Skat.Player (chooseCard, Players(..), Player(..), PL(..), | ||||
| updatePlayer, playersToList, player, MonadPlayer, getSinglePlayer, trump) | |||||
| updatePlayer, playersToList, player, MonadPlayer, getSinglePlayer, trump, game, | |||||
| singlePlayer) | |||||
| import Skat.Utils (shuffle) | import Skat.Utils (shuffle) | ||||
| import Skat.Bidding | |||||
| play_ :: HasCard c => c -> Skat () | play_ :: HasCard c => c -> Skat () | ||||
| play_ card = do | play_ card = do | ||||
| @@ -43,19 +47,34 @@ turnGeneric playFunc depth = do | |||||
| table <- getp tableCards | table <- getp tableCards | ||||
| ps <- gets players | ps <- gets players | ||||
| let p = player ps n | let p = player ps n | ||||
| over <- getp $ handEmpty n | |||||
| trCol <- trump | trCol <- trump | ||||
| case length table of | case length table of | ||||
| 0 -> playFunc p >> modify (setCurrentHand $ next n) >> turnGeneric playFunc depth | |||||
| 0 -> do | |||||
| catchAll | |||||
| (do | |||||
| playFunc p | |||||
| modify (setCurrentHand $ next n) | |||||
| turnGeneric playFunc depth) | |||||
| (\_ -> countGame) | |||||
| 1 -> do | 1 -> do | ||||
| modify $ setTurnColour | modify $ setTurnColour | ||||
| (Just $ effectiveColour trCol $ head table) | (Just $ effectiveColour trCol $ head table) | ||||
| playFunc p | |||||
| modify (setCurrentHand $ next n) | |||||
| turnGeneric playFunc depth | |||||
| 2 -> playFunc p >> modify (setCurrentHand $ next n) >> turnGeneric playFunc depth | |||||
| catchAll | |||||
| (do | |||||
| playFunc p | |||||
| modify (setCurrentHand $ next n) | |||||
| turnGeneric playFunc depth) | |||||
| (\_ -> countGame) | |||||
| 2 -> do | |||||
| catchAll | |||||
| (do | |||||
| playFunc p | |||||
| modify (setCurrentHand $ next n) | |||||
| turnGeneric playFunc depth) | |||||
| (\_ -> countGame) | |||||
| 3 -> do | 3 -> do | ||||
| w <- evaluateTable | w <- evaluateTable | ||||
| over <- gameOver | |||||
| if depth <= 1 || over | if depth <= 1 || over | ||||
| then countGame | then countGame | ||||
| else modify (setCurrentHand w) >> turnGeneric playFunc (depth - 1) | else modify (setCurrentHand w) >> turnGeneric playFunc (depth - 1) | ||||
| @@ -86,7 +105,10 @@ play p = do | |||||
| trump <- trump | trump <- trump | ||||
| cards <- getp $ handCards (hand p) | cards <- getp $ handCards (hand p) | ||||
| fallen <- getp played | fallen <- getp played | ||||
| (card, p') <- chooseCard p table fallen cards | |||||
| ouvert <- isOuvert <$> game | |||||
| mayOuvert <- if ouvert then Just <$> (singlePlayer >>= getp . handCards) | |||||
| else return Nothing | |||||
| (card, p') <- chooseCard p table fallen mayOuvert cards | |||||
| modifyPlayers $ updatePlayer p' | modifyPlayers $ updatePlayer p' | ||||
| modifyp $ playCard (hand p) card | modifyp $ playCard (hand p) card | ||||
| ps <- fmap playersToList $ gets players | ps <- fmap playersToList $ gets players | ||||
| @@ -101,3 +123,13 @@ playOpen p = do | |||||
| card <- chooseCardOpen p | card <- chooseCardOpen p | ||||
| modifyp $ playCard (hand p) card | modifyp $ playCard (hand p) card | ||||
| return card | return card | ||||
| gameOver :: Skat Bool | |||||
| gameOver = do | |||||
| tr <- trump | |||||
| case tr of | |||||
| None -> do | |||||
| singleLost <- gets piles >>= return . not . (Single `isSchwarz`) | |||||
| if singleLost then return True | |||||
| else gets currentHand >>= getp . handCards >>= return . null | |||||
| _ -> gets currentHand >>= getp . handCards >>= return . null | |||||
| @@ -6,11 +6,14 @@ import Control.Monad.IO.Class | |||||
| import Skat.Card | import Skat.Card | ||||
| import Skat.Pile | import Skat.Pile | ||||
| import Skat.Bidding | |||||
| class (Monad m, MonadIO m) => MonadPlayer m where | class (Monad m, MonadIO m) => MonadPlayer m where | ||||
| trump :: m Trump | trump :: m Trump | ||||
| turnColour :: m (Maybe TurnColour) | turnColour :: m (Maybe TurnColour) | ||||
| showSkat :: Player p => p -> m (Maybe [Card]) | showSkat :: Player p => p -> m (Maybe [Card]) | ||||
| singlePlayer :: m Hand | |||||
| game :: m Game | |||||
| class (Monad m, MonadIO m, MonadPlayer m) => MonadPlayerOpen m where | class (Monad m, MonadIO m, MonadPlayer m) => MonadPlayerOpen m where | ||||
| showPiles :: m (Piles) | showPiles :: m (Piles) | ||||
| @@ -18,10 +21,11 @@ class (Monad m, MonadIO m, MonadPlayer m) => MonadPlayerOpen m where | |||||
| class Player p where | class Player p where | ||||
| team :: p -> Team | team :: p -> Team | ||||
| hand :: p -> Hand | hand :: p -> Hand | ||||
| chooseCard :: (HasCard c, MonadPlayer m) | |||||
| chooseCard :: (HasCard d, HasCard c, MonadPlayer m) | |||||
| => p | => p | ||||
| -> [CardS Played] | -> [CardS Played] | ||||
| -> [CardS Played] | -> [CardS Played] | ||||
| -> Maybe [d] | |||||
| -> [c] | -> [c] | ||||
| -> m (Card, p) | -> m (Card, p) | ||||
| onCardPlayed :: MonadPlayer m | onCardPlayed :: MonadPlayer m | ||||
| @@ -37,7 +41,10 @@ class Player p where | |||||
| let table = tableCards piles | let table = tableCards piles | ||||
| fallen = played piles | fallen = played piles | ||||
| myCards = handCards (hand p) piles | myCards = handCards (hand p) piles | ||||
| fst <$> chooseCard p table fallen myCards | |||||
| ouvert <- isOuvert <$> game | |||||
| mayOuvert <- if ouvert then Just <$> (singlePlayer >>= \hnd -> return $ handCards hnd piles) | |||||
| else return Nothing | |||||
| fst <$> chooseCard p table fallen mayOuvert myCards | |||||
| data PL = forall p. (Show p, Player p) => PL p | data PL = forall p. (Show p, Player p) => PL p | ||||
| @@ -47,8 +54,8 @@ instance Show PL where | |||||
| instance Player PL where | instance Player PL where | ||||
| team (PL p) = team p | team (PL p) = team p | ||||
| hand (PL p) = hand p | hand (PL p) = hand p | ||||
| chooseCard (PL p) table fallen hand = do | |||||
| (v, a) <- chooseCard p table fallen hand | |||||
| chooseCard (PL p) table fallen mayOuvert hand = do | |||||
| (v, a) <- chooseCard p table fallen mayOuvert hand | |||||
| return $ (v, PL a) | return $ (v, PL a) | ||||
| onCardPlayed (PL p) card = do | onCardPlayed (PL p) card = do | ||||
| v <- onCardPlayed p card | v <- onCardPlayed p card | ||||
| @@ -3,7 +3,7 @@ | |||||
| module Skat.Preperation ( | module Skat.Preperation ( | ||||
| Bidder(..), Bid, BD(..), Bidders(..), PrepEnv(..), runPreperation, | Bidder(..), Bid, BD(..), Bidders(..), PrepEnv(..), runPreperation, | ||||
| publishGameResults | |||||
| publishGameResults, bidder | |||||
| ) where | ) where | ||||
| import Control.Monad.IO.Class | import Control.Monad.IO.Class | ||||
| @@ -78,7 +78,7 @@ toPlayers single (Bidders b1 b2 b3) = | |||||
| (toPlayer b2 $ if single == Hand2 then Single else Team) | (toPlayer b2 $ if single == Hand2 then Single else Team) | ||||
| (toPlayer b3 $ if single == Hand3 then Single else Team) | (toPlayer b3 $ if single == Hand3 then Single else Team) | ||||
| runPreperation :: Preperation (Maybe (Hand, SkatEnv)) | |||||
| runPreperation :: Preperation (Maybe SkatEnv) | |||||
| runPreperation = do | runPreperation = do | ||||
| bds <- asks bidders | bds <- asks bidders | ||||
| onStart (bidder bds Hand1) | onStart (bidder bds Hand1) | ||||
| @@ -90,9 +90,9 @@ runPreperation = do | |||||
| bid <- askBid (bidder bds finalWinner) finalWinner 0 | bid <- askBid (bidder bds finalWinner) finalWinner 0 | ||||
| publishBid bid finalWinner finalWinner | publishBid bid finalWinner finalWinner | ||||
| case bid of | case bid of | ||||
| Just val -> (Just . (finalWinner,)) <$> initGame finalWinner val | |||||
| Just val -> Just <$> initGame finalWinner val | |||||
| Nothing -> publishNoGame >> return Nothing | Nothing -> publishNoGame >> return Nothing | ||||
| else (Just . (finalWinner,)) <$> initGame finalWinner finalBid | |||||
| else Just <$> initGame finalWinner finalBid | |||||
| runBidding :: Bid -> BD -> BD -> Preperation (Hand, Bid) | runBidding :: Bid -> BD -> BD -> Preperation (Hand, Bid) | ||||
| runBidding startingBid reizer gereizter = do | runBidding startingBid reizer gereizter = do | ||||
| @@ -125,7 +125,7 @@ initGame single bid = do | |||||
| -- publish game start | -- publish game start | ||||
| publishGameStart game single | publishGameStart game single | ||||
| -- construct skat env | -- construct skat env | ||||
| return $ mkSkatEnv ps' Nothing game (toPlayers single bds) Hand1 | |||||
| return $ mkSkatEnv ps' Nothing game (toPlayers single bds) Hand1 single | |||||
| handleGame :: BD -> Bid -> Bool -> Preperation Game | handleGame :: BD -> Bid -> Bool -> Preperation Game | ||||
| handleGame bd bid noSkat = do | handleGame bd bid noSkat = do | ||||