werewolf-1.3.1.0: app/Game/Werewolf/Message/Engine.hs
{-|
Module : Game.Werewolf.Message.Engine
Description : Suite of engine messages used throughout the game.
Copyright : (c) Henry J. Wylde, 2016
License : BSD3
Maintainer : public@hjwylde.com
A 'Message' is used to relay information back to either all players or a single player. This module
defines suite of engine messages used throughout the werewolf game.
-}
-- TODO (hjw): sort this file
module Game.Werewolf.Message.Engine (
playerRolesMessage, playerBootedMessage, villageDrunkJoinedPackMessages, villageDrunkJoinedVillageMessage,
playerTurnedToStoneMessage, playerSeenMessage, playerDivinedMessage, playerDevouredMessage,
noPlayerDevouredMessage, scapegoatChoseAllowedVotersMessage, playerPoisonedMessage,
scapegoatLynchedMessage, saintLynchedMessage, playerLynchedMessage, noPlayerLynchedMessage, jesterLynchedMessage,
ferinaGruntsMessage, orphanJoinedPackMessages, playerKilledMessage, playerLostMessage,
playerContributedMessage, playerWonMessage, witchsTurnMessages, firstWerewolvesTurnMessages,
villagesTurnMessage, nightFallsMessage, sunriseMessage, villageDrunksTurnMessages, spitefulVillagerKilledMessage,
seersTurnMessages, scapegoatsTurnMessage, protectorsTurnMessages, orphansTurnMessages,
oraclesTurnMessages, huntersTurnMessages, stageMessages,
trueVillagerMessage, beholderMessage, newPlayerMessage, rolesInGameMessage,
newPlayersInGameMessage, newGameMessages, gameOverMessages, fallenAngelWonMessage,
werewolfLynchedMessage,
) where
import Control.Lens.Extra
import Data.List.Extra
import Data.Text (Text)
import Game.Werewolf.Game
import Game.Werewolf.Player
import Game.Werewolf.Response
import Game.Werewolf.Role hiding (name)
import Game.Werewolf.Variant.NoRoleKnowledge.Engine as NoRoleKnowledge
import Game.Werewolf.Variant.NoRoleReveal.Engine as NoRoleReveal
import Game.Werewolf.Variant.Standard.Engine as Standard
playerBootedMessage :: Player -> Game -> Message
playerBootedMessage player game
| has (variant . _NoRoleReveal) game = publicMessage $ NoRoleReveal.playerBootedText player
| otherwise = publicMessage $ Standard.playerBootedText player
gameOverMessages :: Game -> [Message]
gameOverMessages game
| hasDullahanWon game = concat
[ [dullahanWonMessage game]
, [playerRolesMessage game]
, [playerWonMessage dullahansName]
, map playerLostMessage (game ^.. players . names \\ [dullahansName])
]
| hasFallenAngelWon game = concat
[ [fallenAngelWonMessage]
, [playerRolesMessage game]
, [playerWonMessage fallenAngelsName]
, map playerLostMessage (game ^.. players . names \\ [fallenAngelsName])
]
| hasEveryoneLost game = concat
[ [everyoneLostMessage]
, [playerRolesMessage game]
, map playerLostMessage (game ^.. players . names)
]
| otherwise = concat
[ [allegianceWonMessage winningAllegiance]
, [playerRolesMessage game]
, playerWonMessages
, playerContributedMessages
, playerLostMessages
]
where
winningAllegiance
| hasVillagersWon game = Villagers
| hasWerewolvesWon game = Werewolves
| otherwise = undefined
winningPlayers = game ^.. players . traverse . filteredBy (role . allegiance) winningAllegiance
losingPlayers = game ^. players \\ winningPlayers
playerWonMessages = map playerWonMessage (winningPlayers ^.. traverse . alive . name)
playerContributedMessages = map playerContributedMessage (winningPlayers ^.. traverse . dead . name)
playerLostMessages = map playerLostMessage (losingPlayers ^.. names)
dullahansName = game ^?! players . dullahans . name
fallenAngelsName = game ^?! players . fallenAngels . name
dullahanWonMessage :: Game -> Message
dullahanWonMessage = publicMessage . dullahanWonText
everyoneLostMessage :: Message
everyoneLostMessage = publicMessage everyoneLostText
fallenAngelWonMessage :: Message
fallenAngelWonMessage = publicMessage fallenAngelWonText
allegianceWonMessage :: Allegiance -> Message
allegianceWonMessage = publicMessage . allegianceWonText
playerRolesMessage :: Game -> Message
playerRolesMessage = publicMessage . playerRolesText
newGameMessages :: Game -> [Message]
newGameMessages game = concat
[ [newPlayersInGameMessage game]
, gameVariantMessages
, [rolesInGameMessage Nothing game]
, map newPlayerMessage players'
, beholderMessages
, dullahanMessages
, trueVillagerMessages
, stageMessages game
]
where
players' = game ^. players
gameVariantMessages =
[ gameVariantMessage game
| hasn't (variant . _Standard) game
]
beholderMessages =
[ beholderMessage beholderName game
| has beholders players'
, has seers players'
, beholderName <- players' ^.. beholders . name
]
dullahanMessages =
[ dullahanMessage dullahanName game
| has dullahans players'
, dullahanName <- players' ^.. dullahans . name
]
trueVillagerMessages =
[ trueVillagerMessage game
| has trueVillagers players'
]
newPlayersInGameMessage :: Game -> Message
newPlayersInGameMessage = publicMessage . playersInGameText
gameVariantMessage :: Game -> Message
gameVariantMessage = publicMessage . gameVariantText
rolesInGameMessage :: Maybe Text -> Game -> Message
rolesInGameMessage mTo game
| has (variant . _NoRoleKnowledge) game = Message mTo $ NoRoleKnowledge.rolesInGameText game
| otherwise = Message mTo $ Standard.rolesInGameText game
newPlayerMessage :: Player -> Message
newPlayerMessage player = privateMessage (player ^. name) $ newPlayerText player
beholderMessage :: Text -> Game -> Message
beholderMessage to = privateMessage to . beholderText
dullahanMessage :: Text -> Game -> Message
dullahanMessage to = privateMessage to . dullahanText
spitefulVillagerKilledMessage :: Text -> Game -> Message
spitefulVillagerKilledMessage to game
| has (variant . _NoRoleReveal) game = privateMessage to $ NoRoleReveal.spitefulVillagerKilledText game
| otherwise = privateMessage to $ Standard.spitefulVillagerKilledText game
trueVillagerMessage :: Game -> Message
trueVillagerMessage = publicMessage . trueVillagerText
stageMessages :: Game -> [Message]
stageMessages game = case game ^. stage of
DruidsTurn -> []
GameOver -> []
HuntersTurn1 -> huntersTurnMessages game
HuntersTurn2 -> huntersTurnMessages game
Lynching -> []
OraclesTurn -> oraclesTurnMessages oraclesName game
OrphansTurn -> orphansTurnMessages orphansName game
ProtectorsTurn -> protectorsTurnMessages protectorsName game
ScapegoatsTurn -> [scapegoatsTurnMessage game]
SeersTurn -> seersTurnMessages seersName game
Sunrise -> [sunriseMessage]
Sunset -> [nightFallsMessage]
VillageDrunksTurn -> villageDrunksTurnMessages game
VillagesTurn -> [villagesTurnMessage]
WerewolvesTurn -> if is firstRound game
then firstWerewolvesTurnMessages game
else werewolvesTurnMessages aliveWerewolfNames game
WitchsTurn -> witchsTurnMessages game
where
players' = game ^. players
oraclesName = players' ^?! oracles . name
orphansName = players' ^?! orphans . name
protectorsName = players' ^?! protectors . name
seersName = players' ^?! seers . name
aliveWerewolfNames = players' ^.. werewolves . alive . name
huntersTurnMessages :: Game -> [Message]
huntersTurnMessages game =
[ publicMessage $ huntersTurnPublicText game
, privateMessage hunterName huntersTurnPrivateText
]
where
hunterName = game ^?! players . hunters . name
oraclesTurnMessages :: Text -> Game -> [Message]
oraclesTurnMessages to game
| has (variant . _NoRoleKnowledge) game =
[ privateMessage to oraclesTurnPrivateText ]
| has (variant . _NoRoleReveal) game =
[ privateMessage to oraclesTurnPrivateText ]
| otherwise =
[ publicMessage oraclesTurnPublicText
, privateMessage to oraclesTurnPrivateText
]
orphansTurnMessages :: Text -> Game -> [Message]
orphansTurnMessages to game
| has (variant . _NoRoleKnowledge) game =
[ privateMessage to orphansTurnPrivateText ]
| has (variant . _NoRoleReveal) game =
[ privateMessage to orphansTurnPrivateText ]
| otherwise =
[ publicMessage orphansTurnPublicText
, privateMessage to orphansTurnPrivateText
]
protectorsTurnMessages :: Text -> Game -> [Message]
protectorsTurnMessages to game
| has (variant . _NoRoleKnowledge) game =
[ privateMessage to protectorsTurnPrivateText ]
| has (variant . _NoRoleReveal) game =
[ privateMessage to protectorsTurnPrivateText ]
| otherwise =
[ publicMessage protectorsTurnPublicText
, privateMessage to protectorsTurnPrivateText
]
scapegoatsTurnMessage :: Game -> Message
scapegoatsTurnMessage = publicMessage . scapegoatsTurnText
seersTurnMessages :: Text -> Game -> [Message]
seersTurnMessages to game
| has (variant . _NoRoleKnowledge) game =
[ privateMessage to seersTurnPrivateText ]
| has (variant . _NoRoleReveal) game =
[ privateMessage to seersTurnPrivateText ]
| otherwise =
[ publicMessage seersTurnPublicText
, privateMessage to seersTurnPrivateText
]
villageDrunksTurnMessages :: Game -> [Message]
villageDrunksTurnMessages game
| has (variant . _NoRoleKnowledge) game = []
| has (variant . _NoRoleReveal) game = []
| otherwise = [publicMessage villageDrunksTurnText]
sunriseMessage :: Message
sunriseMessage = publicMessage sunriseText
nightFallsMessage :: Message
nightFallsMessage = publicMessage sunsetText
villagesTurnMessage :: Message
villagesTurnMessage = publicMessage villagesTurnText
firstWerewolvesTurnMessages :: Game -> [Message]
firstWerewolvesTurnMessages game =
[privateMessage (player ^. name) (firstWerewolvesTurnText player game)
| length werewolves > 1, player <- werewolves]
++ werewolvesTurnMessages (map (view name) werewolves) game
where
werewolves = game ^.. players . traverse . alive . filtered (is werewolf)
werewolvesTurnMessages :: [Text] -> Game -> [Message]
werewolvesTurnMessages tos game
| has (variant . _NoRoleKnowledge) game =
groupMessages tos werewolvesTurnPrivateText
| has (variant . _NoRoleReveal) game =
groupMessages tos werewolvesTurnPrivateText
| otherwise =
publicMessage werewolvesTurnPublicText
: groupMessages tos werewolvesTurnPrivateText
witchsTurnMessages :: Game -> [Message]
witchsTurnMessages game = concat
[ wakeUpMessages
, healMessages
, poisonMessages
, [passMessage]
]
where
to = game ^?! players . witches . name
wakeUpMessages
| has (variant . _NoRoleKnowledge) game = []
| has (variant . _NoRoleReveal) game = []
| otherwise = [publicMessage witchsTurnText]
passMessage = privateMessage to passText
healMessages
| game ^. healUsed = []
| hasn't votee game = []
| otherwise = [privateMessage to $ healText game]
poisonMessages
| game ^. poisonUsed = []
| otherwise = [privateMessage to poisonText]
playerWonMessage :: Text -> Message
playerWonMessage to = privateMessage to playerWonText
playerContributedMessage :: Text -> Message
playerContributedMessage to = privateMessage to playerContributedText
playerLostMessage :: Text -> Message
playerLostMessage to = privateMessage to playerLostText
playerKilledMessage :: Text -> Message
playerKilledMessage to = privateMessage to playerKilledText
orphanJoinedPackMessages :: Text -> Game -> [Message]
orphanJoinedPackMessages to game =
privateMessage to (orphanJoinedWerewolvesPrivateText game)
: groupMessages (map (view name) werewolves) (orphanJoinedWerewolvesGroupText game)
where
orphan = game ^?! players . villageDrunks
werewolves = game ^.. players . traverse . alive . filtered (is werewolf) \\ [orphan]
ferinaGruntsMessage :: Message
ferinaGruntsMessage = publicMessage druidsTurnText
jesterLynchedMessage :: Game -> Message
jesterLynchedMessage = publicMessage . jesterLynchedText
noPlayerLynchedMessage :: Message
noPlayerLynchedMessage = publicMessage noPlayerLynchedText
werewolfLynchedMessage :: Player -> Game -> Message
werewolfLynchedMessage player game
| has (variant . _NoRoleReveal) game = publicMessage $ NoRoleReveal.playerLynchedText player
| otherwise = publicMessage $ Standard.werewolfLynchedText player
playerLynchedMessage :: Player -> Game -> Message
playerLynchedMessage player game
| has (variant . _NoRoleReveal) game = publicMessage $ NoRoleReveal.playerLynchedText player
| otherwise = publicMessage $ Standard.playerLynchedText player
saintLynchedMessage :: [Player] -> Game -> Message
saintLynchedMessage voters game
| has (variant . _NoRoleReveal) game = publicMessage $ NoRoleReveal.saintLynchedText voters
| otherwise = publicMessage $ Standard.saintLynchedText voters
scapegoatLynchedMessage :: Game -> Message
scapegoatLynchedMessage = publicMessage . scapegoatLynchedText
scapegoatChoseAllowedVotersMessage :: Game -> Message
scapegoatChoseAllowedVotersMessage = publicMessage . scapegoatsTurnEndedText
noPlayerDevouredMessage :: Message
noPlayerDevouredMessage = publicMessage noPlayerDevouredText
playerDevouredMessage :: Player -> Game -> Message
playerDevouredMessage player game
| has (variant . _NoRoleReveal) game = publicMessage $ NoRoleReveal.playerDevouredText player
| otherwise = publicMessage $ Standard.playerDevouredText player
playerDivinedMessage :: Text -> Player -> Message
playerDivinedMessage to = privateMessage to . playerDivinedText
playerPoisonedMessage :: Player -> Game -> Message
playerPoisonedMessage player game
| has (variant . _NoRoleReveal) game = publicMessage $ NoRoleReveal.playerPoisonedText player
| otherwise = publicMessage $ Standard.playerPoisonedText player
playerSeenMessage :: Text -> Player -> Message
playerSeenMessage to player
| is alphaWolf player = privateMessage to $ alphaWolfSeenText player
| is lycan player = privateMessage to $ lycanSeenText player
| otherwise = privateMessage to $ playerSeenText player
playerTurnedToStoneMessage :: Player -> Game -> Message
playerTurnedToStoneMessage player game
| has (variant . _NoRoleReveal) game = publicMessage $ NoRoleReveal.playerTurnedToStoneText player
| otherwise = publicMessage $ Standard.playerTurnedToStoneText player
villageDrunkJoinedVillageMessage :: Text -> Message
villageDrunkJoinedVillageMessage to = privateMessage to villageDrunkJoinedVillageText
villageDrunkJoinedPackMessages :: Text -> Game -> [Message]
villageDrunkJoinedPackMessages to game =
privateMessage to (villageDrunkJoinedWerewolvesPrivateText game)
: groupMessages (map (view name) werewolves) (villageDrunkJoinedWerewolvesGroupText game)
where
villageDrunk = game ^?! players . villageDrunks
werewolves = game ^.. players . traverse . alive . filtered (is werewolf) \\ [villageDrunk]