Esempio n. 1
0
    def set_aside_dead_minions(self, own_board: PlayerBoard,
                               enemy_board: PlayerBoard):
        """Remove any dead minions. Return the List of minions to process any deathrattles and reborn triggers.

        Arguments:
            board {PlayerBoard} -- Player board to check for dead minions
        """
        dead_minions = own_board.select_dead()
        left_neighors = []
        for minion in dead_minions:
            left_neighors.append(minion.left_neighbor)

        # Dead minions care about their left neighbor for deathrattle/reborn positioning
        for index, minion in enumerate(dead_minions):
            own_board.remove_minion(minion, enemy_board)
            minion.left_neighbor = left_neighors[index]

        return dead_minions
Esempio 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)