werewolf-1.2.0.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 (
playerBootedMessage, villageDrunkJoinedPackMessages, villageDrunkJoinedVillageMessage,
playerTurnedToStoneMessage, playerSeenMessage, playerDivinedMessage, playerDevouredMessage,
noPlayerDevouredMessage, scapegoatChoseAllowedVotersMessage, playerPoisonedMessage,
scapegoatLynchedMessage, playerLynchedMessage, noPlayerLynchedMessage, jesterLynchedMessage,
ferinaGruntsMessage, orphanJoinedPackMessages, playerKilledMessage, playerLostMessage,
playerContributedMessage, playerWonMessage, witchsTurnMessages, firstWerewolvesTurnMessages,
villagesTurnMessage, nightFallsMessage, sunriseMessage, villageDrunksTurnMessages,
seersTurnMessages, scapegoatsTurnMessage, protectorsTurnMessages, orphansTurnMessages,
oraclesTurnMessages, huntersTurnMessages, stageMessages, fallenAngelMessage,
trueVillagerMessage, spitefulGhostMessage, beholderMessage, newPlayerMessage,
rolesInGameMessage, newPlayersInGameMessage, newGameMessages, gameOverMessages,
fallenAngelWonMessage,
) where
import Control.Lens
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.Standard.Engine as Standard
playerBootedMessage :: Player -> Message
playerBootedMessage = publicMessage . playerBootedText
gameOverMessages :: Game -> [Message]
gameOverMessages game
| hasFallenAngelWon game = concat
[ [fallenAngelWonMessage]
, [playerRolesMessage game]
, [playerWonMessage fallenAngelsName]
, map playerLostMessage (game ^.. players . names \\ [fallenAngelsName])
]
| 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)
fallenAngelsName = game ^?! players . fallenAngels . name
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]
, [rolesInGameMessage Nothing game]
, map newPlayerMessage players'
, beholderMessages
, spitefulGhostMessages
, trueVillagerMessages
, fallenAngelMessages
, stageMessages game
]
where
players' = game ^. players
beholderMessages = case (,) <$> players' ^? beholders <*> players' ^? seers of
Just (beholder, _) -> [beholderMessage (beholder ^. name) game]
_ -> []
spitefulGhostMessages = case players' ^? spitefulGhosts of
Just spitefulGhost -> [spitefulGhostMessage (spitefulGhost ^. name) game]
_ -> []
trueVillagerMessages = [trueVillagerMessage game | has trueVillagers players']
fallenAngelMessages = if has fallenAngels players'
then [fallenAngelMessage]
else []
newPlayersInGameMessage :: Game -> Message
newPlayersInGameMessage = publicMessage . playersInGameText
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
spitefulGhostMessage :: Text -> Game -> Message
spitefulGhostMessage to = privateMessage to . spitefulGhostText
trueVillagerMessage :: Game -> Message
trueVillagerMessage = publicMessage . trueVillagerText
fallenAngelMessage :: Message
fallenAngelMessage = publicMessage fallenAngelText
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 ]
| otherwise =
[ publicMessage oraclesTurnPublicText
, privateMessage to oraclesTurnPrivateText
]
orphansTurnMessages :: Text -> Game -> [Message]
orphansTurnMessages to game
| has (variant . _NoRoleKnowledge) game =
[ privateMessage to orphansTurnPrivateText ]
| otherwise =
[ publicMessage orphansTurnPublicText
, privateMessage to orphansTurnPrivateText
]
protectorsTurnMessages :: Text -> Game -> [Message]
protectorsTurnMessages to game
| has (variant . _NoRoleKnowledge) 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 ]
| otherwise =
[ publicMessage seersTurnPublicText
, privateMessage to seersTurnPrivateText
]
villageDrunksTurnMessages :: Game -> [Message]
villageDrunksTurnMessages game
| has (variant . _NoRoleKnowledge) 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
| 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 = []
| 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
playerLynchedMessage :: Player -> Message
playerLynchedMessage player
| is simpleWerewolf player
|| is alphaWolf player = publicMessage $ werewolfLynchedText player
| otherwise = publicMessage $ playerLynchedText player
scapegoatLynchedMessage :: Game -> Message
scapegoatLynchedMessage = publicMessage . scapegoatLynchedText
scapegoatChoseAllowedVotersMessage :: Game -> Message
scapegoatChoseAllowedVotersMessage = publicMessage . scapegoatsTurnEndedText
noPlayerDevouredMessage :: Message
noPlayerDevouredMessage = publicMessage noPlayerDevouredText
playerDevouredMessage :: Player -> Message
playerDevouredMessage = publicMessage . playerDevouredText
playerDivinedMessage :: Text -> Player -> Message
playerDivinedMessage to = privateMessage to . playerDivinedText
playerPoisonedMessage :: Player -> Message
playerPoisonedMessage = publicMessage . playerPoisonedText
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 -> Message
playerTurnedToStoneMessage = publicMessage . playerTurnedToStoneText
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]