Exemplo n.º 1
0
    def resolve_extra_attacks(self, attacking_player_board: PlayerBoard,
                              defending_player_board: PlayerBoard):
        """Resolve any 'attacks immediately' minions and the consequences of those attacks

        Arguments:
            attacking_player_board {PlayerBoard} -- Player board of attacking player
            defending_player_board {PlayerBoard} -- Player board of defending player
        """
        for attacker in attacking_player_board.get_immediate_attack_minions():
            attacker.immediate_attack_pending = False
            defender = defending_player_board.select_defending_minion()
            if defender:
                self.attack(attacker, defender, attacking_player_board,
                            defending_player_board)
                self.check_deaths(attacking_player_board,
                                  defending_player_board)
            else:
                return
Exemplo n.º 2
0
    def check_deaths(self, attacking_player_board: PlayerBoard,
                     defending_player_board: PlayerBoard):
        """Check deaths on both sides, collect death rattles, process them and resolve consequences (immediate attacks / reborn triggers)

        Arguments:
            attacking_player_board {PlayerBoard} -- Player board of attacking player
            defending_player_board {PlayerBoard} -- Player board of defending player
        """
        # General flow of resolving death states:
        # Resolve attacker deathrattles from left to right, multiplied by baron
        #     Resolve extra attacks after each deathrattle resolves (then recursively check deaths)
        # Resolve defender deathrattles from left to right, multiplied by baron
        #     Resolve extra attacks after each deathrattle resolves (then recursively check deaths)

        # There are some DRY vibes here but for now this is fine
        attacker_dead_minions = self.set_aside_dead_minions(
            attacking_player_board, defending_player_board)
        defender_dead_minions = self.set_aside_dead_minions(
            defending_player_board, attacking_player_board)

        if len(attacker_dead_minions) == 0 and len(defender_dead_minions) == 0 \
            and len(attacking_player_board.get_immediate_attack_minions()) == 0 \
            and len(defending_player_board.get_immediate_attack_minions()) == 0:
            return

        # Resolve death rattles and 'attacks immediately' triggers. Attacker first, then defender
        # TODO: immediate attacks on defender side resolve before attacks deathrattles?
        # TODO: Is there a consistent order to deathrattles??
        for minion in attacker_dead_minions:
            for deathrattle in minion.deathrattles:
                for _ in range(attacking_player_board.deathrattle_multiplier):
                    deathrattle.trigger(minion, attacking_player_board,
                                        defending_player_board)

        # Resolve "after a friendly minion dies" triggers. ie soul juggles after deathrattles
        # TODO: Refactor for performance
        for minion in attacking_player_board.get_living_minions():
            for dead_minion in attacker_dead_minions:
                minion.on_friendly_removal_after(dead_minion,
                                                 attacking_player_board,
                                                 defending_player_board)

        for minion in defender_dead_minions:
            for deathrattle in minion.deathrattles:
                for _ in range(defending_player_board.deathrattle_multiplier):
                    deathrattle.trigger(minion, defending_player_board,
                                        attacking_player_board)

        for minion in defending_player_board.get_living_minions():
            for dead_minion in defender_dead_minions:
                minion.on_friendly_removal_after(dead_minion,
                                                 defending_player_board,
                                                 attacking_player_board)

        # Process deaths here again to see if death rattles resulted in more deaths
        if len(attacking_player_board.select_dead()) > 0 or len(
                defending_player_board.select_dead()):
            self.check_deaths(attacking_player_board, defending_player_board)

        # Resolve reborns after deathrattles
        for minion in attacker_dead_minions:
            if minion.reborn and not minion.reborn_triggered:
                minion.trigger_reborn(attacking_player_board)

        for minion in defender_dead_minions:
            if minion.reborn and not minion.reborn_triggered:
                minion.trigger_reborn(defending_player_board)

        # Continue to resolve extra attacks until all are done
        while attacking_player_board.get_immediate_attack_minions(
        ) or defending_player_board.get_immediate_attack_minions():
            # TODO: Is there a priority for resolving pirate attacks on each other? Are they queued up?
            self.resolve_extra_attacks(attacking_player_board,
                                       defending_player_board)
            self.resolve_extra_attacks(defending_player_board,
                                       attacking_player_board)