def _useless_self_hit(self, battle, order: BattleOrder):

        # Eliminate easy conditions in which this is not a useless self hit
        if not order or not order.is_move(): return False
        if not (order.order.damage or order.order.base_power > 0): return False
        if order.order.self_switch: return False

        # If it's a self-hit
        affected_targets = BattleOrder.get_affected_targets(battle, order)
        if affected_targets and min(affected_targets) < 0:

            # Get the mon who is going to be hit
            target_mon = battle.active_pokemon[min(affected_targets)]

            # Only allow this as a potential move under these conditions
            if target_mon.item == 'weaknesspolicy' and order.order.type.damage_multiplier(
                    *target_mon.types) >= 2:
                return True
            elif target_mon.ability == 'Berserk':
                return False
            elif target_mon.ability == 'Justified' and order.order.type == 'DARK':
                return False
            elif target_mon.ability == 'Water Absorb' and order.order.type == 'WATER':
                return False
            elif target_mon.ability == 'Volt Absorb' and order.order.type == 'ELECTRIC':
                return False
            elif target_mon.ability == 'Flash Fire' and order.order.type == 'FIRE':
                return False
            else:
                return True

        return False
    def choose_move(self, battle):

        best_order = DefaultBattleOrder()

        # If we're not being forced to switch and are choosing our moves
        if not any(battle.force_switch):

            # Go through and get actions, filter them down to what's possible, and then eliminate ones that dont make sense
            orders = self.get_all_doubles_moves(battle)
            filtered_orders = list(
                filter(lambda x: x and DoubleBattleOrder.is_valid(battle, x),
                       orders))

            # Iterate through all actions to pick best short-term move. These are our stored values
            most_damage, best_switch_multiplier = 0, 0

            # Go through every reasonable pair of actions and pick the pair that does the most high damage moves and multipliers of switch
            for double_order in filtered_orders:
                damage, switch_multiplier = 0, 0

                # Add up damage I'm probably going to do and switch multipliers compared to active pokemon
                for order in [
                        double_order.first_order, double_order.second_order
                ]:
                    if not order: continue

                    # If damaging move, Go through each potential target and add up damage (subtract if self-damage)
                    if order.is_move() and (order.order.damage
                                            or order.order.base_power > 0):
                        targets = BattleOrder.get_affected_targets(
                            battle, order)
                        if targets == None: targets = []

                        for target in targets:
                            stab = 1.5 if order.order.type in order.actor.types else 1
                            target_mon = utils.showdown_target_to_mon(
                                battle, target)

                            effectiveness = order.order.type.damage_multiplier(
                                *target_mon.types
                            ) if target_mon is not None else 1
                            base_power = order.order.base_power

                            damage += base_power * stab * effectiveness * (
                                -1 if target < 0 else 1)

                            if order.dynamax: damage += 1

                    # Calculate whether we're going to switch into an good environment (wrt types)
                    elif order.is_switch():
                        switch_multiplier += np.mean([
                            compute_type_advantage(order.actor, opp)
                            for opp in filter(lambda x: x is not None,
                                              battle.opponent_active_pokemon)
                        ])

                # Choose move if it does highest damage, and then if tied, the one that has the best switch
                if damage > most_damage:
                    best_order, most_damage, best_switch_multiplier = double_order, damage, switch_multiplier
                elif damage == most_damage and switch_multiplier >= best_switch_multiplier:
                    best_order, most_damage, best_switch_multiplier = double_order, damage, switch_multiplier

        # Force Switch situation; pick switch that has the best type advantage against the opponent's active mons
        else:
            orders = self.get_all_doubles_moves(battle)
            filtered_orders = list(
                filter(lambda x: DoubleBattleOrder.is_valid(battle, x),
                       orders))

            # Go through every possible switch and choose one that has best type advantage against opponent's mon
            multiplier = -np.inf
            for double_order in filtered_orders:
                if not double_order.first_order or not double_order.first_order.is_switch(
                ):
                    continue

                # Store the score if there's a better switch
                multipliers = []
                for opp in battle.opponent_active_pokemon:
                    if opp is not None:
                        multipliers.append(
                            compute_type_advantage(
                                double_order.first_order.actor, opp))

                if np.mean(multipliers) > multiplier:
                    best_order, multiplier = double_order, np.mean(multipliers)

        return best_order