-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Implementation of the rules of Love Letter
--
-- Implementation of the rules of Love Letter
@package haverer
@version 0.2.0.0
module Haverer.Internal.Ring
data Ring a
makeRing :: [a] -> Maybe (Ring a)
advance :: Ring a -> Ring a
advance1 :: Ring a -> Either a (Ring a)
dropItem :: (Eq a) => Ring a -> a -> Maybe (Ring a)
dropItem1 :: (Eq a) => Ring a -> a -> Either a (Ring a)
toList :: Ring a -> [a]
nextItem :: Ring a -> a
ringSize :: Ring a -> Int
currentItem :: Ring a -> a
instance GHC.Classes.Eq a => GHC.Classes.Eq (Haverer.Internal.Ring.Ring a)
instance GHC.Show.Show a => GHC.Show.Show (Haverer.Internal.Ring.Ring a)
module Haverer.Internal.Error
-- | Assert that the value is Right. Throws error if it's Left.
assertRight :: (Show a) => Text -> Either a b -> b
-- | Assert that the value is Right. Throws error if it's Left.
assertRight' :: Show a => Either a b -> b
-- | error applied to Text
--
-- Since 0.4.1
terror :: Text -> a
module Haverer.Internal.Counter
data Counter k a
increment :: (Ord k, Num a) => Counter k a -> k -> Counter k a
incrementMany :: (Ord k, Num a, Foldable m) => Counter k a -> m k -> Counter k a
initialize :: (Ord k, Num a) => [k] -> Counter k a
toList :: (Ord k) => Counter k a -> [(k, a)]
top :: (Ord k, Ord a, Eq a) => Counter k a -> (a, [k])
topValue :: (Ord k, Ord a) => Counter k a -> a
instance (GHC.Show.Show k, GHC.Show.Show a) => GHC.Show.Show (Haverer.Internal.Counter.Counter k a)
module Haverer.CLI.Prompt
class ConsoleText a
toText :: ConsoleText a => a -> Text
underline :: Char -> Text -> Text
prompt :: ConsoleText e => Text -> (Text -> Either e a) -> IO (Either e a)
repeatedlyPrompt :: ConsoleText e => Text -> (Text -> Either e a) -> IO a
chooseItem :: ConsoleText a => Text -> [a] -> IO a
chooseItem' :: ConsoleText a => Text -> Int -> [a] -> IO a
instance Haverer.CLI.Prompt.ConsoleText Data.Text.Internal.Text
instance Haverer.CLI.Prompt.ConsoleText GHC.Types.Int
module Haverer.Deck
allCards :: [Card]
baseCards :: [Card]
data Card
Soldier :: Card
Clown :: Card
Knight :: Card
Priestess :: Card
Wizard :: Card
General :: Card
Minister :: Card
Prince :: Card
data DeckSize
Incomplete :: DeckSize
Complete :: DeckSize
deal :: FullDeck -> Int -> Maybe (Card, [Card], Deck Incomplete)
data Deck (a :: DeckSize)
type FullDeck = Deck Complete
makeDeck :: [Card] -> Maybe (Deck Complete)
newDeck :: MonadRandom m => m (Deck Complete)
pop :: Deck a -> (Maybe Card, Deck Incomplete)
shuffleDeck :: MonadRandom m => Deck a -> m (Deck a)
toList :: Deck a -> [Card]
instance GHC.Classes.Ord (Haverer.Deck.Deck a)
instance GHC.Show.Show (Haverer.Deck.Deck a)
instance GHC.Classes.Eq (Haverer.Deck.Deck a)
instance GHC.Enum.Enum Haverer.Deck.Card
instance GHC.Classes.Ord Haverer.Deck.Card
instance GHC.Show.Show Haverer.Deck.Card
instance GHC.Classes.Eq Haverer.Deck.Card
module Haverer.Player
bust :: Player -> Card -> Player
data Error a
InvalidNumPlayers :: Int -> Error a
DuplicatePlayers :: [a] -> Error a
discardAndDraw :: Player -> Maybe Card -> Player
eliminate :: Player -> Player
getDiscards :: Player -> [Card]
getHand :: Player -> Maybe Card
isProtected :: Player -> Maybe Bool
makePlayer :: Card -> Player
data Player
data PlayerSet a
-- | Given a dealt and chosen card, update the hand to chosen, and chuck
-- whatever wasn't played onto the discard pile.
playCard :: Player -> Card -> Card -> Maybe Player
protect :: Player -> Player
swapHands :: Player -> Player -> (Player, Player)
toPlayers :: PlayerSet a -> [a]
toPlayerSet :: Ord a => [a] -> Either (Error a) (PlayerSet a)
unprotect :: Player -> Player
instance GHC.Classes.Eq Haverer.Player.Player
instance GHC.Show.Show Haverer.Player.Player
instance GHC.Classes.Eq a => GHC.Classes.Eq (Haverer.Player.PlayerSet a)
instance GHC.Show.Show a => GHC.Show.Show (Haverer.Player.PlayerSet a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Haverer.Player.Error a)
instance GHC.Show.Show a => GHC.Show.Show (Haverer.Player.Error a)
module Haverer.Action
data BadPlay target
-- | A thing that can be done with a card.
data Play target
NoEffect :: Play target
Attack :: target -> Play target
Guess :: target -> Card -> Play target
-- | A validated card + play combination. Only guarantees that such a thing
-- makes sense according to the rules, rather than the current state of
-- the round.
data Action target
-- | If you're holding the Minister, there's a potential to "bust out" --
-- to have to immediately leave the round because you're holding another
-- high card.
bustingHand :: Card -> Card -> Bool
getTarget :: Play target -> Maybe target
-- | Return all valid plays for a hand.
--
-- If the hand is one that would bust out (see bustingHand) then
-- returns an empty list.
getValidPlays :: player -> [player] -> Card -> Card -> [(Card, Play player)]
-- | Given a player, a card, and a choice of play, decide whether it's a
-- valid action.
playToAction :: (Eq target, MonadError (BadPlay target) m) => target -> Card -> Play target -> m (Action target)
viewAction :: Action target -> (target, Card, Play target)
instance GHC.Show.Show target => GHC.Show.Show (Haverer.Action.BadPlay target)
instance GHC.Show.Show target => GHC.Show.Show (Haverer.Action.Action target)
instance GHC.Classes.Eq target => GHC.Classes.Eq (Haverer.Action.Action target)
instance GHC.Show.Show target => GHC.Show.Show (Haverer.Action.Play target)
instance GHC.Classes.Eq target => GHC.Classes.Eq (Haverer.Action.Play target)
module Haverer.Round
data Round playerId
-- | Make a new round, given a complete Deck and a set of players.
makeRound :: (Ord playerId, Show playerId) => FullDeck -> PlayerSet playerId -> Round playerId
-- | Play a turn in a Round.
--
-- This is the main function in this module.
--
-- A turn has two steps. First, the player draws a card. If their hand
-- "busts out" (due to holding the Minister and another high card), then
-- they are eliminated and play proceeds to the next player. This is the
-- Left return value, which returns the new Round and a Result
-- indicating the player bust out.
--
-- Second, the player plays one of these two cards. This is the
-- Right return value, a function that takes the players chosen
-- card and play, and returns either a BadAction or a new Round together
-- with the Result of the play.
playTurn :: (Ord playerId, Show playerId) => Round playerId -> Either (ActionM playerId (Result playerId, Round playerId)) (Card -> Play playerId -> ActionM playerId (Result playerId, Round playerId))
-- | Play a turn in a Round
--
-- Similar to playTurn, except that instead of splitting the turn into
-- two phases, there is a single, optional play. If the hand is a busting
-- hand, then the play must be Nothing; if not, the play must be
-- specified.
playTurn' :: (Ord playerId, Show playerId) => Round playerId -> Maybe (Card, Play playerId) -> ActionM playerId (Result playerId, Round playerId)
data BadAction playerId
-- | The result of a turn.
data Result playerId
-- | The player whose turn it was "busted out", they held the Minister and
-- another high card, and thus didn't get to play.
BustedOut :: playerId -> Card -> Card -> Result playerId
-- | The player performed an Action resulting in Event.
Played :: (Action playerId) -> (Event playerId) -> Result playerId
-- | A change to the Round that comes as result of a player's actions.
data Event playerId
-- | Nothing happened. What the player did had no effect.
NoChange :: Event playerId
-- | The player is now protected.
Protected :: playerId -> Event playerId
-- | The first player has been forced to swap hands with the second.
SwappedHands :: playerId -> playerId -> Event playerId
-- | The player has been eliminated from the round.
Eliminated :: playerId -> Event playerId
-- | The player has been forced to discard their hand.
ForcedDiscard :: playerId -> Event playerId
-- | The second player has been forced to show their hand to the first.
ForcedReveal :: playerId -> playerId -> Card -> Event playerId
-- | The ID of the current player. If the Round is over or not started,
-- this will be Nothing.
currentPlayer :: Round playerId -> Maybe playerId
currentTurn :: Ord playerId => Round playerId -> Maybe (playerId, (Card, Card))
-- | The IDs of all of the active players.
getActivePlayers :: Round playerId -> [playerId]
-- | Get the burn card for the Round. Only possible when the Round is over.
--
-- Since 0.1.1
getBurnCard :: Round playerId -> Maybe Card
-- | Get the player with the given ID. Nothing if there is no such player.
getPlayer :: Ord playerId => Round playerId -> playerId -> Maybe Player
-- | A map of player IDs to players.
getPlayerMap :: Round playerId -> Map playerId Player
-- | The IDs of all of the players.
getPlayers :: Round playerId -> [playerId]
getWinners :: Victory playerId -> [playerId]
nextPlayer :: Round playerId -> Maybe playerId
-- | The number of cards remaining in the deck.
remainingCards :: Round playerId -> Int
data Victory playerId
-- | The given player is the only survivor.
SoleSurvivor :: playerId -> Card -> Victory playerId
-- | These players have the highest card.
HighestCard :: Card -> [playerId] -> [(playerId, Card)] -> Victory playerId
-- | The currently surviving players in the round, with their cards.
survivors :: Victory playerId -> [(playerId, Card)]
-- | If the Round is Over, return the Victory data. Otherwise, Nothing.
victory :: Round playerId -> Maybe (Victory playerId)
-- | Are all the cards in the Round?
prop_allCardsPresent :: Round playerId -> Bool
prop_burnCardsSame :: [Round playerId] -> Bool
prop_multipleActivePlayers :: Round playerId -> Bool
prop_ringIsActivePlayers :: Eq playerId => Round playerId -> Bool
instance GHC.Show.Show playerId => GHC.Show.Show (Haverer.Round.Victory playerId)
instance GHC.Classes.Eq playerId => GHC.Classes.Eq (Haverer.Round.Victory playerId)
instance GHC.Show.Show playerId => GHC.Show.Show (Haverer.Round.Result playerId)
instance GHC.Classes.Eq playerId => GHC.Classes.Eq (Haverer.Round.Result playerId)
instance GHC.Show.Show playerId => GHC.Show.Show (Haverer.Round.Event playerId)
instance GHC.Classes.Eq playerId => GHC.Classes.Eq (Haverer.Round.Event playerId)
instance GHC.Show.Show playerId => GHC.Show.Show (Haverer.Round.BadAction playerId)
instance GHC.Show.Show playerId => GHC.Show.Show (Haverer.Round.Round playerId)
instance GHC.Show.Show Haverer.Round.RoundState
module Haverer.Game
data Game playerId
data Outcome playerId
-- | Get the final scores at the end of the game.
finalScores :: Ord playerId => Outcome playerId -> [(playerId, Int)]
-- | Create a new game for the given set of players.
makeGame :: Ord playerId => PlayerSet playerId -> Game playerId
-- | Start a new round of the game, shuffling the deck cards ourselves.
newRound :: (Functor m, MonadRandom m, Ord playerId, Show playerId) => Game playerId -> m (Round playerId)
-- | Start a new round of the game with an already-shuffled deck of cards.
newRound' :: (Ord playerId, Show playerId) => Game playerId -> FullDeck -> Round playerId
-- | Return the set of all players
players :: Game playerId -> PlayerSet playerId
-- | Indicate that the specified players won.
playersWon :: Ord playerId => Game playerId -> [playerId] -> Either (Outcome playerId) (Game playerId)
-- | Return the number of rounds played.
roundsPlayed :: Game playerId -> Int
-- | Return the current scores of all the players.
scores :: Ord playerId => Game playerId -> [(playerId, Int)]
-- | Get the winners of the game.
winners :: Ord playerId => Outcome playerId -> [playerId]
instance GHC.Show.Show playerId => GHC.Show.Show (Haverer.Game.Outcome playerId)
instance GHC.Show.Show playerId => GHC.Show.Show (Haverer.Game.Game playerId)
module Haverer.CLI.CommandLine
class ConsoleText a
toText :: ConsoleText a => a -> Text
formatScores :: ConsoleText playerId => [(playerId, Int)] -> Text
pickNumPlayers :: IO Int
pickCardToPlay :: (Card, Card) -> IO Card
pickPlay :: ConsoleText playerId => Card -> PlayerSet playerId -> IO (Play playerId)
instance Haverer.CLI.Prompt.ConsoleText Haverer.Deck.Card
instance Haverer.CLI.Prompt.ConsoleText a => Haverer.CLI.Prompt.ConsoleText (Haverer.Round.Round a)
instance (GHC.Classes.Eq a, Haverer.CLI.Prompt.ConsoleText a, GHC.Show.Show a) => Haverer.CLI.Prompt.ConsoleText (Haverer.Round.Result a)
instance Haverer.CLI.Prompt.ConsoleText a => Haverer.CLI.Prompt.ConsoleText (Haverer.Round.Victory a)
module Haverer.Engine
class Monad m => MonadEngine m playerId where badPlay _ = return () gameStarted _ = return () gameOver _ = return () roundStarted _ _ = return () roundOver _ = return () handStarted _ = return () handOver _ = return ()
badPlay :: MonadEngine m playerId => BadAction playerId -> m ()
choosePlay :: MonadEngine m playerId => PlayerSet playerId -> playerId -> Card -> Card -> m (Card, Play playerId)
gameStarted :: MonadEngine m playerId => Game playerId -> m ()
gameOver :: MonadEngine m playerId => Outcome playerId -> m ()
roundStarted :: MonadEngine m playerId => Game playerId -> Round playerId -> m ()
roundOver :: MonadEngine m playerId => Victory playerId -> m ()
handStarted :: MonadEngine m playerId => Round playerId -> m ()
handOver :: MonadEngine m playerId => Result playerId -> m ()
playGame :: (Ord playerId, Show playerId, MonadRandom m, MonadEngine m playerId) => PlayerSet playerId -> m (Outcome playerId)
module Haverer.ValidMoves
getValidMoves :: Ord playerId => Round playerId -> [(Card, Play playerId)]
protectedPlayers :: Ord playerId => Round playerId -> [playerId]
movesThatTargetPlayer :: Ord playerId => Round playerId -> playerId -> [(Card, Play playerId)]
attacksOnProtectedPlayers :: Ord playerId => Round playerId -> [(Card, Play playerId)]
module Haverer.Testing
type PlayerId = Int
-- | Generate an event that might come up in the course of play.
inRoundEvent :: Gen (Result PlayerId)
-- | For a Round and a known-good Card and Play, play the cards and return
-- the round and event. If the hand busts out, Card and Play are ignored.
playTurn' :: (Ord a, Show a) => Round a -> Card -> Play a -> (Result a, Round a)
-- | Generate a random round that might come up in the course of play.
randomRound :: Gen (Round PlayerId)
-- | Generate a random number of consecutive rounds, starting from an
-- initial round.
randomRounds :: Gen [Round PlayerId]
-- | Take a list and generate a shuffled version of it.
shuffled :: [a] -> Gen [a]
instance Test.QuickCheck.Arbitrary.Arbitrary Haverer.Deck.FullDeck
instance Test.QuickCheck.Arbitrary.Arbitrary (Haverer.Player.PlayerSet Haverer.Testing.PlayerId)
instance Test.QuickCheck.Arbitrary.Arbitrary (Haverer.Round.Round Haverer.Testing.PlayerId)
-- | Implementation of the rules of Love Letter.
module Haverer
data Game playerId
-- | Create a new game for the given set of players.
makeGame :: Ord playerId => PlayerSet playerId -> Game playerId
-- | Start a new round of the game, shuffling the deck cards ourselves.
newRound :: (Functor m, MonadRandom m, Ord playerId, Show playerId) => Game playerId -> m (Round playerId)
-- | Start a new round of the game with an already-shuffled deck of cards.
newRound' :: (Ord playerId, Show playerId) => Game playerId -> FullDeck -> Round playerId
-- | Return the set of all players
players :: Game playerId -> PlayerSet playerId
-- | Return the number of rounds played.
roundsPlayed :: Game playerId -> Int
-- | Get the final scores at the end of the game.
finalScores :: Ord playerId => Outcome playerId -> [(playerId, Int)]
-- | Return the current scores of all the players.
scores :: Ord playerId => Game playerId -> [(playerId, Int)]
-- | Get the winners of the game.
winners :: Ord playerId => Outcome playerId -> [playerId]
data Round playerId
data BadAction playerId
-- | The result of a turn.
data Result playerId
-- | The player whose turn it was "busted out", they held the Minister and
-- another high card, and thus didn't get to play.
BustedOut :: playerId -> Card -> Card -> Result playerId
-- | The player performed an Action resulting in Event.
Played :: (Action playerId) -> (Event playerId) -> Result playerId
-- | A change to the Round that comes as result of a player's actions.
data Event playerId
-- | Nothing happened. What the player did had no effect.
NoChange :: Event playerId
-- | The player is now protected.
Protected :: playerId -> Event playerId
-- | The first player has been forced to swap hands with the second.
SwappedHands :: playerId -> playerId -> Event playerId
-- | The player has been eliminated from the round.
Eliminated :: playerId -> Event playerId
-- | The player has been forced to discard their hand.
ForcedDiscard :: playerId -> Event playerId
-- | The second player has been forced to show their hand to the first.
ForcedReveal :: playerId -> playerId -> Card -> Event playerId
-- | Play a turn in a Round.
--
-- This is the main function in this module.
--
-- A turn has two steps. First, the player draws a card. If their hand
-- "busts out" (due to holding the Minister and another high card), then
-- they are eliminated and play proceeds to the next player. This is the
-- Left return value, which returns the new Round and a Result
-- indicating the player bust out.
--
-- Second, the player plays one of these two cards. This is the
-- Right return value, a function that takes the players chosen
-- card and play, and returns either a BadAction or a new Round together
-- with the Result of the play.
playTurn :: (Ord playerId, Show playerId) => Round playerId -> Either (ActionM playerId (Result playerId, Round playerId)) (Card -> Play playerId -> ActionM playerId (Result playerId, Round playerId))
-- | Play a turn in a Round
--
-- Similar to playTurn, except that instead of splitting the turn into
-- two phases, there is a single, optional play. If the hand is a busting
-- hand, then the play must be Nothing; if not, the play must be
-- specified.
playTurn' :: (Ord playerId, Show playerId) => Round playerId -> Maybe (Card, Play playerId) -> ActionM playerId (Result playerId, Round playerId)
-- | The IDs of all of the players.
getPlayers :: Round playerId -> [playerId]
-- | A map of player IDs to players.
getPlayerMap :: Round playerId -> Map playerId Player
-- | The ID of the current player. If the Round is over or not started,
-- this will be Nothing.
currentPlayer :: Round playerId -> Maybe playerId
currentTurn :: Ord playerId => Round playerId -> Maybe (playerId, (Card, Card))
data Card
Soldier :: Card
Clown :: Card
Knight :: Card
Priestess :: Card
Wizard :: Card
General :: Card
Minister :: Card
Prince :: Card
data Deck (a :: DeckSize)
data DeckSize
Incomplete :: DeckSize
Complete :: DeckSize
type FullDeck = Deck Complete
newDeck :: MonadRandom m => m (Deck Complete)
-- | A thing that can be done with a card.
data Play target
NoEffect :: Play target
Attack :: target -> Play target
Guess :: target -> Card -> Play target
viewAction :: Action target -> (target, Card, Play target)
data Player
getDiscards :: Player -> [Card]
getHand :: Player -> Maybe Card
isProtected :: Player -> Maybe Bool
toPlayers :: PlayerSet a -> [a]
toPlayerSet :: Ord a => [a] -> Either (Error a) (PlayerSet a)