Skip to content

Commit b04dbf2

Browse files
committed
Encode in the types that you can't run askPlayer with an empty list.
1 parent b3caa21 commit b04dbf2

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

Startups/Game.hs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,12 @@ playAge age = do
236236
let recyclers = pm ^.. traverse . filtered (has (_2 . cardEffects . _Recycling)) . _1
237237
forM_ recyclers $ \pid -> do
238238
stt <- use id
239-
card <- askCardSafe age pid (stt ^. discardpile) stt "Choose a card to recycle (play for free)"
240-
playermap . ix pid . pCards %= (card :)
239+
case stt ^? discardpile . _NonEmpty of
240+
Just nedp -> do
241+
card <- askCardSafe age pid nedp stt "Choose a card to recycle (play for free)"
242+
playermap . ix pid . pCards %= (card :)
243+
discardpile %= filter (/= card)
244+
Nothing -> tellPlayer pid "The discard pile was empty, you can't recycle."
241245
-- resolve the "military" part
242246
resolvePoaching age
243247

@@ -251,10 +255,12 @@ checkCopyCommunity = use playermap >>= itraverse_ checkPlayer
251255
mvioletCards <- forM (stt ^.. pNeighborhood . traverse) $ \nid ->
252256
toListOf (pCards . traverse . filtered (has (cType . _Community))) <$> getPlayerState nid
253257
let violetCards = concat mvioletCards
254-
unless (null violetCards) $ do
255-
gs <- use id
256-
card <- askCardSafe Age3 pid violetCards gs "Which community would you like to copy ?"
257-
playermap . ix pid . pCards %= (card:)
258+
case violetCards ^? _NonEmpty of
259+
Just nevc -> do
260+
gs <- use id
261+
card <- askCardSafe Age3 pid nevc gs "Which community would you like to copy ?"
262+
playermap . ix pid . pCards %= (card:)
263+
Nothing -> tellPlayer pid "There were no violet cards bought by your neighbors. You can't use your copy capacity."
258264

259265
victoryPoints :: GameStateOnly m => m (M.Map PlayerId (M.Map VictoryType VictoryPoint))
260266
victoryPoints = use playermap >>= itraverse computeScore

Startups/GameTypes.hs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ type Message = String
5151
data PlayerAction = PlayerAction ActionType Card
5252
data ActionType = Play | Drop | BuildCompany
5353

54+
-- | Some types for non empty lists
55+
data NonEmpty a = NonEmpty a [a]
56+
57+
_NonEmpty :: Prism' [a] (NonEmpty a)
58+
_NonEmpty = prism fromNonEmpty toNonEmpty
59+
where
60+
fromNonEmpty (NonEmpty x xs) = x : xs
61+
toNonEmpty l = case l of
62+
[] -> Left l
63+
(x:xs) -> Right (NonEmpty x xs)
64+
5465
-- | This describe the capabilities needed to write the rules, when no
5566
-- interaction with the player is required.
5667
type NonInteractive m = (MonadState GameState m, Monad m, MonadError Message m, Functor m, Applicative m)
@@ -61,15 +72,15 @@ class NonInteractive m => GameMonad m where
6172
playerDecision :: Age -> Turn -> PlayerId -> [Card] -> GameState -> m (PlayerAction, Exchange)
6273
-- | Ask the player to chose a card, along with a descriptive message.
6374
-- This is used for the Recycling and CopyCommunity effects.
64-
askCard :: Age -> PlayerId -> [Card] -> GameState -> Message -> m Card
75+
askCard :: Age -> PlayerId -> NonEmpty Card -> GameState -> Message -> m Card
6576
tellPlayer :: PlayerId -> Message -> m () -- ^ Tell some information to a specific player
6677
generalMessage :: Message -> m () -- ^ Broadcast some information
6778

6879
-- We define "safe" versions of the `askCard` function, that makes sure the
6980
-- player doesn't introduce a new card in the game.
7081

71-
askCardSafe :: GameMonad m => Age -> PlayerId -> [Card] -> GameState -> Message -> m Card
82+
askCardSafe :: GameMonad m => Age -> PlayerId -> NonEmpty Card -> GameState -> Message -> m Card
7283
askCardSafe a p cl s m = do
7384
card <- askCard a p cl s m
74-
when (card `notElem` cl) (throwError "The player tried to play a non proposed card")
85+
when (card `notElem` (cl ^. re _NonEmpty)) (throwError "The player tried to play a non proposed card")
7586
return card

0 commit comments

Comments
 (0)