def test_move_handmaid(self): """Deploy the handmaid and survive attack""" game = Game.new(4, 2) action = PlayerAction(Card.handmaid, 0, Card.noCard, Card.noCard) game, _ = game.move(action) players = game.players() player = players[0] self.assertTrue(PlayerTools.is_playing(player)) self.assertFalse(PlayerActionTools.is_blank(player.actions[0])) self.assertEqual(player.actions[0], action) for action in player.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action)) action_attack = PlayerAction(Card.guard, 0, Card.prince, Card.noCard) game, _ = game.move(action_attack) players = game.players() target = players[0] player = players[1] self.assertTrue(PlayerTools.is_playing(player)) self.assertTrue(PlayerTools.is_playing(target)) self.assertFalse(PlayerActionTools.is_blank(player.actions[0])) self.assertEqual(player.actions[0], action_attack) for action in player.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action)) for action in target.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action))
def test_move_guard_success(self): """Getting a guard move, with a right guess""" game = Game.new() action = PlayerAction(Card.guard, 3, Card.handmaid, 0) self.assertEqual(len(game.opponents()), 3) self.assertListEqual(game.opponent_turn(), [1, 2, 3]) game, _ = game.move(action) self.assertEqual(game.round(), 0) self.assertEqual(game.player_turn(), 1) self.assertEqual(game.cards_left(), 10) self.assertTrue(game.active()) self.assertFalse(game.over()) players = game.players() player = players[0] target = players[3] recent_action = player.actions[0] self.assertListEqual(game.opponent_turn(), [0, 2]) self.assertEqual(len(game.opponents()), 2) self.assertFalse(PlayerTools.is_playing(target)) self.assertEqual(recent_action, action) self.assertEqual(player.hand_card, Card.handmaid) self.assertFalse(PlayerActionTools.is_blank(recent_action)) for action in player.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action))
def test_blank(self): """Create an action""" # play guard, on player 3, guessing Prince, no revealed card action_normal = PlayerAction(1, 3, 5, 0) self.assertEqual(PlayerActionTools.is_blank(action_normal), False) # no action - either hasn't been taken or player was eliminated action_blank = PlayerAction(0, 0, 0, 0) self.assertEqual(PlayerActionTools.is_blank(action_blank), True)
def test_init(self): """Create a Player""" player = PlayerTools.blank(1) self.assertEqual(player.hand_card, 1) self.assertEqual(len(player.actions), 8) for action in player.actions: self.assertTrue(PlayerActionTools.is_blank(action))
def test_move_prince_self(self): """Use prince to force self discard""" game = Game.new(4, 2) action = PlayerAction(Card.prince, 0, Card.noCard, Card.noCard) action_other = PlayerAction(Card.handmaid, 0, Card.noCard, Card.noCard) game, _ = game.move(action) players = game.players() player = players[0] self.assertTrue(PlayerTools.is_playing(player)) self.assertFalse(PlayerActionTools.is_blank(player.actions[0])) self.assertFalse(PlayerActionTools.is_blank(player.actions[1])) self.assertEqual(player.actions[0], action) self.assertEqual(player.actions[1], action_other) for action in player.actions[2:]: self.assertTrue(PlayerActionTools.is_blank(action))
def test_init(self): """Create an action""" # play guard, on player 3, guessing Prince, no revealed card action = PlayerAction(1, 3, 5, 0) self.assertEqual(action.discard, 1) self.assertEqual(action.player_target, 3) self.assertEqual(action.guess, 5) self.assertEqual(action.revealed_card, 0) self.assertEqual(PlayerActionTools.is_blank(action), False)
def test_move_princess(self): """Commit suicide by discarding the princess""" game = Game.new(4, 11) action = PlayerAction(Card.princess, 0, Card.noCard, Card.noCard) game, _ = game.move(action) players = game.players() player = players[0] self.assertFalse(PlayerTools.is_playing(player)) self.assertFalse(PlayerActionTools.is_blank(player.actions[0])) self.assertFalse(PlayerActionTools.is_blank(player.actions[1])) self.assertEqual(player.actions[0], PlayerAction(Card.baron, 0, Card.noCard, Card.noCard)) self.assertEqual(player.actions[1], action) for action in player.actions[2:]: self.assertTrue(PlayerActionTools.is_blank(action))
def test_move_baron_failure(self): """Getting a baron move, with a failure""" game = Game.new(4, 48) action = PlayerAction(Card.baron, 1, Card.noCard, Card.noCard) game, _ = game.move(action) players = game.players() player = players[0] target = players[1] self.assertFalse(PlayerTools.is_playing(player)) self.assertTrue(PlayerTools.is_playing(target)) self.assertFalse(PlayerActionTools.is_blank(player.actions[0])) self.assertFalse(PlayerActionTools.is_blank(player.actions[1])) for action in player.actions[2:]: self.assertTrue(PlayerActionTools.is_blank(action)) for action in target.actions: self.assertTrue(PlayerActionTools.is_blank(action))
def test_move_king(self): """Use king to swap hands with the target""" game = Game.new(4, 0) action = PlayerAction(Card.king, 1, Card.noCard, Card.noCard) game, _ = game.move(action) players = game.players() player = players[0] target = players[1] self.assertTrue(PlayerTools.is_playing(player)) self.assertFalse(PlayerActionTools.is_blank(player.actions[0])) self.assertEqual(player.actions[0], action) self.assertEqual(player.hand_card, Card.priest) for action in player.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action)) self.assertTrue(PlayerTools.is_playing(target)) self.assertEqual(target.hand_card, Card.guard) for action in target.actions: self.assertTrue(PlayerActionTools.is_blank(action))
def is_action_valid(self, action): """Tests if an action is valid given the current game state""" player = self.player() # if player is out, only valid action is no action if player.hand_card == Card.noCard: return PlayerActionTools.is_blank(action) target_player = self._players[action.player_target] player_hand = [player.hand_card, self._deck[0]] # cannot discard a card not in the hand if action.discard not in player_hand: return False new_hand_card = Game.new_hand_card(action.discard, player_hand) # countess must be discarded if the other card is king/prince if new_hand_card == Card.countess and \ (action.discard == Card.prince or action.discard == Card.king): return False # cannot target an invalid player if not self._is_valid_player_target(action.player_target): return False # cannot mis-target a card if self.player_turn() == action.player_target and action.discard in Card.only_other: # Check if self is the only valid target due to everybody else protected (or dead) other_players_invalid = [not PlayerTools.is_playing(p) or PlayerTools.is_defended(p) for p in self._players if p is not self.player()] if all(other_players_invalid): return True else: return False if self.player_turn() != action.player_target and action.discard in Card.only_self: return False if not PlayerTools.is_playing(target_player): return False # Check if target is defender (and not the current player) if PlayerTools.is_defended(target_player) and player != target_player: return False # Cannot guess guard or no card if action.discard == Card.guard and ( action.guess == Card.guard or action.guess == Card.noCard): return False return True
def test_move_baron_success(self): """Getting a baron move, with a success""" game = Game.new(4, 48) action = PlayerAction(Card.baron, 3, Card.noCard, Card.noCard) game, _ = game.move(action) players = game.players() player = players[0] target = players[3] recent_action = player.actions[0] self.assertTrue(PlayerTools.is_playing(player)) self.assertFalse(PlayerTools.is_playing(target)) self.assertEqual(recent_action, action) self.assertFalse(PlayerActionTools.is_blank(recent_action)) for action in player.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action)) self.assertFalse(PlayerActionTools.is_blank(target.actions[0])) for action in target.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action))
def test_move_prince_other(self): """Use prince to force another to discard""" game = Game.new(4, 2) action = PlayerAction(Card.prince, 1, Card.noCard, Card.noCard) action_target = PlayerAction(Card.guard, 0, Card.noCard, Card.noCard) game, _ = game.move(action) players = game.players() player = players[0] target = players[1] self.assertTrue(PlayerTools.is_playing(player)) self.assertFalse(PlayerActionTools.is_blank(player.actions[0])) self.assertEqual(player.actions[0], action) for action in player.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action)) self.assertTrue(PlayerTools.is_playing(target)) self.assertFalse(PlayerActionTools.is_blank(target.actions[0])) self.assertEqual(target.actions[0], action_target) for action in target.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action))
def test_move(self): """Player performs a move""" player = PlayerTools.blank(1) player_next = PlayerTools.move(player, 4, PlayerAction(3, 2, 0, 0)) self.assertEqual(player.hand_card, 1) self.assertEqual(len(player.actions), 8) for action in player.actions: self.assertTrue(PlayerActionTools.is_blank(action)) self.assertEqual(player_next.hand_card, 4) self.assertEqual(len(player_next.actions), 8) action = player_next.actions[0] self.assertEqual(action.discard, 3) self.assertEqual(action.player_target, 2) self.assertEqual(action.guess, 0) self.assertEqual(action.revealed_card, 0) self.assertEqual(PlayerActionTools.is_blank(action), False) for action in player_next.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action))
def test_move_priest(self): """Getting a priest move""" game = Game.new(4, 5) action = PlayerAction(Card.priest, 1, Card.noCard, Card.noCard) action_expected = PlayerAction(Card.priest, 1, Card.noCard, Card.guard) game, _ = game.move(action) self.assertEqual(game.round(), 0) self.assertEqual(game.player_turn(), 1) self.assertEqual(game.cards_left(), 10) self.assertTrue(game.active()) self.assertFalse(game.over()) players = game.players() player = players[0] target = players[1] recent_action = player.actions[0] self.assertTrue(PlayerTools.is_playing(target)) self.assertEqual(recent_action, action_expected) self.assertFalse(PlayerActionTools.is_blank(recent_action)) for action in player.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action))
def test_move_guard_failure(self): """Getting a guard move, with a wrong guess""" game = Game.new() action = PlayerAction(Card.guard, 1, Card.handmaid, 0) game, _ = game.move(action) self.assertEqual(game.round(), 0) self.assertEqual(game.player_turn(), 1) self.assertEqual(game.cards_left(), 10) self.assertTrue(game.active()) self.assertFalse(game.over()) players = game.players() player = players[0] target = players[1] recent_action = player.actions[0] self.assertTrue(PlayerTools.is_playing(target)) self.assertEqual(recent_action, action) self.assertEqual(player.hand_card, Card.handmaid) self.assertFalse(PlayerActionTools.is_blank(recent_action)) for action in player.actions[1:]: self.assertTrue(PlayerActionTools.is_blank(action))
def test_move_guard_guess_guard(self): """Getting a guard move and guessing guard""" game = Game.new() action = PlayerAction(Card.guard, 1, Card.guard, 0) game, _ = game.move(action) self.assertEqual(game.round(), 0) self.assertEqual(game.player_turn(), 0) self.assertEqual(game.cards_left(), 11) self.assertTrue(game.active()) self.assertFalse(game.over()) players = game.players() player = players[0] target = players[1] recent_action = player.actions[0] self.assertTrue(PlayerTools.is_playing(player)) self.assertEqual(player.hand_card, Card.handmaid) self.assertEqual(game.deck()[0], Card.guard) self.assertTrue(PlayerActionTools.is_blank(recent_action)) for action in player.actions: self.assertTrue(PlayerActionTools.is_blank(action))
def is_action_valid(self, action): """Tests if an action is valid given the current game state""" player = self.player() # if player is out, only valid action is no action if player.hand_card == Card.noCard: return PlayerActionTools.is_blank(action) target_player = self._players[action.player_target] player_hand = [player.hand_card, self._deck[0]] # cannot discard a card not in the hand if action.discard not in player_hand: return False new_hand_card = Game.new_hand_card(action.discard, player_hand) # countess must be discarded if the other card is king/prince if new_hand_card == Card.countess and \ (action.discard == Card.prince or action.discard == Card.king): return False # cannot target an invalid player if not self._is_valid_player_target(action.player_target): return False # cannot mis-target a card if self.player_turn() == action.player_target and action.discard in Card.only_other: return False if self.player_turn() != action.player_target and action.discard in Card.only_self: return False if not PlayerTools.is_playing(target_player): return False # Cannot guess guard or no card if action.discard == Card.guard and ( action.guess == Card.guard or action.guess == Card.noCard): return False return True