6 Commits
Author SHA1 Message Date
christian 255971b2f5 publish info on game start 2019-08-28 17:24:06 +02:00
christian 7138f74e8e add preconfigured matches and extend online ai 2019-08-28 16:27:24 +02:00
christian 409ef29da1 update cabal file 2019-08-26 16:11:16 +02:00
christian 045b3fc00a update version 2019-08-26 16:10:23 +02:00
christian 30406df4d7 add license file 2019-08-26 16:08:25 +02:00
christian 98e875eeea update package information 2019-08-26 11:52:58 +02:00
12 changed files with 117 additions and 112 deletions
+1
View File
@@ -2,6 +2,7 @@
!*.*
!*/
!LICENSE
*.hi
*.o
+30
View File
@@ -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.
-88
View File
@@ -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
+4 -1
View File
@@ -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
View File
@@ -35,7 +35,8 @@ runAI = do
if length trs >= 5 && any ((==32) . getID) cs
then do
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
env :: SkatEnv
+5 -5
View File
@@ -1,10 +1,10 @@
name: skat
version: 0.1.0.0
version: 0.1.0.1
github: "githubuser/skat"
license: BSD3
author: "Author name here"
maintainer: "example@example.com"
copyright: "2019 Author name here"
author: "flavis"
maintainer: "christian@flavigny.de"
copyright: "2019"
extra-source-files:
- README.md
@@ -17,7 +17,7 @@ extra-source-files:
# To avoid duplicated efforts in documentation and dealing with the
# complications of embedding Haddock markup inside cabal files, it is
# 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:
- base >= 4.7 && < 5
+7 -6
View File
@@ -4,16 +4,16 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: e2db48733c92b94d7f2d8f4991dd2f7cec26d59666cd3c618710a8a3c22616d0
-- hash: 0d6eafec0c3ba6bb4c0150a39f4dbab784c7a519ec911d0f0344edd1c5d916da
name: skat
version: 0.1.0.0
description: Please see the README on GitHub at <https://github.com/githubuser/skat#readme>
version: 0.1.0.1
description: Please see the README on Gitea at <https://git.flavigny.de/christian/skat>
homepage: https://github.com/githubuser/skat#readme
bug-reports: https://github.com/githubuser/skat/issues
author: Author name here
maintainer: example@example.com
copyright: 2019 Author name here
author: flavis
maintainer: christian@flavigny.de
copyright: 2019
license: BSD3
license-file: LICENSE
build-type: Simple
@@ -34,6 +34,7 @@ library
Skat.AI.Server
Skat.AI.Stupid
Skat.Card
Skat.Matches
Skat.Operations
Skat.Pile
Skat.Player
+18 -10
View File
@@ -33,6 +33,7 @@ instance Player OnlineEnv where
chooseCard p table _ hand = runReaderT (choose table hand) p >>= \c -> return (c, p)
onCardPlayed p c = runReaderT (cardPlayed c) p >> return p
onGameResults p res = runReaderT (onResults res) p
onGameStart p singlePlayer = runReaderT (onStart singlePlayer) p
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 (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
onStart :: MonadPlayer m => Hand -> Online m ()
onStart singlePlayer = do
trCol <- trumpColour
ownHand <- asks getHand
query (BS.unpack $ encode $ GameStartQuery trCol ownHand singlePlayer)
instance ToJSON ChooseQuery where
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) =
object ["query" .= ("choose_card" :: String), "hand" .= hand, "table" .= table]
instance ToJSON CardPlayedQuery where
toJSON (CardPlayedQuery card) =
object ["query" .= ("card_played" :: String), "card" .= card]
instance ToJSON GameResultsQuery where
toJSON (GameResultsQuery sgl 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
<$> v .: "card"
+25
View File
@@ -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
View File
@@ -1,4 +1,7 @@
module Skat.Operations where
module Skat.Operations (
turn, turnGeneric, play, playOpen, publishGameResults,
publishGameStart
) where
import Control.Monad.State
import System.Random (newStdGen, randoms)
@@ -86,3 +89,13 @@ playOpen p = do
card <- chooseCardOpen p
modifyp $ playCard 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)
+5
View File
@@ -28,6 +28,11 @@ instance ToJSON p => ToJSON (CardS p) where
data Hand = Hand1 | Hand2 | Hand3
deriving (Show, Eq, Ord)
toInt :: Hand -> Int
toInt Hand1 = 1
toInt Hand2 = 2
toInt Hand3 = 3
next :: Hand -> Hand
next Hand1 = Hand2
next Hand2 = Hand3
+6
View File
@@ -43,6 +43,11 @@ class Player p where
-> (Int, Int)
-> m ()
onGameResults _ _ = return ()
onGameStart :: MonadPlayer m
=> p
-> Hand
-> m ()
onGameStart _ _ = return ()
data PL = forall p. (Show p, Player p) => PL p
@@ -60,6 +65,7 @@ instance Player PL where
return $ PL v
chooseCardOpen (PL p) = chooseCardOpen p
onGameResults (PL p) res = onGameResults p res
onGameStart (PL p) singlePlayer = onGameStart p singlePlayer
data Players = Players PL PL PL
deriving Show