2 Commits
Author SHA1 Message Date
christian a7824bebea track every trick, return detailed match information 2020-04-01 01:31:16 +02:00
christian be52a008df send bidding log to every bidder 2020-03-31 17:35:53 +02:00
9 changed files with 90 additions and 20 deletions
+2 -2
View File
@@ -41,7 +41,7 @@ runAI = do
trs = filter (isTrump $ TrumpColour Spades) cs trs = filter (isTrump $ TrumpColour Spades) cs
if length trs >= 5 && any ((==32) . getID) cs if length trs >= 5 && any ((==32) . getID) cs
then do then do
pts <- fst <$> evalStateT turn env pts <- fst <$> evalSkat turn env
-- if pts > 60 then return 1 else return 0 -- if pts > 60 then return 1 else return 0
return pts return pts
else runAI else runAI
@@ -109,4 +109,4 @@ application pending = do
putStrLn $ BS.unpack msg putStrLn $ BS.unpack msg
playSkat :: IO () playSkat :: IO ()
playSkat = void $ (flip runStateT) env3 playCLI playSkat = void $ (flip runSkat) env3 playCLI
+14 -1
View File
@@ -5,6 +5,7 @@
module Skat where module Skat where
import Control.Monad.State import Control.Monad.State
import Control.Monad.Writer
import Control.Monad.Reader import Control.Monad.Reader
import Data.List import Data.List
import Data.Vector (Vector) import Data.Vector (Vector)
@@ -22,7 +23,19 @@ data SkatEnv = SkatEnv { piles :: Piles
, currentHand :: Hand } , currentHand :: Hand }
deriving Show deriving Show
type Skat = StateT SkatEnv IO type Trick = (CardS Owner, CardS Owner, CardS Owner)
type Skat = StateT SkatEnv (WriterT [Trick] IO)
runSkat :: Skat a -> SkatEnv -> IO (a, SkatEnv, [Trick])
runSkat action env = do
((val, env'), tricks) <- runWriterT $ runStateT action env
return (val, env', tricks)
evalSkat :: Skat a -> SkatEnv -> IO a
evalSkat action = (fmap fst) . runWriterT . evalStateT action
execSkat :: Skat a -> SkatEnv -> IO SkatEnv
execSkat action = (fmap fst) . runWriterT . execStateT action
instance P.MonadPlayer Skat where instance P.MonadPlayer Skat where
trump = gets $ getTrump . game trump = gets $ getTrump . game
+19
View File
@@ -84,6 +84,10 @@ instance Communicator c => Bidder (PrepOnline c) where
Just (ChosenCards cards) -> return cards Just (ChosenCards cards) -> return cards
Nothing -> askSkat p bid cards Nothing -> askSkat p bid cards
toPlayer p tm = PL $ OnlineEnv tm (prepHand p) (prepConnection p) toPlayer p tm = PL $ OnlineEnv tm (prepHand p) (prepConnection p)
onBid p mayBid reizer gereizter =
liftIO $ send (prepConnection p) (BS.unpack $ encode $ BidEvent mayBid reizer gereizter)
onResponse p response reizer gereizter =
liftIO $ send (prepConnection p) (BS.unpack $ encode $ ResponseEvent response reizer gereizter)
onStart p = do onStart p = do
let cards = sortRender Jacks $ prepCards p let cards = sortRender Jacks $ prepCards p
liftIO $ send (prepConnection p) (BS.unpack $ encode $ CardsQuery cards) liftIO $ send (prepConnection p) (BS.unpack $ encode $ CardsQuery cards)
@@ -133,6 +137,8 @@ data Query = ChooseQuery [Card] [CardS Played]
| AskHandQuery | AskHandQuery
| AskSkatQuery [Card] Bid | AskSkatQuery [Card] Bid
| CardsQuery [Card] | CardsQuery [Card]
| BidEvent (Maybe Bid) Hand Hand
| ResponseEvent Bool Hand Hand
newtype ChosenResponse = ChosenResponse Card newtype ChosenResponse = ChosenResponse Card
newtype BidResponse = BidResponse Int newtype BidResponse = BidResponse Int
@@ -164,6 +170,19 @@ instance ToJSON Query where
object ["query" .= ("cards" :: String), "cards" .= cards ] object ["query" .= ("cards" :: String), "cards" .= cards ]
toJSON (AskGameQuery bid) = toJSON (AskGameQuery bid) =
object ["query" .= ("ask_game" :: String), "bid" .= bid] object ["query" .= ("ask_game" :: String), "bid" .= bid]
toJSON (BidEvent (Just bid) reizer gereizter) =
object ["query" .= ("bid_event" :: String), "bid" .= bid, "reizer" .= show reizer,
"gereizter" .= show gereizter ]
toJSON (BidEvent Nothing reizer gereizter) =
object [ "query" .= ("bid_event" :: String)
, "bid" .= ("weg" :: String)
, "reizer" .= show reizer
, "gereizter" .= show gereizter ]
toJSON (ResponseEvent response reizer gereizter) =
object [ "query" .= ("response_event" :: String)
, "response" .= response
, "reizer" .= show reizer
, "gereizter" .= show gereizter ]
instance FromJSON ChosenResponse where instance FromJSON ChosenResponse where
parseJSON = withObject "ChosenResponse" $ \v -> ChosenResponse parseJSON = withObject "ChosenResponse" $ \v -> ChosenResponse
+3 -3
View File
@@ -22,7 +22,7 @@ import qualified Skat.Player.Utils as P
import Skat.Pile hiding (isSkat) import Skat.Pile hiding (isSkat)
import Skat.Card import Skat.Card
import Skat.Utils import Skat.Utils
import Skat (Skat, modifyp, mkSkatEnv) import Skat (Skat, modifyp, mkSkatEnv, evalSkat)
import Skat.Operations import Skat.Operations
import qualified Skat.AI.Minmax as Minmax import qualified Skat.AI.Minmax as Minmax
import qualified Skat.AI.Stupid as Stupid (Stupid(..)) import qualified Skat.AI.Stupid as Stupid (Stupid(..))
@@ -317,7 +317,7 @@ chooseSimulating = do
(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
liftIO $ evalStateT (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)
=> Card -> m Int => Card -> m Int
@@ -339,7 +339,7 @@ simulate card = do
-- TODO: fix -- TODO: fix
env = mkSkatEnv piles turnCol undefined ps (next myHand) env = mkSkatEnv piles turnCol undefined ps (next myHand)
-- simulate the game after playing the given card -- simulate the game after playing the given card
(sgl, tm) <- liftIO $ evalStateT (do (sgl, tm) <- liftIO $ evalSkat (do
modifyp $ playCard myHand card modifyp $ playCard myHand card
turnGeneric playOpen depth) env turnGeneric playOpen depth) env
let v = if myTeam == Single then (sgl, tm) else (tm, sgl) let v = if myTeam == Single then (sgl, tm) else (tm, sgl)
+4
View File
@@ -1,5 +1,8 @@
module Skat.AI.Stupid where module Skat.AI.Stupid where
import Control.Concurrent
import Control.Monad.State
import Skat.Player import Skat.Player
import Skat.Pile import Skat.Pile
import Skat.Card import Skat.Card
@@ -16,6 +19,7 @@ instance Player Stupid where
chooseCard p _ _ hand = do chooseCard p _ _ hand = do
trumpCol <- trump trumpCol <- trump
turnCol <- turnColour turnCol <- turnColour
liftIO $ threadDelay 1000000
let possible = filter (isAllowed trumpCol turnCol hand) hand let possible = filter (isAllowed trumpCol turnCol hand) hand
return (toCard $ head possible, p) return (toCard $ head possible, p)
+4 -1
View File
@@ -140,7 +140,10 @@ getTrump (Colour col _) = TrumpColour col
getTrump (Grand _) = Jacks getTrump (Grand _) = Jacks
getTrump _ = None getTrump _ = None
data Result = Result Game Int Int Int data Result = Result { resultGame :: Game
, resultScore :: Int
, resultSinglePoints :: Int
, resultTeamPoints :: Int }
deriving (Show, Eq) deriving (Show, Eq)
instance ToJSON Result where instance ToJSON Result where
+14 -7
View File
@@ -1,5 +1,5 @@
module Skat.Matches ( module Skat.Matches (
singleVsBots, pvp, singleWithBidding singleVsBots, pvp, singleWithBidding, Match(..)
) where ) where
import Control.Monad.State import Control.Monad.State
@@ -18,19 +18,26 @@ import Skat.AI.Rulebased
import Skat.AI.Online import Skat.AI.Online
import Skat.AI.Stupid import Skat.AI.Stupid
match :: PrepEnv -> IO () data Match = Match { matchPiles :: Piles
, matchResult :: Result
, matchTricks :: [Trick]
, matchSingle :: Hand }
deriving Show
match :: PrepEnv -> IO (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 Just (sglPlayer, skatEnv) -> do
finished <- execStateT turn skatEnv (_, finished, tricks) <- runSkat turn skatEnv
let res = getResults let res = getResults
(game skatEnv) (game skatEnv)
sglPlayer sglPlayer
(Skat.piles skatEnv) (Skat.piles skatEnv)
(Skat.piles finished) (Skat.piles finished)
publishGameResults res (bidders prepEnv) publishGameResults res (bidders prepEnv)
Nothing -> putStrLn "no one wanted to play" return $ Just $ Match (Skat.piles skatEnv) res tricks sglPlayer
Nothing -> putStrLn "no one wanted to play" >> return Nothing
-- | predefined card distribution for testing purposes -- | predefined card distribution for testing purposes
cardDistr :: Piles cardDistr :: Piles
@@ -54,7 +61,7 @@ singleVsBots comm = do
(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
void $ evalStateT turn env void $ evalSkat turn env
singleWithBidding :: Communicator c => c -> IO () singleWithBidding :: Communicator c => c -> IO ()
singleWithBidding comm = do singleWithBidding comm = do
@@ -66,9 +73,9 @@ singleWithBidding comm = do
(BD $ NoBidder Hand2) (BD $ NoBidder Hand2)
(BD $ NoBidder Hand3) (BD $ NoBidder Hand3)
env = PrepEnv ps bs env = PrepEnv ps bs
match env void $ match env
pvp :: Communicator c => c -> c -> c -> IO () pvp :: Communicator c => c -> c -> c -> IO (Maybe Match)
pvp comm1 comm2 comm3 = do pvp comm1 comm2 comm3 = do
cards <- shuffleCards cards <- shuffleCards
let ps = distribute cards let ps = distribute cards
+2
View File
@@ -4,6 +4,7 @@ module Skat.Operations (
) where ) where
import Control.Monad.State import Control.Monad.State
import Control.Monad.Writer (tell)
import System.Random (newStdGen, randoms) import System.Random (newStdGen, randoms)
import Data.List import Data.List
import Data.Ord import Data.Ord
@@ -72,6 +73,7 @@ evaluateTable = do
winner = player ps winnerHand winner = player ps winnerHand
modifyp $ cleanTable (team winner) modifyp $ cleanTable (team winner)
modify $ setTurnColour Nothing modify $ setTurnColour Nothing
tell [(table !! 2, table !! 1, table !! 0)]
return $ hand winner return $ hand winner
countGame :: Skat (Int, Int) countGame :: Skat (Int, Int)
+28 -6
View File
@@ -32,6 +32,10 @@ class Bidder a where
askHand :: MonadIO m => a -> Bid -> m Bool askHand :: MonadIO m => a -> Bid -> m Bool
askSkat :: MonadIO m => a -> Bid -> [Card] -> m [Card] askSkat :: MonadIO m => a -> Bid -> [Card] -> m [Card]
toPlayer :: a -> Team -> PL toPlayer :: a -> Team -> PL
onBid :: MonadIO m => a -> Maybe Bid -> Hand -> Hand -> m ()
onBid _ _ _ _ = return ()
onResponse :: MonadIO m => a -> Bool -> Hand -> Hand -> m ()
onResponse _ _ _ _ = return ()
onGame :: MonadIO m => a -> Game -> Hand -> m () onGame :: MonadIO m => a -> Game -> Hand -> m ()
onGame _ _ _ = return () onGame _ _ _ = return ()
onResult :: MonadIO m => a -> Result -> m () onResult :: MonadIO m => a -> Result -> m ()
@@ -54,6 +58,8 @@ instance Bidder BD where
onStart (BD b) = onStart b onStart (BD b) = onStart b
onGame (BD b) = onGame b onGame (BD b) = onGame b
onResult (BD b) = onResult b onResult (BD b) = onResult b
onBid (BD b) = onBid b
onResponse (BD b) = onResponse b
data Bidders = Bidders BD BD BD data Bidders = Bidders BD BD BD
deriving Show deriving Show
@@ -79,6 +85,7 @@ runPreperation = do
(finalWinner, finalBid) <- runBidding bid (bidder bds Hand3) (bidder bds winner) (finalWinner, finalBid) <- runBidding bid (bidder bds Hand3) (bidder bds winner)
if finalBid == 0 then do if finalBid == 0 then do
bid <- askBid (bidder bds finalWinner) finalWinner 0 bid <- askBid (bidder bds finalWinner) finalWinner 0
publishBid bid finalWinner finalWinner
case bid of case bid of
Just val -> (Just . (finalWinner,)) <$> initGame finalWinner val Just val -> (Just . (finalWinner,)) <$> initGame finalWinner val
Nothing -> return Nothing Nothing -> return Nothing
@@ -90,11 +97,17 @@ runBidding startingBid reizer gereizter = do
case first of case first of
Just val Just val
| val > startingBid -> do | val > startingBid -> do
publishBid first (hand reizer) (hand gereizter)
response <- askResponse gereizter (hand reizer) val response <- askResponse gereizter (hand reizer) val
publishResponse response (hand reizer) (hand gereizter)
if response then runBidding val reizer gereizter if response then runBidding val reizer gereizter
else return (hand reizer, val) else return (hand reizer, val)
| otherwise -> return (hand gereizter, startingBid) | otherwise -> do
Nothing -> return (hand gereizter, startingBid) publishBid Nothing (hand reizer) (hand gereizter)
return (hand gereizter, startingBid)
Nothing -> do
publishBid Nothing (hand reizer) (hand gereizter)
return (hand gereizter, startingBid)
initGame :: Hand -> Bid -> Preperation SkatEnv initGame :: Hand -> Bid -> Preperation SkatEnv
initGame single bid = do initGame single bid = do
@@ -139,8 +152,17 @@ publishGameResults res bidders = do
onResult (bidder bidders Hand3) res onResult (bidder bidders Hand3) res
publishGameStart :: Game -> Hand -> Preperation () publishGameStart :: Game -> Hand -> Preperation ()
publishGameStart game sglPlayer = do publishGameStart game sglPlayer = mapBidders (\b -> onGame b game sglPlayer)
publishBid :: Maybe Bid -> Hand -> Hand -> Preperation ()
publishBid bid reizer gereizter = mapBidders (\b -> onBid b bid reizer gereizter)
publishResponse :: Bool -> Hand -> Hand -> Preperation ()
publishResponse response reizer gereizter = mapBidders (\b -> onResponse b response reizer gereizter)
mapBidders :: (BD -> Preperation ()) -> Preperation ()
mapBidders f = do
bds <- asks bidders bds <- asks bidders
onGame (bidder bds Hand1) game sglPlayer f (bidder bds Hand1)
onGame (bidder bds Hand2) game sglPlayer f (bidder bds Hand2)
onGame (bidder bds Hand3) game sglPlayer f (bidder bds Hand3)