Copyright | (c) Henry J. Wylde, 2016 |
---|---|
License | BSD3 |
Maintainer | public@hjwylde.com |
Safe Haskell | None |
Language | Haskell2010 |
A game is not quite as simple as players! Roughly speaking though, this engine is stateful. The
game state only changes when a command is issued (see Game.Werewolf.Command). Thus, this module
defines the Game
data structure and any fields required to keep track of the current state.
It also has a few additional functions for manipulating and querying the game state.
- data Game
- stage :: Lens' Game Stage
- round :: Lens' Game Int
- players :: Lens' Game [Player]
- events :: Lens' Game [Event]
- boots :: Lens' Game (Map Text [Text])
- allowedVoters :: Lens' Game [Text]
- heal :: Lens' Game Bool
- healUsed :: Lens' Game Bool
- hunterRetaliated :: Lens' Game Bool
- jesterRevealed :: Lens' Game Bool
- passed :: Lens' Game Bool
- poison :: Lens' Game (Maybe Text)
- poisonUsed :: Lens' Game Bool
- priorProtect :: Lens' Game (Maybe Text)
- protect :: Lens' Game (Maybe Text)
- roleModel :: Lens' Game (Maybe Text)
- scapegoatBlamed :: Lens' Game Bool
- see :: Lens' Game (Maybe Text)
- votes :: Lens' Game (Map Text Text)
- data Stage
- _FerinasGrunt :: Prism' Stage ()
- _GameOver :: Prism' Stage ()
- _HuntersTurn1 :: Prism' Stage ()
- _HuntersTurn2 :: Prism' Stage ()
- _Lynching :: Prism' Stage ()
- _OrphansTurn :: Prism' Stage ()
- _ProtectorsTurn :: Prism' Stage ()
- _ScapegoatsTurn :: Prism' Stage ()
- _SeersTurn :: Prism' Stage ()
- _Sunrise :: Prism' Stage ()
- _Sunset :: Prism' Stage ()
- _VillageDrunksTurn :: Prism' Stage ()
- _VillagesTurn :: Prism' Stage ()
- _WerewolvesTurn :: Prism' Stage ()
- _WitchsTurn :: Prism' Stage ()
- allStages :: [Stage]
- stageCycle :: [Stage]
- stageAvailable :: Game -> Stage -> Bool
- data Event
- _DevourEvent :: Prism' Event Text
- _NoDevourEvent :: Prism' Event ()
- _PoisonEvent :: Prism' Event Text
- newGame :: [Player] -> Game
- killPlayer :: Text -> Game -> Game
- getAllowedVoters :: Game -> [Player]
- getPendingVoters :: Game -> [Player]
- getVoteResult :: Game -> [Player]
- isFirstRound :: Game -> Bool
- isThirdRound :: Game -> Bool
- doesPlayerExist :: Text -> Game -> Bool
- hasAnyoneWon :: Game -> Bool
- hasFallenAngelWon :: Game -> Bool
- hasVillagersWon :: Game -> Bool
- hasWerewolvesWon :: Game -> Bool
Game
There are a few key pieces of information that a game always needs to hold. These are:
Any further fields on the game are specific to one or more roles (and their respective turns!).
Some of the additional fields are reset each round (e.g., the Seer's see
) while others are
kept around for the whole game (e.g., the Orphan's roleModel
).
In order to advance a game's state
, a Command
from a user needs to be
received. Afterwards the following steps should be performed:
apply
theCommand
.- run
checkStage
. - run
checkGameOver
.
checkStage
will perform any additional checks and manipulations to the
game state before advancing the game's stage
. It also runs any relevant events
.
checkGameOver
will check to see if any of the win conditions are met and
if so, advance the game's stage
to GameOver
.
allowedVoters :: Lens' Game [Text] Source
Most of these are fairly self-sufficient (the turn stages). Sunrise
and Sunset
are provided
as meaningful breaks between the day and night as, for example, a VillagesTurn
may not always
be available (curse that retched Scapegoat).
Once the game reaches a turn stage, it requires a Command
to help push
it past. Often only certain roles and commands may be performed at any given stage.
_FerinasGrunt :: Prism' Stage () Source
_HuntersTurn1 :: Prism' Stage () Source
_HuntersTurn2 :: Prism' Stage () Source
_OrphansTurn :: Prism' Stage () Source
_ProtectorsTurn :: Prism' Stage () Source
_ScapegoatsTurn :: Prism' Stage () Source
_SeersTurn :: Prism' Stage () Source
_VillageDrunksTurn :: Prism' Stage () Source
_VillagesTurn :: Prism' Stage () Source
_WerewolvesTurn :: Prism' Stage () Source
_WitchsTurn :: Prism' Stage () Source
stageCycle :: [Stage] Source
An infinite cycle of all Stage
s in the order that they should occur.
stageAvailable :: Game -> Stage -> Bool Source
Checks whether the stage is available for the given Game
. Most often this just involves
checking if there is an applicable role alive, but sometimes it is more complex.
One of the more complex checks here is for the VillagesTurn
. If the Fallen Angel is in play,
then the VillagesTurn
is available on the first day rather than only after the first night.
Events occur after a Stage
is advanced. This is automatically handled in
checkStage
, while an event's specific behaviour is defined by
eventAvailable
and applyEvent
.
For the most part events are used to allow something to happen on a Stage
different to when
it was triggered. E.g., the DeovurEvent
occurs after the village wakes up rather than when
the Werewolves' vote, this gives the Witch a chance to heal the victim.
DevourEvent Text | Werewolves |
NoDevourEvent | Protector, Werewolves and Witch |
PoisonEvent Text | Witch |
_NoDevourEvent :: Prism' Event () Source
Manipulations
killPlayer :: Text -> Game -> Game Source
Kills the given player! This function should be used carefully as it doesn't clear any state
that the player's role may use. If you're after just removing a player from a game for a test,
try using a quitCommand
instead.
Searches
getAllowedVoters :: Game -> [Player] Source
Gets all the allowedVoters
in a game (which is names only) and maps them to their player.
getPendingVoters :: Game -> [Player] Source
Gets all Alive
players that have yet to vote.
getVoteResult :: Game -> [Player] Source
Gets all players that had the highest vote count. This could be 1 or more players depending on whether the votes were in conflict.
Queries
isFirstRound :: Game -> Bool Source
isFirstRound
game = game ^.round
== 0
isThirdRound :: Game -> Bool Source
isThirdRound
game = game ^.round
== 2
doesPlayerExist :: Text -> Game -> Bool Source
Queries whether the player is in the game.
hasAnyoneWon :: Game -> Bool Source
Queries whether anyone has won.
hasFallenAngelWon :: Game -> Bool Source
Queries whether the Fallen Angel has won. The Fallen Angel wins if they manage to get themselves killed on the first round.
N.B., we check that the Fallen Angel isn't a villager
as the Fallen Angel's role is altered
if they don't win.
hasVillagersWon :: Game -> Bool Source
Queries whether the Villagers
have won. The Villagers
win if they are the only players
surviving.
hasWerewolvesWon :: Game -> Bool Source
Queries whether the Werewolves
have won. The Werewolves
win if they are the only players
surviving.