werewolf 1.0.0.0 → 1.0.1.0
raw patch · 11 files changed
+79/−39 lines, 11 files
Files
- CHANGELOG.md +6/−0
- README.md +2/−1
- app/Werewolf/Game.hs +2/−2
- src/Game/Werewolf/Command/Villager.hs +4/−0
- src/Game/Werewolf/Engine.hs +1/−1
- src/Game/Werewolf/Messages.hs +2/−2
- src/Game/Werewolf/Player.hs +20/−4
- src/Game/Werewolf/Role.hs +28/−7
- test/src/Game/Werewolf/Test/Command/Heal.hs +12/−20
- test/src/Game/Werewolf/Test/Engine.hs +1/−1
- werewolf.cabal +1/−1
CHANGELOG.md view
@@ -2,6 +2,12 @@ ### Upcoming +### v1.0.1.0++*Minor*++* Added the Crooked Senator role. ([#142](https://github.com/hjwylde/werewolf/issues/142))+ ### v1.0.0.0 *Major*
README.md view
@@ -59,6 +59,7 @@ The Villagers must lynch all of the Werewolves. +* Crooked Senator * Druid * Hunter * Jester@@ -107,7 +108,7 @@ ```bash > werewolf --caller @foo --tag werewolf start --extra-roles seer @bar @baz @qux @quux @corge @grault {"ok":true,"messages":[- {"to":null,"message":"A new game of werewolf is starting with @foo, @bar, @baz, @qux, @quux, @corge, @grault!"},+ {"to":null,"message":"A new game of werewolf is starting with @foo, @bar, @baz, @qux, @quux, @corge and @grault!"}, {"to":null,"message":"The roles in play are Seer (1), Simple Villager (4) and Simple Werewolf (2) for a total balance of -2."}, {"to":"@foo","message":"You're a Simple Villager.\nA simple, ordinary townsperson in every way. Some may be cobblers, others bakers or even nobles. No matter their differences though, the plight of Werewolves in Fougères unites all the Villagers in this unfortunate time.\nThe Simple Villager has no special abilities, they must use their guile to determine whom among them is not who they say they are."}, ...,
app/Werewolf/Game.hs view
@@ -35,7 +35,7 @@ import System.FilePath createPlayers :: [Text] -> [Role] -> [Player]-createPlayers playerNames roles = zipWith newPlayer playerNames roles+createPlayers = zipWith newPlayer padRoles :: [Role] -> Int -> [Role] padRoles roles n = roles ++ simpleVillagerRoles ++ simpleWerewolfRoles@@ -71,7 +71,7 @@ writeOrDeleteGame :: MonadIO m => Text -> Game -> m () writeOrDeleteGame tag game- | has (stage . _GameOver) game = deleteGame tag+ | has (stage . _GameOver) game = deleteGame tag | otherwise = writeGame tag game doesGameExist :: MonadIO m => Text -> m Bool
src/Game/Werewolf/Command/Villager.hs view
@@ -17,6 +17,7 @@ import Control.Lens import Control.Monad.Except import Control.Monad.Extra+import Control.Monad.Writer import qualified Data.Map as Map import Data.Maybe@@ -35,3 +36,6 @@ validatePlayer callerName targetName votes %= Map.insert callerName targetName++ whenJustM (preuse $ players . crookedSenators . alive) $ \crookedSenator ->+ tell [playerMadeLynchVoteMessage (Just $ crookedSenator ^. name) callerName targetName]
src/Game/Werewolf/Engine.hs view
@@ -160,7 +160,7 @@ advanceStage VillagesTurn -> whenM (null <$> liftM2 intersect getAllowedVoters getPendingVoters) $ do- tell . map (uncurry playerMadeLynchVoteMessage) =<< uses votes Map.toList+ tell . map (uncurry $ playerMadeLynchVoteMessage Nothing) =<< uses votes Map.toList advanceStage
src/Game/Werewolf/Messages.hs view
@@ -499,8 +499,8 @@ , "the Village Drunk has finally sobered up and remembered their true home." ]) -playerMadeLynchVoteMessage :: Text -> Text -> Message-playerMadeLynchVoteMessage voterName targetName = publicMessage $ T.concat+playerMadeLynchVoteMessage :: Maybe Text -> Text -> Text -> Message+playerMadeLynchVoteMessage mTo voterName targetName = Message mTo $ T.concat [ voterName, " voted to lynch ", targetName, "." ]
src/Game/Werewolf/Player.hs view
@@ -26,16 +26,16 @@ newPlayer, -- ** Traversals- druid, fallenAngel, hunter, jester, orphan, protector, scapegoat, seer, simpleVillager,- simpleWerewolf, trueVillager, villageDrunk, witch,+ crookedSenator, druid, fallenAngel, hunter, jester, orphan, protector, scapegoat, seer,+ simpleVillager, simpleWerewolf, trueVillager, villageDrunk, witch, villager, werewolf, -- | These are provided just as a bit of sugar to avoid continually writing @'traverse' .@. names, roles, states, -- | N.B., these are not legal traversals for the same reason 'filtered' isn't!- druids, fallenAngels, hunters, jesters, orphans, protectors, scapegoats, seers, simpleVillagers,- simpleWerewolves, trueVillagers, villageDrunks, witches,+ crookedSenators, druids, fallenAngels, hunters, jesters, orphans, protectors, scapegoats,+ seers, simpleVillagers, simpleWerewolves, trueVillagers, villageDrunks, witches, villagers, werewolves, alive, dead, @@ -75,6 +75,14 @@ newPlayer :: Text -> Role -> Player newPlayer name role = Player name role Alive +-- | The traversal of 'Player's with a 'crookedSenatorRole'.+--+-- @+-- 'crookedSenator' = 'role' . 'only' 'crookedSenatorRole'+-- @+crookedSenator :: Traversal' Player ()+crookedSenator = role . only crookedSenatorRole+ -- | The traversal of 'Player's with a 'druidRole'. -- -- @@@ -218,6 +226,14 @@ -- @ states :: Traversable t => Traversal' (t Player) State states = traverse . state++-- | This 'Traversal' provides the traversal of 'crookedSenator' 'Player's.+--+-- @+-- 'crookedSenators' = 'traverse' . 'filtered' ('is' 'crookedSenator')+-- @+crookedSenators :: Traversable t => Traversal' (t Player) Player+crookedSenators = traverse . filtered (is crookedSenator) -- | This 'Traversal' provides the traversal of 'druid' 'Player's. --
src/Game/Werewolf/Role.hs view
@@ -47,8 +47,8 @@ -- certain few have learnt some tricks over the years that may turn out rather useful. -- The Villagers must lynch all of the Werewolves.- druidRole, hunterRole, jesterRole, protectorRole, scapegoatRole, seerRole, simpleVillagerRole,- trueVillagerRole, witchRole,+ crookedSenatorRole, druidRole, hunterRole, jesterRole, protectorRole, scapegoatRole, seerRole,+ simpleVillagerRole, trueVillagerRole, witchRole, -- *** The Werewolves -- | Hiding in plain sight, the Werewolves are not a small trifle.@@ -107,7 +107,8 @@ -- | A list containing all the roles defined in this file. allRoles :: [Role] allRoles =- [ druidRole+ [ crookedSenatorRole+ , druidRole , fallenAngelRole , hunterRole , jesterRole@@ -227,6 +228,26 @@ ] } +-- | /Never trust a politician. Nor a Crooked Senator for that matter. The Crooked Senator may seem/+-- /like he has the village's best interests at heart, but let's be honest, when put in a tough/+-- /situation he looks after no-one but himself. Even when safe, the Crooked Senator may decide/+-- /to toy with the Villagers' emotions and try pit them against one another./+--+-- The Crooked Senator looks at the Villager votes as they come in.+crookedSenatorRole :: Role+crookedSenatorRole = Role+ { _name = "Crooked Senator"+ , _allegiance = Villagers+ , _balance = 1+ , _description = T.unwords+ [ "Never trust a politician. Nor a Crooked Senator for that matter. The Crooked Senator may"+ , "seem like he has the village's best interests at heart, but let's be honest, when put in"+ , "a tough situation he looks after no-one but himself. Even when safe, the Crooked Senator"+ , "may decide to toy with the Villagers' emotions and try pit them against one another."+ ]+ , _rules = "The Crooked Senator looks at the Villager votes as they come in."+ }+ -- | /How honoured we are to be in the presence of such a noble leader. The return of the Druid/ -- /marks an exceptional time in Fougères's history! Friend of the woodland creatures, practiced/ -- /philosopher and now, with the help of Ferina their companion, a bane to the Werewolves/@@ -376,13 +397,13 @@ } -- | /Every village needs a Jester; they're so stupid, but provide so much entertainment! The/--- /Jester may not have any special abilities, but at least no one in the village wants to hurt/+-- /Jester may not have any special abilities, but at least no-one in the village wants to hurt/ -- /them./ -- -- If the village votes to lynch the Jester, their identity is revealed. The village realise -- there's no point in burning them and so they are set free. ----- The Jester continues to play but may no longer vote as no one can take them seriously.+-- The Jester continues to play but may no longer vote as no-one can take them seriously. jesterRole :: Role jesterRole = Role { _name = "Jester"@@ -390,7 +411,7 @@ , _balance = 0 , _description = T.unwords [ "Every village needs a Jester; they're so stupid, but provide so much entertainment! The"- , "Jester may not have any special abilities, but at least no one in the village wants to"+ , "Jester may not have any special abilities, but at least no-one in the village wants to" , "hurt them." ] , _rules = T.intercalate "\n"@@ -398,7 +419,7 @@ [ "If the village votes to lynch the Jester, their identity is revealed. The village" , "realise there's no point in burning them and so they are set free." ]- , "The Jester continues to play but may no longer vote as no one can take them seriously."+ , "The Jester continues to play but may no longer vote as no-one can take them seriously." ] }
test/src/Game/Werewolf/Test/Command/Heal.hs view
@@ -32,11 +32,7 @@ ] prop_healCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property-prop_healCommandErrorsWhenGameIsOver (GameAtGameOver game) = do- let witch = game ^?! players . witches- let command = healCommand $ witch ^. name-- verbose_runCommandErrors game command+prop_healCommandErrorsWhenGameIsOver (GameAtGameOver game) = verbose_runHealCommandErrors game prop_healCommandErrorsWhenCallerDoesNotExist :: GameWithDevourEvent -> Player -> Property prop_healCommandErrorsWhenCallerDoesNotExist (GameWithDevourEvent game) caller =@@ -52,26 +48,15 @@ verbose_runCommandErrors game' command prop_healCommandErrorsWhenNoTargetIsDevoured :: GameAtWitchsTurn -> Property-prop_healCommandErrorsWhenNoTargetIsDevoured (GameAtWitchsTurn game) = do- let witch = game ^?! players . witches- let command = healCommand $ witch ^. name-- verbose_runCommandErrors game command+prop_healCommandErrorsWhenNoTargetIsDevoured (GameAtWitchsTurn game) = verbose_runHealCommandErrors game prop_healCommandErrorsWhenNotWitchsTurn :: Game -> Property-prop_healCommandErrorsWhenNotWitchsTurn game = do- let witch = game ^?! players . witches- let command = healCommand $ witch ^. name-+prop_healCommandErrorsWhenNotWitchsTurn game = hasn't (stage . _WitchsTurn) game- ==> verbose_runCommandErrors game command+ ==> verbose_runHealCommandErrors game prop_healCommandErrorsWhenCallerHasHealed :: GameWithHeal -> Property-prop_healCommandErrorsWhenCallerHasHealed (GameWithHeal game) = do- let witch = game ^?! players . witches- let command = healCommand $ witch ^. name-- verbose_runCommandErrors game command+prop_healCommandErrorsWhenCallerHasHealed (GameWithHeal game) = verbose_runHealCommandErrors game prop_healCommandErrorsWhenCallerNotWitch :: GameWithDevourEvent -> Property prop_healCommandErrorsWhenCallerNotWitch (GameWithDevourEvent game) =@@ -79,3 +64,10 @@ let command = healCommand (caller ^. name) verbose_runCommandErrors game command++verbose_runHealCommandErrors :: Game -> Property+verbose_runHealCommandErrors game = do+ let witch = game ^?! players . witches+ let command = healCommand $ witch ^. name++ verbose_runCommandErrors game command
test/src/Game/Werewolf/Test/Engine.hs view
@@ -12,7 +12,7 @@ allEngineTests, ) where -import Control.Lens hiding (elements, isn't)+import Control.Lens hiding (elements) import Control.Monad.Except import Control.Monad.Writer
werewolf.cabal view
@@ -1,5 +1,5 @@ name: werewolf-version: 1.0.0.0+version: 1.0.1.0 author: Henry J. Wylde maintainer: public@hjwylde.com