Exemplo n.º 1
0
    def _action_to_move(self, action: int,
                        battle: Battle) -> str:  # pyre-ignore
        """Converts actions to move orders. There are 676 actions - and they can be thought of as a 26 x 26 matrix (first mon's possibilities
        and second mon's possibilities). This is not quite true because you cant choose the same mon twice to switch to, but we handle that when
        determining the legality of the move choices later; If the proposed action is illegal, a random legal move is performed.
        The conversion is done as follows:

        :param action: The action to convert.
        :type action: int
        :param battle: The battle in which to act.
        :type battle: Battle
        :return: the order to send to the server.
        :rtype: str
        """
        row, col = action % 26, int(action / 26)
        first_order = self._action_to_single_move(
            row, 0, battle) if battle.active_pokemon[0] else None
        second_order = self._action_to_single_move(
            col, 1, battle) if battle.active_pokemon[1] else None

        double_order = DoubleBattleOrder(first_order=first_order,
                                         second_order=second_order)
        if DoubleBattleOrder.is_valid(battle, double_order):
            return double_order
        else:
            return DefaultBattleOrder()
Exemplo n.º 2
0
    def choose_default_move(self, *args, **kwargs) -> DefaultBattleOrder:
        """Returns showdown's default move order.

        This order will result in the first legal order - according to showdown's
        ordering - being chosen.
        """
        return DefaultBattleOrder()
Exemplo n.º 3
0
    def choose_move(self, battle):
        orders = self.get_all_doubles_moves(battle)

        filtered_orders = list(
            filter(lambda x: DoubleBattleOrder.is_valid(battle, x), orders))
        if filtered_orders: order = random.choice(filtered_orders)
        else: order = DefaultBattleOrder()
        return order
Exemplo n.º 4
0
    def choose_random_doubles_move(self, battle: DoubleBattle) -> BattleOrder:
        active_orders = [[], []]

        for (
                idx,
            (orders, mon, switches, moves, can_mega, can_z_move, can_dynamax),
        ) in enumerate(
                zip(
                    active_orders,
                    battle.active_pokemon,
                    battle.available_switches,
                    battle.available_moves,
                    battle.can_mega_evolve,
                    battle.can_z_move,
                    battle.can_dynamax,
                )):
            if mon:
                targets = {
                    move: battle.get_possible_showdown_targets(move, mon)
                    for move in moves
                }
                orders.extend([
                    BattleOrder(move, move_target=target) for move in moves
                    for target in targets[move]
                ])
                orders.extend([BattleOrder(switch) for switch in switches])

                if can_mega:
                    orders.extend([
                        BattleOrder(move, move_target=target, mega=True)
                        for move in moves for target in targets[move]
                    ])
                if can_z_move:
                    available_z_moves = set(mon.available_z_moves)
                    orders.extend([
                        BattleOrder(move, move_target=target, z_move=True)
                        for move in moves for target in targets[move]
                        if move in available_z_moves
                    ])

                if can_dynamax:
                    orders.extend([
                        BattleOrder(move, move_target=target, dynamax=True)
                        for move in moves for target in targets[move]
                    ])

                if sum(battle.force_switch) == 1:
                    if orders:
                        return orders[int(random.random() * len(orders))]
                    return self.choose_default_move()

        orders = DoubleBattleOrder.join_orders(*active_orders)

        if orders:
            return orders[int(random.random() * len(orders))]
        else:
            return DefaultBattleOrder()
    def choose_move(self, battle):

        orders = self.get_all_doubles_moves(battle)
        order = None

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

            filtered_orders = list(
                filter(lambda x: DoubleBattleOrder.is_valid(battle, x),
                       orders))
            reasonable_orders = self._filter_to_reasonable_moves(
                battle, filtered_orders)

            if reasonable_orders: order = random.choice(reasonable_orders)
            if len(filtered_orders) > 0: order = random.choice(filtered_orders)
            else: order = DefaultBattleOrder()

            return order

        # Force Switch situation
        else:
            return random.choice(orders)
Exemplo n.º 6
0
    def _convertPartialMessage(self, battle, msg, index):
        if msg == self._DEFAULT_ORDER: return DefaultBattleOrder()

        order, target, mega, dynamax, z_move = None, None, False, False, False
        if 'switch' in msg:
            order = Pokemon(species=re.search("switch\s([a-zA-Z\-\_0-9]+).*",
                                              msg).group(1).lower())
        elif 'move' in msg:
            tokens = msg.split(" ")
            order = Move(tokens[1])

            if len(tokens) <= 2: target = DoubleBattle.EMPTY_TARGET_POSITION
            else:
                target = tokens[2]
                if target.strip().isdigit(): target = int(target)
                elif battle.opponent_active_pokemon[0].species == target.strip(
                ):
                    target = active_pokemon_to_showdown_target(0, opp=True)
                elif battle.opponent_active_pokemon[1].species == target.strip(
                ):
                    target = active_pokemon_to_showdown_target(1, opp=True)
                elif battle.active_pokemon[1 -
                                           index].species == target.strip():
                    target = active_pokemon_to_showdown_target(1 - index,
                                                               opp=False)

        if ' mega' in msg: mega = True
        if 'dynamax' in msg: dynamax = True
        if 'z_move' in msg: z_move = True

        return BattleOrder(order,
                           move_target=target,
                           actor=battle.active_pokemon[index],
                           mega=mega,
                           dynamax=dynamax,
                           z_move=z_move)
    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
 def choose_move(self, battle):
     return DefaultBattleOrder()