diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,17 @@
 
 #### Upcoming
 
+#### v0.4.9.0
+
+*Minor*
+
+* Added player contributed messages upon game over. ([#86](https://github.com/hjwylde/werewolf/issues/86))
+* Changed `choose` command for Scapegoat to take a space separated list rather than comma separated. ([#98](https://github.com/hjwylde/werewolf/issues/98))
+* Filtered `help` commands based on the current game. ([#94](https://github.com/hjwylde/werewolf/issues/94))
+* Added `--all` option to `help` commands. ([#94](https://github.com/hjwylde/werewolf/issues/94))
+* Added the Devoted Servant role. ([#47](https://github.com/hjwylde/werewolf/issues/47))
+* Added `--force` flag to `end`. ([#77](https://github.com/hjwylde/werewolf/issues/77))
+
 #### v0.4.8.0
 
 *Minor*
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -9,9 +9,12 @@
 
 ### Game description
 
-Deep in the American countryside, the little town of Millers Hollow has recently been infiltrated by Werewolves.
-Each night, murders are committed by the Villagers, who due to some mysterious phenomenon (possibly the greenhouse effect) have become Werewolves.
-It is now time to take control and eliminate this ancient evil, before the town loses its last few inhabitants.
+Deep in the American countryside, the little town of Millers Hollow has recently been infiltrated by
+    Werewolves.
+Each night, murders are committed by the Villagers, who due to some mysterious phenomenon (possibly
+    the greenhouse effect) have become Werewolves.
+It is now time to take control and eliminate this ancient evil, before the town loses its last few
+    inhabitants.
 
 Objective of the Game:  
 For the Angel: die in the first round.  
@@ -24,35 +27,48 @@
 
 **The Ambiguous:**
 
-The Ambiguous may change allegiance during the game.
+They could very well be allies of the village or become its enemies.
+During the game, they can change sides or characters.
 
-* Wild-child.
-* Wolf-hound.
+The Ambiguous must aid their side to achieve victory.
 
+* Devoted Servant
+* Wild-child
+* Wolf-hound
+
 **The Loners:**
 
-The Loners have their own win condition.
+Their past could no doubt reveal to us why they hate the inhabitants of Miller's Hollow.
+One thing is known for sure: they really scare everyone!
 
-* Angel.
+The Loners have their own objectives, no matter which side they're on.
 
+* Angel
+
 **The Villagers:**
 
+Attached to the village's survival, the following characters defend its harmony with determination.
+Faced with various menaces, they will be brought to eliminate those they suspect of being too
+    dangerous, even if that might be painful to them.
+
 The Villagers must lynch all of the Werewolves.
 
-* Bear Tamer.
-* Defender.
-* Scapegoat.
-* Seer.
-* Simple Villager.
-* Village Idiot.
-* Villager-Villager.
-* Witch.
+* Bear Tamer
+* Defender
+* Scapegoat
+* Seer
+* Simple Villager
+* Village Idiot
+* Villager-Villager
+* Witch
 
 **The Werewolves:**
 
+They can be lethally dangerous and put in doubt the village's survival.
+
 The Werewolves must devour all of the Villagers.
 
-* Simple Werewolf.
+* Simple Werewolf
 
 ### Installing
 
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -20,22 +20,23 @@
 
 import System.Environment
 
-import qualified Werewolf.Commands.Choose    as Choose
-import qualified Werewolf.Commands.Circle    as Circle
-import qualified Werewolf.Commands.End       as End
-import qualified Werewolf.Commands.Heal      as Heal
-import qualified Werewolf.Commands.Help      as Help
-import qualified Werewolf.Commands.Interpret as Interpret
-import qualified Werewolf.Commands.Pass      as Pass
-import qualified Werewolf.Commands.Ping      as Ping
-import qualified Werewolf.Commands.Poison    as Poison
-import qualified Werewolf.Commands.Protect   as Protect
-import qualified Werewolf.Commands.Quit      as Quit
-import qualified Werewolf.Commands.See       as See
-import qualified Werewolf.Commands.Start     as Start
-import qualified Werewolf.Commands.Status    as Status
-import qualified Werewolf.Commands.Version   as Version
-import qualified Werewolf.Commands.Vote      as Vote
+import qualified Werewolf.Command.Choose    as Choose
+import qualified Werewolf.Command.Circle    as Circle
+import qualified Werewolf.Command.End       as End
+import qualified Werewolf.Command.Heal      as Heal
+import qualified Werewolf.Command.Help      as Help
+import qualified Werewolf.Command.Interpret as Interpret
+import qualified Werewolf.Command.Pass      as Pass
+import qualified Werewolf.Command.Ping      as Ping
+import qualified Werewolf.Command.Poison    as Poison
+import qualified Werewolf.Command.Protect   as Protect
+import qualified Werewolf.Command.Quit      as Quit
+import qualified Werewolf.Command.Reveal    as Reveal
+import qualified Werewolf.Command.See       as See
+import qualified Werewolf.Command.Start     as Start
+import qualified Werewolf.Command.Status    as Status
+import qualified Werewolf.Command.Version   as Version
+import qualified Werewolf.Command.Vote      as Vote
 import           Werewolf.Options
 
 main :: IO ()
@@ -50,13 +51,13 @@
 
     case result of
         Success options -> handle options
-        _               -> handle (Options callerName . Help . Help.Options $ Just Help.Commands)
+        _               -> handle (Options callerName . Help . Help.Options . Just $ Help.Commands False)
 
 handle :: Options -> IO ()
 handle (Options callerName command) = case command of
     Choose options                      -> Choose.handle callerName options
     Circle options                      -> Circle.handle callerName options
-    End                                 -> End.handle callerName
+    End options                         -> End.handle callerName options
     Heal                                -> Heal.handle callerName
     Help options                        -> Help.handle callerName options
     Interpret (Interpret.Options args)  -> interpret callerName args
@@ -65,6 +66,7 @@
     Poison options                      -> Poison.handle callerName options
     Protect options                     -> Protect.handle callerName options
     Quit                                -> Quit.handle callerName
+    Reveal                              -> Reveal.handle callerName
     See options                         -> See.handle callerName options
     Start options                       -> Start.handle callerName options
     Status                              -> Status.handle callerName
diff --git a/app/Werewolf/Command/Choose.hs b/app/Werewolf/Command/Choose.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Choose.hs
@@ -0,0 +1,56 @@
+{-|
+Module      : Werewolf.Command.Choose
+Description : Options and handler for the choose subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Options and handler for the choose subcommand.
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Werewolf.Command.Choose (
+    -- * Options
+    Options(..),
+
+    -- * Handle
+    handle,
+) where
+
+import Control.Lens
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+data Options = Options
+    { args :: [Text]
+    } deriving (Eq, Show)
+
+handle :: MonadIO m => Text -> Options -> m ()
+handle callerName (Options args) = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = case game ^. stage of
+            ScapegoatsTurn  -> choosePlayersCommand callerName args
+            WildChildsTurn  -> choosePlayerCommand callerName (head args)
+            WolfHoundsTurn  -> chooseAllegianceCommand callerName (head args)
+            -- TODO (hjw): throw an error
+            _               -> undefined
+
+    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
+        Left errorMessages      -> exitWith failure { messages = errorMessages }
+        Right (game, messages)  -> writeGame game >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/Circle.hs b/app/Werewolf/Command/Circle.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Circle.hs
@@ -0,0 +1,48 @@
+{-|
+Module      : Werewolf.Command.Circle
+Description : Options and handler for the circle subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Options and handler for the circle subcommand.
+-}
+
+module Werewolf.Command.Circle (
+    -- * Options
+    Options(..),
+
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+data Options = Options
+    { optIncludeDead :: Bool
+    } deriving (Eq, Show)
+
+handle :: MonadIO m => Text -> Options -> m ()
+handle callerName (Options includeDead) = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = circleCommand callerName includeDead
+
+    case runExcept (execWriterT $ execStateT (apply command) game) of
+        Left errorMessages  -> exitWith failure { messages = errorMessages }
+        Right messages      -> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/End.hs b/app/Werewolf/Command/End.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/End.hs
@@ -0,0 +1,51 @@
+{-|
+Module      : Werewolf.Command.End
+Description : Options and handler for the end subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Options and handler for the end subcommand.
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Werewolf.Command.End (
+    -- * Options
+    Options(..),
+
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Extra
+import Control.Monad.IO.Class
+
+import           Data.Text (Text)
+import qualified Data.Text as T
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+data Options = Options
+    { optForce :: Bool
+    } deriving (Eq, Show)
+
+handle :: MonadIO m => Text -> Options -> m ()
+handle callerName (Options force) = do
+    unlessM doesGameExist $ exitWith failure { messages = [noGameRunningMessage callerName] }
+
+    unless force $ do
+        game <- readGame
+
+        unless (doesPlayerExist callerName game) $
+            exitWith failure { messages = [playerCannotDoThatMessage callerName] }
+
+    deleteGame
+
+    exitWith success { messages = [gameEndedMessage] }
+    where
+        gameEndedMessage = publicMessage $ T.concat ["Game ended by ", callerName, "."]
diff --git a/app/Werewolf/Command/Heal.hs b/app/Werewolf/Command/Heal.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Heal.hs
@@ -0,0 +1,43 @@
+{-|
+Module      : Werewolf.Command.Heal
+Description : Handler for the heal subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Handler for the heal subcommand.
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Werewolf.Command.Heal (
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+handle :: MonadIO m => Text -> m ()
+handle callerName = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = healCommand callerName
+
+    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
+        Left errorMessages      -> exitWith failure { messages = errorMessages }
+        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/Help.hs b/app/Werewolf/Command/Help.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Help.hs
@@ -0,0 +1,220 @@
+{-|
+Module      : Werewolf.Command.Help
+Description : Options and handler for the help subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Options and handler for the help subcommand.
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Werewolf.Command.Help (
+    -- * Options
+    Options(..), Command(..),
+
+    -- * Handle
+    handle,
+) where
+
+import Control.Lens
+import Control.Monad.Extra
+import Control.Monad.IO.Class
+
+import           Data.Function
+import           Data.List
+import           Data.Text     (Text)
+import qualified Data.Text     as T
+
+import           Game.Werewolf      hiding (Command)
+import qualified Game.Werewolf.Role as Role
+
+import Werewolf.Game
+
+data Options = Options
+    { argCommand :: Maybe Command
+    } deriving (Eq, Show)
+
+data Command = Commands
+    { optAll :: Bool
+    } | Rules
+    { optAll :: Bool
+    } | Roles
+    { optAll :: Bool
+    } deriving (Eq, Show)
+
+handle :: MonadIO m => Text -> Options -> m ()
+handle callerName (Options (Just (Commands optAll))) = do
+    mGame <- ifM (doesGameExist &&^ return (not optAll)) (Just <$> readGame) (return Nothing)
+
+    exitWith success
+        { messages = map (privateMessage callerName) (commandsMessages callerName mGame)
+        }
+handle callerName (Options (Just (Roles optAll))) = do
+    roles <- (sortBy (compare `on` view Role.name) . nub) <$> ifM (doesGameExist &&^ return (not optAll))
+        (toListOf (players . roles) <$> readGame)
+        (return allRoles)
+
+    exitWith success
+        { messages = map (privateMessage callerName . roleMessage) roles
+        }
+handle callerName (Options (Just (Rules optAll))) = do
+    mGame <- ifM (doesGameExist &&^ return (not optAll)) (Just <$> readGame) (return Nothing)
+
+    exitWith success
+        { messages = map (privateMessage callerName) (rulesMessages mGame)
+        }
+handle callerName (Options Nothing) = exitWith success
+    { messages = map (privateMessage callerName) helpMessages
+    }
+
+commandsMessages :: Text -> Maybe Game -> [Text]
+commandsMessages callerName mGame = map (T.intercalate "\n") $ filter (/= [])
+    [ [ "Global commands:"
+      , "- `start ([-e | --extra-roles ROLE,...] | [-r | --random-extra-roles]) PLAYER...`"
+      , "- `end`"
+      , "- `quit`"
+      , "- `version`"
+      ]
+    , [ "Status commands:"
+      , "- `ping` ping the status of the current game publicly"
+      , "- `status` get the status of the current game"
+      , "- `circle [-a | --include-dead]` get the game circle"
+      ]
+    , [ "Standard commands:"
+      , "- `vote PLAYER`"
+      ]
+    , whenPlayerHasRole callerName mGame defenderRole
+      [ "Defender commands:"
+      , "- `protect PLAYER`"
+      ]
+    , whenPlayerHasRole callerName mGame devotedServantRole
+      [ "Devoted Servant commands:"
+      , "- `reveal`"
+      ]
+    , whenPlayerHasRole callerName mGame scapegoatRole
+      [ "Scapegoat commands:"
+      , "- `choose PLAYER...`"
+      ]
+    , whenPlayerHasRole callerName mGame seerRole
+      [ "Seer commands:"
+      , "- `see PLAYER`"
+      ]
+    , whenPlayerHasRole callerName mGame wildChildRole
+      [ "Wild-child commands:"
+      , "- `choose PLAYER`"
+      ]
+    , whenPlayerHasRole callerName mGame witchRole
+      [ "Witch commands:"
+      , "- `heal`"
+      , "- `poison PLAYER`"
+      , "- `pass`"
+      ]
+    , whenPlayerHasRole callerName mGame wolfHoundRole
+      [ "Wolf-hound commands:"
+      , "- `choose (villagers | werewolves)`"
+      ]
+    ]
+
+roleMessage :: Role -> Text
+roleMessage role = T.intercalate "\n"
+    [ T.concat [role ^. Role.name, " (", T.pack . show $ role ^. balance, "):"]
+    , role ^. description
+    , role ^. advice
+    ]
+
+rulesMessages :: Maybe Game -> [Text]
+rulesMessages mGame = map (T.intercalate "\n")
+    [ [ T.unwords
+        [ "Each night, the Werewolves bite, kill and devour one Villager."
+        , "During the day they try to conceal their identity and vile deeds from the Villagers."
+        , "The number of Werewolves in play depends upon"
+        , " the number of players and variants used in the game."
+        ]
+      , T.unwords
+        [ "Each day,"
+        , "the survivors gather in the town square and try to discover who the Werewolves are."
+        , "This is done by studying the other player's social behaviours"
+        , "for hidden signs of lycanthropy."
+        , "After discussing and debating, the village votes to lynch a suspect,"
+        , "who is then hanged, burned and eliminated from the game."
+        ]
+      ]
+    , filter (/= "") [ T.concat
+        [ "Each player is informed of their role (see `help roles' for a list)"
+        , " at the start of the game."
+        , " A game begins at night and follows a standard cycle."
+        , whenRoleInPlay mGame angelRole
+          " (N.B., when the Angel is in play the game begins with the village vote.)"
+        ]
+      , whenRoleInPlay mGame angelRole
+        "- (When the Angel is in play) the village votes to lynch a suspect."
+      , "- The village falls asleep."
+      , whenRoleInPlay mGame wildChildRole
+        "- (First round only) the Wild-child wakes up and chooses a role model."
+      , whenRoleInPlay mGame defenderRole
+        "- The Defender wakes up and protects someone."
+      , whenRoleInPlay mGame seerRole
+        "- The Seer wakes up and sees someone's allegiance."
+      , whenRoleInPlay mGame wolfHoundRole
+        "- (First round only) the Wolf-hound wakes up and chooses an allegiance."
+      , "- The Werewolves wake up and select a victim."
+      , whenRoleInPlay mGame witchRole
+        "- The Witch wakes up and may heal the victim and/or poison someone."
+      , "- The village wakes up and find the victim."
+      , "- The village votes to lynch a suspect."
+      , whenRoleInPlay mGame devotedServantRole
+        "- The Devoted Servant may choose whether to reveal themselves and take on the role of their master."
+      , whenRoleInPlay mGame scapegoatRole
+        "- (When the Scapegoat is blamed) the Scapegoat chooses whom may vote on the next day."
+      , T.concat
+        [ "The game is over when only Villagers or Werewolves are left alive"
+        , ifRoleInPlay mGame angelRole
+          ", or when one of the Loners completes their own objective."
+          "."
+        ]
+      ]
+    ]
+
+helpMessages :: [Text]
+helpMessages = map (T.intercalate "\n")
+    [ [ T.unwords
+        [ "Deep in the American countryside,"
+        , "the little town of Millers Hollow has recently been infiltrated by Werewolves."
+        ]
+      , T.unwords
+        [ "Each night, murders are committed by the Villagers,"
+        , "who due to some mysterious phenomenon (possibly the greenhouse effect)"
+        , "have become Werewolves."
+        ]
+      , T.unwords
+        [ "It is now time to take control and eliminate this ancient evil,"
+        , "before the town loses its last few inhabitants."
+        ]
+      ]
+    , [ "Help commands:"
+      , "- `help commands [-a | --all]`"
+      , "- `help roles [-a | --all]`"
+      , "- `help rules [-a | --all]`"
+      ]
+    ]
+
+whenPlayerHasRole :: Monoid m => Text -> Maybe Game -> Role -> m -> m
+whenPlayerHasRole _ Nothing _ m                   = m
+whenPlayerHasRole callerName (Just game) role' m
+     | has (players . names . only callerName) game
+        && has (role . only role') player           = m
+    | otherwise                                     = mempty
+     where
+        player = game ^?! players . traverse . filteredBy name callerName
+
+ifRoleInPlay :: Maybe Game -> Role -> a -> a -> a
+ifRoleInPlay Nothing _ true _               = true
+ifRoleInPlay (Just game) role' true false
+    | has (players . roles . only role') game   = true
+    | otherwise                                 = false
+
+whenRoleInPlay :: Monoid m => Maybe Game -> Role -> m -> m
+whenRoleInPlay mGame role m = ifRoleInPlay mGame role m mempty
diff --git a/app/Werewolf/Command/Interpret.hs b/app/Werewolf/Command/Interpret.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Interpret.hs
@@ -0,0 +1,21 @@
+{-|
+Module      : Werewolf.Command.Interpret
+Description : Options for the interpret subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Options for the interpret subcommand.
+-}
+
+module Werewolf.Command.Interpret (
+    -- * Options
+    Options(..),
+) where
+
+import Data.Text (Text)
+
+data Options = Options
+    { args :: [Text]
+    } deriving (Eq, Show)
diff --git a/app/Werewolf/Command/Pass.hs b/app/Werewolf/Command/Pass.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Pass.hs
@@ -0,0 +1,46 @@
+{-|
+Module      : Werewolf.Command.Pass
+Description : Handler for the pass subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Handler for the pass subcommand.
+-}
+
+module Werewolf.Command.Pass (
+    -- * Handle
+    handle,
+) where
+
+import Control.Lens
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+handle :: MonadIO m => Text -> m ()
+handle callerName = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = case game ^. stage of
+            DevotedServantsTurn -> passDevotedServantsTurnCommand callerName
+            WitchsTurn          -> passWitchsTurnCommand callerName
+            -- TODO (hjw): throw an error
+            _                   -> undefined
+
+    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
+        Left errorMessages      -> exitWith failure { messages = errorMessages }
+        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/Ping.hs b/app/Werewolf/Command/Ping.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Ping.hs
@@ -0,0 +1,41 @@
+{-|
+Module      : Werewolf.Command.Ping
+Description : Handler for the ping subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Handler for the ping subcommand.
+-}
+
+module Werewolf.Command.Ping (
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+handle :: MonadIO m => Text -> m ()
+handle callerName = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = pingCommand callerName
+
+    case runExcept (execWriterT $ execStateT (apply command) game) of
+        Left errorMessages  -> exitWith failure { messages = errorMessages }
+        Right messages      -> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/Poison.hs b/app/Werewolf/Command/Poison.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Poison.hs
@@ -0,0 +1,48 @@
+{-|
+Module      : Werewolf.Command.Poison
+Description : Options and handler for the poison subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Options and handler for the poison subcommand.
+-}
+
+module Werewolf.Command.Poison (
+    -- * Options
+    Options(..),
+
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+data Options = Options
+    { argTarget :: Text
+    } deriving (Eq, Show)
+
+handle :: MonadIO m => Text -> Options -> m ()
+handle callerName (Options targetName) = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = poisonCommand callerName targetName
+
+    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
+        Left errorMessages      -> exitWith failure { messages = errorMessages }
+        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/Protect.hs b/app/Werewolf/Command/Protect.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Protect.hs
@@ -0,0 +1,48 @@
+{-|
+Module      : Werewolf.Command.Protect
+Description : Options and handler for the protect subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Options and handler for the protect subcommand.
+-}
+
+module Werewolf.Command.Protect (
+    -- * Options
+    Options(..),
+
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+data Options = Options
+    { argTarget :: Text
+    } deriving (Eq, Show)
+
+handle :: MonadIO m => Text -> Options -> m ()
+handle callerName (Options targetName) = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = protectCommand callerName targetName
+
+    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
+        Left errorMessages      -> exitWith failure { messages = errorMessages }
+        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/Quit.hs b/app/Werewolf/Command/Quit.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Quit.hs
@@ -0,0 +1,41 @@
+{-|
+Module      : Werewolf.Command.Quit
+Description : Handler for the quit subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Handler for the quit subcommand.
+-}
+
+module Werewolf.Command.Quit (
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+handle :: MonadIO m => Text -> m ()
+handle callerName = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = quitCommand callerName
+
+    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
+        Left errorMessages      -> exitWith failure { messages = errorMessages }
+        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/Reveal.hs b/app/Werewolf/Command/Reveal.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Reveal.hs
@@ -0,0 +1,43 @@
+{-|
+Module      : Werewolf.Command.Reveal
+Description : Handler for the reveal subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Handler for the reveal subcommand.
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Werewolf.Command.Reveal (
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+handle :: MonadIO m => Text -> m ()
+handle callerName = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = revealCommand callerName
+
+    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
+        Left errorMessages      -> exitWith failure { messages = errorMessages }
+        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/See.hs b/app/Werewolf/Command/See.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/See.hs
@@ -0,0 +1,48 @@
+{-|
+Module      : Werewolf.Command.See
+Description : Options and handler for the see subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Options and handler for the see subcommand.
+-}
+
+module Werewolf.Command.See (
+    -- * Options
+    Options(..),
+
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+data Options = Options
+    { argTarget :: Text
+    } deriving (Eq, Show)
+
+handle :: MonadIO m => Text -> Options -> m ()
+handle callerName (Options targetName) = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = seeCommand callerName targetName
+
+    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
+        Left errorMessages      -> exitWith failure { messages = errorMessages }
+        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/Start.hs b/app/Werewolf/Command/Start.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Start.hs
@@ -0,0 +1,83 @@
+{-|
+Module      : Werewolf.Command.Start
+Description : Options and handler for the start subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Options and handler for the start subcommand.
+-}
+
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+
+module Werewolf.Command.Start (
+    -- * Options
+    Options(..), ExtraRoles(..),
+
+    -- * Handle
+    handle,
+) where
+
+import Control.Lens
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.Random
+import Control.Monad.State
+import Control.Monad.Writer
+
+import           Data.Text (Text)
+import qualified Data.Text as T
+
+import Game.Werewolf      hiding (name)
+import Game.Werewolf.Role
+
+import System.Random.Shuffle
+
+import Werewolf.Game
+import Werewolf.Messages
+
+data Options = Options
+    { optExtraRoles :: ExtraRoles
+    , argPlayers    :: [Text]
+    } deriving (Eq, Show)
+
+data ExtraRoles = None | Random | Use [Text]
+    deriving (Eq, Show)
+
+handle :: MonadIO m => Text -> Options -> m ()
+handle callerName (Options extraRoles playerNames) = do
+    whenM (doesGameExist &&^ (hasn't (stage . _GameOver) <$> readGame)) $ exitWith failure
+        { messages = [gameAlreadyRunningMessage callerName]
+        }
+
+    result <- runExceptT $ do
+        extraRoles' <- case extraRoles of
+            None            -> return []
+            Random          -> randomExtraRoles $ length playerNames
+            Use roleNames   -> useExtraRoles callerName roleNames
+
+        players <- createPlayers (callerName:playerNames) (padRoles extraRoles' (length playerNames + 1))
+
+        runWriterT $ startGame callerName players >>= execStateT checkStage
+
+    case result of
+        Left errorMessages      -> exitWith failure { messages = errorMessages }
+        Right (game, messages)  -> writeGame game >> exitWith success { messages = messages }
+
+randomExtraRoles :: MonadIO m => Int -> m [Role]
+randomExtraRoles n = liftIO . evalRandIO $ do
+    let minimum = n `div` 3
+
+    count <- getRandomR (minimum, minimum + 2)
+
+    take count <$> shuffleM restrictedRoles
+
+useExtraRoles :: MonadError [Message] m => Text -> [Text] -> m [Role]
+useExtraRoles callerName roleNames = forM roleNames $ \roleName -> case findByName roleName of
+    Just role   -> return role
+    Nothing     -> throwError [roleDoesNotExistMessage callerName roleName]
+
+findByName :: Text -> Maybe Role
+findByName name' = restrictedRoles ^? traverse . filtered ((name' ==) . T.toLower . view name)
diff --git a/app/Werewolf/Command/Status.hs b/app/Werewolf/Command/Status.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Status.hs
@@ -0,0 +1,41 @@
+{-|
+Module      : Werewolf.Command.Status
+Description : Handler for the status subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Handler for the status subcommand.
+-}
+
+module Werewolf.Command.Status (
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+handle :: MonadIO m => Text -> m ()
+handle callerName = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = statusCommand callerName
+
+    case runExcept (execWriterT $ execStateT (apply command) game) of
+        Left errorMessages  -> exitWith failure { messages = errorMessages }
+        Right messages      -> exitWith success { messages = messages }
diff --git a/app/Werewolf/Command/Version.hs b/app/Werewolf/Command/Version.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Version.hs
@@ -0,0 +1,27 @@
+{-|
+Module      : Werewolf.Command.Version
+Description : Handler for the version subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Handler for the start subcommand.
+-}
+
+module Werewolf.Command.Version (
+    -- * Handle
+    handle,
+) where
+
+import Control.Monad.Except
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Messages
+import Werewolf.Version
+
+handle :: MonadIO m => Text -> m ()
+handle callerName = exitWith success { messages = [engineVersionMessage callerName version] }
diff --git a/app/Werewolf/Command/Vote.hs b/app/Werewolf/Command/Vote.hs
new file mode 100644
--- /dev/null
+++ b/app/Werewolf/Command/Vote.hs
@@ -0,0 +1,53 @@
+{-|
+Module      : Werewolf.Command.Vote
+Description : Options and handler for the vote subcommand.
+
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+
+Options and handler for the vote subcommand.
+-}
+
+module Werewolf.Command.Vote (
+    -- * Options
+    Options(..),
+
+    -- * Handle
+    handle,
+) where
+
+import Control.Lens
+import Control.Monad.Except
+import Control.Monad.Extra
+import Control.Monad.State
+import Control.Monad.Writer
+
+import Data.Text (Text)
+
+import Game.Werewolf
+
+import Werewolf.Game
+import Werewolf.Messages
+
+data Options = Options
+    { argTarget :: Text
+    } deriving (Eq, Show)
+
+handle :: MonadIO m => Text -> Options -> m ()
+handle callerName (Options targetName) = do
+    unlessM doesGameExist $ exitWith failure
+        { messages = [noGameRunningMessage callerName]
+        }
+
+    game <- readGame
+
+    let command = case game ^. stage of
+            VillagesTurn    -> voteLynchCommand callerName targetName
+            WerewolvesTurn  -> voteDevourCommand callerName targetName
+            -- TODO (hjw): throw an error
+            _               -> undefined
+
+    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
+        Left errorMessages      -> exitWith failure { messages = errorMessages }
+        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/Choose.hs b/app/Werewolf/Commands/Choose.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Choose.hs
+++ /dev/null
@@ -1,57 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Choose
-Description : Options and handler for the choose subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Options and handler for the choose subcommand.
--}
-
-{-# LANGUAGE OverloadedStrings #-}
-
-module Werewolf.Commands.Choose (
-    -- * Options
-    Options(..),
-
-    -- * Handle
-    handle,
-) where
-
-import Control.Lens
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import           Data.Text (Text)
-import qualified Data.Text as T
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-data Options = Options
-    { arg :: Text
-    } deriving (Eq, Show)
-
-handle :: MonadIO m => Text -> Options -> m ()
-handle callerName (Options arg) = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = case game ^. stage of
-            ScapegoatsTurn  -> choosePlayersCommand callerName (filter (/= T.empty) (T.splitOn "," arg))
-            WildChildsTurn  -> choosePlayerCommand callerName arg
-            WolfHoundsTurn  -> chooseAllegianceCommand callerName arg
-            -- TODO (hjw): throw an error
-            _               -> undefined
-
-    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
-        Left errorMessages      -> exitWith failure { messages = errorMessages }
-        Right (game, messages)  -> writeGame game >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/Circle.hs b/app/Werewolf/Commands/Circle.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Circle.hs
+++ /dev/null
@@ -1,48 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Circle
-Description : Options and handler for the circle subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Options and handler for the circle subcommand.
--}
-
-module Werewolf.Commands.Circle (
-    -- * Options
-    Options(..),
-
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-data Options = Options
-    { optIncludeDead :: Bool
-    } deriving (Eq, Show)
-
-handle :: MonadIO m => Text -> Options -> m ()
-handle callerName (Options includeDead) = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = circleCommand callerName includeDead
-
-    case runExcept (execWriterT $ execStateT (apply command) game) of
-        Left errorMessages  -> exitWith failure { messages = errorMessages }
-        Right messages      -> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/End.hs b/app/Werewolf/Commands/End.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/End.hs
+++ /dev/null
@@ -1,43 +0,0 @@
-{-|
-Module      : Werewolf.Commands.End
-Description : Handler for the end subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Handler for the end subcommand.
--}
-
-{-# LANGUAGE OverloadedStrings #-}
-
-module Werewolf.Commands.End (
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Extra
-import Control.Monad.IO.Class
-
-import           Data.Text (Text)
-import qualified Data.Text as T
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-handle :: MonadIO m => Text -> m ()
-handle callerName = do
-    unlessM doesGameExist $ exitWith failure { messages = [noGameRunningMessage callerName] }
-
-    game <- readGame
-
-    unless (doesPlayerExist callerName game) $
-        exitWith failure { messages = [playerCannotDoThatMessage callerName] }
-
-    deleteGame
-
-    exitWith success { messages = [gameEndedMessage] }
-    where
-        gameEndedMessage = publicMessage $ T.concat ["Game ended by ", callerName, "."]
diff --git a/app/Werewolf/Commands/Heal.hs b/app/Werewolf/Commands/Heal.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Heal.hs
+++ /dev/null
@@ -1,43 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Heal
-Description : Handler for the heal subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Handler for the heal subcommand.
--}
-
-{-# LANGUAGE OverloadedStrings #-}
-
-module Werewolf.Commands.Heal (
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-handle :: MonadIO m => Text -> m ()
-handle callerName = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = healCommand callerName
-
-    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
-        Left errorMessages      -> exitWith failure { messages = errorMessages }
-        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/Help.hs b/app/Werewolf/Commands/Help.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Help.hs
+++ /dev/null
@@ -1,168 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Help
-Description : Options and handler for the help subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Options and handler for the help subcommand.
--}
-
-{-# LANGUAGE OverloadedStrings #-}
-
-module Werewolf.Commands.Help (
-    -- * Options
-    Options(..), Command(..),
-
-    -- * Handle
-    handle,
-) where
-
-import Control.Lens
-import Control.Monad.IO.Class
-
-import           Data.Text (Text)
-import qualified Data.Text as T
-
-import Game.Werewolf      hiding (Command)
-import Game.Werewolf.Role as Role
-
-data Options = Options
-    { argCommand :: Maybe Command
-    } deriving (Eq, Show)
-
-data Command = Commands | Description | Rules | Roles
-    deriving (Eq, Show)
-
-handle :: MonadIO m => Text -> Options -> m ()
-handle callerName (Options (Just Commands)) = exitWith success
-    { messages = map (privateMessage callerName) commandsMessages
-    }
-handle callerName (Options (Just Description)) = exitWith success
-    { messages = map (privateMessage callerName) descriptionMessages
-    }
-handle callerName (Options (Just Roles)) = exitWith success
-    { messages = map (\role -> privateMessage callerName $ T.intercalate "\n"
-        [ T.concat [role ^. Role.name, " (", T.pack . show $ role ^. balance, "):"]
-        , role ^. description
-        , role ^. advice
-        ]) allRoles
-    }
-handle callerName (Options (Just Rules)) = exitWith success
-    { messages = map (privateMessage callerName) rulesMessages
-    }
-handle callerName (Options Nothing) = exitWith success
-    { messages = map (privateMessage callerName) helpMessages
-    }
-
-commandsMessages :: [Text]
-commandsMessages = map (T.intercalate "\n")
-    [ [ "Global commands:"
-      , "start ([--extra-roles ROLE,...] | [--random-extra-roles]) PLAYER..."
-      , "end"
-      , "quit"
-      , "version"
-      ]
-    , [ "Status commands:"
-      , "ping - ping the status of the current game publicly."
-      , "status - get the status of the current game."
-      , "circle [--include-dead] - get the game circle."
-      ]
-    , [ "Standard commands:"
-      , "vote PLAYER"
-      ]
-    , [ "Defender commands:"
-      , "protect PLAYER"
-      ]
-    , [ "Scapegoat commands:"
-      , "choose PLAYER,..."
-      ]
-    , [ "Seer commands:"
-      , "see PLAYER"
-      ]
-    , [ "Wild-child commands:"
-      , "choose PLAYER"
-      ]
-    , [ "Witch commands:"
-      , "heal"
-      , "poison PLAYER"
-      , "pass"
-      ]
-    , [ "Wolf-hound commands:"
-      , "choose (villagers | werewolves)"
-      ]
-    ]
-
-descriptionMessages :: [Text]
-descriptionMessages = map (T.intercalate "\n")
-    [ [ T.unwords
-        [ "Deep in the American countryside,"
-        , "the little town of Millers Hollow has recently been infiltrated by Werewolves."
-        ]
-      , T.unwords
-        [ "Each night, murders are committed by the Villagers,"
-        , "who due to some mysterious phenomenon (possibly the greenhouse effect)"
-        , "have become Werewolves."
-        ]
-      , T.unwords
-        [ "It is now time to take control and eliminate this ancient evil,"
-        , "before the town loses its last few inhabitants."
-        ]
-      ]
-    , [ "Objective of the Game:"
-      , "For the Angel: die in the first round."
-      , "For the Villagers: lynch all of the Werewolves."
-      , "For the Werewolves: devour all of the Villagers."
-      ]
-    ]
-
-rulesMessages :: [Text]
-rulesMessages = map (T.intercalate "\n")
-    [ [ T.unwords
-        [ "Each night, the Werewolves bite, kill and devour one Villager."
-        , "During the day they try to conceal their identity and vile deeds from the Villagers."
-        , "The number of Werewolves in play depends upon"
-        , " the number of players and variants used in the game."
-        ]
-      , T.unwords
-        [ "Each day,"
-        , "the survivors gather in the town square and try to discover who the Werewolves are."
-        , "This is done by studying the other player's social behaviours"
-        , "for hidden signs of lycanthropy."
-        , "After discussing and debating, the village votes to lynch a suspect,"
-        , "who is then hanged, burned and eliminated from the game."
-        ]
-      ]
-    , [ T.unwords
-        [ "Each player is informed of their role (see `help roles' for a list)"
-        , "at the start of the game. A game begins at night and follows a standard cycle."
-        , "(N.B., when the Angel is in play the game begins with the village vote.)"
-        ]
-      , "1. (When the Angel is in play) the village votes to lynch a suspect."
-      , "2. The village falls asleep."
-      , "3. (First round only) the Wild-child wakes up and chooses a role model."
-      , "4. The Defender wakes up and protects someone."
-      , "5. The Seer wakes up and sees someone's allegiance."
-      , "6. (First round only) the Wolf-hound wakes up and chooses an allegiance."
-      , "7. The Werewolves wake up and select a victim."
-      , "8. The Witch wakes up and may heal the victim and/or poison someone."
-      , "9. The village wakes up and find the victim."
-      , "10. The village votes to lynch a suspect."
-      , "11. (When the Scapegoat is blamed) the Scapegot chooses whom may vote on the next day."
-      , T.unwords
-        [ "The game is over when only Villagers or Werewolves are left alive,"
-        , "or when one of the Loners completes their own objective."
-        ]
-      ]
-    ]
-
-helpMessages :: [Text]
-helpMessages =
-    [ T.intercalate "\n"
-        [ "help commands - print the in-game commands."
-        , "help description - print the game description."
-        , "help roles - print the roles and their description."
-        , "help rules - print the game rules."
-        ]
-    ]
diff --git a/app/Werewolf/Commands/Interpret.hs b/app/Werewolf/Commands/Interpret.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Interpret.hs
+++ /dev/null
@@ -1,21 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Interpret
-Description : Options for the interpret subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Options for the interpret subcommand.
--}
-
-module Werewolf.Commands.Interpret (
-    -- * Options
-    Options(..),
-) where
-
-import Data.Text (Text)
-
-data Options = Options
-    { args :: [Text]
-    } deriving (Eq, Show)
diff --git a/app/Werewolf/Commands/Pass.hs b/app/Werewolf/Commands/Pass.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Pass.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Pass
-Description : Handler for the pass subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Handler for the pass subcommand.
--}
-
-module Werewolf.Commands.Pass (
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-handle :: MonadIO m => Text -> m ()
-handle callerName = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = passCommand callerName
-
-    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
-        Left errorMessages      -> exitWith failure { messages = errorMessages }
-        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/Ping.hs b/app/Werewolf/Commands/Ping.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Ping.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Ping
-Description : Handler for the ping subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Handler for the ping subcommand.
--}
-
-module Werewolf.Commands.Ping (
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-handle :: MonadIO m => Text -> m ()
-handle callerName = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = pingCommand callerName
-
-    case runExcept (execWriterT $ execStateT (apply command) game) of
-        Left errorMessages  -> exitWith failure { messages = errorMessages }
-        Right messages      -> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/Poison.hs b/app/Werewolf/Commands/Poison.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Poison.hs
+++ /dev/null
@@ -1,48 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Poison
-Description : Options and handler for the poison subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Options and handler for the poison subcommand.
--}
-
-module Werewolf.Commands.Poison (
-    -- * Options
-    Options(..),
-
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-data Options = Options
-    { argTarget :: Text
-    } deriving (Eq, Show)
-
-handle :: MonadIO m => Text -> Options -> m ()
-handle callerName (Options targetName) = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = poisonCommand callerName targetName
-
-    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
-        Left errorMessages      -> exitWith failure { messages = errorMessages }
-        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/Protect.hs b/app/Werewolf/Commands/Protect.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Protect.hs
+++ /dev/null
@@ -1,48 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Protect
-Description : Options and handler for the protect subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Options and handler for the protect subcommand.
--}
-
-module Werewolf.Commands.Protect (
-    -- * Options
-    Options(..),
-
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-data Options = Options
-    { argTarget :: Text
-    } deriving (Eq, Show)
-
-handle :: MonadIO m => Text -> Options -> m ()
-handle callerName (Options targetName) = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = protectCommand callerName targetName
-
-    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
-        Left errorMessages      -> exitWith failure { messages = errorMessages }
-        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/Quit.hs b/app/Werewolf/Commands/Quit.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Quit.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Quit
-Description : Handler for the quit subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Handler for the quit subcommand.
--}
-
-module Werewolf.Commands.Quit (
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-handle :: MonadIO m => Text -> m ()
-handle callerName = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = quitCommand callerName
-
-    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
-        Left errorMessages      -> exitWith failure { messages = errorMessages }
-        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/See.hs b/app/Werewolf/Commands/See.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/See.hs
+++ /dev/null
@@ -1,48 +0,0 @@
-{-|
-Module      : Werewolf.Commands.See
-Description : Options and handler for the see subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Options and handler for the see subcommand.
--}
-
-module Werewolf.Commands.See (
-    -- * Options
-    Options(..),
-
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-data Options = Options
-    { argTarget :: Text
-    } deriving (Eq, Show)
-
-handle :: MonadIO m => Text -> Options -> m ()
-handle callerName (Options targetName) = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = seeCommand callerName targetName
-
-    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
-        Left errorMessages      -> exitWith failure { messages = errorMessages }
-        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/Start.hs b/app/Werewolf/Commands/Start.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Start.hs
+++ /dev/null
@@ -1,83 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Start
-Description : Options and handler for the start subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Options and handler for the start subcommand.
--}
-
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-
-module Werewolf.Commands.Start (
-    -- * Options
-    Options(..), ExtraRoles(..),
-
-    -- * Handle
-    handle,
-) where
-
-import Control.Lens
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.Random
-import Control.Monad.State
-import Control.Monad.Writer
-
-import           Data.Text (Text)
-import qualified Data.Text as T
-
-import Game.Werewolf      hiding (name)
-import Game.Werewolf.Role
-
-import System.Random.Shuffle
-
-import Werewolf.Game
-import Werewolf.Messages
-
-data Options = Options
-    { optExtraRoles :: ExtraRoles
-    , argPlayers    :: [Text]
-    } deriving (Eq, Show)
-
-data ExtraRoles = None | Random | Use [Text]
-    deriving (Eq, Show)
-
-handle :: MonadIO m => Text -> Options -> m ()
-handle callerName (Options extraRoles playerNames) = do
-    whenM (doesGameExist &&^ (hasn't (stage . _GameOver) <$> readGame)) $ exitWith failure
-        { messages = [gameAlreadyRunningMessage callerName]
-        }
-
-    result <- runExceptT $ do
-        extraRoles' <- case extraRoles of
-            None            -> return []
-            Random          -> randomExtraRoles $ length playerNames
-            Use roleNames   -> useExtraRoles callerName roleNames
-
-        players <- createPlayers (callerName:playerNames) (padRoles extraRoles' (length playerNames + 1))
-
-        runWriterT $ startGame callerName players >>= execStateT checkStage
-
-    case result of
-        Left errorMessages      -> exitWith failure { messages = errorMessages }
-        Right (game, messages)  -> writeGame game >> exitWith success { messages = messages }
-
-randomExtraRoles :: MonadIO m => Int -> m [Role]
-randomExtraRoles n = liftIO . evalRandIO $ do
-    let minimum = n `div` 3
-
-    count <- getRandomR (minimum, minimum + 2)
-
-    take count <$> shuffleM restrictedRoles
-
-useExtraRoles :: MonadError [Message] m => Text -> [Text] -> m [Role]
-useExtraRoles callerName roleNames = forM roleNames $ \roleName -> case findByName roleName of
-    Just role   -> return role
-    Nothing     -> throwError [roleDoesNotExistMessage callerName roleName]
-
-findByName :: Text -> Maybe Role
-findByName name' = restrictedRoles ^? traverse . filtered ((name' ==) . T.toLower . view name)
diff --git a/app/Werewolf/Commands/Status.hs b/app/Werewolf/Commands/Status.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Status.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Status
-Description : Handler for the status subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Handler for the status subcommand.
--}
-
-module Werewolf.Commands.Status (
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-handle :: MonadIO m => Text -> m ()
-handle callerName = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = statusCommand callerName
-
-    case runExcept (execWriterT $ execStateT (apply command) game) of
-        Left errorMessages  -> exitWith failure { messages = errorMessages }
-        Right messages      -> exitWith success { messages = messages }
diff --git a/app/Werewolf/Commands/Version.hs b/app/Werewolf/Commands/Version.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Version.hs
+++ /dev/null
@@ -1,27 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Version
-Description : Handler for the version subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Handler for the start subcommand.
--}
-
-module Werewolf.Commands.Version (
-    -- * Handle
-    handle,
-) where
-
-import Control.Monad.Except
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Messages
-import Werewolf.Version
-
-handle :: MonadIO m => Text -> m ()
-handle callerName = exitWith success { messages = [engineVersionMessage callerName version] }
diff --git a/app/Werewolf/Commands/Vote.hs b/app/Werewolf/Commands/Vote.hs
deleted file mode 100644
--- a/app/Werewolf/Commands/Vote.hs
+++ /dev/null
@@ -1,53 +0,0 @@
-{-|
-Module      : Werewolf.Commands.Vote
-Description : Options and handler for the vote subcommand.
-
-Copyright   : (c) Henry J. Wylde, 2016
-License     : BSD3
-Maintainer  : public@hjwylde.com
-
-Options and handler for the vote subcommand.
--}
-
-module Werewolf.Commands.Vote (
-    -- * Options
-    Options(..),
-
-    -- * Handle
-    handle,
-) where
-
-import Control.Lens
-import Control.Monad.Except
-import Control.Monad.Extra
-import Control.Monad.State
-import Control.Monad.Writer
-
-import Data.Text (Text)
-
-import Game.Werewolf
-
-import Werewolf.Game
-import Werewolf.Messages
-
-data Options = Options
-    { argTarget :: Text
-    } deriving (Eq, Show)
-
-handle :: MonadIO m => Text -> Options -> m ()
-handle callerName (Options targetName) = do
-    unlessM doesGameExist $ exitWith failure
-        { messages = [noGameRunningMessage callerName]
-        }
-
-    game <- readGame
-
-    let command = case game ^. stage of
-            VillagesTurn    -> voteLynchCommand callerName targetName
-            WerewolvesTurn  -> voteDevourCommand callerName targetName
-            -- TODO (hjw): throw an error
-            _               -> undefined
-
-    case runExcept (runWriterT $ execStateT (apply command >> checkStage >> checkGameOver) game) of
-        Left errorMessages      -> exitWith failure { messages = errorMessages }
-        Right (game', messages) -> writeGame game' >> exitWith success { messages = messages }
diff --git a/app/Werewolf/Options.hs b/app/Werewolf/Options.hs
--- a/app/Werewolf/Options.hs
+++ b/app/Werewolf/Options.hs
@@ -23,16 +23,17 @@
 import qualified Data.Text    as T
 import           Data.Version (showVersion)
 
-import qualified Werewolf.Commands.Choose    as Choose
-import qualified Werewolf.Commands.Circle    as Circle
-import qualified Werewolf.Commands.Help      as Help
-import qualified Werewolf.Commands.Interpret as Interpret
-import qualified Werewolf.Commands.Poison    as Poison
-import qualified Werewolf.Commands.Protect   as Protect
-import qualified Werewolf.Commands.See       as See
-import qualified Werewolf.Commands.Start     as Start
-import qualified Werewolf.Commands.Vote      as Vote
-import qualified Werewolf.Version            as This
+import qualified Werewolf.Command.Choose    as Choose
+import qualified Werewolf.Command.Circle    as Circle
+import qualified Werewolf.Command.End as End
+import qualified Werewolf.Command.Help      as Help
+import qualified Werewolf.Command.Interpret as Interpret
+import qualified Werewolf.Command.Poison    as Poison
+import qualified Werewolf.Command.Protect   as Protect
+import qualified Werewolf.Command.See       as See
+import qualified Werewolf.Command.Start     as Start
+import qualified Werewolf.Command.Vote      as Vote
+import qualified Werewolf.Version           as This
 
 import Options.Applicative
 
@@ -44,7 +45,7 @@
 data Command
     = Choose Choose.Options
     | Circle Circle.Options
-    | End
+    | End End.Options
     | Heal
     | Help Help.Options
     | Interpret Interpret.Options
@@ -53,6 +54,7 @@
     | Poison Poison.Options
     | Protect Protect.Options
     | Quit
+    | Reveal
     | See See.Options
     | Start Start.Options
     | Status
@@ -95,12 +97,13 @@
         , command "end"         $ info (helper <*> end)         (fullDesc <> progDesc "End the current game")
         , command "heal"        $ info (helper <*> heal)        (fullDesc <> progDesc "Heal the devoured player")
         , command "help"        $ info (helper <*> help_)       (fullDesc <> progDesc "Help documents")
-        , command "interpret"   $ info (helper <*> interpret)   (fullDesc <> progDesc "Interpret a command" <> noIntersperse)
+        , command "interpret"   $ info (helper <*> interpret)   (fullDesc <> noIntersperse <> progDesc "Interpret a command")
         , command "pass"        $ info (helper <*> pass)        (fullDesc <> progDesc "Pass")
         , command "ping"        $ info (helper <*> ping)        (fullDesc <> progDesc "Ping the status of the current game publicly")
         , command "poison"      $ info (helper <*> poison)      (fullDesc <> progDesc "Poison a player")
         , command "protect"     $ info (helper <*> protect)     (fullDesc <> progDesc "Protect a player")
         , command "quit"        $ info (helper <*> quit)        (fullDesc <> progDesc "Quit the current game")
+        , command "reveal"      $ info (helper <*> reveal)      (fullDesc <> progDesc "Reveal yourself")
         , command "see"         $ info (helper <*> see)         (fullDesc <> progDesc "See a player's allegiance")
         , command "start"       $ info (helper <*> start)       (fullDesc <> progDesc "Start a new game")
         , command "status"      $ info (helper <*> status)      (fullDesc <> progDesc "Get the status of the current game")
@@ -109,7 +112,7 @@
         ])
 
 choose :: Parser Command
-choose = Choose . Choose.Options . T.pack <$> strArgument (metavar "ALLEGIANCE | PLAYER,...")
+choose = Choose . Choose.Options . map T.pack <$> some (strArgument $ metavar "(ALLEGIANCE | PLAYER...)")
 
 circle :: Parser Command
 circle = Circle . Circle.Options
@@ -119,7 +122,11 @@
         ])
 
 end :: Parser Command
-end = pure End
+end = End . End.Options
+    <$> switch (mconcat
+        [ long "force", short 'f'
+        , help "Force the game to end"
+        ])
 
 heal :: Parser Command
 heal = pure Heal
@@ -127,11 +134,12 @@
 help_ :: Parser Command
 help_ = Help . Help.Options
     <$> optional (subparser $ mconcat
-        [ command "commands"    $ info (pure Help.Commands)     (fullDesc <> progDesc "Print the in-game commands")
-        , command "description" $ info (pure Help.Description)  (fullDesc <> progDesc "Print the game description")
-        , command "rules"       $ info (pure Help.Rules)        (fullDesc <> progDesc "Print the game rules")
-        , command "roles"       $ info (pure Help.Roles)        (fullDesc <> progDesc "Print the roles and their descriptions")
+        [ command "commands"    $ info (Help.Commands <$> allOption)    (fullDesc <> progDesc "Print the in-game commands")
+        , command "roles"       $ info (Help.Roles <$> allOption)       (fullDesc <> progDesc "Print the roles and their descriptions")
+        , command "rules"       $ info (Help.Rules <$> allOption)       (fullDesc <> progDesc "Print the game rules")
         ])
+    where
+        allOption = switch $ long "all" <> short 'a'
 
 interpret :: Parser Command
 interpret = Interpret . Interpret.Options
@@ -152,6 +160,9 @@
 quit :: Parser Command
 quit = pure Quit
 
+reveal :: Parser Command
+reveal = pure Reveal
+
 see :: Parser Command
 see = See . See.Options <$> playerArgument
 
@@ -161,13 +172,13 @@
     <*> some (T.pack <$> strArgument (metavar "PLAYER..."))
     where
         extraRolesOption = fmap (Start.Use . filter (/= T.empty) . T.splitOn "," . T.pack) (strOption $ mconcat
-            [ long "extra-roles", metavar "ROLE,..."
+            [ long "extra-roles", short 'e', metavar "ROLE,..."
             , value []
             , help "Specify the extra roles to use"
             ])
 
         randomExtraRolesOption = flag Start.None Start.Random $ mconcat
-            [ long "random-extra-roles"
+            [ long "random-extra-roles", short 'r'
             , help "Use random extra roles"
             ]
 
diff --git a/src/Game/Werewolf/Command.hs b/src/Game/Werewolf/Command.hs
--- a/src/Game/Werewolf/Command.hs
+++ b/src/Game/Werewolf/Command.hs
@@ -20,8 +20,9 @@
 
     -- ** Instances
     chooseAllegianceCommand, choosePlayerCommand, choosePlayersCommand, circleCommand, healCommand,
-    noopCommand, passCommand, pingCommand, poisonCommand, protectCommand, quitCommand, seeCommand,
-    statusCommand, voteDevourCommand, voteLynchCommand,
+    noopCommand, passDevotedServantsTurnCommand, passWitchsTurnCommand, pingCommand, poisonCommand,
+    protectCommand, quitCommand, revealCommand, seeCommand, statusCommand, voteDevourCommand,
+    voteLynchCommand,
 ) where
 
 import Control.Lens
@@ -36,7 +37,8 @@
 import           Data.Text  (Text)
 import qualified Data.Text  as T
 
-import           Game.Werewolf.Game     hiding (doesPlayerExist, getPendingVoters, killPlayer)
+import           Game.Werewolf.Game     hiding (doesPlayerExist, getPendingVoters, getVoteResult,
+                                         killPlayer)
 import           Game.Werewolf.Messages
 import           Game.Werewolf.Player
 import           Game.Werewolf.Response
@@ -103,55 +105,67 @@
 noopCommand :: Command
 noopCommand = Command $ return ()
 
-passCommand :: Text -> Command
-passCommand callerName = Command $ do
+passDevotedServantsTurnCommand :: Text -> Command
+passDevotedServantsTurnCommand callerName = Command $ do
+    validateDevotedServantsCommand callerName
+
+    passes %= nub . cons callerName
+
+passWitchsTurnCommand :: Text -> Command
+passWitchsTurnCommand callerName = Command $ do
     validateWitchsCommand callerName
 
     passes %= nub . cons callerName
 
 pingCommand :: Text -> Command
 pingCommand callerName = Command $ use stage >>= \stage' -> case stage' of
-    GameOver        -> tell [gameIsOverMessage callerName]
-    DefendersTurn   -> do
+    DefendersTurn       -> do
         defender <- findPlayerBy_ role defenderRole
 
         tell [pingRoleMessage $ defenderRole ^. Role.name]
         tell [pingPlayerMessage $ defender ^. name]
-    ScapegoatsTurn  -> do
+    DevotedServantsTurn -> do
+        devotedServant <- findPlayerBy_ role devotedServantRole
+
+        tell [pingRoleMessage $ devotedServantRole ^. Role.name]
+        tell [pingPlayerMessage $ devotedServant ^. name]
+    GameOver            -> tell [gameIsOverMessage callerName]
+    Lynching            -> return ()
+    ScapegoatsTurn      -> do
         scapegoat <- findPlayerBy_ role scapegoatRole
 
         tell [pingRoleMessage $ scapegoatRole ^. Role.name]
         tell [pingPlayerMessage $ scapegoat ^. name]
-    SeersTurn       -> do
+    SeersTurn           -> do
         seer <- findPlayerBy_ role seerRole
 
         tell [pingRoleMessage $ seerRole ^. Role.name]
         tell [pingPlayerMessage $ seer ^. name]
-    Sunrise         -> return ()
-    Sunset          -> return ()
-    UrsussGrunt     -> return ()
-    VillagesTurn    -> do
+    Sunrise             -> return ()
+    Sunset              -> return ()
+    UrsussGrunt         -> return ()
+    VillagesTurn        -> do
         allowedVoterNames <- use allowedVoters
         pendingVoterNames <- toListOf names <$> getPendingVoters
 
         tell [waitingOnMessage Nothing $ allowedVoterNames `intersect` pendingVoterNames]
         tell $ map pingPlayerMessage (allowedVoterNames `intersect` pendingVoterNames)
-    WerewolvesTurn  -> do
+    WerewolvesTurn      -> do
         pendingVoters <- getPendingVoters
 
         tell [pingRoleMessage "Werewolves"]
         tell $ map pingPlayerMessage (pendingVoters ^.. werewolves . name)
-    WildChildsTurn  -> do
+    WildChildsTurn      -> do
         wildChild <- findPlayerBy_ role wildChildRole
 
         tell [pingRoleMessage $ wildChildRole ^. Role.name]
         tell [pingPlayerMessage $ wildChild ^. name]
-    WitchsTurn      -> do
+    WitchsTurn          -> do
         witch <- findPlayerBy_ role witchRole
 
         tell [pingRoleMessage $ witchRole ^. Role.name]
         tell [pingPlayerMessage $ witch ^. name]
-    WolfHoundsTurn  -> do
+    WolfHoundsTurn      -> do
         wolfHound <- findPlayerBy_ role wolfHoundRole
 
         tell [pingRoleMessage $ wolfHoundRole ^. Role.name]
@@ -203,6 +217,33 @@
         poisonUsed  .= False
     when (is wolfHound caller)  $ allegianceChosen .= Nothing
 
+revealCommand :: Text -> Command
+revealCommand callerName = Command $ do
+    validateDevotedServantsCommand callerName
+
+    target <- head <$> getVoteResult
+
+    let targetRole = target ^. role
+    let targetName = target ^. name
+
+    setPlayerRole callerName targetRole
+    setPlayerRole targetName devotedServantRole
+
+    tell [devotedServantRevealedMessage callerName]
+
+    resetRole targetRole
+    where
+        resetRole role
+            | role == simpleWerewolfRole    = do
+                aliveWerewolfNames <- toListOf (players . werewolves . alive . name) <$> get
+
+                tell $ devotedServantJoinedPackMessages callerName aliveWerewolfNames
+            | role == villageIdiotRole      = villageIdiotRevealed .= False
+            | role == wildChildRole         = roleModel .= Nothing
+            | role == witchRole             = healUsed .= False >> poisonUsed .= False
+            | role == wolfHoundRole         = allegianceChosen .= Nothing
+            | otherwise                     = return ()
+
 seeCommand :: Text -> Text -> Command
 seeCommand callerName targetName = Command $ do
     validatePlayer callerName callerName
@@ -215,8 +256,10 @@
 statusCommand :: Text -> Command
 statusCommand callerName = Command $ use stage >>= \stage' -> case stage' of
     GameOver        -> tell [gameIsOverMessage callerName]
+    Lynching        -> return ()
     Sunrise         -> return ()
     Sunset          -> return ()
+    UrsussGrunt     -> return ()
     VillagesTurn    -> do
         allowedVoterNames <- use allowedVoters
         pendingVoterNames <- toListOf names <$> getPendingVoters
@@ -267,6 +310,12 @@
     whenM isGameOver                $ throwError [gameIsOverMessage callerName]
     unlessM (doesPlayerExist name)  $ throwError [playerDoesNotExistMessage callerName name]
     whenM (isPlayerDead name)       $ throwError [if callerName == name then playerIsDeadMessage callerName else targetIsDeadMessage callerName name]
+
+validateDevotedServantsCommand :: (MonadError [Message] m, MonadState Game m) => Text -> m ()
+validateDevotedServantsCommand callerName = do
+    validatePlayer callerName callerName
+    unlessM (isPlayerDevotedServant callerName) $ throwError [playerCannotDoThatMessage callerName]
+    unlessM isDevotedServantsTurn               $ throwError [playerCannotDoThatRightNowMessage callerName]
 
 validateWitchsCommand :: (MonadError [Message] m, MonadState Game m) => Text -> m ()
 validateWitchsCommand callerName = do
diff --git a/src/Game/Werewolf/Engine.hs b/src/Game/Werewolf/Engine.hs
--- a/src/Game/Werewolf/Engine.hs
+++ b/src/Game/Werewolf/Engine.hs
@@ -55,13 +55,31 @@
 
 checkStage' :: (MonadState Game m, MonadWriter [Message] m) => m ()
 checkStage' = use stage >>= \stage' -> case stage' of
-    GameOver -> return ()
-
     DefendersTurn -> do
         whenM (has (players . defenders . dead) <$> get) advanceStage
 
         whenM (isJust <$> use protect) advanceStage
 
+    DevotedServantsTurn -> do
+        whenM (has (players . devotedServants . dead) <$> get) advanceStage
+
+        whenM (has devotedServants <$> getVoteResult)   advanceStage
+        whenM (has devotedServants <$> getPassers)      advanceStage
+
+    GameOver -> return ()
+
+    Lynching -> do
+        getVoteResult >>= lynchVotees
+
+        allVoters       <- ifM (use villageIdiotRevealed)
+            (uses players $ filter (isn't villageIdiot))
+            (use players)
+        allowedVoters   .= allVoters ^.. traverse . alive . name
+
+        votes .= Map.empty
+
+        advanceStage
+
     ScapegoatsTurn -> unlessM (use scapegoatBlamed) $ do
         allowedVoters' <- use allowedVoters
         tell [scapegoatChoseAllowedVotersMessage allowedVoters']
@@ -99,8 +117,7 @@
 
                 setPlayerAllegiance (wildChild ^. name) Werewolves
 
-                tell [playerJoinedPackMessage (wildChild ^. name) aliveWerewolfNames]
-                tell $ wildChildJoinedPackMessages aliveWerewolfNames (wildChild ^. name)
+                tell $ wildChildJoinedPackMessages (wildChild ^. name) aliveWerewolfNames
 
         advanceStage
 
@@ -115,19 +132,13 @@
     VillagesTurn -> whenM (null <$> liftM2 intersect getAllowedVoters getPendingVoters) $ do
         tell . map (uncurry playerMadeLynchVoteMessage) =<< uses votes Map.toList
 
-        getVoteResult >>= lynchVotees
-
-        allVoters       <- ifM (use villageIdiotRevealed)
-            (uses players $ filter (isn't villageIdiot))
-            (use players)
-        allowedVoters   .= allVoters ^.. traverse . alive . name
-
         advanceStage
 
     WerewolvesTurn -> whenM (none (is werewolf) <$> getPendingVoters) $ do
         getVoteResult >>= devourVotees
 
         protect .= Nothing
+        votes .= Map.empty
 
         advanceStage
 
@@ -195,7 +206,6 @@
     stage   .= nextStage
     passes  .= []
     see     .= Nothing
-    votes   .= Map.empty
 
     tell . stageMessages =<< get
 
diff --git a/src/Game/Werewolf/Game.hs b/src/Game/Werewolf/Game.hs
--- a/src/Game/Werewolf/Game.hs
+++ b/src/Game/Werewolf/Game.hs
@@ -21,8 +21,9 @@
     poisonUsed, priorProtect, protect, roleModel, scapegoatBlamed, see, villageIdiotRevealed, votes,
 
     Stage(..),
-    _DefendersTurn, _GameOver, _ScapegoatsTurn, _SeersTurn, _Sunrise, _Sunset, _UrsussGrunt,
-    _VillagesTurn, _WerewolvesTurn, _WildChildsTurn, _WitchsTurn, _WolfHoundsTurn,
+    _DefendersTurn, _DevotedServantsTurn, _GameOver, _Lynching, _ScapegoatsTurn, _SeersTurn,
+    _Sunrise, _Sunset, _UrsussGrunt, _VillagesTurn, _WerewolvesTurn, _WildChildsTurn, _WitchsTurn,
+    _WolfHoundsTurn,
 
     allStages,
     stageCycle, stageAvailable,
@@ -106,9 +107,9 @@
 --
 --   Once the game reaches a turn stage, it requires a 'Game.Werewolf.Command.Command' to help push
 --   it past. Often only certain roles and commands may be performed at any given stage.
-data Stage  = GameOver | DefendersTurn | ScapegoatsTurn | SeersTurn | Sunrise | Sunset
-            | UrsussGrunt | VillagesTurn | WerewolvesTurn | WildChildsTurn | WitchsTurn
-            | WolfHoundsTurn
+data Stage  = DefendersTurn | DevotedServantsTurn | GameOver | Lynching | ScapegoatsTurn
+            | SeersTurn | Sunrise | Sunset | UrsussGrunt | VillagesTurn | WerewolvesTurn
+            | WildChildsTurn | WitchsTurn | WolfHoundsTurn
     deriving (Eq, Read, Show)
 
 -- | Events occur /after/ a 'Stage' is advanced. This is automatically handled in
@@ -133,6 +134,8 @@
 allStages :: [Stage]
 allStages =
     [ VillagesTurn
+    , DevotedServantsTurn
+    , Lynching
     , ScapegoatsTurn
     , Sunset
     , WolfHoundsTurn
@@ -153,29 +156,34 @@
 -- | 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 most complex checks here is for the 'VillagesTurn'. If the Angel is in play, then
+--   One of the more complex checks here is for the 'VillagesTurn'. If the Angel is in play, then
 --   the 'VillagesTurn' is available on the first day rather than only after the first night.
 stageAvailable :: Game -> Stage -> Bool
-stageAvailable game DefendersTurn   = has (players . defenders . alive) game
-stageAvailable _ GameOver           = False
-stageAvailable game ScapegoatsTurn  = game ^. scapegoatBlamed
-stageAvailable game SeersTurn       = has (players . seers . alive) game
-stageAvailable _ Sunrise            = True
-stageAvailable _ Sunset             = True
-stageAvailable game UrsussGrunt     = has (players . bearTamers . alive) game
-stageAvailable game VillagesTurn    =
+stageAvailable game DefendersTurn       = has (players . defenders . alive) game
+stageAvailable game DevotedServantsTurn =
+    has (players . devotedServants . alive) game
+    && length (getVoteResult game) == 1
+    && isn't devotedServant (head $ getVoteResult game)
+stageAvailable _ GameOver               = False
+stageAvailable game Lynching            = Map.size (game ^. votes) > 0
+stageAvailable game ScapegoatsTurn      = game ^. scapegoatBlamed
+stageAvailable game SeersTurn           = has (players . seers . alive) game
+stageAvailable _ Sunrise                = True
+stageAvailable _ Sunset                 = True
+stageAvailable game UrsussGrunt         = has (players . bearTamers . alive) game
+stageAvailable game VillagesTurn        =
     (has (players . angels . alive) game || not (isFirstRound game))
     && any (is alive) (getAllowedVoters game)
-stageAvailable game WerewolvesTurn  = has (players . werewolves . alive) game
-stageAvailable game WildChildsTurn  =
+stageAvailable game WerewolvesTurn      = has (players . werewolves . alive) game
+stageAvailable game WildChildsTurn      =
     has (players . wildChildren . alive) game
     && isNothing (game ^. roleModel)
-stageAvailable game WitchsTurn      =
+stageAvailable game WitchsTurn          =
     has (players . witches . alive) game
     && (not (game ^. healUsed) || not (game ^. poisonUsed))
-stageAvailable game WolfHoundsTurn  =
+stageAvailable game WolfHoundsTurn      =
     has (players . wolfHounds . alive) game
-    && (isNothing $ game ^. allegianceChosen)
+    && isNothing (game ^. allegianceChosen)
 
 -- | Creates a new 'Game' with the given players. No validations are performed here, those are left
 --   to 'Game.Werewolf.Engine.startGame'.
@@ -224,7 +232,9 @@
 -- | Gets all players that had /the/ highest vote count. This could be 1 or more players depending
 --   on whether the votes were in conflict.
 getVoteResult :: Game -> [Player]
-getVoteResult game = map (\name' -> game ^?! players . traverse . filteredBy name name') result
+getVoteResult game
+    | Map.null (game ^. votes)  = []
+    | otherwise                 = map (\name' -> game ^?! players . traverse . filteredBy name name') result
     where
         votees = Map.elems $ game ^. votes
         result = last $ groupSortOn (length . (`elemIndices` votees)) (nub votees)
diff --git a/src/Game/Werewolf/Messages.hs b/src/Game/Werewolf/Messages.hs
--- a/src/Game/Werewolf/Messages.hs
+++ b/src/Game/Werewolf/Messages.hs
@@ -45,6 +45,9 @@
     -- ** Error messages
     playerCannotProtectSamePlayerTwiceInARowMessage,
 
+    -- * Devoted Servant's turn messages
+    devotedServantRevealedMessage, devotedServantJoinedPackMessages,
+
     -- * Scapegoat's turn messages
     scapegoatChoseAllowedVotersMessage,
 
@@ -68,7 +71,7 @@
     playerCannotDevourAnotherWerewolfMessage,
 
     -- * Wild-child's turn messages
-    playerJoinedPackMessage, wildChildJoinedPackMessages,
+    wildChildJoinedPackMessages,
 
     -- ** Error messages
     playerCannotChooseSelfMessage,
@@ -136,25 +139,29 @@
 
 stageMessages :: Game -> [Message]
 stageMessages game = case game ^. stage of
-    GameOver        -> []
-    DefendersTurn   -> defendersTurnMessages defendersName
-    ScapegoatsTurn  -> scapegoatsTurnMessages scapegoatsName
-    SeersTurn       -> seersTurnMessages seersName
-    Sunrise         -> [sunriseMessage]
-    Sunset          -> [nightFallsMessage]
-    UrsussGrunt     -> []
-    VillagesTurn    -> if isFirstRound game
+    DefendersTurn       -> defendersTurnMessages defendersName
+    DevotedServantsTurn -> devotedServantsTurnMessages devotedServantsName victimsName
+    GameOver            -> []
+    Lynching            -> []
+    ScapegoatsTurn      -> scapegoatsTurnMessages scapegoatsName
+    SeersTurn           -> seersTurnMessages seersName
+    Sunrise             -> [sunriseMessage]
+    Sunset              -> [nightFallsMessage]
+    UrsussGrunt         -> []
+    VillagesTurn        -> if isFirstRound game
         then firstVillagesTurnMessages
         else villagesTurnMessages
-    WerewolvesTurn  -> if isFirstRound game
+    WerewolvesTurn      -> if isFirstRound game
         then firstWerewolvesTurnMessages aliveWerewolfNames
         else werewolvesTurnMessages aliveWerewolfNames
-    WildChildsTurn  -> wildChildsTurnMessages wildChildsName
-    WitchsTurn      -> witchsTurnMessages game
-    WolfHoundsTurn  -> wolfHoundsTurnMessages wolfHoundsName
+    WildChildsTurn      -> wildChildsTurnMessages wildChildsName
+    WitchsTurn          -> witchsTurnMessages game
+    WolfHoundsTurn      -> wolfHoundsTurnMessages wolfHoundsName
     where
         players'            = game ^. players
         defendersName       = players' ^?! defenders . name
+        devotedServantsName = players' ^?! devotedServants . name
+        victimsName         = head (getVoteResult game) ^. name
         scapegoatsName      = players' ^?! scapegoats . name
         seersName           = players' ^?! seers . name
         aliveWerewolfNames  = players' ^.. werewolves . alive . name
@@ -167,6 +174,13 @@
     , privateMessage to "Whom would you like to `protect`?"
     ]
 
+devotedServantsTurnMessages :: Text -> Text -> [Message]
+devotedServantsTurnMessages to victimsName =
+    [ publicMessage "The Devoted Servant ponders."
+    , privateMessage to $ T.concat
+        ["Would you like to `reveal` yourself and take on ", victimsName, "'s role?"]
+    ]
+
 scapegoatsTurnMessages :: Text -> [Message]
 scapegoatsTurnMessages scapegoatsName =
     [ publicMessage "Just before he burns to a complete crisp, he cries out a dying wish."
@@ -271,12 +285,14 @@
         [ [publicMessage "The game is over! The Villagers have won."]
         , [playerRolesMessage]
         , playerWonMessages
+        , playerContributedMessages
         , playerLostMessages
         ]
     | hasWerewolvesWon game = concat
         [ [publicMessage "The game is over! The Werewolves have won."]
         , [playerRolesMessage]
         , playerWonMessages
+        , playerContributedMessages
         , playerLostMessages
         ]
     | otherwise             = undefined
@@ -297,17 +313,21 @@
             | hasWerewolvesWon game = Werewolves
             | otherwise             = undefined
 
-        winningPlayerNames  = game ^.. players . traverse . filteredBy (role . allegiance) winningAllegiance . name
-        losingPlayerNames   = game ^.. players . names \\ winningPlayerNames
+        winningPlayers  = game ^.. players . traverse . filteredBy (role . allegiance) winningAllegiance
+        losingPlayers   = game ^. players \\ winningPlayers
 
-        playerWonMessages   = map playerWonMessage winningPlayerNames
-        playerLostMessages  = map playerLostMessage losingPlayerNames
+        playerWonMessages           = map playerWonMessage (winningPlayers ^.. traverse . alive . name)
+        playerContributedMessages   = map playerContributedMessage (winningPlayers ^.. traverse . dead . name)
+        playerLostMessages          = map playerLostMessage (losingPlayers ^.. names)
 
 playerWonMessage :: Text -> Message
 playerWonMessage to = privateMessage to "Victory! You won!"
 
+playerContributedMessage :: Text -> Message
+playerContributedMessage to = privateMessage to "Your team won, but you died. Congratulations?"
+
 playerLostMessage :: Text -> Message
-playerLostMessage to = privateMessage to "Feck, you lost this time round..."
+playerLostMessage to = privateMessage to "Feck, you lost this time round."
 
 playerQuitMessage :: Player -> Message
 playerQuitMessage player = publicMessage $ T.unwords [playerName, "the", playerRole, "has quit!"]
@@ -349,6 +369,7 @@
 
 currentStageMessages :: Text -> Stage -> [Message]
 currentStageMessages to GameOver    = [gameIsOverMessage to]
+currentStageMessages _ Lynching     = []
 currentStageMessages _ Sunrise      = []
 currentStageMessages _ Sunset       = []
 currentStageMessages _ UrsussGrunt  = []
@@ -357,18 +378,20 @@
     ]]
     where
         showTurn :: Stage -> Text
-        showTurn DefendersTurn  = "Defender's"
-        showTurn GameOver       = undefined
-        showTurn ScapegoatsTurn = "Scapegoat's"
-        showTurn SeersTurn      = "Seer's"
-        showTurn Sunrise        = undefined
-        showTurn Sunset         = undefined
-        showTurn UrsussGrunt    = undefined
-        showTurn VillagesTurn   = "Village's"
-        showTurn WerewolvesTurn = "Werewolves'"
-        showTurn WildChildsTurn = "Wild-child's"
-        showTurn WitchsTurn     = "Witch's"
-        showTurn WolfHoundsTurn = "Wolf-hound's"
+        showTurn DefendersTurn          = "Defender's"
+        showTurn DevotedServantsTurn    = "Devoted Servant's"
+        showTurn GameOver               = undefined
+        showTurn Lynching               = undefined
+        showTurn ScapegoatsTurn         = "Scapegoat's"
+        showTurn SeersTurn              = "Seer's"
+        showTurn Sunrise                = undefined
+        showTurn Sunset                 = undefined
+        showTurn UrsussGrunt            = undefined
+        showTurn VillagesTurn           = "village's"
+        showTurn WerewolvesTurn         = "Werewolves'"
+        showTurn WildChildsTurn         = "Wild-child's"
+        showTurn WitchsTurn             = "Witch's"
+        showTurn WolfHoundsTurn         = "Wolf-hound's"
 
 rolesInGameMessage :: Maybe Text -> [Role] -> Message
 rolesInGameMessage mTo roles = Message mTo $ T.concat
@@ -419,6 +442,25 @@
 playerCannotProtectSamePlayerTwiceInARowMessage to =
     privateMessage to "You cannot protect the same player twice in a row!"
 
+devotedServantRevealedMessage :: Text -> Message
+devotedServantRevealedMessage devotedServantsName = publicMessage $ T.unwords
+    [ devotedServantsName, " the stands up in horror."
+    , "Determined to not let their master's abilities be lost forever,"
+    , "she selflessly takes on their role."
+    ]
+
+devotedServantJoinedPackMessages :: Text -> [Text] -> [Message]
+devotedServantJoinedPackMessages devotedServantsName werewolfNames =
+    -- TODO (hjw): what if the pack's empty?
+    privateMessage devotedServantsName (T.unwords
+        [ "Upon learning your master was a Werewolf, you head towards the woods to learn more about his home and family."
+        , "As you enter you see his pack", T.intercalate ", " werewolfNames
+        , "waiting for you."
+        ])
+    : groupMessages werewolfNames (T.unwords
+        [ devotedServantsName, "heads towards the woods in search of his master's home and family."
+        ])
+
 scapegoatChoseAllowedVotersMessage :: [Text] -> Message
 scapegoatChoseAllowedVotersMessage allowedVoters = publicMessage $ T.unwords
     [ "On the next day only", T.intercalate ", " allowedVoters, "shall be allowed to vote."
@@ -512,20 +554,19 @@
 playerCannotDevourAnotherWerewolfMessage :: Text -> Message
 playerCannotDevourAnotherWerewolfMessage to = privateMessage to "You cannot devour another Werewolf!"
 
-playerJoinedPackMessage :: Text -> [Text] -> Message
-playerJoinedPackMessage to werewolfNames = privateMessage to $ T.unwords
-    [ "The death of your role model is distressing."
-    , "Without second thought you abandon the Villagers and run off into the woods,"
-    , "towards your old home."
-    , "As you arrive you see the familiar faces of", T.intercalate ", " werewolfNames
-    , "waiting and happy to have you back."
-    ]
-
-wildChildJoinedPackMessages :: [Text] -> Text -> [Message]
-wildChildJoinedPackMessages tos wildChildsName = groupMessages tos $ T.unwords
-    [ wildChildsName, "the Wild-child scampers off into the woods."
-    , "Without his role model nothing is holding back his true, wolfish, nature."
-    ]
+wildChildJoinedPackMessages :: Text -> [Text] -> [Message]
+wildChildJoinedPackMessages wildChildsName werewolfNames =
+    privateMessage wildChildsName (T.unwords
+        [ "The death of your role model is distressing."
+        , "Without second thought you abandon the Villagers and run off into the woods,"
+        , "towards your old home."
+        , "As you arrive you see the familiar faces of", T.intercalate ", " werewolfNames
+        , "waiting and happy to have you back."
+        ])
+    : groupMessages werewolfNames (T.unwords
+        [ wildChildsName, "the Wild-child scampers off into the woods."
+        , "Without his role model nothing is holding back his true, wolfish, nature."
+        ])
 
 playerCannotChooseSelfMessage :: Text -> Message
 playerCannotChooseSelfMessage to = privateMessage to "You cannot choose yourself!"
diff --git a/src/Game/Werewolf/Player.hs b/src/Game/Werewolf/Player.hs
--- a/src/Game/Werewolf/Player.hs
+++ b/src/Game/Werewolf/Player.hs
@@ -26,16 +26,16 @@
     newPlayer,
 
     -- ** Traversals
-    angel, bearTamer, defender, scapegoat, seer, simpleVillager, simpleWerewolf, villageIdiot,
-    villagerVillager, wildChild, witch, wolfHound,
+    angel, bearTamer, defender, devotedServant, scapegoat, seer, simpleVillager, simpleWerewolf,
+    villageIdiot, villagerVillager, wildChild, witch, wolfHound,
     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!
-    angels, bearTamers, defenders, scapegoats, seers, simpleVillagers, simpleWerewolves,
-    villageIdiots, villagerVillagers, wildChildren, witches, wolfHounds,
+    angels, bearTamers, defenders, devotedServants, scapegoats, seers, simpleVillagers,
+    simpleWerewolves, villageIdiots, villagerVillagers, wildChildren, witches, wolfHounds,
     villagers, werewolves,
     alive, dead,
 
@@ -99,6 +99,14 @@
 defender :: Traversal' Player ()
 defender = role . only defenderRole
 
+-- | The traversal of 'Player's with a 'devotedServantRole'.
+--
+-- @
+-- 'devotedServant' = 'role' . 'only' 'devotedServantRole'
+-- @
+devotedServant :: Traversal' Player ()
+devotedServant = role . only devotedServantRole
+
 -- | The traversal of 'Player's with a 'scapegoatRole'.
 --
 -- @
@@ -234,6 +242,14 @@
 -- @
 defenders :: Traversable t => Traversal' (t Player) Player
 defenders = traverse . filtered (is defender)
+
+-- | This 'Traversal' provides the traversal of 'devotedServant' 'Player's.
+--
+-- @
+-- 'devotedServants' = 'traverse' . 'filtered' ('is' 'devotedServant')
+-- @
+devotedServants :: Traversable t => Traversal' (t Player) Player
+devotedServants = traverse . filtered (is devotedServant)
 
 -- | This 'Traversal' provides the traversal of 'scapegoat' 'Player's.
 --
diff --git a/src/Game/Werewolf/Role.hs b/src/Game/Werewolf/Role.hs
--- a/src/Game/Werewolf/Role.hs
+++ b/src/Game/Werewolf/Role.hs
@@ -31,20 +31,32 @@
     allAllegiances,
 
     -- *** The Ambiguous
-    -- | The Ambiguous may change allegiance during the game.
-    wildChildRole, wolfHoundRole,
+    -- | They could very well be allies of the village or become its enemies. During the game, they
+    --   can change sides or characters.
+    --
+    --   The Ambiguous must aid their side to achieve victory.
+    devotedServantRole, wildChildRole, wolfHoundRole,
 
     -- *** The Loners
-    -- | The Loners have their own win condition.
+    -- | Their past could no doubt reveal to us why they hate the inhabitants of Miller's Hollow.
+    --   One thing is known for sure: they really scare everyone!
+    --
+    --   The Loners have their own objectives, no matter which side they're on.
     angelRole,
 
     -- *** The Villagers
-    -- | The Villagers must lynch all of the Werewolves.
+    -- | Attached to the village's survival, the following characters defend its harmony with
+    --   determination. Faced with various menaces, they will be brought to eliminate those they
+    --   suspect of being too dangerous, even if that might be painful to them.
+    --
+    --   The Villagers must lynch all of the Werewolves.
     bearTamerRole, defenderRole, scapegoatRole, seerRole, simpleVillagerRole, villageIdiotRole,
     villagerVillagerRole, witchRole,
 
     -- *** The Werewolves
-    -- | The Werewolves must devour all of the Villagers.
+    -- | They can be lethally dangerous and put in doubt the village's survival.
+    --
+    --   The Werewolves must devour all of the Villagers.
     simpleWerewolfRole,
 
     -- * Utility functions
@@ -94,6 +106,7 @@
     [ angelRole
     , bearTamerRole
     , defenderRole
+    , devotedServantRole
     , scapegoatRole
     , seerRole
     , simpleVillagerRole
@@ -118,6 +131,30 @@
 --   TODO (hjw): use reflection to get this list
 allAllegiances :: [Allegiance]
 allAllegiances = [Angel, Villagers, Werewolves]
+
+-- | /Who could dream of a better servant than one willing to give up her life for that of her/
+--   /masters? Don't rejoice too fast, as the devouring ambition within her could spell the end of/
+--   /the village!/
+--
+--   Before the revelation of the card of the player eliminated by the village's vote, she can
+--   reveal herself by showing her card and taking on the role of the eliminated player.
+devotedServantRole :: Role
+devotedServantRole = Role
+    { _name         = "Devoted Servant"
+    , _allegiance   = Villagers
+    , _balance      = 1
+    , _description  = T.unwords
+        [ "Who could dream of a better servant than one willing to give up her life for that of her"
+        , "masters?"
+        , "Don't rejoice too fast,"
+        , "as the devouring ambition within her could spell the end of the village!"
+        ]
+    , _advice       = T.unwords
+        [ "Think twice before trying to take on the role of a Werewolf."
+        , "If people strongly believed your master as such,"
+        , "then they will be quick to point fingers at you too!"
+        ]
+    }
 
 -- | /Abandoned in the woods by his parents at a young age, he was raised by wolves. As soon as he/
 --   /learned how to walk on all fours, the Wild-child began to wander around Miller's Hollow. One/
diff --git a/src/Game/Werewolf/Util.hs b/src/Game/Werewolf/Util.hs
--- a/src/Game/Werewolf/Util.hs
+++ b/src/Game/Werewolf/Util.hs
@@ -17,23 +17,23 @@
     -- * Game
 
     -- ** Manipulations
-    killPlayer, setPlayerAllegiance,
+    killPlayer, setPlayerAllegiance, setPlayerRole,
 
     -- ** Searches
     findPlayerBy_, getAdjacentAlivePlayers, getPassers, getPlayerVote,
     getAllowedVoters, getPendingVoters, getVoteResult,
 
     -- ** Queries
-    isDefendersTurn, isGameOver, isScapegoatsTurn, isSeersTurn, isSunrise, isVillagesTurn,
-    isWerewolvesTurn, isWildChildsTurn, isWitchsTurn, isWolfHoundsTurn,
+    isDefendersTurn, isDevotedServantsTurn, isGameOver, isScapegoatsTurn, isSeersTurn, isSunrise,
+    isVillagesTurn, isWerewolvesTurn, isWildChildsTurn, isWitchsTurn, isWolfHoundsTurn,
     hasAnyoneWon, hasAngelWon, hasVillagersWon, hasWerewolvesWon,
 
     -- * Player
 
     -- ** Queries
     doesPlayerExist,
-    isPlayerDefender, isPlayerScapegoat, isPlayerSeer, isPlayerVillageIdiot, isPlayerWildChild,
-    isPlayerWitch, isPlayerWolfHound,
+    isPlayerDefender, isPlayerDevotedServant, isPlayerScapegoat, isPlayerSeer, isPlayerVillageIdiot,
+    isPlayerWildChild, isPlayerWitch, isPlayerWolfHound,
     isPlayerWerewolf,
     isPlayerAlive, isPlayerDead,
 ) where
@@ -63,6 +63,11 @@
 setPlayerAllegiance :: MonadState Game m => Text -> Allegiance -> m ()
 setPlayerAllegiance name' allegiance' = modify $ players . traverse . filteredBy name name' . role . allegiance .~ allegiance'
 
+-- | Fudges the player's role. This function is useful for roles such as the Devoted Servant where
+--   they take on a different role.
+setPlayerRole :: MonadState Game m => Text -> Role -> m ()
+setPlayerRole name' role' = modify $ players . traverse . filteredBy name name' . role .~ role'
+
 findPlayerBy_ :: (Eq a, MonadState Game m) => Lens' Player a -> a -> m Player
 findPlayerBy_ lens value = fromJust <$> preuse (players . traverse . filteredBy lens value)
 
@@ -94,6 +99,9 @@
 isDefendersTurn :: MonadState Game m => m Bool
 isDefendersTurn = has (stage . _DefendersTurn) <$> get
 
+isDevotedServantsTurn :: MonadState Game m => m Bool
+isDevotedServantsTurn = has (stage . _DevotedServantsTurn) <$> get
+
 isGameOver :: MonadState Game m => m Bool
 isGameOver = has (stage . _GameOver) <$> get
 
@@ -138,6 +146,9 @@
 
 isPlayerDefender :: MonadState Game m => Text -> m Bool
 isPlayerDefender name' = is defender <$> findPlayerBy_ name name'
+
+isPlayerDevotedServant :: MonadState Game m => Text -> m Bool
+isPlayerDevotedServant name' = is devotedServant <$> findPlayerBy_ name name'
 
 isPlayerScapegoat :: MonadState Game m => Text -> m Bool
 isPlayerScapegoat name' = is scapegoat <$> findPlayerBy_ name name'
diff --git a/test/src/Game/Werewolf/Test/Arbitrary.hs b/test/src/Game/Werewolf/Test/Arbitrary.hs
--- a/test/src/Game/Werewolf/Test/Arbitrary.hs
+++ b/test/src/Game/Werewolf/Test/Arbitrary.hs
@@ -12,15 +12,17 @@
 
     -- ** Game
     NewGame(..),
-    GameAtDefendersTurn(..), GameAtGameOver(..), GameAtScapegoatsTurn(..), GameAtSeersTurn(..),
-    GameAtSunrise(..), GameAtVillagesTurn(..), GameAtWerewolvesTurn(..), GameAtWildChildsTurn(..),
-    GameAtWitchsTurn(..), GameAtWolfHoundsTurn(..),
+    GameAtDefendersTurn(..), GameAtDevotedServantsTurn(..), GameAtGameOver(..),
+    GameAtScapegoatsTurn(..), GameAtSeersTurn(..), GameAtSunrise(..), GameAtVillagesTurn(..),
+    GameAtWerewolvesTurn(..), GameAtWildChildsTurn(..), GameAtWitchsTurn(..),
+    GameAtWolfHoundsTurn(..),
     GameOnSecondRound(..),
-    GameWithAllegianceChosen(..), GameWithAllowedVoters(..), GameWithDeadPlayers(..),
-    GameWithDevourEvent(..), GameWithDevourVotes(..), GameWithHeal(..), GameWithLynchVotes(..),
-    GameWithOneAllegianceAlive(..), GameWithPoison(..), GameWithProtect(..),
+    GameWithAllegianceChosen(..), GameWithAllowedVoters(..), GameWithConflictingVote(..),
+    GameWithDeadPlayers(..), GameWithDevourEvent(..), GameWithDevourVotes(..), GameWithHeal(..),
+    GameWithLynchVotes(..), GameWithMajorityVote(..), GameWithOneAllegianceAlive(..),
+    GameWithPassAtDevotedServantsTurn(..), GameWithPoison(..), GameWithProtect(..),
     GameWithProtectAndDevourVotes(..), GameWithRoleModel(..), GameWithRoleModelAtVillagesTurn(..),
-    GameWithScapegoatBlamed(..), GameWithSee(..), GameWithVillageIdiotRevealedAtVillagesTurn(..),
+    GameWithSee(..), GameWithVillageIdiotRevealedAtVillagesTurn(..),
 
     -- ** Player
     arbitraryPlayerSet,
@@ -29,9 +31,10 @@
 
     -- ** Command
     arbitraryCommand, arbitraryChooseAllegianceCommand, arbitraryChoosePlayerCommand,
-    arbitraryChoosePlayersCommand, arbitraryHealCommand, arbitraryPassCommand,
-    arbitraryPoisonCommand, arbitraryProtectCommand, arbitraryQuitCommand, arbitrarySeeCommand,
-    arbitraryVoteDevourCommand, arbitraryVoteLynchCommand,
+    arbitraryChoosePlayersCommand, arbitraryHealCommand, arbitraryPassDevotedServantsTurnCommand,
+    arbitraryPassWitchsTurnCommand, arbitraryPoisonCommand, arbitraryProtectCommand,
+    arbitraryQuitCommand, arbitraryRevealCommand, arbitrarySeeCommand, arbitraryVoteDevourCommand,
+    arbitraryVoteLynchCommand,
     runArbitraryCommands,
 
     -- ** Player
@@ -96,6 +99,16 @@
 
         return $ GameAtDefendersTurn (game & stage .~ DefendersTurn)
 
+newtype GameAtDevotedServantsTurn = GameAtDevotedServantsTurn Game
+    deriving (Eq, Show)
+
+instance Arbitrary GameAtDevotedServantsTurn where
+    arbitrary = do
+        (GameWithMajorityVote game) <- suchThat arbitrary $ \(GameWithMajorityVote game) ->
+            isn't devotedServant (head $ getVoteResult game)
+
+        return $ GameAtDevotedServantsTurn (run_ checkStage game)
+
 newtype GameAtGameOver = GameAtGameOver Game
     deriving (Eq, Show)
 
@@ -110,7 +123,7 @@
 
 instance Arbitrary GameAtScapegoatsTurn where
     arbitrary = do
-        (GameWithScapegoatBlamed game) <- arbitrary
+        (GameWithConflictingVote game) <- arbitrary
 
         return $ GameAtScapegoatsTurn (run_ checkStage game)
 
@@ -206,6 +219,16 @@
 
         return $ GameWithAllowedVoters (run_ (apply command) game)
 
+newtype GameWithConflictingVote = GameWithConflictingVote Game
+    deriving (Eq, Show)
+
+instance Arbitrary GameWithConflictingVote where
+    arbitrary = do
+        (GameWithLynchVotes game) <- suchThat arbitrary $ \(GameWithLynchVotes game) ->
+            length (getVoteResult game) > 1
+
+        return $ GameWithConflictingVote game
+
 newtype GameWithDeadPlayers = GameWithDeadPlayers Game
     deriving (Eq, Show)
 
@@ -255,6 +278,25 @@
 
         GameWithLynchVotes <$> runArbitraryCommands (length $ game ^. players) (game & stage .~ VillagesTurn)
 
+newtype GameWithMajorityVote = GameWithMajorityVote Game
+    deriving (Eq, Show)
+
+instance Arbitrary GameWithMajorityVote where
+    arbitrary = do
+        (GameWithLynchVotes game) <- suchThat arbitrary $ \(GameWithLynchVotes game) ->
+            length (getVoteResult game) == 1
+
+        return $ GameWithMajorityVote game
+
+newtype GameWithMajorityVoteAtDevotedServantsTurn = GameWithMajorityVoteAtDevotedServantsTurn Game
+    deriving (Eq, Show)
+
+instance Arbitrary GameWithMajorityVoteAtDevotedServantsTurn where
+    arbitrary = do
+        (GameWithMajorityVote game) <- arbitrary
+
+        return . GameWithMajorityVoteAtDevotedServantsTurn $ run_ checkStage game
+
 newtype GameWithOneAllegianceAlive = GameWithOneAllegianceAlive Game
     deriving (Eq, Show)
 
@@ -267,16 +309,26 @@
 
         return $ GameWithOneAllegianceAlive game'
 
-newtype GameWithPass = GameWithPass Game
+newtype GameWithPassAtDevotedServantsTurn = GameWithPassAtDevotedServantsTurn Game
     deriving (Eq, Show)
 
-instance Arbitrary GameWithPass where
+instance Arbitrary GameWithPassAtDevotedServantsTurn where
     arbitrary = do
+        (GameAtDevotedServantsTurn game)    <- arbitrary
+        (Blind command)                     <- arbitraryPassDevotedServantsTurnCommand game
+
+        return $ GameWithPassAtDevotedServantsTurn (run_ (apply command) game)
+
+newtype GameWithPassAtWitchsTurn = GameWithPassAtWitchsTurn Game
+    deriving (Eq, Show)
+
+instance Arbitrary GameWithPassAtWitchsTurn where
+    arbitrary = do
         game            <- arbitrary
         let game'       = game & stage .~ WitchsTurn
-        (Blind command) <- arbitraryPassCommand game'
+        (Blind command) <- arbitraryPassWitchsTurnCommand game'
 
-        return $ GameWithPass (run_ (apply command) game')
+        return $ GameWithPassAtWitchsTurn (run_ (apply command) game')
 
 newtype GameWithPoison = GameWithPoison Game
     deriving (Eq, Show)
@@ -330,16 +382,6 @@
 
         return $ GameWithRoleModelAtVillagesTurn (game & stage .~ VillagesTurn)
 
-newtype GameWithScapegoatBlamed = GameWithScapegoatBlamed Game
-    deriving (Eq, Show)
-
-instance Arbitrary GameWithScapegoatBlamed where
-    arbitrary = do
-        (GameWithLynchVotes game) <- suchThat arbitrary $ \(GameWithLynchVotes game) ->
-            length (getVoteResult game) > 1
-
-        return $ GameWithScapegoatBlamed game
-
 newtype GameWithSee = GameWithSee Game
     deriving (Eq, Show)
 
@@ -385,22 +427,27 @@
 
 arbitraryCommand :: Game -> Gen (Blind Command)
 arbitraryCommand game = case game ^. stage of
-    GameOver        -> return $ Blind noopCommand
-    DefendersTurn   -> arbitraryProtectCommand game
-    ScapegoatsTurn  -> arbitraryChoosePlayersCommand game
-    SeersTurn       -> arbitrarySeeCommand game
-    Sunrise         -> return $ Blind noopCommand
-    Sunset          -> return $ Blind noopCommand
-    UrsussGrunt     -> return $ Blind noopCommand
-    VillagesTurn    -> arbitraryVoteLynchCommand game
-    WerewolvesTurn  -> arbitraryVoteDevourCommand game
-    WildChildsTurn  -> arbitraryChoosePlayerCommand game
-    WitchsTurn      -> oneof [
-        arbitraryHealCommand game,
-        arbitraryPassCommand game,
-        arbitraryPoisonCommand game
+    DefendersTurn       -> arbitraryProtectCommand game
+    DevotedServantsTurn -> oneof
+        [ arbitraryPassDevotedServantsTurnCommand game
+        , arbitraryRevealCommand game
         ]
-    WolfHoundsTurn  -> arbitraryChooseAllegianceCommand game
+    GameOver            -> return $ Blind noopCommand
+    Lynching            -> return $ Blind noopCommand
+    ScapegoatsTurn      -> arbitraryChoosePlayersCommand game
+    SeersTurn           -> arbitrarySeeCommand game
+    Sunrise             -> return $ Blind noopCommand
+    Sunset              -> return $ Blind noopCommand
+    UrsussGrunt         -> return $ Blind noopCommand
+    VillagesTurn        -> arbitraryVoteLynchCommand game
+    WerewolvesTurn      -> arbitraryVoteDevourCommand game
+    WildChildsTurn      -> arbitraryChoosePlayerCommand game
+    WitchsTurn          -> oneof
+        [ arbitraryHealCommand game
+        , arbitraryPassWitchsTurnCommand game
+        , arbitraryPoisonCommand game
+        ]
+    WolfHoundsTurn      -> arbitraryChooseAllegianceCommand game
 
 arbitraryChooseAllegianceCommand :: Game -> Gen (Blind Command)
 arbitraryChooseAllegianceCommand game = do
@@ -431,11 +478,17 @@
         then noopCommand
         else healCommand witchsName
 
-arbitraryPassCommand :: Game -> Gen (Blind Command)
-arbitraryPassCommand game = do
+arbitraryPassDevotedServantsTurnCommand :: Game -> Gen (Blind Command)
+arbitraryPassDevotedServantsTurnCommand game = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+
+    return . Blind $ passDevotedServantsTurnCommand devotedServantsName
+
+arbitraryPassWitchsTurnCommand :: Game -> Gen (Blind Command)
+arbitraryPassWitchsTurnCommand game = do
     let witchsName = game ^?! players . witches . name
 
-    return . Blind $ passCommand witchsName
+    return . Blind $ passWitchsTurnCommand witchsName
 
 arbitraryPoisonCommand :: Game -> Gen (Blind Command)
 arbitraryPoisonCommand game = do
@@ -464,6 +517,12 @@
         then return $ Blind noopCommand
         else elements applicableCallerNames >>= \callersName ->
             return . Blind $ quitCommand callersName
+
+arbitraryRevealCommand :: Game -> Gen (Blind Command)
+arbitraryRevealCommand game = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+
+    return . Blind $ revealCommand devotedServantsName
 
 arbitrarySeeCommand :: Game -> Gen (Blind Command)
 arbitrarySeeCommand game = do
diff --git a/test/src/Game/Werewolf/Test/Command.hs b/test/src/Game/Werewolf/Test/Command.hs
--- a/test/src/Game/Werewolf/Test/Command.hs
+++ b/test/src/Game/Werewolf/Test/Command.hs
@@ -12,873 +12,27 @@
     allCommandTests,
 ) where
 
-import Control.Lens hiding (elements, isn't)
-
-import           Data.Either.Extra
-import qualified Data.Map          as Map
-import           Data.Maybe
-import           Data.Text         (Text)
-import qualified Data.Text         as T
-
-import Game.Werewolf.Command
-import Game.Werewolf.Engine         (checkStage)
-import Game.Werewolf.Game
-import Game.Werewolf.Player
-import Game.Werewolf.Role           hiding (name)
-import Game.Werewolf.Test.Arbitrary
-import Game.Werewolf.Test.Util
+import Game.Werewolf.Test.Command.Choose
+import Game.Werewolf.Test.Command.Heal
+import Game.Werewolf.Test.Command.Pass
+import Game.Werewolf.Test.Command.Poison
+import Game.Werewolf.Test.Command.Protect
+import Game.Werewolf.Test.Command.Quit
+import Game.Werewolf.Test.Command.Reveal
+import Game.Werewolf.Test.Command.See
+import Game.Werewolf.Test.Command.Vote
 
 import Test.Tasty
-import Test.Tasty.QuickCheck
 
 allCommandTests :: [TestTree]
-allCommandTests =
-    [ testProperty "choose allegiance command errors when game is over"                 prop_chooseAllegianceCommandErrorsWhenGameIsOver
-    , testProperty "choose allegiance command errors when caller does not exist"        prop_chooseAllegianceCommandErrorsWhenCallerDoesNotExist
-    , testProperty "choose allegiance command errors when caller is dead"               prop_chooseAllegianceCommandErrorsWhenCallerIsDead
-    , testProperty "choose allegiance command errors when not wolf-hound's turn"        prop_chooseAllegianceCommandErrorsWhenNotWolfHoundsTurn
-    , testProperty "choose allegiance command errors when caller not wolf-hound"        prop_chooseAllegianceCommandErrorsWhenCallerNotWolfHound
-    , testProperty "choose allegiance command errors when allegiance does not exist"    prop_chooseAllegianceCommandErrorsWhenAllegianceDoesNotExist
-    , testProperty "choose allegiance command sets allegiance chosen"                   prop_chooseAllegianceCommandSetsAllegianceChosen
-
-    , testProperty "choose player command errors when game is over"             prop_choosePlayerCommandErrorsWhenGameIsOver
-    , testProperty "choose player command errors when caller does not exist"    prop_choosePlayerCommandErrorsWhenCallerDoesNotExist
-    , testProperty "choose player command errors when target does not exist"    prop_choosePlayerCommandErrorsWhenTargetDoesNotExist
-    , testProperty "choose player command errors when caller is dead"           prop_choosePlayerCommandErrorsWhenCallerIsDead
-    , testProperty "choose player command errors when target is dead"           prop_choosePlayerCommandErrorsWhenTargetIsDead
-    , testProperty "choose player command errors when target is caller"         prop_choosePlayerCommandErrorsWhenTargetIsCaller
-    , testProperty "choose player command errors when not wild-child's turn"    prop_choosePlayerCommandErrorsWhenNotWildChildsTurn
-    , testProperty "choose player command errors when caller not wild-child"    prop_choosePlayerCommandErrorsWhenCallerNotWildChild
-    , testProperty "choose player command sets role model"                      prop_choosePlayerCommandSetsRoleModel
-
-    , testProperty "choose players command errors when game is over"                prop_choosePlayersCommandErrorsWhenGameIsOver
-    , testProperty "choose players command errors when caller does not exist"       prop_choosePlayersCommandErrorsWhenCallerDoesNotExist
-    , testProperty "choose players command errors when any target does not exist"   prop_choosePlayersCommandErrorsWhenAnyTargetDoesNotExist
-    , testProperty "choose players command errors when any target is dead"          prop_choosePlayersCommandErrorsWhenAnyTargetIsDead
-    , testProperty "choose players command errors when not scapegoat's turn"        prop_choosePlayersCommandErrorsWhenNotScapegoatsTurn
-    , testProperty "choose players command errors when caller not scapegoat"        prop_choosePlayersCommandErrorsWhenCallerNotScapegoat
-    , testProperty "choose players command sets allowed voters"                     prop_choosePlayersCommandSetsAllowedVoters
-    , testProperty "choose players command resets scapegoat blamed"                 prop_choosePlayersCommandResetsScapegoatBlamed
-
-    , testProperty "heal command errors when game is over"          prop_healCommandErrorsWhenGameIsOver
-    , testProperty "heal command errors when caller does not exist" prop_healCommandErrorsWhenCallerDoesNotExist
-    , testProperty "heal command errors when caller is dead"        prop_healCommandErrorsWhenCallerIsDead
-    , testProperty "heal command errors when no target is devoured" prop_healCommandErrorsWhenNoTargetIsDevoured
-    , testProperty "heal command errors when not witch's turn"      prop_healCommandErrorsWhenNotWitchsTurn
-    , testProperty "heal command errors when caller has healed"     prop_healCommandErrorsWhenCallerHasHealed
-    , testProperty "heal command errors when caller not witch"      prop_healCommandErrorsWhenCallerNotWitch
-    , testProperty "heal command sets heal"                         prop_healCommandSetsHeal
-    , testProperty "heal command sets heal used"                    prop_healCommandSetsHealUsed
-
-    , testProperty "pass command errors when game is over"          prop_passCommandErrorsWhenGameIsOver
-    , testProperty "pass command errors when caller does not exist" prop_passCommandErrorsWhenCallerDoesNotExist
-    , testProperty "pass command errors when caller is dead"        prop_passCommandErrorsWhenCallerIsDead
-    , testProperty "pass command errors when not witch's turn"      prop_passCommandErrorsWhenNotWitchsTurn
-    , testProperty "pass command updates passes"                    prop_passCommandUpdatesPasses
-
-    , testProperty "poison command errors when game is over"            prop_poisonCommandErrorsWhenGameIsOver
-    , testProperty "poison command errors when caller does not exist"   prop_poisonCommandErrorsWhenCallerDoesNotExist
-    , testProperty "poison command errors when target does not exist"   prop_poisonCommandErrorsWhenTargetDoesNotExist
-    , testProperty "poison command errors when caller is dead"          prop_poisonCommandErrorsWhenCallerIsDead
-    , testProperty "poison command errors when target is dead"          prop_poisonCommandErrorsWhenTargetIsDead
-    , testProperty "poison command errors when target is devoured"      prop_poisonCommandErrorsWhenTargetIsDevoured
-    , testProperty "poison command errors when not witch's turn"        prop_poisonCommandErrorsWhenNotWitchsTurn
-    , testProperty "poison command errors when caller has poisoned"     prop_poisonCommandErrorsWhenCallerHasPoisoned
-    , testProperty "poison command errors when caller not witch"        prop_poisonCommandErrorsWhenCallerNotWitch
-    -- TODO (hjw): implement this test case
-    --, testProperty "poison command errors when caller devoured and not healed"   prop_poisonCommandErrorsWhenCallerDevouredAndNotHealed
-    , testProperty "poison command sets poison"                         prop_poisonCommandSetsPoison
-    , testProperty "poison command sets poison used"                    prop_poisonCommandSetsPoisonUsed
-
-    , testProperty "protect command errors when game is over"               prop_protectCommandErrorsWhenGameIsOver
-    , testProperty "protect command errors when caller does not exist"      prop_protectCommandErrorsWhenCallerDoesNotExist
-    , testProperty "protect command errors when target does not exist"      prop_protectCommandErrorsWhenTargetDoesNotExist
-    , testProperty "protect command errors when caller is dead"             prop_protectCommandErrorsWhenCallerIsDead
-    , testProperty "protect command errors when target is dead"             prop_protectCommandErrorsWhenTargetIsDead
-    , testProperty "protect command errors when not defender's turn"        prop_protectCommandErrorsWhenNotDefendersTurn
-    , testProperty "protect command errors when caller not defender"        prop_protectCommandErrorsWhenCallerNotDefender
-    , testProperty "protect command errors when target is prior protect"    prop_protectCommandErrorsWhenTargetIsPriorProtect
-    , testProperty "protect command sets prior protect"                     prop_protectCommandSetsPriorProtect
-    , testProperty "protect command sets protect"                           prop_protectCommandSetsProtect
-
-    , testProperty "quit command errors when game is over"                              prop_quitCommandErrorsWhenGameIsOver
-    , testProperty "quit command errors when caller does not exist"                     prop_quitCommandErrorsWhenCallerDoesNotExist
-    , testProperty "quit command errors when caller is dead"                            prop_quitCommandErrorsWhenCallerIsDead
-    , testProperty "quit command kills player"                                          prop_quitCommandKillsPlayer
-    , testProperty "quit command clears allegiance chosen when caller is wolf-hound"    prop_quitCommandClearsAllegianceChosenWhenCallerIsWolfHound
-    , testProperty "quit command clears heal when caller is witch"                      prop_quitCommandClearsHealWhenCallerIsWitch
-    , testProperty "quit command clears heal used when caller is witch"                 prop_quitCommandClearsHealUsedWhenCallerIsWitch
-    , testProperty "quit command clears poison when caller is witch"                    prop_quitCommandClearsPoisonWhenCallerIsWitch
-    , testProperty "quit command clears poison used when caller is witch"               prop_quitCommandClearsPoisonUsedWhenCallerIsWitch
-    , testProperty "quit command clears prior protect when caller is defender"          prop_quitCommandClearsPriorProtectWhenCallerIsDefender
-    , testProperty "quit command clears protect when caller is defender"                prop_quitCommandClearsProtectWhenCallerIsDefender
-    , testProperty "quit command clears player's devour vote"                           prop_quitCommandClearsPlayersDevourVote
-    , testProperty "quit command clears player's lynch vote"                            prop_quitCommandClearsPlayersLynchVote
-    , testProperty "quit command clears role model when caller is wild-child"           prop_quitCommandClearsRoleModelWhenCallerIsWildChild
-    , testProperty "quit command sets angel's allegiance when caller is angel"          prop_quitCommandSetsAngelsAllegianceWhenCallerIsAngel
-
-    , testProperty "see command errors when game is over"           prop_seeCommandErrorsWhenGameIsOver
-    , testProperty "see command errors when caller does not exist"  prop_seeCommandErrorsWhenCallerDoesNotExist
-    , testProperty "see command errors when target does not exist"  prop_seeCommandErrorsWhenTargetDoesNotExist
-    , testProperty "see command errors when caller is dead"         prop_seeCommandErrorsWhenCallerIsDead
-    , testProperty "see command errors when target is dead"         prop_seeCommandErrorsWhenTargetIsDead
-    , testProperty "see command errors when not seer's turn"        prop_seeCommandErrorsWhenNotSeersTurn
-    , testProperty "see command errors when caller not seer"        prop_seeCommandErrorsWhenCallerNotSeer
-    , testProperty "see command sets see"                           prop_seeCommandSetsSee
-
-    , testProperty "vote devour command errors when game is over"           prop_voteDevourCommandErrorsWhenGameIsOver
-    , testProperty "vote devour command errors when caller does not exist"  prop_voteDevourCommandErrorsWhenCallerDoesNotExist
-    , testProperty "vote devour command errors when target does not exist"  prop_voteDevourCommandErrorsWhenTargetDoesNotExist
-    , testProperty "vote devour command errors when caller is dead"         prop_voteDevourCommandErrorsWhenCallerIsDead
-    , testProperty "vote devour command errors when target is dead"         prop_voteDevourCommandErrorsWhenTargetIsDead
-    , testProperty "vote devour command errors when not werewolves turn"    prop_voteDevourCommandErrorsWhenNotWerewolvesTurn
-    , testProperty "vote devour command errors when caller not werewolf"    prop_voteDevourCommandErrorsWhenCallerNotWerewolf
-    , testProperty "vote devour command errors when caller has voted"       prop_voteDevourCommandErrorsWhenCallerHasVoted
-    , testProperty "vote devour command errors when target werewolf"        prop_voteDevourCommandErrorsWhenTargetWerewolf
-    , testProperty "vote devour command updates votes"                      prop_voteDevourCommandUpdatesVotes
-
-    , testProperty "vote lynch command errors when game is over"                    prop_voteLynchCommandErrorsWhenGameIsOver
-    , testProperty "vote lynch command errors when caller does not exist"           prop_voteLynchCommandErrorsWhenCallerDoesNotExist
-    , testProperty "vote lynch command errors when target does not exist"           prop_voteLynchCommandErrorsWhenTargetDoesNotExist
-    , testProperty "vote lynch command errors when caller is dead"                  prop_voteLynchCommandErrorsWhenCallerIsDead
-    , testProperty "vote lynch command errors when target is dead"                  prop_voteLynchCommandErrorsWhenTargetIsDead
-    , testProperty "vote lynch command errors when not villages turn"               prop_voteLynchCommandErrorsWhenNotVillagesTurn
-    , testProperty "vote lynch command errors when caller has voted"                prop_voteLynchCommandErrorsWhenCallerHasVoted
-    , testProperty "vote lynch command errors when caller is not in allowed voters" prop_voteLynchCommandErrorsWhenCallerIsNotInAllowedVoters
-    , testProperty "vote lynch command errors when caller is known village idiot"   prop_voteLynchCommandErrorsWhenCallerIsKnownVillageIdiot
-    , testProperty "vote lynch command updates votes"                               prop_voteLynchCommandUpdatesVotes
+allCommandTests = concat
+    [ allChooseCommandTests
+    , allHealCommandTests
+    , allPassCommandTests
+    , allPoisonCommandTests
+    , allProtectCommandTests
+    , allQuitCommandTests
+    , allRevealCommandTests
+    , allSeeCommandTests
+    , allVoteCommandTests
     ]
-
-prop_chooseAllegianceCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_chooseAllegianceCommandErrorsWhenGameIsOver (GameAtGameOver game) =
-    forAll (arbitraryChooseAllegianceCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_chooseAllegianceCommandErrorsWhenCallerDoesNotExist :: GameAtWolfHoundsTurn -> Player -> Allegiance -> Property
-prop_chooseAllegianceCommandErrorsWhenCallerDoesNotExist (GameAtWolfHoundsTurn game) caller allegiance = do
-    let command = chooseAllegianceCommand (caller ^. name) (T.pack $ show allegiance)
-
-    not (doesPlayerExist (caller ^. name) game)
-        ==> verbose_runCommandErrors game command
-
-prop_chooseAllegianceCommandErrorsWhenCallerIsDead :: GameAtWolfHoundsTurn -> Allegiance -> Property
-prop_chooseAllegianceCommandErrorsWhenCallerIsDead (GameAtWolfHoundsTurn game) allegiance = do
-    let wolfHound   = game ^?! players . wolfHounds
-    let game'       = killPlayer (wolfHound ^. name) game
-    let command     = chooseAllegianceCommand (wolfHound ^. name) (T.pack $ show allegiance)
-
-    verbose_runCommandErrors game' command
-
-prop_chooseAllegianceCommandErrorsWhenNotWolfHoundsTurn :: Game -> Property
-prop_chooseAllegianceCommandErrorsWhenNotWolfHoundsTurn game =
-    hasn't (stage . _WolfHoundsTurn) game
-    ==> forAll (arbitraryChooseAllegianceCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_chooseAllegianceCommandErrorsWhenCallerNotWolfHound :: GameAtWolfHoundsTurn -> Allegiance -> Property
-prop_chooseAllegianceCommandErrorsWhenCallerNotWolfHound (GameAtWolfHoundsTurn game) allegiance =
-    forAll (suchThat (arbitraryPlayer game) (isn't wolfHound)) $ \caller -> do
-        let command = chooseAllegianceCommand (caller ^. name) (T.pack $ show allegiance)
-
-        verbose_runCommandErrors game command
-
-prop_chooseAllegianceCommandErrorsWhenAllegianceDoesNotExist :: GameAtWolfHoundsTurn -> Text -> Property
-prop_chooseAllegianceCommandErrorsWhenAllegianceDoesNotExist (GameAtWolfHoundsTurn game) allegiance = do
-    let wolfHound   = game ^?! players . wolfHounds
-    let command     = chooseAllegianceCommand (wolfHound ^. name) allegiance
-
-    allegiance `notElem` ["Villagers", "Werewolves"]
-        ==> verbose_runCommandErrors game command
-
-prop_chooseAllegianceCommandSetsAllegianceChosen :: GameAtWolfHoundsTurn -> Property
-prop_chooseAllegianceCommandSetsAllegianceChosen (GameAtWolfHoundsTurn game) = do
-    let wolfHoundsName = game ^?! players . wolfHounds . name
-
-    forAll (elements [Villagers, Werewolves]) $ \allegiance' -> do
-        let command = chooseAllegianceCommand wolfHoundsName (T.pack $ show allegiance')
-        let game'   = run_ (apply command) game
-
-        fromJust (game' ^. allegianceChosen) === allegiance'
-
-prop_choosePlayerCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_choosePlayerCommandErrorsWhenGameIsOver (GameAtGameOver game) =
-    forAll (arbitraryChoosePlayerCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_choosePlayerCommandErrorsWhenCallerDoesNotExist :: GameAtWildChildsTurn -> Player -> Property
-prop_choosePlayerCommandErrorsWhenCallerDoesNotExist (GameAtWildChildsTurn game) caller =
-    forAll (arbitraryPlayer game) $ \target -> do
-        let command = choosePlayerCommand (caller ^. name) (target ^. name)
-
-        not (doesPlayerExist (caller ^. name) game)
-            ==> verbose_runCommandErrors game command
-
-prop_choosePlayerCommandErrorsWhenTargetDoesNotExist :: GameAtWildChildsTurn -> Player -> Property
-prop_choosePlayerCommandErrorsWhenTargetDoesNotExist (GameAtWildChildsTurn game) target = do
-    let wildChild   = game ^?! players . wildChildren
-    let command     = choosePlayerCommand (wildChild ^. name) (target ^. name)
-
-    not (doesPlayerExist (target ^. name) game)
-        ==> verbose_runCommandErrors game command
-
-prop_choosePlayerCommandErrorsWhenCallerIsDead :: GameAtWildChildsTurn -> Property
-prop_choosePlayerCommandErrorsWhenCallerIsDead (GameAtWildChildsTurn game) = do
-    let wildChild   = game ^?! players . wildChildren
-    let game'       = killPlayer (wildChild ^. name) game
-
-    forAll (arbitraryPlayer game') $ \target -> do
-        let command = choosePlayerCommand (wildChild ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_choosePlayerCommandErrorsWhenTargetIsDead :: GameAtWildChildsTurn -> Property
-prop_choosePlayerCommandErrorsWhenTargetIsDead (GameAtWildChildsTurn game) = do
-    let wildChild = game ^?! players . wildChildren
-
-    forAll (arbitraryPlayer game) $ \target -> do
-        let game'   = killPlayer (target ^. name) game
-        let command = choosePlayerCommand (wildChild ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_choosePlayerCommandErrorsWhenTargetIsCaller :: GameAtWildChildsTurn -> Property
-prop_choosePlayerCommandErrorsWhenTargetIsCaller (GameAtWildChildsTurn game) = do
-    let wildChild   = game ^?! players . wildChildren
-    let command     = choosePlayerCommand (wildChild ^. name) (wildChild ^. name)
-
-    verbose_runCommandErrors game command
-
-prop_choosePlayerCommandErrorsWhenNotWildChildsTurn :: Game -> Property
-prop_choosePlayerCommandErrorsWhenNotWildChildsTurn game =
-    hasn't (stage . _WildChildsTurn) game
-    ==> forAll (arbitraryChoosePlayerCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_choosePlayerCommandErrorsWhenCallerNotWildChild :: GameAtWildChildsTurn -> Property
-prop_choosePlayerCommandErrorsWhenCallerNotWildChild (GameAtWildChildsTurn game) =
-    forAll (suchThat (arbitraryPlayer game) (isn't wildChild)) $ \caller ->
-    forAll (arbitraryPlayer game) $ \target -> do
-        let command = choosePlayerCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_choosePlayerCommandSetsRoleModel :: GameAtWildChildsTurn -> Property
-prop_choosePlayerCommandSetsRoleModel (GameAtWildChildsTurn game) = do
-    let wildChild = game ^?! players . wildChildren
-
-    forAll (suchThat (arbitraryPlayer game) (wildChild /=)) $ \target -> do
-        let command = choosePlayerCommand (wildChild ^. name) (target ^. name)
-        let game'   = run_ (apply command) game
-
-        fromJust (game' ^. roleModel) === target ^. name
-
-prop_choosePlayersCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_choosePlayersCommandErrorsWhenGameIsOver (GameAtGameOver game) =
-    forAll (arbitraryChoosePlayersCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_choosePlayersCommandErrorsWhenCallerDoesNotExist :: GameAtScapegoatsTurn -> Player -> Property
-prop_choosePlayersCommandErrorsWhenCallerDoesNotExist (GameAtScapegoatsTurn game) caller =
-    forAll (NonEmpty <$> sublistOf (game ^.. players . traverse . alive)) $ \(NonEmpty targets) -> do
-        let command = choosePlayersCommand (caller ^. name) (targets ^.. names)
-
-        not (doesPlayerExist (caller ^. name) game)
-            ==> verbose_runCommandErrors game command
-
-prop_choosePlayersCommandErrorsWhenAnyTargetDoesNotExist :: GameAtScapegoatsTurn -> Player -> Property
-prop_choosePlayersCommandErrorsWhenAnyTargetDoesNotExist (GameAtScapegoatsTurn game) target = do
-    let scapegoat   = game ^?! players . scapegoats
-    let command     = choosePlayersCommand (scapegoat ^. name) [target ^. name]
-
-    not (doesPlayerExist (target ^. name) game)
-        ==> verbose_runCommandErrors game command
-
-prop_choosePlayersCommandErrorsWhenAnyTargetIsDead :: GameAtScapegoatsTurn -> Property
-prop_choosePlayersCommandErrorsWhenAnyTargetIsDead (GameAtScapegoatsTurn game) = do
-    let scapegoat = game ^?! players . scapegoats
-
-    forAll (NonEmpty <$> sublistOf (game ^.. players . traverse . alive)) $ \(NonEmpty targets) ->
-        forAll (elements targets) $ \target -> do
-            let game'   = killPlayer (target ^. name) game
-            let command = choosePlayersCommand (scapegoat ^. name) (targets ^.. names)
-
-            verbose_runCommandErrors game' command
-
-prop_choosePlayersCommandErrorsWhenNotScapegoatsTurn :: Game -> Property
-prop_choosePlayersCommandErrorsWhenNotScapegoatsTurn game =
-    hasn't (stage . _ScapegoatsTurn) game
-    ==> forAll (arbitraryChoosePlayersCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_choosePlayersCommandErrorsWhenCallerNotScapegoat :: GameAtScapegoatsTurn -> Property
-prop_choosePlayersCommandErrorsWhenCallerNotScapegoat (GameAtScapegoatsTurn game) =
-    forAll (suchThat (arbitraryPlayer game) (isn't scapegoat)) $ \caller ->
-    forAll (NonEmpty <$> sublistOf (game ^.. players . traverse . alive)) $ \(NonEmpty targets) -> do
-        let command = choosePlayersCommand (caller ^. name) (targets ^.. names)
-
-        verbose_runCommandErrors game command
-
-prop_choosePlayersCommandSetsAllowedVoters :: GameAtScapegoatsTurn -> Property
-prop_choosePlayersCommandSetsAllowedVoters (GameAtScapegoatsTurn game) = do
-    let scapegoat = game ^?! players . scapegoats
-
-    forAll (NonEmpty <$> sublistOf (game ^.. players . traverse . alive)) $ \(NonEmpty targets) -> do
-        let command = choosePlayersCommand (scapegoat ^. name) (targets ^.. names)
-        let game'   = run_ (apply command) game
-
-        game' ^. allowedVoters === targets ^.. names
-
-prop_choosePlayersCommandResetsScapegoatBlamed :: GameAtScapegoatsTurn -> Property
-prop_choosePlayersCommandResetsScapegoatBlamed (GameAtScapegoatsTurn game) = do
-    forAll (arbitraryChoosePlayersCommand game) $ \(Blind command) ->
-        not $ run_ (apply command) game ^. scapegoatBlamed
-
-prop_healCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_healCommandErrorsWhenGameIsOver (GameAtGameOver game) = do
-    let witch   = game ^?! players . witches
-    let command = healCommand $ witch ^. name
-
-    verbose_runCommandErrors game command
-
-prop_healCommandErrorsWhenCallerDoesNotExist :: GameWithDevourEvent -> Player -> Property
-prop_healCommandErrorsWhenCallerDoesNotExist (GameWithDevourEvent game) caller =
-    not (doesPlayerExist (caller ^. name) game)
-    ==> verbose_runCommandErrors game (healCommand (caller ^. name))
-
-prop_healCommandErrorsWhenCallerIsDead :: GameWithDevourEvent -> Property
-prop_healCommandErrorsWhenCallerIsDead (GameWithDevourEvent game) =
-    forAll (arbitraryPlayer game) $ \caller -> do
-        let game'   = killPlayer (caller ^. name) game
-        let command = healCommand (caller ^. name)
-
-        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_healCommandErrorsWhenNotWitchsTurn :: Game -> Property
-prop_healCommandErrorsWhenNotWitchsTurn game = do
-    let witch   = game ^?! players . witches
-    let command = healCommand $ witch ^. name
-
-    hasn't (stage . _WitchsTurn) game
-        ==> verbose_runCommandErrors game command
-
-prop_healCommandErrorsWhenCallerHasHealed :: GameWithHeal -> Property
-prop_healCommandErrorsWhenCallerHasHealed (GameWithHeal game) = do
-    let witch   = game ^?! players . witches
-    let command = healCommand $ witch ^. name
-
-    verbose_runCommandErrors game command
-
-prop_healCommandErrorsWhenCallerNotWitch :: GameWithDevourEvent -> Property
-prop_healCommandErrorsWhenCallerNotWitch (GameWithDevourEvent game) =
-    forAll (suchThat (arbitraryPlayer game) (isn't witch)) $ \caller -> do
-        let command = healCommand (caller ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_healCommandSetsHeal :: GameWithDevourEvent -> Property
-prop_healCommandSetsHeal (GameWithDevourEvent game) =
-    forAll (arbitraryHealCommand game) $ \(Blind command) ->
-        (run_ (apply command) game) ^. heal
-
-prop_healCommandSetsHealUsed :: GameWithDevourEvent -> Property
-prop_healCommandSetsHealUsed (GameWithDevourEvent game) =
-    forAll (arbitraryHealCommand game) $ \(Blind command) ->
-        (run_ (apply command) game) ^. healUsed
-
-prop_passCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_passCommandErrorsWhenGameIsOver (GameAtGameOver game) =
-    forAll (arbitraryPassCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_passCommandErrorsWhenCallerDoesNotExist :: GameAtWitchsTurn -> Player -> Property
-prop_passCommandErrorsWhenCallerDoesNotExist (GameAtWitchsTurn game) caller =
-    not (doesPlayerExist (caller ^. name) game)
-    ==> verbose_runCommandErrors game (passCommand (caller ^. name))
-
-prop_passCommandErrorsWhenCallerIsDead :: GameAtWitchsTurn -> Property
-prop_passCommandErrorsWhenCallerIsDead (GameAtWitchsTurn game) =
-    forAll (arbitraryPlayer game) $ \caller -> do
-        let game'   = killPlayer (caller ^. name) game
-        let command = passCommand (caller ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_passCommandErrorsWhenNotWitchsTurn :: Game -> Property
-prop_passCommandErrorsWhenNotWitchsTurn game =
-    hasn't (stage . _WitchsTurn) game
-    ==> forAll (arbitraryPassCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_passCommandUpdatesPasses :: GameAtWitchsTurn -> Property
-prop_passCommandUpdatesPasses (GameAtWitchsTurn game) =
-    forAll (arbitraryPassCommand game) $ \(Blind command) -> do
-        let game' = run_ (apply command) game
-
-        length (game' ^. passes) == 1
-
-prop_poisonCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_poisonCommandErrorsWhenGameIsOver (GameAtGameOver game) =
-    forAll (arbitraryPoisonCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_poisonCommandErrorsWhenCallerDoesNotExist :: GameAtWitchsTurn -> Player -> Property
-prop_poisonCommandErrorsWhenCallerDoesNotExist (GameAtWitchsTurn game) caller =
-    not (doesPlayerExist (caller ^. name) game)
-    ==> forAll (arbitraryPlayer game) $ \target -> do
-        let command = poisonCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_poisonCommandErrorsWhenTargetDoesNotExist :: GameAtWitchsTurn -> Player -> Property
-prop_poisonCommandErrorsWhenTargetDoesNotExist (GameAtWitchsTurn game) target = do
-    let witch   = game ^?! players . witches
-    let command = poisonCommand (witch ^. name) (target ^. name)
-
-    not (doesPlayerExist (target ^. name) game)
-        ==> verbose_runCommandErrors game command
-
-prop_poisonCommandErrorsWhenCallerIsDead :: GameAtWitchsTurn -> Property
-prop_poisonCommandErrorsWhenCallerIsDead (GameAtWitchsTurn game) = do
-    let witch = game ^?! players . witches
-
-    forAll (arbitraryPlayer game) $ \target -> do
-        let game'   = killPlayer (witch ^. name) game
-        let command = poisonCommand (witch ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_poisonCommandErrorsWhenTargetIsDead :: GameAtWitchsTurn -> Property
-prop_poisonCommandErrorsWhenTargetIsDead (GameAtWitchsTurn game) = do
-    let witch = game ^?! players . witches
-
-    forAll (arbitraryPlayer game) $ \target -> do
-        let game'   = killPlayer (target ^. name) game
-        let command = poisonCommand (witch ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_poisonCommandErrorsWhenTargetIsDevoured :: GameWithDevourEvent -> Property
-prop_poisonCommandErrorsWhenTargetIsDevoured (GameWithDevourEvent game) = do
-    let witchsName  = game ^?! players . witches . name
-    let targetName  = game ^?! events . traverse . _DevourEvent
-    let command     = poisonCommand witchsName targetName
-
-    verbose_runCommandErrors game command
-
-prop_poisonCommandErrorsWhenNotWitchsTurn :: Game -> Property
-prop_poisonCommandErrorsWhenNotWitchsTurn game =
-    hasn't (stage . _WitchsTurn) game
-    ==> forAll (arbitraryPoisonCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_poisonCommandErrorsWhenCallerHasPoisoned :: GameWithPoison -> Property
-prop_poisonCommandErrorsWhenCallerHasPoisoned (GameWithPoison game) = do
-    let witch = game ^?! players . witches
-
-    forAll (arbitraryPlayer game) $ \target -> do
-        let command = poisonCommand (witch ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_poisonCommandErrorsWhenCallerNotWitch :: GameAtWitchsTurn -> Property
-prop_poisonCommandErrorsWhenCallerNotWitch (GameAtWitchsTurn game) =
-    forAll (suchThat (arbitraryPlayer game) (isn't witch)) $ \caller ->
-    forAll (arbitraryPlayer game) $ \target -> do
-        let command = poisonCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_poisonCommandSetsPoison :: GameAtWitchsTurn -> Property
-prop_poisonCommandSetsPoison (GameAtWitchsTurn game) =
-    forAll (arbitraryPoisonCommand game) $ \(Blind command) ->
-    isJust (run_ (apply command) game ^. poison)
-
-prop_poisonCommandSetsPoisonUsed :: GameAtWitchsTurn -> Property
-prop_poisonCommandSetsPoisonUsed (GameAtWitchsTurn game) =
-    forAll (arbitraryPoisonCommand game) $ \(Blind command) ->
-    run_ (apply command) game ^. poisonUsed
-
-prop_protectCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_protectCommandErrorsWhenGameIsOver (GameAtGameOver game) =
-    forAll (arbitraryProtectCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_protectCommandErrorsWhenCallerDoesNotExist :: GameAtDefendersTurn -> Player -> Property
-prop_protectCommandErrorsWhenCallerDoesNotExist (GameAtDefendersTurn game) caller =
-    not (doesPlayerExist (caller ^. name) game)
-    ==> forAll (arbitraryPlayer game) $ \target -> do
-        let command = protectCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_protectCommandErrorsWhenTargetDoesNotExist :: GameAtDefendersTurn -> Player -> Property
-prop_protectCommandErrorsWhenTargetDoesNotExist (GameAtDefendersTurn game) target = do
-    let defender    = game ^?! players . defenders
-    let command     = protectCommand (defender ^. name) (target ^. name)
-
-    not (doesPlayerExist (target ^. name) game)
-        ==> verbose_runCommandErrors game command
-
-prop_protectCommandErrorsWhenCallerIsDead :: GameAtDefendersTurn -> Property
-prop_protectCommandErrorsWhenCallerIsDead (GameAtDefendersTurn game) = do
-    let defender    = game ^?! players . defenders
-    let game'       = killPlayer (defender ^. name) game
-
-    forAll (arbitraryPlayer game') $ \target -> do
-        let command = protectCommand (defender ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_protectCommandErrorsWhenTargetIsDead :: GameAtDefendersTurn -> Property
-prop_protectCommandErrorsWhenTargetIsDead (GameAtDefendersTurn game) = do
-    let defender = game ^?! players . defenders
-
-    forAll (arbitraryPlayer game) $ \target -> do
-        let game'   = killPlayer (target ^. name) game
-        let command = protectCommand (defender ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_protectCommandErrorsWhenNotDefendersTurn :: Game -> Property
-prop_protectCommandErrorsWhenNotDefendersTurn game =
-    hasn't (stage . _DefendersTurn) game
-    ==> forAll (arbitraryProtectCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_protectCommandErrorsWhenCallerNotDefender :: GameAtDefendersTurn -> Property
-prop_protectCommandErrorsWhenCallerNotDefender (GameAtDefendersTurn game) =
-    forAll (suchThat (arbitraryPlayer game) (isn't defender)) $ \caller ->
-    forAll (arbitraryPlayer game) $ \target -> do
-        let command = protectCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_protectCommandErrorsWhenTargetIsPriorProtect :: GameWithProtect -> Property
-prop_protectCommandErrorsWhenTargetIsPriorProtect (GameWithProtect game) = do
-    let game' = game & protect .~ Nothing
-
-    let defender    = game ^?! players . defenders
-    let command     = protectCommand (defender ^. name) (fromJust $ game' ^. priorProtect)
-
-    verbose_runCommandErrors game' command
-
-prop_protectCommandSetsPriorProtect :: GameAtDefendersTurn -> Property
-prop_protectCommandSetsPriorProtect (GameAtDefendersTurn game) =
-    forAll (arbitraryProtectCommand game) $ \(Blind command) ->
-    isJust $ run_ (apply command) game ^. priorProtect
-
-prop_protectCommandSetsProtect :: GameAtDefendersTurn -> Property
-prop_protectCommandSetsProtect (GameAtDefendersTurn game) =
-    forAll (arbitraryProtectCommand game) $ \(Blind command) ->
-    isJust $ run_ (apply command) game ^. protect
-
-prop_quitCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_quitCommandErrorsWhenGameIsOver (GameAtGameOver game) =
-    forAll (arbitraryQuitCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_quitCommandErrorsWhenCallerDoesNotExist :: Game -> Player -> Property
-prop_quitCommandErrorsWhenCallerDoesNotExist game caller =
-    not (doesPlayerExist (caller ^. name) game)
-    ==> verbose_runCommandErrors game (quitCommand $ caller ^. name)
-
-prop_quitCommandErrorsWhenCallerIsDead :: Game -> Property
-prop_quitCommandErrorsWhenCallerIsDead game =
-    forAll (arbitraryPlayer game) $ \caller -> do
-        let game'   = killPlayer (caller ^. name) game
-        let command = quitCommand $ caller ^. name
-
-        verbose_runCommandErrors game' command
-
-prop_quitCommandKillsPlayer :: Game -> Property
-prop_quitCommandKillsPlayer game =
-    hasn't (stage . _GameOver) game
-    ==> forAll (arbitraryQuitCommand game) $ \(Blind command) -> do
-        let game' = run_ (apply command) game
-
-        length (game' ^.. players . traverse . dead) == 1
-
-prop_quitCommandClearsAllegianceChosenWhenCallerIsWolfHound :: GameWithAllegianceChosen -> Bool
-prop_quitCommandClearsAllegianceChosenWhenCallerIsWolfHound (GameWithAllegianceChosen game) = do
-    let wolfHoundsName  = game ^?! players . wolfHounds . name
-    let command         = quitCommand wolfHoundsName
-
-    isNothing $ run_ (apply command) game ^. allegianceChosen
-
-prop_quitCommandClearsHealWhenCallerIsWitch :: GameWithHeal -> Bool
-prop_quitCommandClearsHealWhenCallerIsWitch (GameWithHeal game) = do
-    let witch   = game ^?! players . witches
-    let command = quitCommand (witch ^. name)
-
-    not $ run_ (apply command) game ^. heal
-
-prop_quitCommandClearsHealUsedWhenCallerIsWitch :: GameWithHeal -> Bool
-prop_quitCommandClearsHealUsedWhenCallerIsWitch (GameWithHeal game) = do
-    let witch   = game ^?! players . witches
-    let command = quitCommand (witch ^. name)
-
-    not $ run_ (apply command) game ^. healUsed
-
-prop_quitCommandClearsPoisonWhenCallerIsWitch :: GameWithPoison -> Bool
-prop_quitCommandClearsPoisonWhenCallerIsWitch (GameWithPoison game) = do
-    let witch   = game ^?! players . witches
-    let command = quitCommand (witch ^. name)
-
-    isNothing $ run_ (apply command) game ^. poison
-
-prop_quitCommandClearsPoisonUsedWhenCallerIsWitch :: GameWithPoison -> Bool
-prop_quitCommandClearsPoisonUsedWhenCallerIsWitch (GameWithPoison game) = do
-    let witch   = game ^?! players . witches
-    let command = quitCommand (witch ^. name)
-
-    not $ run_ (apply command) game ^. poisonUsed
-
-prop_quitCommandClearsPriorProtectWhenCallerIsDefender :: GameWithProtect -> Bool
-prop_quitCommandClearsPriorProtectWhenCallerIsDefender (GameWithProtect game) = do
-    let defender    = game ^?! players . defenders
-    let command     = quitCommand (defender ^. name)
-
-    isNothing $ run_ (apply command) game ^. priorProtect
-
-prop_quitCommandClearsProtectWhenCallerIsDefender :: GameWithProtect -> Bool
-prop_quitCommandClearsProtectWhenCallerIsDefender (GameWithProtect game) = do
-    let defender    = game ^?! players . defenders
-    let command     = quitCommand (defender ^. name)
-
-    isNothing $ run_ (apply command) game ^. protect
-
-prop_quitCommandClearsPlayersDevourVote :: GameWithDevourVotes -> Property
-prop_quitCommandClearsPlayersDevourVote (GameWithDevourVotes game) =
-    forAll (arbitraryWerewolf game) $ \caller -> do
-        let command = quitCommand (caller ^. name)
-
-        isNothing $ run_ (apply command) game ^. votes . at (caller ^. name)
-
-prop_quitCommandClearsPlayersLynchVote :: GameWithLynchVotes -> Property
-prop_quitCommandClearsPlayersLynchVote (GameWithLynchVotes game) =
-    forAll (arbitraryPlayer game) $ \caller -> do
-        let command = quitCommand (caller ^. name)
-
-        isNothing $ run_ (apply command) game ^. votes . at (caller ^. name)
-
-prop_quitCommandClearsRoleModelWhenCallerIsWildChild :: GameWithRoleModel -> Bool
-prop_quitCommandClearsRoleModelWhenCallerIsWildChild (GameWithRoleModel game) = do
-    let wildChild   = game ^?! players . wildChildren
-    let command     = quitCommand (wildChild ^. name)
-
-    isNothing $ run_ (apply command) game ^. roleModel
-
-prop_quitCommandSetsAngelsAllegianceWhenCallerIsAngel :: Game -> Bool
-prop_quitCommandSetsAngelsAllegianceWhenCallerIsAngel game = do
-    let angelsName  = game ^?! players . angels . name
-    let command     = quitCommand angelsName
-    let game'       = run_ (apply command) game
-
-    is villager $ game' ^?! players . angels
-
-prop_seeCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_seeCommandErrorsWhenGameIsOver (GameAtGameOver game) =
-    forAll (arbitrarySeeCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_seeCommandErrorsWhenCallerDoesNotExist :: GameAtSeersTurn -> Player -> Property
-prop_seeCommandErrorsWhenCallerDoesNotExist (GameAtSeersTurn game) caller =
-    not (doesPlayerExist (caller ^. name) game)
-    ==> forAll (arbitraryPlayer game) $ \target -> do
-        let command = seeCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_seeCommandErrorsWhenTargetDoesNotExist :: GameAtSeersTurn -> Player -> Property
-prop_seeCommandErrorsWhenTargetDoesNotExist (GameAtSeersTurn game) target = do
-    let seer    = game ^?! players . seers
-    let command = seeCommand (seer ^. name) (target ^. name)
-
-    not (doesPlayerExist (target ^. name) game)
-        ==> verbose_runCommandErrors game command
-
-prop_seeCommandErrorsWhenCallerIsDead :: GameAtSeersTurn -> Property
-prop_seeCommandErrorsWhenCallerIsDead (GameAtSeersTurn game) = do
-    let seer    = game ^?! players . seers
-    let game'   = killPlayer (seer ^. name) game
-
-    forAll (arbitraryPlayer game') $ \target -> do
-        let command = seeCommand (seer ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_seeCommandErrorsWhenTargetIsDead :: GameAtSeersTurn -> Property
-prop_seeCommandErrorsWhenTargetIsDead (GameAtSeersTurn game) = do
-    let seer = game ^?! players . seers
-
-    forAll (arbitraryPlayer game) $ \target -> do
-        let game'   = killPlayer (target ^. name) game
-        let command = seeCommand (seer ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_seeCommandErrorsWhenNotSeersTurn :: Game -> Property
-prop_seeCommandErrorsWhenNotSeersTurn game =
-    hasn't (stage . _SeersTurn) game
-    ==> forAll (arbitrarySeeCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_seeCommandErrorsWhenCallerNotSeer :: GameAtSeersTurn -> Property
-prop_seeCommandErrorsWhenCallerNotSeer (GameAtSeersTurn game) =
-    forAll (suchThat (arbitraryPlayer game) (isn't seer)) $ \caller ->
-    forAll (arbitraryPlayer game) $ \target -> do
-        let command = seeCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_seeCommandSetsSee :: GameAtSeersTurn -> Property
-prop_seeCommandSetsSee (GameAtSeersTurn game) =
-    forAll (arbitrarySeeCommand game) $ \(Blind command) ->
-    isJust $ run_ (apply command) game ^. see
-
-prop_voteDevourCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_voteDevourCommandErrorsWhenGameIsOver (GameAtGameOver game) =
-    forAll (arbitraryVoteDevourCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_voteDevourCommandErrorsWhenCallerDoesNotExist :: GameAtWerewolvesTurn -> Player -> Property
-prop_voteDevourCommandErrorsWhenCallerDoesNotExist (GameAtWerewolvesTurn game) caller =
-    not (doesPlayerExist (caller ^. name) game)
-    ==> forAll (arbitraryPlayer game) $ \target -> do
-        let command = voteDevourCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_voteDevourCommandErrorsWhenTargetDoesNotExist :: GameAtWerewolvesTurn -> Player -> Property
-prop_voteDevourCommandErrorsWhenTargetDoesNotExist (GameAtWerewolvesTurn game) target =
-    not (doesPlayerExist (target ^. name) game)
-    ==> forAll (arbitraryWerewolf game) $ \caller -> do
-        let command = voteDevourCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_voteDevourCommandErrorsWhenCallerIsDead :: GameAtWerewolvesTurn -> Property
-prop_voteDevourCommandErrorsWhenCallerIsDead (GameAtWerewolvesTurn game) =
-    forAll (arbitraryWerewolf game) $ \caller ->
-    forAll (arbitraryPlayer game) $ \target -> do
-        let game'   = killPlayer (caller ^. name) game
-        let command = voteDevourCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_voteDevourCommandErrorsWhenTargetIsDead :: GameAtWerewolvesTurn -> Property
-prop_voteDevourCommandErrorsWhenTargetIsDead (GameAtWerewolvesTurn game) =
-    forAll (arbitraryWerewolf game) $ \caller ->
-    forAll (arbitraryPlayer game) $ \target -> do
-        let game'   = killPlayer (target ^. name) game
-        let command = voteDevourCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_voteDevourCommandErrorsWhenNotWerewolvesTurn :: Game -> Property
-prop_voteDevourCommandErrorsWhenNotWerewolvesTurn game =
-    hasn't (stage . _WerewolvesTurn) game
-    ==> forAll (arbitraryVoteDevourCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_voteDevourCommandErrorsWhenCallerNotWerewolf :: GameAtWerewolvesTurn -> Property
-prop_voteDevourCommandErrorsWhenCallerNotWerewolf (GameAtWerewolvesTurn game) =
-    forAll (suchThat (arbitraryPlayer game) (isn't werewolf)) $ \caller ->
-    forAll (arbitraryPlayer game) $ \target -> do
-        let command = voteDevourCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_voteDevourCommandErrorsWhenCallerHasVoted :: GameWithDevourVotes -> Property
-prop_voteDevourCommandErrorsWhenCallerHasVoted (GameWithDevourVotes game) =
-    forAll (arbitraryWerewolf game) $ \caller ->
-    forAll (suchThat (arbitraryPlayer game) (isn't werewolf)) $ \target -> do
-        let command = voteDevourCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_voteDevourCommandErrorsWhenTargetWerewolf :: GameAtWerewolvesTurn -> Property
-prop_voteDevourCommandErrorsWhenTargetWerewolf (GameAtWerewolvesTurn game) =
-    forAll (arbitraryPlayer game) $ \caller ->
-    forAll (arbitraryWerewolf game) $ \target ->
-    verbose_runCommandErrors game (voteDevourCommand (caller ^. name) (target ^. name))
-
-prop_voteDevourCommandUpdatesVotes :: GameAtWerewolvesTurn -> Property
-prop_voteDevourCommandUpdatesVotes (GameAtWerewolvesTurn game) =
-    forAll (arbitraryVoteDevourCommand game) $ \(Blind command) -> do
-        let game' = run_ (apply command) game
-
-        Map.size (game' ^. votes) == 1
-
-prop_voteLynchCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
-prop_voteLynchCommandErrorsWhenGameIsOver (GameAtGameOver game) =
-    forAll (arbitraryVoteLynchCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_voteLynchCommandErrorsWhenCallerDoesNotExist :: GameAtVillagesTurn -> Player -> Property
-prop_voteLynchCommandErrorsWhenCallerDoesNotExist (GameAtVillagesTurn game) caller =
-    not (doesPlayerExist (caller ^. name) game)
-    ==> forAll (arbitraryPlayer game) $ \target -> do
-        let command = voteLynchCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_voteLynchCommandErrorsWhenTargetDoesNotExist :: GameAtVillagesTurn -> Player -> Property
-prop_voteLynchCommandErrorsWhenTargetDoesNotExist (GameAtVillagesTurn game) target =
-    not (doesPlayerExist (target ^. name) game)
-    ==> forAll (arbitraryPlayer game) $ \caller -> do
-        let command = voteLynchCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_voteLynchCommandErrorsWhenCallerIsDead :: GameAtVillagesTurn -> Property
-prop_voteLynchCommandErrorsWhenCallerIsDead (GameAtVillagesTurn game) =
-    forAll (arbitraryPlayer game) $ \caller ->
-    forAll (arbitraryPlayer game) $ \target -> do
-        let game'   = killPlayer (caller ^. name) game
-        let command = voteLynchCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_voteLynchCommandErrorsWhenTargetIsDead :: GameAtVillagesTurn -> Property
-prop_voteLynchCommandErrorsWhenTargetIsDead (GameAtVillagesTurn game) =
-    forAll (arbitraryPlayer game) $ \caller ->
-    forAll (arbitraryPlayer game) $ \target -> do
-        let game'   = killPlayer (target ^. name) game
-        let command = voteLynchCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-
-prop_voteLynchCommandErrorsWhenNotVillagesTurn :: Game -> Property
-prop_voteLynchCommandErrorsWhenNotVillagesTurn game =
-    hasn't (stage . _VillagesTurn) game
-    ==> forAll (arbitraryVoteLynchCommand game) $ verbose_runCommandErrors game . getBlind
-
-prop_voteLynchCommandErrorsWhenCallerHasVoted :: GameWithLynchVotes -> Property
-prop_voteLynchCommandErrorsWhenCallerHasVoted (GameWithLynchVotes game) =
-    forAll (arbitraryPlayer game) $ \caller ->
-    forAll (arbitraryPlayer game) $ \target -> do
-        let command = voteLynchCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-
-prop_voteLynchCommandErrorsWhenCallerIsNotInAllowedVoters :: GameWithAllowedVoters -> Property
-prop_voteLynchCommandErrorsWhenCallerIsNotInAllowedVoters (GameWithAllowedVoters game) =
-    forAll (suchThat (arbitraryPlayer game') (`notElem` getAllowedVoters game')) $ \caller ->
-    forAll (arbitraryPlayer game') $ \target -> do
-        let command = voteLynchCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game' command
-    where
-        game' = run_ checkStage game
-
-prop_voteLynchCommandErrorsWhenCallerIsKnownVillageIdiot :: GameWithVillageIdiotRevealedAtVillagesTurn -> Property
-prop_voteLynchCommandErrorsWhenCallerIsKnownVillageIdiot (GameWithVillageIdiotRevealedAtVillagesTurn game) =
-    forAll (arbitraryPlayer game) $ \target -> do
-        let command = voteLynchCommand (caller ^. name) (target ^. name)
-
-        verbose_runCommandErrors game command
-    where
-        caller = game ^?! players . villageIdiots
-
-prop_voteLynchCommandUpdatesVotes :: GameAtVillagesTurn -> Property
-prop_voteLynchCommandUpdatesVotes (GameAtVillagesTurn game) =
-    forAll (arbitraryVoteLynchCommand game) $ \(Blind command) -> do
-        let game' = run_ (apply command) game
-
-        Map.size (game' ^. votes) == 1
-
-verbose_runCommandErrors :: Game -> Command -> Property
-verbose_runCommandErrors game command = whenFail (mapM_ putStrLn data_) (isLeft result)
-    where
-        result  = run (apply command) game
-        data_   = [show game, show $ fromRight result]
diff --git a/test/src/Game/Werewolf/Test/Command/Choose.hs b/test/src/Game/Werewolf/Test/Command/Choose.hs
new file mode 100644
--- /dev/null
+++ b/test/src/Game/Werewolf/Test/Command/Choose.hs
@@ -0,0 +1,237 @@
+{-|
+Module      : Game.Werewolf.Test.Command.Choose
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Game.Werewolf.Test.Command.Choose (
+    -- * Tests
+    allChooseCommandTests,
+) where
+
+import Control.Lens hiding (elements, isn't)
+
+import           Data.Maybe
+import           Data.Text  (Text)
+import qualified Data.Text  as T
+
+import Game.Werewolf.Command
+import Game.Werewolf.Game
+import Game.Werewolf.Player
+import Game.Werewolf.Role           hiding (name)
+import Game.Werewolf.Test.Arbitrary
+import Game.Werewolf.Test.Util
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+allChooseCommandTests :: [TestTree]
+allChooseCommandTests =
+    [ testProperty "choose allegiance command errors when game is over"                 prop_chooseAllegianceCommandErrorsWhenGameIsOver
+    , testProperty "choose allegiance command errors when caller does not exist"        prop_chooseAllegianceCommandErrorsWhenCallerDoesNotExist
+    , testProperty "choose allegiance command errors when caller is dead"               prop_chooseAllegianceCommandErrorsWhenCallerIsDead
+    , testProperty "choose allegiance command errors when not wolf-hound's turn"        prop_chooseAllegianceCommandErrorsWhenNotWolfHoundsTurn
+    , testProperty "choose allegiance command errors when caller not wolf-hound"        prop_chooseAllegianceCommandErrorsWhenCallerNotWolfHound
+    , testProperty "choose allegiance command errors when allegiance does not exist"    prop_chooseAllegianceCommandErrorsWhenAllegianceDoesNotExist
+    , testProperty "choose allegiance command sets allegiance chosen"                   prop_chooseAllegianceCommandSetsAllegianceChosen
+
+    , testProperty "choose player command errors when game is over"             prop_choosePlayerCommandErrorsWhenGameIsOver
+    , testProperty "choose player command errors when caller does not exist"    prop_choosePlayerCommandErrorsWhenCallerDoesNotExist
+    , testProperty "choose player command errors when target does not exist"    prop_choosePlayerCommandErrorsWhenTargetDoesNotExist
+    , testProperty "choose player command errors when caller is dead"           prop_choosePlayerCommandErrorsWhenCallerIsDead
+    , testProperty "choose player command errors when target is dead"           prop_choosePlayerCommandErrorsWhenTargetIsDead
+    , testProperty "choose player command errors when target is caller"         prop_choosePlayerCommandErrorsWhenTargetIsCaller
+    , testProperty "choose player command errors when not wild-child's turn"    prop_choosePlayerCommandErrorsWhenNotWildChildsTurn
+    , testProperty "choose player command errors when caller not wild-child"    prop_choosePlayerCommandErrorsWhenCallerNotWildChild
+    , testProperty "choose player command sets role model"                      prop_choosePlayerCommandSetsRoleModel
+
+    , testProperty "choose players command errors when game is over"                prop_choosePlayersCommandErrorsWhenGameIsOver
+    , testProperty "choose players command errors when caller does not exist"       prop_choosePlayersCommandErrorsWhenCallerDoesNotExist
+    , testProperty "choose players command errors when any target does not exist"   prop_choosePlayersCommandErrorsWhenAnyTargetDoesNotExist
+    , testProperty "choose players command errors when any target is dead"          prop_choosePlayersCommandErrorsWhenAnyTargetIsDead
+    , testProperty "choose players command errors when not scapegoat's turn"        prop_choosePlayersCommandErrorsWhenNotScapegoatsTurn
+    , testProperty "choose players command errors when caller not scapegoat"        prop_choosePlayersCommandErrorsWhenCallerNotScapegoat
+    , testProperty "choose players command sets allowed voters"                     prop_choosePlayersCommandSetsAllowedVoters
+    , testProperty "choose players command resets scapegoat blamed"                 prop_choosePlayersCommandResetsScapegoatBlamed
+    ]
+
+prop_chooseAllegianceCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_chooseAllegianceCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryChooseAllegianceCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_chooseAllegianceCommandErrorsWhenCallerDoesNotExist :: GameAtWolfHoundsTurn -> Player -> Allegiance -> Property
+prop_chooseAllegianceCommandErrorsWhenCallerDoesNotExist (GameAtWolfHoundsTurn game) caller allegiance = do
+    let command = chooseAllegianceCommand (caller ^. name) (T.pack $ show allegiance)
+
+    not (doesPlayerExist (caller ^. name) game)
+        ==> verbose_runCommandErrors game command
+
+prop_chooseAllegianceCommandErrorsWhenCallerIsDead :: GameAtWolfHoundsTurn -> Allegiance -> Property
+prop_chooseAllegianceCommandErrorsWhenCallerIsDead (GameAtWolfHoundsTurn game) allegiance = do
+    let wolfHound   = game ^?! players . wolfHounds
+    let game'       = killPlayer (wolfHound ^. name) game
+    let command     = chooseAllegianceCommand (wolfHound ^. name) (T.pack $ show allegiance)
+
+    verbose_runCommandErrors game' command
+
+prop_chooseAllegianceCommandErrorsWhenNotWolfHoundsTurn :: Game -> Property
+prop_chooseAllegianceCommandErrorsWhenNotWolfHoundsTurn game =
+    hasn't (stage . _WolfHoundsTurn) game
+    ==> forAll (arbitraryChooseAllegianceCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_chooseAllegianceCommandErrorsWhenCallerNotWolfHound :: GameAtWolfHoundsTurn -> Allegiance -> Property
+prop_chooseAllegianceCommandErrorsWhenCallerNotWolfHound (GameAtWolfHoundsTurn game) allegiance =
+    forAll (suchThat (arbitraryPlayer game) (isn't wolfHound)) $ \caller -> do
+        let command = chooseAllegianceCommand (caller ^. name) (T.pack $ show allegiance)
+
+        verbose_runCommandErrors game command
+
+prop_chooseAllegianceCommandErrorsWhenAllegianceDoesNotExist :: GameAtWolfHoundsTurn -> Text -> Property
+prop_chooseAllegianceCommandErrorsWhenAllegianceDoesNotExist (GameAtWolfHoundsTurn game) allegiance = do
+    let wolfHound   = game ^?! players . wolfHounds
+    let command     = chooseAllegianceCommand (wolfHound ^. name) allegiance
+
+    allegiance `notElem` ["Villagers", "Werewolves"]
+        ==> verbose_runCommandErrors game command
+
+prop_chooseAllegianceCommandSetsAllegianceChosen :: GameAtWolfHoundsTurn -> Property
+prop_chooseAllegianceCommandSetsAllegianceChosen (GameAtWolfHoundsTurn game) = do
+    let wolfHoundsName = game ^?! players . wolfHounds . name
+
+    forAll (elements [Villagers, Werewolves]) $ \allegiance' -> do
+        let command = chooseAllegianceCommand wolfHoundsName (T.pack $ show allegiance')
+        let game'   = run_ (apply command) game
+
+        fromJust (game' ^. allegianceChosen) === allegiance'
+
+prop_choosePlayerCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_choosePlayerCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryChoosePlayerCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_choosePlayerCommandErrorsWhenCallerDoesNotExist :: GameAtWildChildsTurn -> Player -> Property
+prop_choosePlayerCommandErrorsWhenCallerDoesNotExist (GameAtWildChildsTurn game) caller =
+    forAll (arbitraryPlayer game) $ \target -> do
+        let command = choosePlayerCommand (caller ^. name) (target ^. name)
+
+        not (doesPlayerExist (caller ^. name) game)
+            ==> verbose_runCommandErrors game command
+
+prop_choosePlayerCommandErrorsWhenTargetDoesNotExist :: GameAtWildChildsTurn -> Player -> Property
+prop_choosePlayerCommandErrorsWhenTargetDoesNotExist (GameAtWildChildsTurn game) target = do
+    let wildChild   = game ^?! players . wildChildren
+    let command     = choosePlayerCommand (wildChild ^. name) (target ^. name)
+
+    not (doesPlayerExist (target ^. name) game)
+        ==> verbose_runCommandErrors game command
+
+prop_choosePlayerCommandErrorsWhenCallerIsDead :: GameAtWildChildsTurn -> Property
+prop_choosePlayerCommandErrorsWhenCallerIsDead (GameAtWildChildsTurn game) = do
+    let wildChild   = game ^?! players . wildChildren
+    let game'       = killPlayer (wildChild ^. name) game
+
+    forAll (arbitraryPlayer game') $ \target -> do
+        let command = choosePlayerCommand (wildChild ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_choosePlayerCommandErrorsWhenTargetIsDead :: GameAtWildChildsTurn -> Property
+prop_choosePlayerCommandErrorsWhenTargetIsDead (GameAtWildChildsTurn game) = do
+    let wildChild = game ^?! players . wildChildren
+
+    forAll (arbitraryPlayer game) $ \target -> do
+        let game'   = killPlayer (target ^. name) game
+        let command = choosePlayerCommand (wildChild ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_choosePlayerCommandErrorsWhenTargetIsCaller :: GameAtWildChildsTurn -> Property
+prop_choosePlayerCommandErrorsWhenTargetIsCaller (GameAtWildChildsTurn game) = do
+    let wildChild   = game ^?! players . wildChildren
+    let command     = choosePlayerCommand (wildChild ^. name) (wildChild ^. name)
+
+    verbose_runCommandErrors game command
+
+prop_choosePlayerCommandErrorsWhenNotWildChildsTurn :: Game -> Property
+prop_choosePlayerCommandErrorsWhenNotWildChildsTurn game =
+    hasn't (stage . _WildChildsTurn) game
+    ==> forAll (arbitraryChoosePlayerCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_choosePlayerCommandErrorsWhenCallerNotWildChild :: GameAtWildChildsTurn -> Property
+prop_choosePlayerCommandErrorsWhenCallerNotWildChild (GameAtWildChildsTurn game) =
+    forAll (suchThat (arbitraryPlayer game) (isn't wildChild)) $ \caller ->
+    forAll (arbitraryPlayer game) $ \target -> do
+        let command = choosePlayerCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_choosePlayerCommandSetsRoleModel :: GameAtWildChildsTurn -> Property
+prop_choosePlayerCommandSetsRoleModel (GameAtWildChildsTurn game) = do
+    let wildChild = game ^?! players . wildChildren
+
+    forAll (suchThat (arbitraryPlayer game) (wildChild /=)) $ \target -> do
+        let command = choosePlayerCommand (wildChild ^. name) (target ^. name)
+        let game'   = run_ (apply command) game
+
+        fromJust (game' ^. roleModel) === target ^. name
+
+prop_choosePlayersCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_choosePlayersCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryChoosePlayersCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_choosePlayersCommandErrorsWhenCallerDoesNotExist :: GameAtScapegoatsTurn -> Player -> Property
+prop_choosePlayersCommandErrorsWhenCallerDoesNotExist (GameAtScapegoatsTurn game) caller =
+    forAll (NonEmpty <$> sublistOf (game ^.. players . traverse . alive)) $ \(NonEmpty targets) -> do
+        let command = choosePlayersCommand (caller ^. name) (targets ^.. names)
+
+        not (doesPlayerExist (caller ^. name) game)
+            ==> verbose_runCommandErrors game command
+
+prop_choosePlayersCommandErrorsWhenAnyTargetDoesNotExist :: GameAtScapegoatsTurn -> Player -> Property
+prop_choosePlayersCommandErrorsWhenAnyTargetDoesNotExist (GameAtScapegoatsTurn game) target = do
+    let scapegoat   = game ^?! players . scapegoats
+    let command     = choosePlayersCommand (scapegoat ^. name) [target ^. name]
+
+    not (doesPlayerExist (target ^. name) game)
+        ==> verbose_runCommandErrors game command
+
+prop_choosePlayersCommandErrorsWhenAnyTargetIsDead :: GameAtScapegoatsTurn -> Property
+prop_choosePlayersCommandErrorsWhenAnyTargetIsDead (GameAtScapegoatsTurn game) = do
+    let scapegoat = game ^?! players . scapegoats
+
+    forAll (NonEmpty <$> sublistOf (game ^.. players . traverse . alive)) $ \(NonEmpty targets) ->
+        forAll (elements targets) $ \target -> do
+            let game'   = killPlayer (target ^. name) game
+            let command = choosePlayersCommand (scapegoat ^. name) (targets ^.. names)
+
+            verbose_runCommandErrors game' command
+
+prop_choosePlayersCommandErrorsWhenNotScapegoatsTurn :: Game -> Property
+prop_choosePlayersCommandErrorsWhenNotScapegoatsTurn game =
+    hasn't (stage . _ScapegoatsTurn) game
+    ==> forAll (arbitraryChoosePlayersCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_choosePlayersCommandErrorsWhenCallerNotScapegoat :: GameAtScapegoatsTurn -> Property
+prop_choosePlayersCommandErrorsWhenCallerNotScapegoat (GameAtScapegoatsTurn game) =
+    forAll (suchThat (arbitraryPlayer game) (isn't scapegoat)) $ \caller ->
+    forAll (NonEmpty <$> sublistOf (game ^.. players . traverse . alive)) $ \(NonEmpty targets) -> do
+        let command = choosePlayersCommand (caller ^. name) (targets ^.. names)
+
+        verbose_runCommandErrors game command
+
+prop_choosePlayersCommandSetsAllowedVoters :: GameAtScapegoatsTurn -> Property
+prop_choosePlayersCommandSetsAllowedVoters (GameAtScapegoatsTurn game) = do
+    let scapegoat = game ^?! players . scapegoats
+
+    forAll (NonEmpty <$> sublistOf (game ^.. players . traverse . alive)) $ \(NonEmpty targets) -> do
+        let command = choosePlayersCommand (scapegoat ^. name) (targets ^.. names)
+        let game'   = run_ (apply command) game
+
+        game' ^. allowedVoters === targets ^.. names
+
+prop_choosePlayersCommandResetsScapegoatBlamed :: GameAtScapegoatsTurn -> Property
+prop_choosePlayersCommandResetsScapegoatBlamed (GameAtScapegoatsTurn game) = do
+    forAll (arbitraryChoosePlayersCommand game) $ \(Blind command) ->
+        not $ run_ (apply command) game ^. scapegoatBlamed
diff --git a/test/src/Game/Werewolf/Test/Command/Heal.hs b/test/src/Game/Werewolf/Test/Command/Heal.hs
new file mode 100644
--- /dev/null
+++ b/test/src/Game/Werewolf/Test/Command/Heal.hs
@@ -0,0 +1,96 @@
+{-|
+Module      : Game.Werewolf.Test.Command.Heal
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Game.Werewolf.Test.Command.Heal (
+    -- * Tests
+    allHealCommandTests,
+) where
+
+import Control.Lens hiding (elements, isn't)
+
+import Game.Werewolf.Command
+import Game.Werewolf.Game
+import Game.Werewolf.Player
+import Game.Werewolf.Test.Arbitrary
+import Game.Werewolf.Test.Util
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+allHealCommandTests :: [TestTree]
+allHealCommandTests =
+    [ testProperty "heal command errors when game is over"          prop_healCommandErrorsWhenGameIsOver
+    , testProperty "heal command errors when caller does not exist" prop_healCommandErrorsWhenCallerDoesNotExist
+    , testProperty "heal command errors when caller is dead"        prop_healCommandErrorsWhenCallerIsDead
+    , testProperty "heal command errors when no target is devoured" prop_healCommandErrorsWhenNoTargetIsDevoured
+    , testProperty "heal command errors when not witch's turn"      prop_healCommandErrorsWhenNotWitchsTurn
+    , testProperty "heal command errors when caller has healed"     prop_healCommandErrorsWhenCallerHasHealed
+    , testProperty "heal command errors when caller not witch"      prop_healCommandErrorsWhenCallerNotWitch
+    , testProperty "heal command sets heal"                         prop_healCommandSetsHeal
+    , testProperty "heal command sets heal used"                    prop_healCommandSetsHealUsed
+    ]
+
+prop_healCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_healCommandErrorsWhenGameIsOver (GameAtGameOver game) = do
+    let witch   = game ^?! players . witches
+    let command = healCommand $ witch ^. name
+
+    verbose_runCommandErrors game command
+
+prop_healCommandErrorsWhenCallerDoesNotExist :: GameWithDevourEvent -> Player -> Property
+prop_healCommandErrorsWhenCallerDoesNotExist (GameWithDevourEvent game) caller =
+    not (doesPlayerExist (caller ^. name) game)
+    ==> verbose_runCommandErrors game (healCommand (caller ^. name))
+
+prop_healCommandErrorsWhenCallerIsDead :: GameWithDevourEvent -> Property
+prop_healCommandErrorsWhenCallerIsDead (GameWithDevourEvent game) =
+    forAll (arbitraryPlayer game) $ \caller -> do
+        let game'   = killPlayer (caller ^. name) game
+        let command = healCommand (caller ^. name)
+
+        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_healCommandErrorsWhenNotWitchsTurn :: Game -> Property
+prop_healCommandErrorsWhenNotWitchsTurn game = do
+    let witch   = game ^?! players . witches
+    let command = healCommand $ witch ^. name
+
+    hasn't (stage . _WitchsTurn) game
+        ==> verbose_runCommandErrors game command
+
+prop_healCommandErrorsWhenCallerHasHealed :: GameWithHeal -> Property
+prop_healCommandErrorsWhenCallerHasHealed (GameWithHeal game) = do
+    let witch   = game ^?! players . witches
+    let command = healCommand $ witch ^. name
+
+    verbose_runCommandErrors game command
+
+prop_healCommandErrorsWhenCallerNotWitch :: GameWithDevourEvent -> Property
+prop_healCommandErrorsWhenCallerNotWitch (GameWithDevourEvent game) =
+    forAll (suchThat (arbitraryPlayer game) (isn't witch)) $ \caller -> do
+        let command = healCommand (caller ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_healCommandSetsHeal :: GameWithDevourEvent -> Property
+prop_healCommandSetsHeal (GameWithDevourEvent game) =
+    forAll (arbitraryHealCommand game) $ \(Blind command) ->
+        (run_ (apply command) game) ^. heal
+
+prop_healCommandSetsHealUsed :: GameWithDevourEvent -> Property
+prop_healCommandSetsHealUsed (GameWithDevourEvent game) =
+    forAll (arbitraryHealCommand game) $ \(Blind command) ->
+        (run_ (apply command) game) ^. healUsed
diff --git a/test/src/Game/Werewolf/Test/Command/Pass.hs b/test/src/Game/Werewolf/Test/Command/Pass.hs
new file mode 100644
--- /dev/null
+++ b/test/src/Game/Werewolf/Test/Command/Pass.hs
@@ -0,0 +1,97 @@
+{-|
+Module      : Game.Werewolf.Test.Command.Pass
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Game.Werewolf.Test.Command.Pass (
+    -- * Tests
+    allPassCommandTests,
+) where
+
+import Control.Lens hiding (elements, isn't)
+
+import Game.Werewolf.Command
+import Game.Werewolf.Game
+import Game.Werewolf.Player
+import Game.Werewolf.Test.Arbitrary
+import Game.Werewolf.Test.Util
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+allPassCommandTests :: [TestTree]
+allPassCommandTests =
+    [ testProperty "pass devoted servant's turn command errors when game is over"               prop_passDevotedServantsTurnCommandErrorsWhenGameIsOver
+    , testProperty "pass devoted servant's turn command errors when caller does not exist"      prop_passDevotedServantsTurnCommandErrorsWhenCallerDoesNotExist
+    , testProperty "pass devoted servant's turn command errors when caller is dead"             prop_passDevotedServantsTurnCommandErrorsWhenCallerIsDead
+    , testProperty "pass devoted servant's turn command errors when not devoted servant's turn" prop_passDevotedServantsTurnCommandErrorsWhenNotDevotedServantsTurn
+    , testProperty "pass devoted servant's turn command updates passes"                         prop_passDevotedServantsTurnCommandUpdatesPasses
+
+    , testProperty "pass witch's turn command errors when game is over"             prop_passWitchsTurnCommandErrorsWhenGameIsOver
+    , testProperty "pass witch's turn command errors when caller does not exist"    prop_passWitchsTurnCommandErrorsWhenCallerDoesNotExist
+    , testProperty "pass witch's turn command errors when caller is dead"           prop_passWitchsTurnCommandErrorsWhenCallerIsDead
+    , testProperty "pass witch's turn command errors when not witch's turn"         prop_passWitchsTurnCommandErrorsWhenNotWitchsTurn
+    , testProperty "pass witch's turn command updates passes"                       prop_passWitchsTurnCommandUpdatesPasses
+    ]
+
+prop_passDevotedServantsTurnCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_passDevotedServantsTurnCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryPassDevotedServantsTurnCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_passDevotedServantsTurnCommandErrorsWhenCallerDoesNotExist :: GameAtDevotedServantsTurn -> Player -> Property
+prop_passDevotedServantsTurnCommandErrorsWhenCallerDoesNotExist (GameAtDevotedServantsTurn game) caller =
+    not (doesPlayerExist (caller ^. name) game)
+    ==> verbose_runCommandErrors game (passDevotedServantsTurnCommand (caller ^. name))
+
+prop_passDevotedServantsTurnCommandErrorsWhenCallerIsDead :: GameAtDevotedServantsTurn -> Property
+prop_passDevotedServantsTurnCommandErrorsWhenCallerIsDead (GameAtDevotedServantsTurn game) = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+    let game'               = killPlayer devotedServantsName game
+    let command             = passDevotedServantsTurnCommand devotedServantsName
+
+    verbose_runCommandErrors game' command
+
+prop_passDevotedServantsTurnCommandErrorsWhenNotDevotedServantsTurn :: Game -> Property
+prop_passDevotedServantsTurnCommandErrorsWhenNotDevotedServantsTurn game =
+    hasn't (stage . _DevotedServantsTurn) game
+    ==> forAll (arbitraryPassDevotedServantsTurnCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_passDevotedServantsTurnCommandUpdatesPasses :: GameAtDevotedServantsTurn -> Property
+prop_passDevotedServantsTurnCommandUpdatesPasses (GameAtDevotedServantsTurn game) =
+    forAll (arbitraryPassDevotedServantsTurnCommand game) $ \(Blind command) -> do
+        let game' = run_ (apply command) game
+
+        length (game' ^. passes) == 1
+
+prop_passWitchsTurnCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_passWitchsTurnCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryPassWitchsTurnCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_passWitchsTurnCommandErrorsWhenCallerDoesNotExist :: GameAtWitchsTurn -> Player -> Property
+prop_passWitchsTurnCommandErrorsWhenCallerDoesNotExist (GameAtWitchsTurn game) caller =
+    not (doesPlayerExist (caller ^. name) game)
+    ==> verbose_runCommandErrors game (passWitchsTurnCommand (caller ^. name))
+
+prop_passWitchsTurnCommandErrorsWhenCallerIsDead :: GameAtWitchsTurn -> Property
+prop_passWitchsTurnCommandErrorsWhenCallerIsDead (GameAtWitchsTurn game) = do
+    let witchsName  = game ^?! players . witches . name
+    let game'       = killPlayer witchsName game
+    let command     = passWitchsTurnCommand witchsName
+
+    verbose_runCommandErrors game' command
+
+prop_passWitchsTurnCommandErrorsWhenNotWitchsTurn :: Game -> Property
+prop_passWitchsTurnCommandErrorsWhenNotWitchsTurn game =
+    hasn't (stage . _WitchsTurn) game
+    ==> forAll (arbitraryPassWitchsTurnCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_passWitchsTurnCommandUpdatesPasses :: GameAtWitchsTurn -> Property
+prop_passWitchsTurnCommandUpdatesPasses (GameAtWitchsTurn game) =
+    forAll (arbitraryPassWitchsTurnCommand game) $ \(Blind command) -> do
+        let game' = run_ (apply command) game
+
+        length (game' ^. passes) == 1
diff --git a/test/src/Game/Werewolf/Test/Command/Poison.hs b/test/src/Game/Werewolf/Test/Command/Poison.hs
new file mode 100644
--- /dev/null
+++ b/test/src/Game/Werewolf/Test/Command/Poison.hs
@@ -0,0 +1,121 @@
+{-|
+Module      : Game.Werewolf.Test.Command.Poison
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Game.Werewolf.Test.Command.Poison (
+    -- * Tests
+    allPoisonCommandTests,
+) where
+
+import Control.Lens hiding (elements, isn't)
+
+import Data.Maybe
+
+import Game.Werewolf.Command
+import Game.Werewolf.Game
+import Game.Werewolf.Player
+import Game.Werewolf.Test.Arbitrary
+import Game.Werewolf.Test.Util
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+allPoisonCommandTests :: [TestTree]
+allPoisonCommandTests =
+    [ testProperty "poison command errors when game is over"            prop_poisonCommandErrorsWhenGameIsOver
+    , testProperty "poison command errors when caller does not exist"   prop_poisonCommandErrorsWhenCallerDoesNotExist
+    , testProperty "poison command errors when target does not exist"   prop_poisonCommandErrorsWhenTargetDoesNotExist
+    , testProperty "poison command errors when caller is dead"          prop_poisonCommandErrorsWhenCallerIsDead
+    , testProperty "poison command errors when target is dead"          prop_poisonCommandErrorsWhenTargetIsDead
+    , testProperty "poison command errors when target is devoured"      prop_poisonCommandErrorsWhenTargetIsDevoured
+    , testProperty "poison command errors when not witch's turn"        prop_poisonCommandErrorsWhenNotWitchsTurn
+    , testProperty "poison command errors when caller has poisoned"     prop_poisonCommandErrorsWhenCallerHasPoisoned
+    , testProperty "poison command errors when caller not witch"        prop_poisonCommandErrorsWhenCallerNotWitch
+    , testProperty "poison command sets poison"                         prop_poisonCommandSetsPoison
+    , testProperty "poison command sets poison used"                    prop_poisonCommandSetsPoisonUsed
+    ]
+
+prop_poisonCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_poisonCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryPoisonCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_poisonCommandErrorsWhenCallerDoesNotExist :: GameAtWitchsTurn -> Player -> Property
+prop_poisonCommandErrorsWhenCallerDoesNotExist (GameAtWitchsTurn game) caller =
+    not (doesPlayerExist (caller ^. name) game)
+    ==> forAll (arbitraryPlayer game) $ \target -> do
+        let command = poisonCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_poisonCommandErrorsWhenTargetDoesNotExist :: GameAtWitchsTurn -> Player -> Property
+prop_poisonCommandErrorsWhenTargetDoesNotExist (GameAtWitchsTurn game) target = do
+    let witch   = game ^?! players . witches
+    let command = poisonCommand (witch ^. name) (target ^. name)
+
+    not (doesPlayerExist (target ^. name) game)
+        ==> verbose_runCommandErrors game command
+
+prop_poisonCommandErrorsWhenCallerIsDead :: GameAtWitchsTurn -> Property
+prop_poisonCommandErrorsWhenCallerIsDead (GameAtWitchsTurn game) = do
+    let witch = game ^?! players . witches
+
+    forAll (arbitraryPlayer game) $ \target -> do
+        let game'   = killPlayer (witch ^. name) game
+        let command = poisonCommand (witch ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_poisonCommandErrorsWhenTargetIsDead :: GameAtWitchsTurn -> Property
+prop_poisonCommandErrorsWhenTargetIsDead (GameAtWitchsTurn game) = do
+    let witch = game ^?! players . witches
+
+    forAll (arbitraryPlayer game) $ \target -> do
+        let game'   = killPlayer (target ^. name) game
+        let command = poisonCommand (witch ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_poisonCommandErrorsWhenTargetIsDevoured :: GameWithDevourEvent -> Property
+prop_poisonCommandErrorsWhenTargetIsDevoured (GameWithDevourEvent game) = do
+    let witchsName  = game ^?! players . witches . name
+    let targetName  = game ^?! events . traverse . _DevourEvent
+    let command     = poisonCommand witchsName targetName
+
+    verbose_runCommandErrors game command
+
+prop_poisonCommandErrorsWhenNotWitchsTurn :: Game -> Property
+prop_poisonCommandErrorsWhenNotWitchsTurn game =
+    hasn't (stage . _WitchsTurn) game
+    ==> forAll (arbitraryPoisonCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_poisonCommandErrorsWhenCallerHasPoisoned :: GameWithPoison -> Property
+prop_poisonCommandErrorsWhenCallerHasPoisoned (GameWithPoison game) = do
+    let witch = game ^?! players . witches
+
+    forAll (arbitraryPlayer game) $ \target -> do
+        let command = poisonCommand (witch ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_poisonCommandErrorsWhenCallerNotWitch :: GameAtWitchsTurn -> Property
+prop_poisonCommandErrorsWhenCallerNotWitch (GameAtWitchsTurn game) =
+    forAll (suchThat (arbitraryPlayer game) (isn't witch)) $ \caller ->
+    forAll (arbitraryPlayer game) $ \target -> do
+        let command = poisonCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_poisonCommandSetsPoison :: GameAtWitchsTurn -> Property
+prop_poisonCommandSetsPoison (GameAtWitchsTurn game) =
+    forAll (arbitraryPoisonCommand game) $ \(Blind command) ->
+    isJust (run_ (apply command) game ^. poison)
+
+prop_poisonCommandSetsPoisonUsed :: GameAtWitchsTurn -> Property
+prop_poisonCommandSetsPoisonUsed (GameAtWitchsTurn game) =
+    forAll (arbitraryPoisonCommand game) $ \(Blind command) ->
+    run_ (apply command) game ^. poisonUsed
diff --git a/test/src/Game/Werewolf/Test/Command/Protect.hs b/test/src/Game/Werewolf/Test/Command/Protect.hs
new file mode 100644
--- /dev/null
+++ b/test/src/Game/Werewolf/Test/Command/Protect.hs
@@ -0,0 +1,112 @@
+{-|
+Module      : Game.Werewolf.Test.Command.Protect
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Game.Werewolf.Test.Command.Protect (
+    -- * Tests
+    allProtectCommandTests,
+) where
+
+import Control.Lens hiding (elements, isn't)
+
+import Data.Maybe
+
+import Game.Werewolf.Command
+import Game.Werewolf.Game
+import Game.Werewolf.Player
+import Game.Werewolf.Test.Arbitrary
+import Game.Werewolf.Test.Util
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+allProtectCommandTests :: [TestTree]
+allProtectCommandTests =
+    [ testProperty "protect command errors when game is over"               prop_protectCommandErrorsWhenGameIsOver
+    , testProperty "protect command errors when caller does not exist"      prop_protectCommandErrorsWhenCallerDoesNotExist
+    , testProperty "protect command errors when target does not exist"      prop_protectCommandErrorsWhenTargetDoesNotExist
+    , testProperty "protect command errors when caller is dead"             prop_protectCommandErrorsWhenCallerIsDead
+    , testProperty "protect command errors when target is dead"             prop_protectCommandErrorsWhenTargetIsDead
+    , testProperty "protect command errors when not defender's turn"        prop_protectCommandErrorsWhenNotDefendersTurn
+    , testProperty "protect command errors when caller not defender"        prop_protectCommandErrorsWhenCallerNotDefender
+    , testProperty "protect command errors when target is prior protect"    prop_protectCommandErrorsWhenTargetIsPriorProtect
+    , testProperty "protect command sets prior protect"                     prop_protectCommandSetsPriorProtect
+    , testProperty "protect command sets protect"                           prop_protectCommandSetsProtect
+    ]
+
+prop_protectCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_protectCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryProtectCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_protectCommandErrorsWhenCallerDoesNotExist :: GameAtDefendersTurn -> Player -> Property
+prop_protectCommandErrorsWhenCallerDoesNotExist (GameAtDefendersTurn game) caller =
+    not (doesPlayerExist (caller ^. name) game)
+    ==> forAll (arbitraryPlayer game) $ \target -> do
+        let command = protectCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_protectCommandErrorsWhenTargetDoesNotExist :: GameAtDefendersTurn -> Player -> Property
+prop_protectCommandErrorsWhenTargetDoesNotExist (GameAtDefendersTurn game) target = do
+    let defender    = game ^?! players . defenders
+    let command     = protectCommand (defender ^. name) (target ^. name)
+
+    not (doesPlayerExist (target ^. name) game)
+        ==> verbose_runCommandErrors game command
+
+prop_protectCommandErrorsWhenCallerIsDead :: GameAtDefendersTurn -> Property
+prop_protectCommandErrorsWhenCallerIsDead (GameAtDefendersTurn game) = do
+    let defender    = game ^?! players . defenders
+    let game'       = killPlayer (defender ^. name) game
+
+    forAll (arbitraryPlayer game') $ \target -> do
+        let command = protectCommand (defender ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_protectCommandErrorsWhenTargetIsDead :: GameAtDefendersTurn -> Property
+prop_protectCommandErrorsWhenTargetIsDead (GameAtDefendersTurn game) = do
+    let defender = game ^?! players . defenders
+
+    forAll (arbitraryPlayer game) $ \target -> do
+        let game'   = killPlayer (target ^. name) game
+        let command = protectCommand (defender ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_protectCommandErrorsWhenNotDefendersTurn :: Game -> Property
+prop_protectCommandErrorsWhenNotDefendersTurn game =
+    hasn't (stage . _DefendersTurn) game
+    ==> forAll (arbitraryProtectCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_protectCommandErrorsWhenCallerNotDefender :: GameAtDefendersTurn -> Property
+prop_protectCommandErrorsWhenCallerNotDefender (GameAtDefendersTurn game) =
+    forAll (suchThat (arbitraryPlayer game) (isn't defender)) $ \caller ->
+    forAll (arbitraryPlayer game) $ \target -> do
+        let command = protectCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_protectCommandErrorsWhenTargetIsPriorProtect :: GameWithProtect -> Property
+prop_protectCommandErrorsWhenTargetIsPriorProtect (GameWithProtect game) = do
+    let game' = game & protect .~ Nothing
+
+    let defender    = game ^?! players . defenders
+    let command     = protectCommand (defender ^. name) (fromJust $ game' ^. priorProtect)
+
+    verbose_runCommandErrors game' command
+
+prop_protectCommandSetsPriorProtect :: GameAtDefendersTurn -> Property
+prop_protectCommandSetsPriorProtect (GameAtDefendersTurn game) =
+    forAll (arbitraryProtectCommand game) $ \(Blind command) ->
+    isJust $ run_ (apply command) game ^. priorProtect
+
+prop_protectCommandSetsProtect :: GameAtDefendersTurn -> Property
+prop_protectCommandSetsProtect (GameAtDefendersTurn game) =
+    forAll (arbitraryProtectCommand game) $ \(Blind command) ->
+    isJust $ run_ (apply command) game ^. protect
diff --git a/test/src/Game/Werewolf/Test/Command/Quit.hs b/test/src/Game/Werewolf/Test/Command/Quit.hs
new file mode 100644
--- /dev/null
+++ b/test/src/Game/Werewolf/Test/Command/Quit.hs
@@ -0,0 +1,148 @@
+{-|
+Module      : Game.Werewolf.Test.Command.Quit
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Game.Werewolf.Test.Command.Quit (
+    -- * Tests
+    allQuitCommandTests,
+) where
+
+import Control.Lens hiding (elements, isn't)
+
+import Data.Maybe
+
+import Game.Werewolf.Command
+import Game.Werewolf.Game
+import Game.Werewolf.Player
+import Game.Werewolf.Test.Arbitrary
+import Game.Werewolf.Test.Util
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+allQuitCommandTests :: [TestTree]
+allQuitCommandTests =
+    [ testProperty "quit command errors when game is over"                              prop_quitCommandErrorsWhenGameIsOver
+    , testProperty "quit command errors when caller does not exist"                     prop_quitCommandErrorsWhenCallerDoesNotExist
+    , testProperty "quit command errors when caller is dead"                            prop_quitCommandErrorsWhenCallerIsDead
+    , testProperty "quit command kills player"                                          prop_quitCommandKillsPlayer
+    , testProperty "quit command clears allegiance chosen when caller is wolf-hound"    prop_quitCommandClearsAllegianceChosenWhenCallerIsWolfHound
+    , testProperty "quit command clears heal when caller is witch"                      prop_quitCommandClearsHealWhenCallerIsWitch
+    , testProperty "quit command clears heal used when caller is witch"                 prop_quitCommandClearsHealUsedWhenCallerIsWitch
+    , testProperty "quit command clears poison when caller is witch"                    prop_quitCommandClearsPoisonWhenCallerIsWitch
+    , testProperty "quit command clears poison used when caller is witch"               prop_quitCommandClearsPoisonUsedWhenCallerIsWitch
+    , testProperty "quit command clears prior protect when caller is defender"          prop_quitCommandClearsPriorProtectWhenCallerIsDefender
+    , testProperty "quit command clears protect when caller is defender"                prop_quitCommandClearsProtectWhenCallerIsDefender
+    , testProperty "quit command clears player's devour vote"                           prop_quitCommandClearsPlayersDevourVote
+    , testProperty "quit command clears player's lynch vote"                            prop_quitCommandClearsPlayersLynchVote
+    , testProperty "quit command clears role model when caller is wild-child"           prop_quitCommandClearsRoleModelWhenCallerIsWildChild
+    , testProperty "quit command sets angel's allegiance when caller is angel"          prop_quitCommandSetsAngelsAllegianceWhenCallerIsAngel
+    ]
+
+prop_quitCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_quitCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryQuitCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_quitCommandErrorsWhenCallerDoesNotExist :: Game -> Player -> Property
+prop_quitCommandErrorsWhenCallerDoesNotExist game caller =
+    not (doesPlayerExist (caller ^. name) game)
+    ==> verbose_runCommandErrors game (quitCommand $ caller ^. name)
+
+prop_quitCommandErrorsWhenCallerIsDead :: Game -> Property
+prop_quitCommandErrorsWhenCallerIsDead game =
+    forAll (arbitraryPlayer game) $ \caller -> do
+        let game'   = killPlayer (caller ^. name) game
+        let command = quitCommand $ caller ^. name
+
+        verbose_runCommandErrors game' command
+
+prop_quitCommandKillsPlayer :: Game -> Property
+prop_quitCommandKillsPlayer game =
+    hasn't (stage . _GameOver) game
+    ==> forAll (arbitraryQuitCommand game) $ \(Blind command) -> do
+        let game' = run_ (apply command) game
+
+        length (game' ^.. players . traverse . dead) == 1
+
+prop_quitCommandClearsAllegianceChosenWhenCallerIsWolfHound :: GameWithAllegianceChosen -> Bool
+prop_quitCommandClearsAllegianceChosenWhenCallerIsWolfHound (GameWithAllegianceChosen game) = do
+    let wolfHoundsName  = game ^?! players . wolfHounds . name
+    let command         = quitCommand wolfHoundsName
+
+    isNothing $ run_ (apply command) game ^. allegianceChosen
+
+prop_quitCommandClearsHealWhenCallerIsWitch :: GameWithHeal -> Bool
+prop_quitCommandClearsHealWhenCallerIsWitch (GameWithHeal game) = do
+    let witch   = game ^?! players . witches
+    let command = quitCommand (witch ^. name)
+
+    not $ run_ (apply command) game ^. heal
+
+prop_quitCommandClearsHealUsedWhenCallerIsWitch :: GameWithHeal -> Bool
+prop_quitCommandClearsHealUsedWhenCallerIsWitch (GameWithHeal game) = do
+    let witch   = game ^?! players . witches
+    let command = quitCommand (witch ^. name)
+
+    not $ run_ (apply command) game ^. healUsed
+
+prop_quitCommandClearsPoisonWhenCallerIsWitch :: GameWithPoison -> Bool
+prop_quitCommandClearsPoisonWhenCallerIsWitch (GameWithPoison game) = do
+    let witch   = game ^?! players . witches
+    let command = quitCommand (witch ^. name)
+
+    isNothing $ run_ (apply command) game ^. poison
+
+prop_quitCommandClearsPoisonUsedWhenCallerIsWitch :: GameWithPoison -> Bool
+prop_quitCommandClearsPoisonUsedWhenCallerIsWitch (GameWithPoison game) = do
+    let witch   = game ^?! players . witches
+    let command = quitCommand (witch ^. name)
+
+    not $ run_ (apply command) game ^. poisonUsed
+
+prop_quitCommandClearsPriorProtectWhenCallerIsDefender :: GameWithProtect -> Bool
+prop_quitCommandClearsPriorProtectWhenCallerIsDefender (GameWithProtect game) = do
+    let defender    = game ^?! players . defenders
+    let command     = quitCommand (defender ^. name)
+
+    isNothing $ run_ (apply command) game ^. priorProtect
+
+prop_quitCommandClearsProtectWhenCallerIsDefender :: GameWithProtect -> Bool
+prop_quitCommandClearsProtectWhenCallerIsDefender (GameWithProtect game) = do
+    let defender    = game ^?! players . defenders
+    let command     = quitCommand (defender ^. name)
+
+    isNothing $ run_ (apply command) game ^. protect
+
+prop_quitCommandClearsPlayersDevourVote :: GameWithDevourVotes -> Property
+prop_quitCommandClearsPlayersDevourVote (GameWithDevourVotes game) =
+    forAll (arbitraryWerewolf game) $ \caller -> do
+        let command = quitCommand (caller ^. name)
+
+        isNothing $ run_ (apply command) game ^. votes . at (caller ^. name)
+
+prop_quitCommandClearsPlayersLynchVote :: GameWithLynchVotes -> Property
+prop_quitCommandClearsPlayersLynchVote (GameWithLynchVotes game) =
+    forAll (arbitraryPlayer game) $ \caller -> do
+        let command = quitCommand (caller ^. name)
+
+        isNothing $ run_ (apply command) game ^. votes . at (caller ^. name)
+
+prop_quitCommandClearsRoleModelWhenCallerIsWildChild :: GameWithRoleModel -> Bool
+prop_quitCommandClearsRoleModelWhenCallerIsWildChild (GameWithRoleModel game) = do
+    let wildChild   = game ^?! players . wildChildren
+    let command     = quitCommand (wildChild ^. name)
+
+    isNothing $ run_ (apply command) game ^. roleModel
+
+prop_quitCommandSetsAngelsAllegianceWhenCallerIsAngel :: Game -> Bool
+prop_quitCommandSetsAngelsAllegianceWhenCallerIsAngel game = do
+    let angelsName  = game ^?! players . angels . name
+    let command     = quitCommand angelsName
+    let game'       = run_ (apply command) game
+
+    is villager $ game' ^?! players . angels
diff --git a/test/src/Game/Werewolf/Test/Command/Reveal.hs b/test/src/Game/Werewolf/Test/Command/Reveal.hs
new file mode 100644
--- /dev/null
+++ b/test/src/Game/Werewolf/Test/Command/Reveal.hs
@@ -0,0 +1,137 @@
+{-|
+Module      : Game.Werewolf.Test.Command.Reveal
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Game.Werewolf.Test.Command.Reveal (
+    -- * Tests
+    allRevealCommandTests,
+) where
+
+import Control.Lens hiding (isn't)
+
+import Data.Maybe
+
+import Game.Werewolf.Game
+import Game.Werewolf.Test.Arbitrary
+import Game.Werewolf.Player
+import Game.Werewolf.Role hiding (name)
+import Game.Werewolf.Command
+import Game.Werewolf.Test.Util
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+allRevealCommandTests :: [TestTree]
+allRevealCommandTests =
+    [ testProperty "reveal command errors when game is over"                prop_revealCommandErrorsWhenGameIsOver
+    , testProperty "reveal command errors when caller does not exist"       prop_revealCommandErrorsWhenCallerDoesNotExist
+    , testProperty "reveal command errors when caller is dead"              prop_revealCommandErrorsWhenCallerIsDead
+    , testProperty "reveal command errors when not devoted servant's turn"  prop_revealCommandErrorsWhenNotDevotedServantsTurn
+    , testProperty "reveal command errors when caller not devoted servant"  prop_revealCommandErrorsWhenCallerNotDevotedServant
+    , testProperty "reveal command sets caller's role"                      prop_revealCommandSetsCallersRole
+    , testProperty "reveal command sets target's role"                      prop_revealCommandSetsTargetsRole
+    , testProperty "reveal command resets role when village idiot"          prop_revealCommandResetsRoleWhenVillageIdiot
+    , testProperty "reveal command resets role when wild-child"             prop_revealCommandResetsRoleWhenWildChild
+    , testProperty "reveal command resets role when witch"                  prop_revealCommandResetsRoleWhenWitch
+    , testProperty "reveal command resets role when wolf-hound"             prop_revealCommandResetsRoleWhenWolfHound
+    ]
+
+prop_revealCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_revealCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryRevealCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_revealCommandErrorsWhenCallerDoesNotExist :: GameAtDevotedServantsTurn -> Player -> Property
+prop_revealCommandErrorsWhenCallerDoesNotExist (GameAtDevotedServantsTurn game) caller = do
+    let command = revealCommand $ caller ^. name
+
+    not (doesPlayerExist (caller ^. name) game)
+        ==> verbose_runCommandErrors game command
+
+prop_revealCommandErrorsWhenCallerIsDead :: GameAtDevotedServantsTurn -> Property
+prop_revealCommandErrorsWhenCallerIsDead (GameAtDevotedServantsTurn game) = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+    let game'               = killPlayer devotedServantsName game
+    let command             = revealCommand devotedServantsName
+
+    verbose_runCommandErrors game' command
+
+prop_revealCommandErrorsWhenNotDevotedServantsTurn :: Game -> Property
+prop_revealCommandErrorsWhenNotDevotedServantsTurn game =
+    hasn't (stage . _DevotedServantsTurn) game
+    ==> forAll (arbitraryRevealCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_revealCommandErrorsWhenCallerNotDevotedServant :: GameAtDevotedServantsTurn -> Property
+prop_revealCommandErrorsWhenCallerNotDevotedServant (GameAtDevotedServantsTurn game) =
+    forAll (suchThat (arbitraryPlayer game) (isn't devotedServant)) $ \caller -> do
+        let command = revealCommand $ caller ^. name
+
+        verbose_runCommandErrors game command
+
+prop_revealCommandSetsCallersRole :: GameAtDevotedServantsTurn -> Property
+prop_revealCommandSetsCallersRole (GameAtDevotedServantsTurn game) = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+    let command             = revealCommand devotedServantsName
+    let game'               = run_ (apply command) game
+
+    game' ^?! players . traverse . filteredBy name devotedServantsName . role === target ^. role
+    where
+        target = head $ getVoteResult game
+
+prop_revealCommandSetsTargetsRole :: GameAtDevotedServantsTurn -> Bool
+prop_revealCommandSetsTargetsRole (GameAtDevotedServantsTurn game) = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+    let command             = revealCommand devotedServantsName
+    let game'               = run_ (apply command) game
+
+    is devotedServant $ game' ^?! players . traverse . filteredBy name targetsName
+    where
+        targetsName = head (getVoteResult game) ^. name
+
+prop_revealCommandResetsRoleWhenVillageIdiot :: GameAtDevotedServantsTurn -> Bool
+prop_revealCommandResetsRoleWhenVillageIdiot (GameAtDevotedServantsTurn game) = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+    let command             = revealCommand devotedServantsName
+    let game''              = run_ (apply command) game'
+
+    not $ game'' ^. villageIdiotRevealed
+    where
+        targetsName = head (getVoteResult game) ^. name
+        game'       = game & players . traverse . filteredBy name targetsName . role .~ villageIdiotRole & villageIdiotRevealed .~ True
+
+prop_revealCommandResetsRoleWhenWildChild :: GameAtDevotedServantsTurn -> Bool
+prop_revealCommandResetsRoleWhenWildChild (GameAtDevotedServantsTurn game) = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+    let command             = revealCommand devotedServantsName
+    let game''              = run_ (apply command) game'
+
+    isNothing $ game'' ^. roleModel
+    where
+        targetsName = head (getVoteResult game) ^. name
+        game'       = game & players . traverse . filteredBy name targetsName . role .~ wildChildRole & roleModel .~ Just targetsName
+
+prop_revealCommandResetsRoleWhenWitch :: GameAtDevotedServantsTurn -> Bool
+prop_revealCommandResetsRoleWhenWitch (GameAtDevotedServantsTurn game) = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+    let command             = revealCommand devotedServantsName
+    let game''              = run_ (apply command) game'
+
+    not (game'' ^. healUsed) && not (game'' ^. poisonUsed)
+    where
+        targetsName = head (getVoteResult game) ^. name
+        game'       = game & players . traverse . filteredBy name targetsName . role .~ witchRole & healUsed .~ True & poisonUsed .~ True
+
+prop_revealCommandResetsRoleWhenWolfHound :: GameAtDevotedServantsTurn -> Bool
+prop_revealCommandResetsRoleWhenWolfHound (GameAtDevotedServantsTurn game) = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+    let command             = revealCommand devotedServantsName
+    let game''              = run_ (apply command) game'
+
+    isNothing $ game'' ^. allegianceChosen
+    where
+        targetsName = head (getVoteResult game) ^. name
+        game'       = game & players . traverse . filteredBy name targetsName . role .~ wolfHoundRole & allegianceChosen .~ Just Villagers
diff --git a/test/src/Game/Werewolf/Test/Command/See.hs b/test/src/Game/Werewolf/Test/Command/See.hs
new file mode 100644
--- /dev/null
+++ b/test/src/Game/Werewolf/Test/Command/See.hs
@@ -0,0 +1,96 @@
+{-|
+Module      : Game.Werewolf.Test.Command.See
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Game.Werewolf.Test.Command.See (
+    -- * Tests
+    allSeeCommandTests,
+) where
+
+import Control.Lens hiding (elements, isn't)
+
+import Data.Maybe
+
+import Game.Werewolf.Command
+import Game.Werewolf.Game
+import Game.Werewolf.Player
+import Game.Werewolf.Test.Arbitrary
+import Game.Werewolf.Test.Util
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+allSeeCommandTests :: [TestTree]
+allSeeCommandTests =
+    [ testProperty "see command errors when game is over"           prop_seeCommandErrorsWhenGameIsOver
+    , testProperty "see command errors when caller does not exist"  prop_seeCommandErrorsWhenCallerDoesNotExist
+    , testProperty "see command errors when target does not exist"  prop_seeCommandErrorsWhenTargetDoesNotExist
+    , testProperty "see command errors when caller is dead"         prop_seeCommandErrorsWhenCallerIsDead
+    , testProperty "see command errors when target is dead"         prop_seeCommandErrorsWhenTargetIsDead
+    , testProperty "see command errors when not seer's turn"        prop_seeCommandErrorsWhenNotSeersTurn
+    , testProperty "see command errors when caller not seer"        prop_seeCommandErrorsWhenCallerNotSeer
+    , testProperty "see command sets see"                           prop_seeCommandSetsSee
+    ]
+
+prop_seeCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_seeCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitrarySeeCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_seeCommandErrorsWhenCallerDoesNotExist :: GameAtSeersTurn -> Player -> Property
+prop_seeCommandErrorsWhenCallerDoesNotExist (GameAtSeersTurn game) caller =
+    not (doesPlayerExist (caller ^. name) game)
+    ==> forAll (arbitraryPlayer game) $ \target -> do
+        let command = seeCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_seeCommandErrorsWhenTargetDoesNotExist :: GameAtSeersTurn -> Player -> Property
+prop_seeCommandErrorsWhenTargetDoesNotExist (GameAtSeersTurn game) target = do
+    let seer    = game ^?! players . seers
+    let command = seeCommand (seer ^. name) (target ^. name)
+
+    not (doesPlayerExist (target ^. name) game)
+        ==> verbose_runCommandErrors game command
+
+prop_seeCommandErrorsWhenCallerIsDead :: GameAtSeersTurn -> Property
+prop_seeCommandErrorsWhenCallerIsDead (GameAtSeersTurn game) = do
+    let seer    = game ^?! players . seers
+    let game'   = killPlayer (seer ^. name) game
+
+    forAll (arbitraryPlayer game') $ \target -> do
+        let command = seeCommand (seer ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_seeCommandErrorsWhenTargetIsDead :: GameAtSeersTurn -> Property
+prop_seeCommandErrorsWhenTargetIsDead (GameAtSeersTurn game) = do
+    let seer = game ^?! players . seers
+
+    forAll (arbitraryPlayer game) $ \target -> do
+        let game'   = killPlayer (target ^. name) game
+        let command = seeCommand (seer ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_seeCommandErrorsWhenNotSeersTurn :: Game -> Property
+prop_seeCommandErrorsWhenNotSeersTurn game =
+    hasn't (stage . _SeersTurn) game
+    ==> forAll (arbitrarySeeCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_seeCommandErrorsWhenCallerNotSeer :: GameAtSeersTurn -> Property
+prop_seeCommandErrorsWhenCallerNotSeer (GameAtSeersTurn game) =
+    forAll (suchThat (arbitraryPlayer game) (isn't seer)) $ \caller ->
+    forAll (arbitraryPlayer game) $ \target -> do
+        let command = seeCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_seeCommandSetsSee :: GameAtSeersTurn -> Property
+prop_seeCommandSetsSee (GameAtSeersTurn game) =
+    forAll (arbitrarySeeCommand game) $ \(Blind command) ->
+    isJust $ run_ (apply command) game ^. see
diff --git a/test/src/Game/Werewolf/Test/Command/Vote.hs b/test/src/Game/Werewolf/Test/Command/Vote.hs
new file mode 100644
--- /dev/null
+++ b/test/src/Game/Werewolf/Test/Command/Vote.hs
@@ -0,0 +1,201 @@
+{-|
+Module      : Game.Werewolf.Test.Command.Vote
+Copyright   : (c) Henry J. Wylde, 2016
+License     : BSD3
+Maintainer  : public@hjwylde.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Game.Werewolf.Test.Command.Vote (
+    -- * Tests
+    allVoteCommandTests,
+) where
+
+import Control.Lens hiding (elements, isn't)
+
+import qualified Data.Map as Map
+
+import Game.Werewolf.Command
+import Game.Werewolf.Engine         (checkStage)
+import Game.Werewolf.Game
+import Game.Werewolf.Player
+import Game.Werewolf.Test.Arbitrary
+import Game.Werewolf.Test.Util
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+allVoteCommandTests :: [TestTree]
+allVoteCommandTests =
+    [ testProperty "vote devour command errors when game is over"           prop_voteDevourCommandErrorsWhenGameIsOver
+    , testProperty "vote devour command errors when caller does not exist"  prop_voteDevourCommandErrorsWhenCallerDoesNotExist
+    , testProperty "vote devour command errors when target does not exist"  prop_voteDevourCommandErrorsWhenTargetDoesNotExist
+    , testProperty "vote devour command errors when caller is dead"         prop_voteDevourCommandErrorsWhenCallerIsDead
+    , testProperty "vote devour command errors when target is dead"         prop_voteDevourCommandErrorsWhenTargetIsDead
+    , testProperty "vote devour command errors when not werewolves turn"    prop_voteDevourCommandErrorsWhenNotWerewolvesTurn
+    , testProperty "vote devour command errors when caller not werewolf"    prop_voteDevourCommandErrorsWhenCallerNotWerewolf
+    , testProperty "vote devour command errors when caller has voted"       prop_voteDevourCommandErrorsWhenCallerHasVoted
+    , testProperty "vote devour command errors when target werewolf"        prop_voteDevourCommandErrorsWhenTargetWerewolf
+    , testProperty "vote devour command updates votes"                      prop_voteDevourCommandUpdatesVotes
+
+    , testProperty "vote lynch command errors when game is over"                    prop_voteLynchCommandErrorsWhenGameIsOver
+    , testProperty "vote lynch command errors when caller does not exist"           prop_voteLynchCommandErrorsWhenCallerDoesNotExist
+    , testProperty "vote lynch command errors when target does not exist"           prop_voteLynchCommandErrorsWhenTargetDoesNotExist
+    , testProperty "vote lynch command errors when caller is dead"                  prop_voteLynchCommandErrorsWhenCallerIsDead
+    , testProperty "vote lynch command errors when target is dead"                  prop_voteLynchCommandErrorsWhenTargetIsDead
+    , testProperty "vote lynch command errors when not villages turn"               prop_voteLynchCommandErrorsWhenNotVillagesTurn
+    , testProperty "vote lynch command errors when caller has voted"                prop_voteLynchCommandErrorsWhenCallerHasVoted
+    , testProperty "vote lynch command errors when caller is not in allowed voters" prop_voteLynchCommandErrorsWhenCallerIsNotInAllowedVoters
+    , testProperty "vote lynch command errors when caller is known village idiot"   prop_voteLynchCommandErrorsWhenCallerIsKnownVillageIdiot
+    , testProperty "vote lynch command updates votes"                               prop_voteLynchCommandUpdatesVotes
+    ]
+
+prop_voteDevourCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_voteDevourCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryVoteDevourCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_voteDevourCommandErrorsWhenCallerDoesNotExist :: GameAtWerewolvesTurn -> Player -> Property
+prop_voteDevourCommandErrorsWhenCallerDoesNotExist (GameAtWerewolvesTurn game) caller =
+    not (doesPlayerExist (caller ^. name) game)
+    ==> forAll (arbitraryPlayer game) $ \target -> do
+        let command = voteDevourCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_voteDevourCommandErrorsWhenTargetDoesNotExist :: GameAtWerewolvesTurn -> Player -> Property
+prop_voteDevourCommandErrorsWhenTargetDoesNotExist (GameAtWerewolvesTurn game) target =
+    not (doesPlayerExist (target ^. name) game)
+    ==> forAll (arbitraryWerewolf game) $ \caller -> do
+        let command = voteDevourCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_voteDevourCommandErrorsWhenCallerIsDead :: GameAtWerewolvesTurn -> Property
+prop_voteDevourCommandErrorsWhenCallerIsDead (GameAtWerewolvesTurn game) =
+    forAll (arbitraryWerewolf game) $ \caller ->
+    forAll (arbitraryPlayer game) $ \target -> do
+        let game'   = killPlayer (caller ^. name) game
+        let command = voteDevourCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_voteDevourCommandErrorsWhenTargetIsDead :: GameAtWerewolvesTurn -> Property
+prop_voteDevourCommandErrorsWhenTargetIsDead (GameAtWerewolvesTurn game) =
+    forAll (arbitraryWerewolf game) $ \caller ->
+    forAll (arbitraryPlayer game) $ \target -> do
+        let game'   = killPlayer (target ^. name) game
+        let command = voteDevourCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_voteDevourCommandErrorsWhenNotWerewolvesTurn :: Game -> Property
+prop_voteDevourCommandErrorsWhenNotWerewolvesTurn game =
+    hasn't (stage . _WerewolvesTurn) game
+    ==> forAll (arbitraryVoteDevourCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_voteDevourCommandErrorsWhenCallerNotWerewolf :: GameAtWerewolvesTurn -> Property
+prop_voteDevourCommandErrorsWhenCallerNotWerewolf (GameAtWerewolvesTurn game) =
+    forAll (suchThat (arbitraryPlayer game) (isn't werewolf)) $ \caller ->
+    forAll (arbitraryPlayer game) $ \target -> do
+        let command = voteDevourCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_voteDevourCommandErrorsWhenCallerHasVoted :: GameWithDevourVotes -> Property
+prop_voteDevourCommandErrorsWhenCallerHasVoted (GameWithDevourVotes game) =
+    forAll (arbitraryWerewolf game) $ \caller ->
+    forAll (suchThat (arbitraryPlayer game) (isn't werewolf)) $ \target -> do
+        let command = voteDevourCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_voteDevourCommandErrorsWhenTargetWerewolf :: GameAtWerewolvesTurn -> Property
+prop_voteDevourCommandErrorsWhenTargetWerewolf (GameAtWerewolvesTurn game) =
+    forAll (arbitraryPlayer game) $ \caller ->
+    forAll (arbitraryWerewolf game) $ \target ->
+    verbose_runCommandErrors game (voteDevourCommand (caller ^. name) (target ^. name))
+
+prop_voteDevourCommandUpdatesVotes :: GameAtWerewolvesTurn -> Property
+prop_voteDevourCommandUpdatesVotes (GameAtWerewolvesTurn game) =
+    forAll (arbitraryVoteDevourCommand game) $ \(Blind command) -> do
+        let game' = run_ (apply command) game
+
+        Map.size (game' ^. votes) == 1
+
+prop_voteLynchCommandErrorsWhenGameIsOver :: GameAtGameOver -> Property
+prop_voteLynchCommandErrorsWhenGameIsOver (GameAtGameOver game) =
+    forAll (arbitraryVoteLynchCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_voteLynchCommandErrorsWhenCallerDoesNotExist :: GameAtVillagesTurn -> Player -> Property
+prop_voteLynchCommandErrorsWhenCallerDoesNotExist (GameAtVillagesTurn game) caller =
+    not (doesPlayerExist (caller ^. name) game)
+    ==> forAll (arbitraryPlayer game) $ \target -> do
+        let command = voteLynchCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_voteLynchCommandErrorsWhenTargetDoesNotExist :: GameAtVillagesTurn -> Player -> Property
+prop_voteLynchCommandErrorsWhenTargetDoesNotExist (GameAtVillagesTurn game) target =
+    not (doesPlayerExist (target ^. name) game)
+    ==> forAll (arbitraryPlayer game) $ \caller -> do
+        let command = voteLynchCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_voteLynchCommandErrorsWhenCallerIsDead :: GameAtVillagesTurn -> Property
+prop_voteLynchCommandErrorsWhenCallerIsDead (GameAtVillagesTurn game) =
+    forAll (arbitraryPlayer game) $ \caller ->
+    forAll (arbitraryPlayer game) $ \target -> do
+        let game'   = killPlayer (caller ^. name) game
+        let command = voteLynchCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_voteLynchCommandErrorsWhenTargetIsDead :: GameAtVillagesTurn -> Property
+prop_voteLynchCommandErrorsWhenTargetIsDead (GameAtVillagesTurn game) =
+    forAll (arbitraryPlayer game) $ \caller ->
+    forAll (arbitraryPlayer game) $ \target -> do
+        let game'   = killPlayer (target ^. name) game
+        let command = voteLynchCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+
+prop_voteLynchCommandErrorsWhenNotVillagesTurn :: Game -> Property
+prop_voteLynchCommandErrorsWhenNotVillagesTurn game =
+    hasn't (stage . _VillagesTurn) game
+    ==> forAll (arbitraryVoteLynchCommand game) $ verbose_runCommandErrors game . getBlind
+
+prop_voteLynchCommandErrorsWhenCallerHasVoted :: GameWithLynchVotes -> Property
+prop_voteLynchCommandErrorsWhenCallerHasVoted (GameWithLynchVotes game) =
+    forAll (arbitraryPlayer game) $ \caller ->
+    forAll (arbitraryPlayer game) $ \target -> do
+        let command = voteLynchCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+
+prop_voteLynchCommandErrorsWhenCallerIsNotInAllowedVoters :: GameWithAllowedVoters -> Property
+prop_voteLynchCommandErrorsWhenCallerIsNotInAllowedVoters (GameWithAllowedVoters game) =
+    forAll (suchThat (arbitraryPlayer game') (`notElem` getAllowedVoters game')) $ \caller ->
+    forAll (arbitraryPlayer game') $ \target -> do
+        let command = voteLynchCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game' command
+    where
+        game' = run_ checkStage game
+
+prop_voteLynchCommandErrorsWhenCallerIsKnownVillageIdiot :: GameWithVillageIdiotRevealedAtVillagesTurn -> Property
+prop_voteLynchCommandErrorsWhenCallerIsKnownVillageIdiot (GameWithVillageIdiotRevealedAtVillagesTurn game) =
+    forAll (arbitraryPlayer game) $ \target -> do
+        let command = voteLynchCommand (caller ^. name) (target ^. name)
+
+        verbose_runCommandErrors game command
+    where
+        caller = game ^?! players . villageIdiots
+
+prop_voteLynchCommandUpdatesVotes :: GameAtVillagesTurn -> Property
+prop_voteLynchCommandUpdatesVotes (GameAtVillagesTurn game) =
+    forAll (arbitraryVoteLynchCommand game) $ \(Blind command) -> do
+        let game' = run_ (apply command) game
+
+        Map.size (game' ^. votes) == 1
diff --git a/test/src/Game/Werewolf/Test/Engine.hs b/test/src/Game/Werewolf/Test/Engine.hs
--- a/test/src/Game/Werewolf/Test/Engine.hs
+++ b/test/src/Game/Werewolf/Test/Engine.hs
@@ -37,19 +37,37 @@
 
 allEngineTests :: [TestTree]
 allEngineTests =
-    [ testProperty "check stage skips defender's turn when no defender"         prop_checkStageSkipsDefendersTurnWhenNoDefender
-    , testProperty "check stage skips scapegoat's turn when no seer"            prop_checkStageSkipsScapegoatsTurnWhenNoScapegoat
-    , testProperty "check stage skips seer's turn when no seer"                 prop_checkStageSkipsSeersTurnWhenNoSeer
-    , testProperty "check stage skips village's turn when allowed voters empty" prop_checkStageSkipsVillagesTurnWhenAllowedVotersEmpty
-    , testProperty "check stage skips wild-child's turn when no wild-child"     prop_checkStageSkipsWildChildsTurnWhenNoWildChild
-    , testProperty "check stage skips witch's turn when no witch"               prop_checkStageSkipsWitchsTurnWhenNoWitch
-    , testProperty "check stage skips wolf-hound's turn when no wolf-hound"     prop_checkStageSkipsWolfHoundsTurnWhenNoWolfHound
-    , testProperty "check stage does nothing when game over"                    prop_checkStageDoesNothingWhenGameOver
+    [ testProperty "check stage skips defender's turn when no defender"                 prop_checkStageSkipsDefendersTurnWhenNoDefender
+    , testProperty "check stage skips devoted servant's turn when no devoted servant"   prop_checkStageSkipsDevotedServantsTurnWhenNoDevotedServant
+    , testProperty "check stage skips scapegoat's turn when no scapegoat"               prop_checkStageSkipsScapegoatsTurnWhenNoScapegoat
+    , testProperty "check stage skips seer's turn when no seer"                         prop_checkStageSkipsSeersTurnWhenNoSeer
+    , testProperty "check stage skips village's turn when allowed voters empty"         prop_checkStageSkipsVillagesTurnWhenAllowedVotersEmpty
+    , testProperty "check stage skips wild-child's turn when no wild-child"             prop_checkStageSkipsWildChildsTurnWhenNoWildChild
+    , testProperty "check stage skips witch's turn when no witch"                       prop_checkStageSkipsWitchsTurnWhenNoWitch
+    , testProperty "check stage skips wolf-hound's turn when no wolf-hound"             prop_checkStageSkipsWolfHoundsTurnWhenNoWolfHound
 
     , testProperty "check defender's turn advances to werewolves' turn"     prop_checkDefendersTurnAdvancesToWerewolvesTurn
     , testProperty "check defender's turn advances when no defender"        prop_checkDefendersTurnAdvancesWhenNoDefender
     , testProperty "check defender's turn does nothing unless protected"    prop_checkDefendersTurnDoesNothingUnlessProtected
 
+    , testProperty "check devoted servant's turn advances to wolf-hound's turn"             prop_checkDevotedServantsTurnAdvancesToWolfHoundsTurn
+    , testProperty "check devoted servant's turn advances when no devoted servant"          prop_checkDevotedServantsTurnAdvancesWhenNoDevotedServant
+    , testProperty "check devoted servant's turn does nothing unless revealed or passed"    prop_checkDevotedServantsTurnDoesNothingUnlessRevealedOrPassed
+
+    , testProperty "check lynching lynches one player when consensus"                   prop_checkLynchingLynchesOnePlayerWhenConsensus
+    , testProperty "check lynching lynches no one when target is village idiot"         prop_checkLynchingLynchesNoOneWhenTargetIsVillageIdiot
+    , testProperty "check lynching lynches scapegoat when conflicted"                   prop_checkLynchingLynchesScapegoatWhenConflicted
+    , testProperty "check lynching lynches no one when conflicted and no scapegoats"    prop_checkLynchingLynchesNoOneWhenConflictedAndNoScapegoats
+    , testProperty "check lynching resets votes"                                        prop_checkLynchingResetsVotes
+    , testProperty "check lynching sets allowed voters"                                 prop_checkLynchingSetsAllowedVoters
+
+    , testProperty "check game over advances stage when one allegiance alive"                   prop_checkGameOverAdvancesStageWhenOneAllegianceAlive
+    -- TODO (hjw): pending
+    --, testProperty "check game over does nothing when at least two allegiances alive"   prop_checkGameOverDoesNothingWhenAtLeastTwoAllegiancesAlive
+    , testProperty "check game over advances stage when after first round and angel dead"       prop_checkGameOverAdvancesStageWhenAfterFirstRoundAndAngelDead
+    , testProperty "check game over does nothing when angel dead but aligned with villagers"    prop_checkGameOverDoesNothingWhenAngelDeadButAlignedWithVillagers
+    , testProperty "check game over does nothing when game over"                                prop_checkGameOverDoesNothingWhenGameOver
+
     , testProperty "check scapegoat's turn advances to wolf-hound's turn"                   prop_checkScapegoatsTurnAdvancesToWolfHoundsTurn
     , testProperty "check scapegoat's turn skips wolf-hound's turn when allegiance chosen"  prop_checkScapegoatsTurnSkipsWolfHoundsTurnWhenAllegianceChosen
     , testProperty "check scapegoat's turn does nothing while scapegoat blamed"             prop_checkScapegoatsTurnDoesNothingWhileScapegoatBlamed
@@ -64,14 +82,9 @@
 
     , testProperty "check sunset sets wild-child's allegiance when role model dead" prop_checkSunsetSetsWildChildsAllegianceWhenRoleModelDead
 
-    , testProperty "check villages' turn advances to scapegoat's turn"                      prop_checkVillagesTurnAdvancesToScapegoatsTurn
-    , testProperty "check villages' turn lynches one player when consensus"                 prop_checkVillagesTurnLynchesOnePlayerWhenConsensus
-    , testProperty "check villages' turn lynches no one when target is village idiot"       prop_checkVillagesTurnLynchesNoOneWhenTargetIsVillageIdiot
-    , testProperty "check villages' turn lynches no one when conflicted and no scapegoats"  prop_checkVillagesTurnLynchesNoOneWhenConflictedAndNoScapegoats
-    , testProperty "check villages' turn lynches scapegoat when conflicted"                 prop_checkVillagesTurnLynchesScapegoatWhenConflicted
-    , testProperty "check villages' turn resets votes"                                      prop_checkVillagesTurnResetsVotes
-    , testProperty "check villages' turn sets allowed voters"                               prop_checkVillagesTurnSetsAllowedVoters
-    , testProperty "check villages' turn does nothing unless all voted"                     prop_checkVillagesTurnDoesNothingUnlessAllVoted
+    , testProperty "check villages' turn advances to devoted servant's turn"            prop_checkVillagesTurnAdvancesToDevotedServantsTurn
+    , testProperty "check villages' turn skips devoted servant's turn when conflicted"  prop_checkVillagesTurnSkipsDevotedServantsTurnWhenConflicted
+    , testProperty "check villages' turn does nothing unless all voted"                 prop_checkVillagesTurnDoesNothingUnlessAllVoted
 
     , testProperty "check werewolves' turn advances to witch's turn"                    prop_checkWerewolvesTurnAdvancesToWitchsTurn
     , testProperty "check werewolves' turn skips witch's turn when healed and poisoned" prop_checkWerewolvesTurnSkipsWitchsTurnWhenHealedAndPoisoned
@@ -101,12 +114,6 @@
     , testProperty "check wolf-hound's turn sets wolf-hound's allegiance"           prop_checkWolfHoundsTurnSetsWolfHoundsAllegiance
     , testProperty "check wolf-hound's turn does nothing unless allegiance chosen"  prop_checkWolfHoundsTurnDoesNothingUnlessAllegianceChosen
 
-    , testProperty "check game over advances stage when one allegiance alive"                   prop_checkGameOverAdvancesStageWhenOneAllegianceAlive
-    -- TODO (hjw): pending
-    --, testProperty "check game over does nothing when at least two allegiances alive"   prop_checkGameOverDoesNothingWhenAtLeastTwoAllegiancesAlive
-    , testProperty "check game over advances stage when after first round and angel dead"       prop_checkGameOverAdvancesStageWhenAfterFirstRoundAndAngelDead
-    , testProperty "check game over does nothing when angel dead but aligned with villagers"    prop_checkGameOverDoesNothingWhenAngelDeadButAlignedWithVillagers
-
     , testProperty "start game uses given players"                              prop_startGameUsesGivenPlayers
     , testProperty "start game errors unless unique player names"               prop_startGameErrorsUnlessUniquePlayerNames
     , testProperty "start game errors when less than 7 players"                 prop_startGameErrorsWhenLessThan7Players
@@ -121,15 +128,22 @@
         defendersName   = game ^?! players . defenders . name
         game'           = run_ (apply (quitCommand defendersName) >> checkStage) game
 
-prop_checkStageSkipsScapegoatsTurnWhenNoScapegoat :: GameWithLynchVotes -> Bool
-prop_checkStageSkipsScapegoatsTurnWhenNoScapegoat (GameWithLynchVotes game) =
+prop_checkStageSkipsDevotedServantsTurnWhenNoDevotedServant :: GameWithMajorityVote -> Bool
+prop_checkStageSkipsDevotedServantsTurnWhenNoDevotedServant (GameWithMajorityVote game) =
+    hasn't (stage . _DevotedServantsTurn) game'
+    where
+        devotedServantsName = game ^?! players . devotedServants . name
+        game'               = run_ (apply (quitCommand devotedServantsName) >> checkStage) game
+
+prop_checkStageSkipsScapegoatsTurnWhenNoScapegoat :: GameWithConflictingVote -> Bool
+prop_checkStageSkipsScapegoatsTurnWhenNoScapegoat (GameWithConflictingVote game) =
     hasn't (stage . _ScapegoatsTurn) game'
     where
         scapegoatsName  = game ^?! players . scapegoats . name
         game'           = run_ (apply (quitCommand scapegoatsName) >> checkStage) game
 
-prop_checkStageSkipsSeersTurnWhenNoSeer :: GameWithLynchVotes -> Bool
-prop_checkStageSkipsSeersTurnWhenNoSeer (GameWithLynchVotes game) =
+prop_checkStageSkipsSeersTurnWhenNoSeer :: GameWithPassAtDevotedServantsTurn -> Bool
+prop_checkStageSkipsSeersTurnWhenNoSeer (GameWithPassAtDevotedServantsTurn game) =
     hasn't (stage . _SeersTurn) game'
     where
         seersName   = game ^?! players . seers . name
@@ -137,8 +151,8 @@
 
 prop_checkStageSkipsVillagesTurnWhenAllowedVotersEmpty :: GameAtWitchsTurn -> Property
 prop_checkStageSkipsVillagesTurnWhenAllowedVotersEmpty (GameAtWitchsTurn game) =
-    forAll (arbitraryPassCommand game') $ \(Blind passCommand) -> do
-        hasn't (stage . _VillagesTurn) (run_ (apply passCommand >> checkStage) game')
+    forAll (arbitraryPassWitchsTurnCommand game') $ \(Blind passWitchsTurnCommand) -> do
+        hasn't (stage . _VillagesTurn) (run_ (apply passWitchsTurnCommand >> checkStage) game')
     where
         game' = game & allowedVoters .~ []
 
@@ -164,10 +178,6 @@
         wolfHoundsName  = game ^?! players . wolfHounds . name
         game'           = run_ (apply (quitCommand wolfHoundsName) >> checkStage) game
 
-prop_checkStageDoesNothingWhenGameOver :: GameAtGameOver -> Property
-prop_checkStageDoesNothingWhenGameOver (GameAtGameOver game) =
-    run_ checkStage game === game
-
 prop_checkDefendersTurnAdvancesToWerewolvesTurn :: GameWithProtect -> Bool
 prop_checkDefendersTurnAdvancesToWerewolvesTurn (GameWithProtect game) =
     has (stage . _WerewolvesTurn) (run_ checkStage game)
@@ -183,6 +193,60 @@
 prop_checkDefendersTurnDoesNothingUnlessProtected (GameAtDefendersTurn game) =
     has (stage . _DefendersTurn) (run_ checkStage game)
 
+prop_checkDevotedServantsTurnAdvancesToWolfHoundsTurn :: GameAtDevotedServantsTurn -> Property
+prop_checkDevotedServantsTurnAdvancesToWolfHoundsTurn (GameAtDevotedServantsTurn game) = do
+    forAll (arbitraryCommand game) $ \(Blind command) ->
+        isn't angel target && isn't wolfHound target
+        ==> has (stage . _WolfHoundsTurn) (run_ (apply command >> checkStage) game)
+    where
+        target = head $ getVoteResult game
+
+prop_checkDevotedServantsTurnAdvancesWhenNoDevotedServant :: GameAtDevotedServantsTurn -> Bool
+prop_checkDevotedServantsTurnAdvancesWhenNoDevotedServant (GameAtDevotedServantsTurn game) = do
+    let devotedServantsName = game ^?! players . devotedServants . name
+    let command             = quitCommand devotedServantsName
+
+    hasn't (stage . _DevotedServantsTurn) (run_ (apply command >> checkStage) game)
+
+prop_checkDevotedServantsTurnDoesNothingUnlessRevealedOrPassed :: GameAtDevotedServantsTurn -> Bool
+prop_checkDevotedServantsTurnDoesNothingUnlessRevealedOrPassed (GameAtDevotedServantsTurn game) =
+    has (stage . _DevotedServantsTurn) (run_ checkStage game)
+
+prop_checkLynchingLynchesOnePlayerWhenConsensus :: GameWithPassAtDevotedServantsTurn -> Property
+prop_checkLynchingLynchesOnePlayerWhenConsensus (GameWithPassAtDevotedServantsTurn game) =
+    isn't villageIdiot target
+    ==> length (run_ checkStage game ^.. players . traverse . dead) == 1
+    where
+        target = head $ getVoteResult game
+
+prop_checkLynchingLynchesNoOneWhenTargetIsVillageIdiot :: GameAtVillagesTurn -> Bool
+prop_checkLynchingLynchesNoOneWhenTargetIsVillageIdiot (GameAtVillagesTurn game) = do
+    let game' = foldr (\player -> run_ (apply $ voteLynchCommand (player ^. name) (villageIdiot ^. name))) game (game ^. players)
+
+    none (is dead) (run_ checkStage game' ^. players)
+    where
+        villageIdiot = game ^?! players . villageIdiots
+
+prop_checkLynchingLynchesScapegoatWhenConflicted :: GameAtScapegoatsTurn -> Bool
+prop_checkLynchingLynchesScapegoatWhenConflicted (GameAtScapegoatsTurn game) =
+    is dead $ run_ checkStage game ^?! players . scapegoats
+
+prop_checkLynchingResetsVotes :: GameWithPassAtDevotedServantsTurn -> Property
+prop_checkLynchingResetsVotes (GameWithPassAtDevotedServantsTurn game) =
+    isn't devotedServant target
+    ==> Map.null $ run_ checkStage game ^. votes
+    where
+        target = head $ getVoteResult game
+
+prop_checkLynchingSetsAllowedVoters :: GameWithLynchVotes -> Property
+prop_checkLynchingSetsAllowedVoters (GameWithLynchVotes game) =
+    game' ^. allowedVoters === expectedAllowedVoters ^.. names
+    where
+        game' = run_ checkStage game
+        expectedAllowedVoters
+            | game' ^. villageIdiotRevealed = filter (isn't villageIdiot) $ game' ^. players
+            | otherwise                     = game' ^.. players . traverse . alive
+
 prop_checkScapegoatsTurnAdvancesToWolfHoundsTurn :: GameWithAllowedVoters -> Bool
 prop_checkScapegoatsTurnAdvancesToWolfHoundsTurn (GameWithAllowedVoters game) =
     has (stage . _WolfHoundsTurn) (run_ checkStage game)
@@ -231,34 +295,28 @@
 prop_checkSunsetSetsWildChildsAllegianceWhenRoleModelDead (GameWithRoleModelAtVillagesTurn game) = do
     let game' = foldr (\player -> run_ (apply $ voteLynchCommand (player ^. name) (roleModel' ^. name))) game (game ^. players)
 
-    isn't angel roleModel' && isn't villageIdiot roleModel'
-        ==> is werewolf $ run_ checkStage game' ^?! players . wildChildren
+    let devotedServantsName = game ^?! players . devotedServants . name
+    let command             = passDevotedServantsTurnCommand devotedServantsName
+
+    isn't angel roleModel' && isn't devotedServant roleModel' && isn't villageIdiot roleModel'
+        ==> is werewolf $ run_ (checkStage >> apply command >> checkStage) game' ^?! players . wildChildren
     where
         roleModel' = game ^?! players . traverse . filteredBy name (fromJust $ game ^. roleModel)
 
-prop_checkVillagesTurnAdvancesToScapegoatsTurn :: GameWithScapegoatBlamed -> Bool
-prop_checkVillagesTurnAdvancesToScapegoatsTurn (GameWithScapegoatBlamed game) =
-    has (stage . _ScapegoatsTurn) (run_ checkStage game)
-
-prop_checkVillagesTurnLynchesOnePlayerWhenConsensus :: GameWithLynchVotes -> Property
-prop_checkVillagesTurnLynchesOnePlayerWhenConsensus (GameWithLynchVotes game) =
-    length (getVoteResult game) == 1
-    && isn't villageIdiot target
-    ==> length (run_ checkStage game ^.. players . traverse . dead) == 1
+prop_checkVillagesTurnAdvancesToDevotedServantsTurn :: GameWithMajorityVote -> Property
+prop_checkVillagesTurnAdvancesToDevotedServantsTurn (GameWithMajorityVote game) =
+    isn't angel target && isn't devotedServant target
+    ==> has (stage . _DevotedServantsTurn) (run_ checkStage game)
     where
         target = head $ getVoteResult game
 
-prop_checkVillagesTurnLynchesNoOneWhenTargetIsVillageIdiot :: GameAtVillagesTurn -> Bool
-prop_checkVillagesTurnLynchesNoOneWhenTargetIsVillageIdiot (GameAtVillagesTurn game) = do
-    let game' = foldr (\player -> run_ (apply $ voteLynchCommand (player ^. name) (villageIdiot ^. name))) game (game ^. players)
-
-    none (is dead) (run_ checkStage game' ^. players)
-    where
-        villageIdiot = game ^?! players . villageIdiots
+prop_checkVillagesTurnSkipsDevotedServantsTurnWhenConflicted :: GameWithConflictingVote -> Bool
+prop_checkVillagesTurnSkipsDevotedServantsTurnWhenConflicted (GameWithConflictingVote game) =
+    hasn't (stage . _DevotedServantsTurn) (run_ checkStage game)
 
 -- TODO (hjw): tidy this test
-prop_checkVillagesTurnLynchesNoOneWhenConflictedAndNoScapegoats :: Game -> Property
-prop_checkVillagesTurnLynchesNoOneWhenConflictedAndNoScapegoats game =
+prop_checkLynchingLynchesNoOneWhenConflictedAndNoScapegoats :: Game -> Property
+prop_checkLynchingLynchesNoOneWhenConflictedAndNoScapegoats game =
     forAll (runArbitraryCommands n game') $ \game'' ->
     length (getVoteResult game'') > 1
     ==> run_ checkStage game'' ^. players == game' ^. players
@@ -267,23 +325,6 @@
         game'           = killPlayer scapegoatsName game & stage .~ VillagesTurn
         n               = length $ game' ^. players
 
-prop_checkVillagesTurnLynchesScapegoatWhenConflicted :: GameAtScapegoatsTurn -> Bool
-prop_checkVillagesTurnLynchesScapegoatWhenConflicted (GameAtScapegoatsTurn game) =
-    is dead $ run_ checkStage game ^?! players . scapegoats
-
-prop_checkVillagesTurnResetsVotes :: GameWithLynchVotes -> Bool
-prop_checkVillagesTurnResetsVotes (GameWithLynchVotes game) =
-    Map.null $ run_ checkStage game ^. votes
-
-prop_checkVillagesTurnSetsAllowedVoters :: GameWithLynchVotes -> Property
-prop_checkVillagesTurnSetsAllowedVoters (GameWithLynchVotes game) =
-    game' ^. allowedVoters === expectedAllowedVoters ^.. names
-    where
-        game' = run_ checkStage game
-        expectedAllowedVoters
-            | game' ^. villageIdiotRevealed = filter (isn't villageIdiot) $ game' ^. players
-            | otherwise                     = game' ^.. players . traverse . alive
-
 prop_checkVillagesTurnDoesNothingUnlessAllVoted :: GameAtVillagesTurn -> Property
 prop_checkVillagesTurnDoesNothingUnlessAllVoted (GameAtVillagesTurn game) =
     forAll (runArbitraryCommands n game) $ \game' ->
@@ -353,7 +394,7 @@
 
 prop_checkWitchsTurnAdvancesToVillagesTurn :: GameAtWitchsTurn -> Property
 prop_checkWitchsTurnAdvancesToVillagesTurn (GameAtWitchsTurn game) =
-    forAll (arbitraryPassCommand game) $ \(Blind command) ->
+    forAll (arbitraryPassWitchsTurnCommand game) $ \(Blind command) ->
     has (stage . _VillagesTurn) (run_ (apply command >> checkStage) game)
 
 prop_checkWitchsTurnAdvancesWhenNoWitch :: GameAtWitchsTurn -> Bool
@@ -365,17 +406,17 @@
 
 prop_checkWitchsTurnHealsDevoureeWhenHealed :: GameWithHeal -> Property
 prop_checkWitchsTurnHealsDevoureeWhenHealed (GameWithHeal game) =
-    forAll (arbitraryPassCommand game) $ \(Blind command) ->
+    forAll (arbitraryPassWitchsTurnCommand game) $ \(Blind command) ->
     none (is dead) (run_ (apply command >> checkStage) game ^. players)
 
 prop_checkWitchsTurnKillsOnePlayerWhenPoisoned :: GameWithPoison -> Property
 prop_checkWitchsTurnKillsOnePlayerWhenPoisoned (GameWithPoison game) =
-    forAll (arbitraryPassCommand game) $ \(Blind command) ->
+    forAll (arbitraryPassWitchsTurnCommand game) $ \(Blind command) ->
     length (run_ (apply command >> checkStage) game ^.. players . traverse . dead) == 1
 
 prop_checkWitchsTurnDoesNothingWhenPassed :: GameAtWitchsTurn -> Property
 prop_checkWitchsTurnDoesNothingWhenPassed (GameAtWitchsTurn game) =
-    forAll (arbitraryPassCommand game) $ \(Blind command) ->
+    forAll (arbitraryPassWitchsTurnCommand game) $ \(Blind command) ->
     none (is dead) $ run_ (apply command >> checkStage) game ^. players
 
 prop_checkWitchsTurnDoesNothingUnlessActionedOrPassed :: GameAtWitchsTurn -> Bool
@@ -384,17 +425,17 @@
 
 prop_checkWitchsTurnResetsHeal :: GameWithHeal -> Property
 prop_checkWitchsTurnResetsHeal (GameWithHeal game) =
-    forAll (arbitraryPassCommand game) $ \(Blind command) ->
+    forAll (arbitraryPassWitchsTurnCommand game) $ \(Blind command) ->
     not $ run_ (apply command >> checkStage) game ^. heal
 
 prop_checkWitchsTurnResetsPoison :: GameWithPoison -> Property
 prop_checkWitchsTurnResetsPoison (GameWithPoison game) =
-    forAll (arbitraryPassCommand game) $ \(Blind command) ->
+    forAll (arbitraryPassWitchsTurnCommand game) $ \(Blind command) ->
     isNothing $ run_ (apply command >> checkStage) game ^. poison
 
 prop_checkWitchsTurnClearsPasses :: GameAtWitchsTurn -> Property
 prop_checkWitchsTurnClearsPasses (GameAtWitchsTurn game) =
-    forAll (arbitraryPassCommand game) $ \(Blind command) ->
+    forAll (arbitraryPassWitchsTurnCommand game) $ \(Blind command) ->
     null $ run_ (apply command >> checkStage) game ^. passes
 
 prop_checkWolfHoundsTurnAdvancesToSeersTurn :: GameAtWolfHoundsTurn -> Property
@@ -425,6 +466,10 @@
         let game' = foldr killPlayer game (players' ^.. names)
 
         has (stage . _GameOver) $ run_ checkGameOver game'
+
+prop_checkGameOverDoesNothingWhenGameOver :: GameAtGameOver -> Property
+prop_checkGameOverDoesNothingWhenGameOver (GameAtGameOver game) =
+    run_ checkStage game === game
 
 -- TODO (hjw): pending
 --prop_checkGameOverDoesNothingWhenAtLeastTwoAllegiancesAlive :: GameWithDeadPlayers -> Property
diff --git a/test/src/Game/Werewolf/Test/Util.hs b/test/src/Game/Werewolf/Test/Util.hs
--- a/test/src/Game/Werewolf/Test/Util.hs
+++ b/test/src/Game/Werewolf/Test/Util.hs
@@ -7,7 +7,7 @@
 
 module Game.Werewolf.Test.Util (
     -- * Utility functions
-    run, run_,
+    run, run_, verbose_runCommandErrors,
 ) where
 
 import Control.Monad.Except
@@ -16,11 +16,20 @@
 
 import Data.Either.Extra
 
+import Game.Werewolf.Command
 import Game.Werewolf.Game
 import Game.Werewolf.Response
 
+import Test.QuickCheck
+
 run :: StateT Game (WriterT [Message] (Except [Message])) a -> Game -> Either [Message] (Game, [Message])
 run action game = runExcept . runWriterT $ execStateT action game
 
 run_ :: StateT Game (WriterT [Message] (Except [Message])) a -> Game -> Game
 run_ action = fst . fromRight . run action
+
+verbose_runCommandErrors :: Game -> Command -> Property
+verbose_runCommandErrors game command = whenFail (mapM_ putStrLn data_) (isLeft result)
+    where
+        result  = run (apply command) game
+        data_   = [show game, show $ fromRight result]
diff --git a/werewolf.cabal b/werewolf.cabal
--- a/werewolf.cabal
+++ b/werewolf.cabal
@@ -1,5 +1,5 @@
 name:           werewolf
-version:        0.4.8.0
+version:        0.4.9.0
 
 author:         Henry J. Wylde
 maintainer:     public@hjwylde.com
@@ -28,22 +28,23 @@
     hs-source-dirs: app/
     ghc-options:    -threaded -with-rtsopts=-N
     other-modules:
-        Werewolf.Commands.Choose
-        Werewolf.Commands.Circle
-        Werewolf.Commands.End
-        Werewolf.Commands.Heal
-        Werewolf.Commands.Help
-        Werewolf.Commands.Interpret
-        Werewolf.Commands.Pass
-        Werewolf.Commands.Ping
-        Werewolf.Commands.Poison
-        Werewolf.Commands.Protect
-        Werewolf.Commands.Quit
-        Werewolf.Commands.See
-        Werewolf.Commands.Start
-        Werewolf.Commands.Status
-        Werewolf.Commands.Version
-        Werewolf.Commands.Vote
+        Werewolf.Command.Choose
+        Werewolf.Command.Circle
+        Werewolf.Command.End
+        Werewolf.Command.Heal
+        Werewolf.Command.Help
+        Werewolf.Command.Interpret
+        Werewolf.Command.Pass
+        Werewolf.Command.Ping
+        Werewolf.Command.Poison
+        Werewolf.Command.Protect
+        Werewolf.Command.Quit
+        Werewolf.Command.Reveal
+        Werewolf.Command.See
+        Werewolf.Command.Start
+        Werewolf.Command.Status
+        Werewolf.Command.Version
+        Werewolf.Command.Vote
         Werewolf.Game
         Werewolf.Messages
         Werewolf.Options
@@ -113,6 +114,15 @@
     other-modules:
         Game.Werewolf.Test.Arbitrary
         Game.Werewolf.Test.Command
+        Game.Werewolf.Test.Command.Choose
+        Game.Werewolf.Test.Command.Heal
+        Game.Werewolf.Test.Command.Pass
+        Game.Werewolf.Test.Command.Poison
+        Game.Werewolf.Test.Command.Protect
+        Game.Werewolf.Test.Command.Quit
+        Game.Werewolf.Test.Command.Reveal
+        Game.Werewolf.Test.Command.See
+        Game.Werewolf.Test.Command.Vote
         Game.Werewolf.Test.Engine
         Game.Werewolf.Test.Game
         Game.Werewolf.Test.Player
