implement online player bidding
This commit is contained in:
+91
-6
@@ -15,6 +15,8 @@ import qualified Skat.Player.Utils as P
|
|||||||
import Skat.Pile
|
import Skat.Pile
|
||||||
import Skat.Card
|
import Skat.Card
|
||||||
import Skat.Render
|
import Skat.Render
|
||||||
|
import Skat.Preperation
|
||||||
|
import Skat.Bidding
|
||||||
|
|
||||||
class Communicator a where
|
class Communicator a where
|
||||||
send :: a -> String -> IO ()
|
send :: a -> String -> IO ()
|
||||||
@@ -32,16 +34,61 @@ data OnlineEnv c = OnlineEnv { getTeam :: Team
|
|||||||
, getHand :: Hand
|
, getHand :: Hand
|
||||||
, connection :: c }
|
, connection :: c }
|
||||||
|
|
||||||
|
data PrepOnline c = PrepOnline { prepHand :: Hand
|
||||||
|
, prepConnection :: c
|
||||||
|
, prepCards :: [Card] }
|
||||||
|
|
||||||
instance Show (OnlineEnv c) where
|
instance Show (OnlineEnv c) where
|
||||||
show _ = "An online env"
|
show _ = "An online env"
|
||||||
|
|
||||||
|
instance Show (PrepOnline c) where
|
||||||
|
show _ = "An online prep env"
|
||||||
|
|
||||||
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 _ 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
|
onGameStart p singlePlayer = runReaderT (onStartOnline singlePlayer) p
|
||||||
|
|
||||||
|
instance Communicator c => Bidder (PrepOnline c) where
|
||||||
|
hand = prepHand
|
||||||
|
askBid p against bid = do
|
||||||
|
liftIO $ send (prepConnection p) (BS.unpack $ encode $ BidQuery against bid)
|
||||||
|
r <- liftIO $ receive (prepConnection p)
|
||||||
|
case decode (BS.pack r) of
|
||||||
|
Just (BidResponse newBid) -> do
|
||||||
|
if newBid > bid then return $ Just newBid else return Nothing
|
||||||
|
Nothing -> askBid p against bid
|
||||||
|
askResponse p bidder bid = do
|
||||||
|
liftIO $ send (prepConnection p) (BS.unpack $ encode $ BidResponseQuery bidder bid)
|
||||||
|
r <- liftIO $ receive (prepConnection p)
|
||||||
|
case decode (BS.pack r) of
|
||||||
|
Just (YesNo value) -> return value
|
||||||
|
Nothing -> askResponse p bidder bid
|
||||||
|
askGame p bid = do
|
||||||
|
liftIO $ send (prepConnection p) (BS.unpack $ encode $ AskGameQuery bid)
|
||||||
|
r <- liftIO $ receive (prepConnection p)
|
||||||
|
case decode (BS.pack r) of
|
||||||
|
Just (GameResponse game) -> return game
|
||||||
|
Nothing -> askGame p bid
|
||||||
|
askHand p bid = do
|
||||||
|
liftIO $ send (prepConnection p) (BS.unpack $ encode $ AskHandQuery)
|
||||||
|
r <- liftIO $ receive (prepConnection p)
|
||||||
|
case decode (BS.pack r) of
|
||||||
|
Just (YesNo value) -> return value
|
||||||
|
Nothing -> askHand p bid
|
||||||
|
askSkat p bid cards = do
|
||||||
|
liftIO $ send (prepConnection p) (BS.unpack $ encode $ AskSkatQuery cards bid)
|
||||||
|
r <- liftIO $ receive (prepConnection p)
|
||||||
|
case decode (BS.pack r) of
|
||||||
|
Just (ChosenCards cards) -> return cards
|
||||||
|
Nothing -> askSkat p bid cards
|
||||||
|
toPlayer p tm = PL $ OnlineEnv tm (prepHand p) (prepConnection p)
|
||||||
|
onStart p = do
|
||||||
|
let cards = prepCards p
|
||||||
|
liftIO $ send (prepConnection p) (BS.unpack $ encode $ CardsQuery cards)
|
||||||
|
|
||||||
type Online a m = ReaderT (OnlineEnv a) m
|
type Online a m = ReaderT (OnlineEnv a) m
|
||||||
|
|
||||||
@@ -75,18 +122,30 @@ cardPlayed card = query (BS.unpack $ encode $ CardPlayedQuery card)
|
|||||||
onResults :: (Communicator c, MonadIO m) => (Int, Int) -> Online c m ()
|
onResults :: (Communicator c, MonadIO m) => (Int, Int) -> Online c m ()
|
||||||
onResults (sgl, tm) = query (BS.unpack $ encode $ GameResultsQuery sgl tm)
|
onResults (sgl, tm) = query (BS.unpack $ encode $ GameResultsQuery sgl tm)
|
||||||
|
|
||||||
onStart :: (Communicator c, MonadPlayer m) => Hand -> Online c m ()
|
onStartOnline :: (Communicator c, MonadPlayer m) => Hand -> Online c m ()
|
||||||
onStart singlePlayer = do
|
onStartOnline singlePlayer = do
|
||||||
trCol <- trumpColour
|
trCol <- trumpColour
|
||||||
ownHand <- asks getHand
|
ownHand <- asks getHand
|
||||||
query (BS.unpack $ encode $ GameStartQuery trCol ownHand singlePlayer)
|
query (BS.unpack $ encode $ GameStartQuery trCol ownHand singlePlayer)
|
||||||
|
|
||||||
|
-- | QUERIES AND RESPONSES
|
||||||
|
|
||||||
data Query = ChooseQuery [Card] [CardS Played]
|
data Query = ChooseQuery [Card] [CardS Played]
|
||||||
| CardPlayedQuery (CardS Played)
|
| CardPlayedQuery (CardS Played)
|
||||||
| GameResultsQuery Int Int
|
| GameResultsQuery Int Int
|
||||||
| GameStartQuery Colour Hand Hand
|
| GameStartQuery Colour Hand Hand
|
||||||
|
| BidQuery Hand Bid
|
||||||
|
| BidResponseQuery Hand Bid
|
||||||
|
| AskGameQuery Bid
|
||||||
|
| AskHandQuery
|
||||||
|
| AskSkatQuery [Card] Bid
|
||||||
|
| CardsQuery [Card]
|
||||||
|
|
||||||
data Response = ChosenResponse Card
|
newtype ChosenResponse = ChosenResponse Card
|
||||||
|
newtype BidResponse = BidResponse Int
|
||||||
|
newtype YesNo = YesNo Bool
|
||||||
|
newtype GameResponse = GameResponse Game
|
||||||
|
newtype ChosenCards = ChosenCards [Card]
|
||||||
|
|
||||||
instance ToJSON Query where
|
instance ToJSON Query where
|
||||||
toJSON (ChooseQuery hand table) =
|
toJSON (ChooseQuery hand table) =
|
||||||
@@ -97,8 +156,34 @@ instance ToJSON Query where
|
|||||||
object ["query" .= ("results" :: String), "single" .= sgl, "team" .= tm]
|
object ["query" .= ("results" :: String), "single" .= sgl, "team" .= tm]
|
||||||
toJSON (GameStartQuery trumps handNo sglPlayer) =
|
toJSON (GameStartQuery trumps handNo sglPlayer) =
|
||||||
object ["query" .= ("start_game" :: String), "trumps" .= show trumps,
|
object ["query" .= ("start_game" :: String), "trumps" .= show trumps,
|
||||||
"hand" .= toInt handNo, "single" .= toInt sglPlayer]
|
"hand" .= toInt handNo, "single" .= toInt sglPlayer ]
|
||||||
|
toJSON (BidQuery hand bid) =
|
||||||
|
object ["query" .= ("bid" :: String), "whom" .= show hand ]
|
||||||
|
toJSON (BidResponseQuery hand bid) =
|
||||||
|
object ["query" .= ("bid_response" :: String), "from" .= show hand ]
|
||||||
|
toJSON (AskHandQuery) =
|
||||||
|
object ["query" .= ("play_hand" :: String)]
|
||||||
|
toJSON (AskSkatQuery cards bid) =
|
||||||
|
object ["query" .= ("skat" :: String), "cards" .= cards, "bid" .= bid ]
|
||||||
|
toJSON (CardsQuery cards) =
|
||||||
|
object ["query" .= ("cards" :: String), "cards" .= cards ]
|
||||||
|
|
||||||
instance FromJSON Response where
|
instance FromJSON ChosenResponse where
|
||||||
parseJSON = withObject "ChosenResponse" $ \v -> ChosenResponse
|
parseJSON = withObject "ChosenResponse" $ \v -> ChosenResponse
|
||||||
<$> v .: "card"
|
<$> v .: "card"
|
||||||
|
|
||||||
|
instance FromJSON BidResponse where
|
||||||
|
parseJSON = withObject "BidResponse" $ \v -> BidResponse
|
||||||
|
<$> v .: "bid"
|
||||||
|
|
||||||
|
instance FromJSON YesNo where
|
||||||
|
parseJSON = withObject "BidYesNo" $ \v -> YesNo
|
||||||
|
<$> v .: "yesno"
|
||||||
|
|
||||||
|
instance FromJSON GameResponse where
|
||||||
|
parseJSON = withObject "GameResponse" $ \v -> GameResponse
|
||||||
|
<$> v .: "game"
|
||||||
|
|
||||||
|
instance FromJSON ChosenCards where
|
||||||
|
parseJSON = withObject "ChosenCards" $ \v -> ChosenCards
|
||||||
|
<$> v .: "cards"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ module Skat.AI.Stupid where
|
|||||||
import Skat.Player
|
import Skat.Player
|
||||||
import Skat.Pile
|
import Skat.Pile
|
||||||
import Skat.Card
|
import Skat.Card
|
||||||
|
import Skat.Preperation
|
||||||
|
|
||||||
data Stupid = Stupid { getTeam :: Team
|
data Stupid = Stupid { getTeam :: Team
|
||||||
, getHand :: Hand }
|
, getHand :: Hand }
|
||||||
@@ -16,3 +17,17 @@ instance Player Stupid where
|
|||||||
turnCol <- turnColour
|
turnCol <- turnColour
|
||||||
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)
|
||||||
|
|
||||||
|
newtype NoBidder = NoBidder Hand
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
-- | no bidding from that player
|
||||||
|
instance Bidder NoBidder where
|
||||||
|
hand (NoBidder h) = h
|
||||||
|
askBid _ _ _ = return Nothing
|
||||||
|
askResponse _ _ _ = return False
|
||||||
|
askGame _ _ = undefined -- never called
|
||||||
|
askHand _ _ = return False -- never called
|
||||||
|
askSkat _ _ _ = undefined -- never called
|
||||||
|
toPlayer (NoBidder h) team = PL $ Stupid team h
|
||||||
|
onStart _ = return ()
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
module Skat.Bidding (
|
module Skat.Bidding (
|
||||||
biddingScore, Game(..), Modifier(..)
|
biddingScore, Game(..), Modifier(..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Data.Aeson hiding (Null)
|
||||||
|
|
||||||
import Skat.Card
|
import Skat.Card
|
||||||
import Data.List (sortOn)
|
import Data.List (sortOn)
|
||||||
import Data.Ord (Down(..))
|
import Data.Ord (Down(..))
|
||||||
@@ -15,6 +19,22 @@ data Game = Colour Colour Modifier
|
|||||||
| NullOuvertHand
|
| NullOuvertHand
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
instance FromJSON Game where
|
||||||
|
parseJSON = withObject "Game" $ \v -> do
|
||||||
|
gamekind <- v .: "game"
|
||||||
|
case (gamekind :: String) of
|
||||||
|
"colour" -> do
|
||||||
|
col <- v .: "colour"
|
||||||
|
mod <- v .: "modifier"
|
||||||
|
return $ Colour (read col) mod
|
||||||
|
"grand" -> do
|
||||||
|
mod <- v .: "modifier"
|
||||||
|
return $ Grand mod
|
||||||
|
"null" -> return Null
|
||||||
|
"nullhand" -> return NullHand
|
||||||
|
"nullouvert" -> return NullOuvert
|
||||||
|
"nullouverthand" -> return NullOuvertHand
|
||||||
|
|
||||||
-- | modifiers for grand and colour games
|
-- | modifiers for grand and colour games
|
||||||
data Modifier = Einfach
|
data Modifier = Einfach
|
||||||
| Schneider
|
| Schneider
|
||||||
@@ -28,6 +48,19 @@ data Modifier = Einfach
|
|||||||
| Ouvert
|
| Ouvert
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
instance FromJSON Modifier where
|
||||||
|
parseJSON = withObject "Modifier" $ \v -> do
|
||||||
|
hnd <- v .: "hand"
|
||||||
|
if read hnd then do
|
||||||
|
schneider <- v .: "schneider"
|
||||||
|
schwarz <- v .: "schwarz"
|
||||||
|
ouvert <- v .: "ouvert"
|
||||||
|
case (schneider, schwarz, ouvert) of
|
||||||
|
(_, _, True) -> return Ouvert
|
||||||
|
(True, False, _) -> return HandSchneiderAngesagt
|
||||||
|
(_, True, _) -> return HandSchwarzAngesagt
|
||||||
|
else return Einfach
|
||||||
|
|
||||||
-- | 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
|
||||||
|
|||||||
+21
-1
@@ -1,8 +1,9 @@
|
|||||||
module Skat.Matches (
|
module Skat.Matches (
|
||||||
singleVsBots, pvp
|
singleVsBots, pvp, pvpWithBidding
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
|
import Control.Monad.Reader
|
||||||
import System.Random (mkStdGen)
|
import System.Random (mkStdGen)
|
||||||
|
|
||||||
import Skat
|
import Skat
|
||||||
@@ -10,6 +11,7 @@ import Skat.Operations
|
|||||||
import Skat.Player
|
import Skat.Player
|
||||||
import Skat.Pile
|
import Skat.Pile
|
||||||
import Skat.Card
|
import Skat.Card
|
||||||
|
import Skat.Preperation
|
||||||
|
|
||||||
import Skat.AI.Rulebased
|
import Skat.AI.Rulebased
|
||||||
import Skat.AI.Online
|
import Skat.AI.Online
|
||||||
@@ -48,3 +50,21 @@ pvp comm1 comm2 comm3 = do
|
|||||||
(PL $ OnlineEnv Team Hand3 comm3)
|
(PL $ OnlineEnv Team Hand3 comm3)
|
||||||
env = SkatEnv (distribute cards) Nothing Spades ps Hand1
|
env = SkatEnv (distribute cards) Nothing Spades ps Hand1
|
||||||
liftIO $ evalStateT (publishGameStart Hand3 >> turn >>= publishGameResults) env
|
liftIO $ evalStateT (publishGameStart Hand3 >> turn >>= publishGameResults) env
|
||||||
|
|
||||||
|
pvpWithBidding :: Communicator c => c -> c -> c -> IO ()
|
||||||
|
pvpWithBidding comm1 comm2 comm3 = do
|
||||||
|
cards <- shuffleCards
|
||||||
|
let ps = distribute cards
|
||||||
|
h1 = map toCard $ handCards Hand1 ps
|
||||||
|
h2 = map toCard $ handCards Hand2 ps
|
||||||
|
h3 = map toCard $ handCards Hand3 ps
|
||||||
|
bs = Bidders
|
||||||
|
(BD $ PrepOnline Hand1 comm1 $ h1)
|
||||||
|
(BD $ PrepOnline Hand2 comm2 $ h2)
|
||||||
|
(BD $ PrepOnline Hand3 comm3 $ h3)
|
||||||
|
env = PrepEnv ps bs
|
||||||
|
maySkatEnv <- liftIO $ runReaderT runPreperation env
|
||||||
|
case maySkatEnv of
|
||||||
|
Just skatEnv ->
|
||||||
|
liftIO $ evalStateT (publishGameStart Hand3 >> turn >>= publishGameResults) skatEnv
|
||||||
|
Nothing -> putStrLn "No one wanted to play."
|
||||||
|
|||||||
+13
-10
@@ -1,11 +1,11 @@
|
|||||||
{-# LANGUAGE ExistentialQuantification #-}
|
{-# LANGUAGE ExistentialQuantification #-}
|
||||||
|
|
||||||
module Skat.Preperation (
|
module Skat.Preperation (
|
||||||
|
Bidder(..), Bid, BD(..), Bidders(..), PrepEnv(..), runPreperation
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
import Control.Monad.State
|
import Control.Monad.Reader
|
||||||
|
|
||||||
import Skat.Pile
|
import Skat.Pile
|
||||||
import Skat.Card
|
import Skat.Card
|
||||||
@@ -16,17 +16,16 @@ import Skat (SkatEnv, mkSkatEnv)
|
|||||||
type Bid = Int
|
type Bid = Int
|
||||||
|
|
||||||
data PrepEnv = PrepEnv { piles :: Piles
|
data PrepEnv = PrepEnv { piles :: Piles
|
||||||
, currentBid :: Bid
|
|
||||||
, currentHand :: Hand
|
|
||||||
, bidders :: Bidders }
|
, bidders :: Bidders }
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
type Preperation = StateT PrepEnv IO
|
type Preperation = ReaderT PrepEnv IO
|
||||||
|
|
||||||
class Bidder a where
|
class Bidder a where
|
||||||
hand :: a -> Hand
|
hand :: a -> Hand
|
||||||
|
onStart :: MonadIO m => a -> m ()
|
||||||
askBid :: MonadIO m => a -> Hand -> Bid -> m (Maybe Bid)
|
askBid :: MonadIO m => a -> Hand -> Bid -> m (Maybe Bid)
|
||||||
askResponse :: MonadIO m => a -> Hand -> m Bool
|
askResponse :: MonadIO m => a -> Hand -> Bid -> m Bool
|
||||||
askGame :: MonadIO m => a -> Bid -> m Game
|
askGame :: MonadIO m => a -> Bid -> m Game
|
||||||
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]
|
||||||
@@ -46,6 +45,7 @@ instance Bidder BD where
|
|||||||
askSkat (BD b) = askSkat b
|
askSkat (BD b) = askSkat b
|
||||||
askResponse (BD b) = askResponse b
|
askResponse (BD b) = askResponse b
|
||||||
toPlayer (BD b) = toPlayer b
|
toPlayer (BD b) = toPlayer b
|
||||||
|
onStart (BD b) = onStart b
|
||||||
|
|
||||||
data Bidders = Bidders BD BD BD
|
data Bidders = Bidders BD BD BD
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -63,7 +63,10 @@ toPlayers single (Bidders b1 b2 b3) =
|
|||||||
|
|
||||||
runPreperation :: Preperation (Maybe SkatEnv)
|
runPreperation :: Preperation (Maybe SkatEnv)
|
||||||
runPreperation = do
|
runPreperation = do
|
||||||
bds <- gets bidders
|
bds <- asks bidders
|
||||||
|
onStart (bidder bds Hand1)
|
||||||
|
onStart (bidder bds Hand2)
|
||||||
|
onStart (bidder bds Hand3)
|
||||||
(winner, bid) <- runBidding 0 (bidder bds Hand2) (bidder bds Hand1)
|
(winner, bid) <- runBidding 0 (bidder bds Hand2) (bidder bds Hand1)
|
||||||
(finalWinner, finalBid) <- runBidding 0 (bidder bds Hand3) (bidder bds winner)
|
(finalWinner, finalBid) <- runBidding 0 (bidder bds Hand3) (bidder bds winner)
|
||||||
if finalBid == 0 then do
|
if finalBid == 0 then do
|
||||||
@@ -78,15 +81,15 @@ runBidding startingBid reizer gereizter = do
|
|||||||
first <- askBid reizer (hand gereizter) startingBid
|
first <- askBid reizer (hand gereizter) startingBid
|
||||||
case first of
|
case first of
|
||||||
Just val -> do
|
Just val -> do
|
||||||
response <- askResponse gereizter (hand reizer)
|
response <- askResponse gereizter (hand reizer) val
|
||||||
if response then runBidding val reizer gereizter
|
if response then runBidding val reizer gereizter
|
||||||
else return (hand reizer, val)
|
else return (hand reizer, val)
|
||||||
Nothing -> return (hand gereizter, startingBid)
|
Nothing -> return (hand gereizter, startingBid)
|
||||||
|
|
||||||
initGame :: Hand -> Bid -> Preperation SkatEnv
|
initGame :: Hand -> Bid -> Preperation SkatEnv
|
||||||
initGame single bid = do
|
initGame single bid = do
|
||||||
ps <- gets piles
|
ps <- asks piles
|
||||||
bds <- gets bidders
|
bds <- asks bidders
|
||||||
-- ask if player wants to play hand
|
-- ask if player wants to play hand
|
||||||
noSkat <- askHand (bidder bds single) bid
|
noSkat <- askHand (bidder bds single) bid
|
||||||
-- either return piles or ask for skat cards and modify piles
|
-- either return piles or ask for skat cards and modify piles
|
||||||
|
|||||||
Reference in New Issue
Block a user