Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
255971b2f5 | ||
|
|
7138f74e8e | ||
|
|
409ef29da1 | ||
|
|
045b3fc00a | ||
|
|
30406df4d7 | ||
|
|
98e875eeea |
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
!*.*
|
!*.*
|
||||||
!*/
|
!*/
|
||||||
|
!LICENSE
|
||||||
|
|
||||||
*.hi
|
*.hi
|
||||||
*.o
|
*.o
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
Copyright Author name here (c) 2019
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Author name here nor the names of other
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
@@ -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
|
|
||||||
@@ -1 +1,4 @@
|
|||||||
# skat
|
# Skat
|
||||||
|
|
||||||
|
This is a Haskell implementation of the famous german card game Skat. It provides
|
||||||
|
a library implementing all the game mechanics and a simple AI.
|
||||||
|
|||||||
+2
-1
@@ -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
|
||||||
|
|||||||
+5
-5
@@ -1,10 +1,10 @@
|
|||||||
name: skat
|
name: skat
|
||||||
version: 0.1.0.0
|
version: 0.1.0.1
|
||||||
github: "githubuser/skat"
|
github: "githubuser/skat"
|
||||||
license: BSD3
|
license: BSD3
|
||||||
author: "Author name here"
|
author: "flavis"
|
||||||
maintainer: "example@example.com"
|
maintainer: "christian@flavigny.de"
|
||||||
copyright: "2019 Author name here"
|
copyright: "2019"
|
||||||
|
|
||||||
extra-source-files:
|
extra-source-files:
|
||||||
- README.md
|
- README.md
|
||||||
@@ -17,7 +17,7 @@ extra-source-files:
|
|||||||
# To avoid duplicated efforts in documentation and dealing with the
|
# To avoid duplicated efforts in documentation and dealing with the
|
||||||
# complications of embedding Haddock markup inside cabal files, it is
|
# complications of embedding Haddock markup inside cabal files, it is
|
||||||
# common to point users to the README.md file.
|
# common to point users to the README.md file.
|
||||||
description: Please see the README on GitHub at <https://github.com/githubuser/skat#readme>
|
description: Please see the README on Gitea at <https://git.flavigny.de/christian/skat>
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- base >= 4.7 && < 5
|
- base >= 4.7 && < 5
|
||||||
|
|||||||
+7
-6
@@ -4,16 +4,16 @@ cabal-version: 1.12
|
|||||||
--
|
--
|
||||||
-- see: https://github.com/sol/hpack
|
-- see: https://github.com/sol/hpack
|
||||||
--
|
--
|
||||||
-- hash: e2db48733c92b94d7f2d8f4991dd2f7cec26d59666cd3c618710a8a3c22616d0
|
-- hash: 0d6eafec0c3ba6bb4c0150a39f4dbab784c7a519ec911d0f0344edd1c5d916da
|
||||||
|
|
||||||
name: skat
|
name: skat
|
||||||
version: 0.1.0.0
|
version: 0.1.0.1
|
||||||
description: Please see the README on GitHub at <https://github.com/githubuser/skat#readme>
|
description: Please see the README on Gitea at <https://git.flavigny.de/christian/skat>
|
||||||
homepage: https://github.com/githubuser/skat#readme
|
homepage: https://github.com/githubuser/skat#readme
|
||||||
bug-reports: https://github.com/githubuser/skat/issues
|
bug-reports: https://github.com/githubuser/skat/issues
|
||||||
author: Author name here
|
author: flavis
|
||||||
maintainer: example@example.com
|
maintainer: christian@flavigny.de
|
||||||
copyright: 2019 Author name here
|
copyright: 2019
|
||||||
license: BSD3
|
license: BSD3
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
build-type: Simple
|
build-type: Simple
|
||||||
@@ -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
|
||||||
|
|||||||
+18
-10
@@ -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]
|
onStart :: MonadPlayer m => Hand -> Online m ()
|
||||||
data CardPlayedQuery = CardPlayedQuery (CardS Played)
|
onStart singlePlayer = do
|
||||||
data GameResultsQuery = GameResultsQuery Int Int
|
trCol <- trumpColour
|
||||||
data ChosenResponse = ChosenResponse Card
|
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
|
||||||
|
|
||||||
instance ToJSON ChooseQuery where
|
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 (publishGameStart Hand3 >> turn Hand1 >>= publishGameResults) env
|
||||||
+14
-1
@@ -1,4 +1,7 @@
|
|||||||
module Skat.Operations where
|
module Skat.Operations (
|
||||||
|
turn, turnGeneric, play, playOpen, publishGameResults,
|
||||||
|
publishGameStart
|
||||||
|
) where
|
||||||
|
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import System.Random (newStdGen, randoms)
|
import System.Random (newStdGen, randoms)
|
||||||
@@ -86,3 +89,13 @@ 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)
|
||||||
|
|
||||||
|
publishGameStart :: Hand -> Skat ()
|
||||||
|
publishGameStart sglPlayer = do
|
||||||
|
pls <- gets players
|
||||||
|
mapM_ (\p -> onGameStart p sglPlayer) (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
|
||||||
|
|||||||
Reference in New Issue
Block a user