{-| 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, zombiesReturnedToGraveMessage, ) 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 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]) ] | hasNecromancerWon game = concat [ [necromancerWonMessage] , [playerRolesMessage game] , map playerWonMessage (necromancersName:zombieNames) , map playerLostMessage (game ^.. players . names \\ (necromancersName:zombieNames)) ] | 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 necromancersName = game ^?! players . necromancers . name zombieNames = game ^.. players . zombies . name dullahanWonMessage :: Game -> Message dullahanWonMessage = publicMessage . dullahanWonText everyoneLostMessage :: Message everyoneLostMessage = publicMessage everyoneLostText fallenAngelWonMessage :: Message fallenAngelWonMessage = publicMessage fallenAngelWonText necromancerWonMessage :: Message necromancerWonMessage = publicMessage necromancerWonText 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 -> [] NecromancersTurn -> necromancersTurnMessages necromancersName game 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 necromancersName = players' ^?! necromancers . name 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 necromancersTurnMessages :: Text -> Game -> [Message] necromancersTurnMessages to game | has (variant . noRoleKnowledge) game = [ privateMessage to necromancersTurnPrivateText ] | has (variant . noRoleReveal) game = [ privateMessage to necromancersTurnPrivateText ] | otherwise = [ publicMessage necromancersTurnPublicText , privateMessage to necromancersTurnPrivateText ] 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] zombiesReturnedToGraveMessage :: Game -> Message zombiesReturnedToGraveMessage = publicMessage . zombiesReturnedToGraveText