예제 #1
0
    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
예제 #2
0
파일: game.py 프로젝트: user01/love-letter
    def _move_guard(self, current_players, action, deck_new):
        """
        Handle a guard action into a new game state

        Player makes a guess to try and eliminate the opponent
        """
        if self._players[action.player_target].hand_card == action.guess and \
                not PlayerTools.is_defended(self._players[action.player_target]):
            # then target player is out
            player_target = PlayerTools.force_discard(
                self._players[action.player_target])
            current_players = Game._set_player(
                current_players, player_target, action.player_target)

        return Game(deck_new, current_players, self._turn_index + 1)
예제 #3
0
파일: game.py 프로젝트: user01/love-letter
    def _move_priest(self, action, player_hand_new, deck_new):
        """
        Handle a priest action into a new game state

        Action gains knowledge of other player's card
        """
        player_targets_card = Card.noCard if \
            PlayerTools.is_defended(self._players[action.player_target]) \
            else self._players[action.player_target].hand_card
        action_updated = PlayerAction(
            action.discard, action.player_target, action.guess, player_targets_card)

        player = PlayerTools.move(
            self.player(), player_hand_new, action_updated)
        current_players = Game._set_player(
            self._players, player, self.player_turn())

        return Game(deck_new, current_players, self._turn_index + 1)
예제 #4
0
    def _move_baron(self, action, current_players, player_hand_new, deck_new):
        """
        Handle a baron action into a new game state

        Player and target compare hand cards. Player with lower hand
        card is eliminated
        """
        card_target = self._players[action.player_target].hand_card
        if player_hand_new > card_target:
            if not PlayerTools.is_defended(self._players[action.player_target]):
                # target is eliminated
                player_target = PlayerTools.force_discard(
                    self._players[action.player_target])
                current_players = Game._set_player(
                    current_players, player_target, action.player_target)
                action_updated = action._replace(player=self.player_turn(),
                                                 force_discarded=card_target,
                                                 force_discarder=action.player_target)
            else:
                action_updated = action._replace(player=self.player_turn())

        elif player_hand_new == card_target:
            # Tie, nobody wins
            action_updated = action._replace(player=self.player_turn(),
                                             revealed_card=card_target)

        else:
            # player is eliminated
            player = PlayerTools.force_discard(self.player(), player_hand_new)
            player = PlayerTools.force_discard(player)
            current_players = Game._set_player(
                current_players, player, self.player_turn())
            action_updated = action._replace(player=self.player_turn(),
                                             force_discarded=player_hand_new,
                                             force_discarder=action.player)

        return Game(deck_new, current_players, self._turn_index + 1,
                    [*self._action_log, action_updated])
예제 #5
0
파일: game.py 프로젝트: user01/love-letter
    def _move_baron(self, action, current_players, player_hand_new, deck_new):
        """
        Handle a baron action into a new game state

        Player and target compare hand cards. Player with lower hand
        card is eliminated
        """
        card_target = self._players[action.player_target].hand_card
        if player_hand_new > card_target:
            if not PlayerTools.is_defended(self._players[action.player_target]):
                # target is eliminated
                player_target = PlayerTools.force_discard(
                    self._players[action.player_target])
                current_players = Game._set_player(
                    current_players, player_target, action.player_target)
        else:
            # player is eliminated
            player = PlayerTools.force_discard(self.player(), player_hand_new)
            player = PlayerTools.force_discard(player)
            current_players = Game._set_player(
                current_players, player, self.player_turn())

        return Game(deck_new, current_players, self._turn_index + 1)