def setUp(self):
     self.state = State(
         Side(
             Pokemon.from_state_pokemon_dict(StatePokemon("pikachu", 100).to_dict()),
             {
                 "rattata": Pokemon.from_state_pokemon_dict(StatePokemon("rattata", 100).to_dict()),
                 "charmander": Pokemon.from_state_pokemon_dict(StatePokemon("charmander", 100).to_dict()),
                 "squirtle": Pokemon.from_state_pokemon_dict(StatePokemon("squirtle", 100).to_dict()),
                 "bulbasaur": Pokemon.from_state_pokemon_dict(StatePokemon("bulbasaur", 100).to_dict()),
                 "pidgey": Pokemon.from_state_pokemon_dict(StatePokemon("pidgey", 100).to_dict())
             },
             (0, 0),
             defaultdict(lambda: 0)
         ),
         Side(
             Pokemon.from_state_pokemon_dict(StatePokemon("pikachu", 100).to_dict()),
             {
                 "rattata": Pokemon.from_state_pokemon_dict(StatePokemon("rattata", 100).to_dict()),
                 "charmander": Pokemon.from_state_pokemon_dict(StatePokemon("charmander", 100).to_dict()),
                 "squirtle": Pokemon.from_state_pokemon_dict(StatePokemon("squirtle", 100).to_dict()),
                 "bulbasaur": Pokemon.from_state_pokemon_dict(StatePokemon("bulbasaur", 100).to_dict()),
                 "pidgey": Pokemon.from_state_pokemon_dict(StatePokemon("pidgey", 100).to_dict())
             },
             (0, 0),
             defaultdict(lambda: 0)
         ),
         None,
         None,
         False
     )
     self.mutator = StateMutator(self.state)
Example #2
0
def pick_safest_move_using_dynamic_search_depth(battles):
    """
    Dynamically decides how far to look into the game.

    This requires a strong computer to be able to search 3/4 turns ahead.
    Using a pypy interpreter will also result in better performance.

    """
    all_scores = dict()
    num_battles = len(battles)

    if num_battles > 1:
        search_depth = 2

        for i, b in enumerate(battles):
            state = b.create_state()
            mutator = StateMutator(state)
            user_options, opponent_options = b.get_all_options()
            logger.debug("Searching through the state: {}".format(mutator.state))
            scores = get_payoff_matrix(mutator, user_options, opponent_options, depth=search_depth, prune=True)
            prefixed_scores = prefix_opponent_move(scores, str(i))
            all_scores = {**all_scores, **prefixed_scores}

    elif num_battles == 1:
        search_depth = 3

        b = battles[0]
        state = b.create_state()
        mutator = StateMutator(state)
        user_options, opponent_options = b.get_all_options()

        num_user_options = len(user_options)
        num_opponent_options = len(opponent_options)
        options_product = num_user_options * num_opponent_options
        if options_product < 20 and num_user_options > 1 and num_opponent_options > 1:
            logger.debug("Low options product, looking an additional depth")
            search_depth += 1

        logger.debug("Searching through the state: {}".format(mutator.state))
        logger.debug("Options Product: {}".format(options_product))
        logger.debug("My Options: {}".format(user_options))
        logger.debug("Opponent Options: {}".format(opponent_options))
        logger.debug("Search depth: {}".format(search_depth))
        all_scores = get_payoff_matrix(mutator, user_options, opponent_options, depth=search_depth, prune=True)

    else:
        raise ValueError("less than 1 battle?: {}".format(battles))

    decision, payoff = pick_safest(all_scores, remove_guaranteed=True)
    bot_choice = decision[0]
    logger.debug("Safest: {}, {}".format(bot_choice, payoff))
    logger.debug("Depth: {}".format(search_depth))
    return bot_choice
Example #3
0
 def generate_next_child(self, chosen_transition):
     """
     Generates a child node by choosing the most likely mutation instructions
     (instructions are potential results of a transition) of the given transition.
     Params:
         - chosen_transition: the pair of (our move : opponent move) to apply
     """
     mutator = StateMutator(copy.deepcopy(self.state))
     state_instructions = get_all_state_instructions(
         mutator, chosen_transition[0], chosen_transition[1])
     choice = max(state_instructions,
                  key=lambda i: i.percentage).instructions
     mutator.apply(choice)
     return MonteCarloTree(mutator.state)
Example #4
0
    def find_best_move(self):
        battles = self.prepare_battles()
        if len(battles) > 7:
            logger.debug(
                "Not enough is known about the opponent's active pokemon - falling back to safest decision making"
            )
            battles = self.prepare_battles(join_moves_together=True)
            decision = pick_safest_move_from_battles(battles)
        else:
            list_of_payoffs = list()
            for b in battles:
                state = b.create_state()
                mutator = StateMutator(state)
                logger.debug("Attempting to find best move from: {}".format(
                    mutator.state))
                user_options, opponent_options = b.get_all_options()
                scores = get_payoff_matrix(mutator,
                                           user_options,
                                           opponent_options,
                                           prune=False)
                list_of_payoffs.append(scores)

            decision = pick_move_in_equilibrium_from_multiple_score_lookups(
                list_of_payoffs)

        return format_decision(self, decision)
Example #5
0
    def pick_bfs_move(self, battle):

        state = battle.create_state()
        mutator = StateMutator(state)
        user_options, opponent_options = battle.get_all_options()
        logger.debug("Attempting to find best move from: {}".format(mutator.state))

        is_winning = self.is_winning(state)

        # Builds a tree to search for opponent's moves, assume opponent picks safest
        scores = get_payoff_matrix(mutator, user_options, opponent_options, is_winning, depth=3, prune=True)

        logger.debug(f"\nScores: {scores}")

        move_string = "Aggresive"

        if is_winning:
            decision, payoff = self.pick_safest(scores)
            move_string = "Safest"
        else:
            decision, payoff = self.pick_aggresive(scores)

        bot_choice = decision[0]
        logger.debug(f"{move_string}: {bot_choice}, {payoff}")
        return bot_choice
Example #6
0
def calculate_value(state, transition, depth):
    """
    Takes in the current state, a specific transition (pair of our move and opponent move), 
    and estimates the value associated with applying this transition at current search depth, 
    taking into account the probability of this transition occuring
    """
    state_instructions = get_all_state_instructions(StateMutator(state),
                                                    transition[0],
                                                    transition[1])

    total_value = 0

    for instruction in state_instructions:
        mutator = StateMutator(copy.deepcopy(state))
        mutator.apply(instruction.instructions)
        value = expectiminimax(mutator.state, depth)
        total_value += value * instruction.percentage

    return total_value
Example #7
0
    def random_playout(self, initial_position, depth):
        """
        Random playout of from this node. If max depth is reached then
        the evaluation function of the state is compared against initial_position.
        If the evaluation of the state is better than the initial position, it is
        counted as win, since the bot position was improved.
        """
        self.total += 1

        mutator = StateMutator(copy.deepcopy(self.state))
        while True:
            if depth == MAX_DEPTH:
                if evaluate(mutator.state) >= initial_position:
                    self.wins += 1
                    return True
                else:
                    return False

            winner = mutator.state.battle_is_finished()
            if winner:
                if winner == 1:
                    self.wins += 1
                    return True
                else:
                    return False

            transition = random.choice(get_transitions(mutator.state))
            state_instructions = get_all_state_instructions(
                mutator, transition[0], transition[1])
            possible_instrucitons = [
                i.instructions for i in state_instructions
            ]
            weights = [i.percentage for i in state_instructions]
            choice = random.choices(possible_instrucitons, weights=weights)[0]
            mutator.apply(choice)

            depth += 1
Example #8
0
def pick_safest_move_from_battles(battles):
    all_scores = dict()
    for i, b in enumerate(battles):
        state = b.create_state()
        mutator = StateMutator(state)
        user_options, opponent_options = b.get_all_options()
        logger.debug("Searching through the state: {}".format(mutator.state))
        scores = get_payoff_matrix(mutator, user_options, opponent_options, depth=config.search_depth, prune=True)

        prefixed_scores = prefix_opponent_move(scores, str(i))
        all_scores = {**all_scores, **prefixed_scores}

    decision, payoff = pick_safest(all_scores, remove_guaranteed=True)
    bot_choice = decision[0]
    logger.debug("Safest: {}, {}".format(bot_choice, payoff))
    return bot_choice
Example #9
0
def pick_safest_move_from_battles(battles):
    all_scores = dict()
    for i, b in enumerate(battles):
        state = b.create_state()
        mutator = StateMutator(state)
        user_options, opponent_options = b.get_all_options()
        logger.debug("Attempting to find best move from: {}".format(
            mutator.state))
        scores = get_payoff_matrix(mutator,
                                   user_options,
                                   opponent_options,
                                   prune=True)
        prefixed_scores = prefix_opponent_move(scores, str(i))
        all_scores = {**all_scores, **prefixed_scores}

    decision, payoff = pick_safest(all_scores)
    bot_choice = decision[0]
    logger.debug("Safest: {}, {}".format(bot_choice, payoff))
    return bot_choice
Example #10
0
def make_a_choice(battles):
    # Battles is a list of possible states the opponent's team might be in
    # The list is based on guesses done by the framework, one battle per guess
    # There's always at least one battle
    # The probability of each battle/state can be assumed to be equal

    # Below a battle is transformed into a StateMutator
    # We can apply choices to the StateMutator in order to create new states
    a_battle = battles[0]
    a_state = a_battle.to_object()
    a_mutator = StateMutator(a_state)

    # Fetch possible options for you and your opponent by calling get_all_options on a StateMutator
    # user_options includes using one of your four moves or switching to a remaining Pokémon
    # opponent_options is based on assumptions about what the opponent might be able to do
    user_options, opponent_options = get_all_options(a_mutator)

    # We can evaluate a state using the pre-defined evaluate method
    # The method is already fine-tuned in order to save us some time
    # But you can play around with it by checking out evaluate.py
    a_score = evaluate(a_mutator.state)

    # By picking an option and assuming the opponent's option, we can generate a list of low-level state instructions
    # Because certain moves can lead to several different states (because of randomness), the list of possible instructions might be long
    # Applying one of the possible instructions to the StateMutator mutates the state
    # After evaluating the score of the new state, we might want to reverse the changes and try something else
    all_possible_instructions = get_all_state_instructions(
        a_mutator, user_options[0], opponent_options[0])
    a_mutator.apply(all_possible_instructions[0].instructions)
    a_mutator.reverse(all_possible_instructions[0].instructions)

    # Logging data might be handy
    logger.debug("User's options: {}".format(user_options))
    logger.debug("Opponent's options: {}".format(opponent_options))
    logger.debug("Current state's score: {}".format(a_score))

    # For now, let's just return a random choice
    a_random_choice = random.choice(user_options)
    logger.debug("Move chosen: {}".format(a_random_choice))
    return a_random_choice
class TestStatemutator(unittest.TestCase):
    def setUp(self):
        self.state = State(
            Side(
                Pokemon.from_state_pokemon_dict(
                    StatePokemon("pikachu", 100).to_dict()), {
                        "rattata":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("rattata", 100).to_dict()),
                        "charmander":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("charmander", 100).to_dict()),
                        "squirtle":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("squirtle", 100).to_dict()),
                        "bulbasaur":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("bulbasaur", 100).to_dict()),
                        "pidgey":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("pidgey", 100).to_dict())
                    }, defaultdict(lambda: 0)),
            Side(
                Pokemon.from_state_pokemon_dict(
                    StatePokemon("pikachu", 100).to_dict()), {
                        "rattata":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("rattata", 100).to_dict()),
                        "charmander":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("charmander", 100).to_dict()),
                        "squirtle":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("squirtle", 100).to_dict()),
                        "bulbasaur":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("bulbasaur", 100).to_dict()),
                        "pidgey":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("pidgey", 100).to_dict())
                    }, defaultdict(lambda: 0)), None, None, False)
        self.mutator = StateMutator(self.state)

    def test_switch_instruction_replaces_active(self):
        instruction = (constants.MUTATOR_SWITCH, constants.SELF, "pikachu",
                       "rattata")

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual("rattata", self.state.self.active.id)

    def test_switch_instruction_replaces_active_for_opponent(self):
        instruction = (constants.MUTATOR_SWITCH, constants.OPPONENT, "pikachu",
                       "rattata")

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual("rattata", self.state.opponent.active.id)

    def test_switch_instruction_places_active_into_reserve(self):
        instruction = (constants.MUTATOR_SWITCH, constants.SELF, "pikachu",
                       "rattata")

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        try:
            self.state.self.reserve["pikachu"]
        except KeyError:
            self.fail("`pikachu` is not in `self.reserve`")

    def test_reverse_switch_instruction_replaces_active(self):
        instruction = (constants.MUTATOR_SWITCH, constants.SELF, "rattata",
                       "pikachu")

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual("rattata", self.state.self.active.id)

    def test_apply_volatile_status_properly_applies_status(self):
        instruction = (constants.MUTATOR_APPLY_VOLATILE_STATUS, constants.SELF,
                       "leechseed")

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertIn("leechseed", self.state.self.active.volatile_status)

    def test_reverse_volatile_status_properly_removes_status(self):
        self.state.self.active.volatile_status.add("leechseed")
        instruction = (constants.MUTATOR_APPLY_VOLATILE_STATUS, constants.SELF,
                       "leechseed")

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertNotIn("leechseed", self.state.self.active.volatile_status)

    def test_damage_is_properly_applied(self):
        instruction = (constants.MUTATOR_DAMAGE, constants.SELF, 50)

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        damage_taken = self.state.self.active.maxhp - self.state.self.active.hp

        self.assertEqual(50, damage_taken)

    def test_damage_is_properly_reversed(self):
        self.state.self.active.hp -= 50
        instruction = (constants.MUTATOR_DAMAGE, constants.SELF, 50)

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        damage_taken = self.state.self.active.maxhp - self.state.self.active.hp

        self.assertEqual(0, damage_taken)

    def test_healing_is_properly_applied(self):
        self.state.self.active.hp -= 50
        instruction = (constants.MUTATOR_HEAL, constants.SELF, 50)

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        damage_taken = self.state.self.active.maxhp - self.state.self.active.hp

        self.assertEqual(0, damage_taken)

    def test_healing_is_properly_reversed(self):
        instruction = (constants.MUTATOR_HEAL, constants.SELF, 50)

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        damage_taken = self.state.self.active.maxhp - self.state.self.active.hp

        self.assertEqual(50, damage_taken)

    def test_boost_is_properly_applied(self):
        instruction = (constants.MUTATOR_BOOST, constants.SELF,
                       constants.ATTACK, 1)

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual(1, self.state.self.active.attack_boost)

    def test_boost_is_properly_reversed(self):
        self.state.self.active.attack_boost = 1
        instruction = (constants.MUTATOR_BOOST, constants.SELF,
                       constants.ATTACK, 1)

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(0, self.state.self.active.attack_boost)

    def test_boost_is_properly_reversed_when_a_boost_previously_existed(self):
        # the pokemon had attack_boost=2 before
        # it boosted to 4, and now it is being reversed
        self.state.self.active.attack_boost = 4
        instruction = (constants.MUTATOR_BOOST, constants.SELF,
                       constants.ATTACK, 2)

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(2, self.state.self.active.attack_boost)

    def test_unboost_is_properly_applied(self):
        instruction = (constants.MUTATOR_UNBOOST, constants.SELF,
                       constants.ATTACK, 1)

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual(-1, self.state.self.active.attack_boost)

    def test_unboost_is_properly_reversed(self):
        self.state.self.active.attack_boost = -1
        instruction = (constants.MUTATOR_UNBOOST, constants.SELF,
                       constants.ATTACK, 1)

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(0, self.state.self.active.attack_boost)

    def test_apply_status_properly_applies_status(self):
        instruction = (constants.MUTATOR_APPLY_STATUS, constants.SELF,
                       constants.BURN)

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual(constants.BURN, self.state.self.active.status)

    def test_apply_status_is_properly_reversed(self):
        self.state.self.active.status = constants.BURN
        instruction = (constants.MUTATOR_APPLY_STATUS, constants.SELF,
                       constants.BURN)

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(None, self.state.self.active.status)

    def test_remove_status_properly_removes_status(self):
        self.state.self.active.status = constants.BURN
        instruction = (constants.MUTATOR_REMOVE_STATUS, constants.SELF,
                       constants.BURN)

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual(None, self.state.self.active.status)

    def test_remove_status_is_properly_reversed(self):
        instruction = (constants.MUTATOR_REMOVE_STATUS, constants.SELF,
                       constants.BURN)

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(constants.BURN, self.state.self.active.status)

    def test_side_start_is_properly_applied(self):
        instruction = (constants.MUTATOR_SIDE_START, constants.SELF,
                       constants.STEALTH_ROCK, 1)

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual(
            1, self.state.self.side_conditions[constants.STEALTH_ROCK])

    def test_side_start_is_properly_reversed(self):
        self.state.self.side_conditions[constants.STEALTH_ROCK] = 1
        instruction = (constants.MUTATOR_SIDE_START, constants.SELF,
                       constants.STEALTH_ROCK, 1)

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(
            0, self.state.self.side_conditions[constants.STEALTH_ROCK])

    def test_side_end_is_properly_applied(self):
        self.state.self.side_conditions[constants.STEALTH_ROCK] = 2
        instruction = (constants.MUTATOR_SIDE_END, constants.SELF,
                       constants.STEALTH_ROCK, 2)

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual(
            0, self.state.self.side_conditions[constants.STEALTH_ROCK])

    def test_side_end_is_properly_reversed(self):
        instruction = (constants.MUTATOR_SIDE_END, constants.SELF,
                       constants.STEALTH_ROCK, 2)

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(
            2, self.state.self.side_conditions[constants.STEALTH_ROCK])

    def test_disable_move(self):
        move = {'id': 'return', 'disabled': False, 'current_pp': 16}
        self.state.self.active.moves = [move]
        instruction = (
            constants.MUTATOR_DISABLE_MOVE,
            constants.SELF,
            "return",
        )

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertTrue(move[constants.DISABLED])

    def test_reverse_disable_move(self):
        move = {'id': 'return', 'disabled': True, 'current_pp': 16}
        self.state.self.active.moves = [move]
        instruction = (
            constants.MUTATOR_DISABLE_MOVE,
            constants.SELF,
            "return",
        )

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertFalse(move[constants.DISABLED])

    def test_enable_move(self):
        move = {'id': 'return', 'disabled': True, 'current_pp': 16}
        self.state.self.active.moves = [move]
        instruction = (
            constants.MUTATOR_ENABLE_MOVE,
            constants.SELF,
            "return",
        )

        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertFalse(move[constants.DISABLED])

    def test_reverse_enable_move(self):
        move = {'id': 'return', 'disabled': False, 'current_pp': 16}
        self.state.self.active.moves = [move]
        instruction = (
            constants.MUTATOR_ENABLE_MOVE,
            constants.SELF,
            "return",
        )

        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertTrue(move[constants.DISABLED])

    def test_setting_weather(self):
        self.state.weather = None
        instruction = (constants.MUTATOR_WEATHER_START, constants.SUN, None)
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual(constants.SUN, self.state.weather)

    def test_setting_weather_when_previous_weather_exists(self):
        self.state.weather = constants.RAIN
        instruction = (constants.MUTATOR_WEATHER_START, constants.SUN,
                       constants.RAIN)
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual(constants.SUN, self.state.weather)

    def test_reversing_weather_when_previous_weather_exists(self):
        self.state.weather = constants.SUN
        instruction = (constants.MUTATOR_WEATHER_START, constants.SUN,
                       constants.RAIN)
        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(constants.RAIN, self.state.weather)

    def test_reverse_setting_weather(self):
        self.state.weather = constants.SUN
        instruction = (constants.MUTATOR_WEATHER_START, constants.SUN, None)
        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(None, self.state.weather)

    def test_apply_and_reverse_setting_weather_works(self):
        self.state.weather = None
        instruction = (constants.MUTATOR_WEATHER_START, constants.SUN, None)
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)
        if not self.state.weather == constants.SUN:
            self.fail("Sun was not set")

        self.mutator.reverse(list_of_instructions)

        self.assertEqual(None, self.state.weather)

    def test_apply_and_reverse_setting_weather_works_with_weather_previously_existing(
            self):
        self.state.weather = constants.RAIN
        instruction = (constants.MUTATOR_WEATHER_START, constants.SUN,
                       constants.RAIN)
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)
        if not self.state.weather == constants.SUN:
            self.fail("Sun was not set")

        self.mutator.reverse(list_of_instructions)

        self.assertEqual(constants.RAIN, self.state.weather)

    def test_setting_field(self):
        self.state.field = None
        instruction = (constants.MUTATOR_FIELD_START,
                       constants.PSYCHIC_TERRAIN, None)
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual(constants.PSYCHIC_TERRAIN, self.state.field)

    def test_reverse_setting_field(self):
        self.state.field = constants.PSYCHIC_TERRAIN
        instruction = (constants.MUTATOR_FIELD_START,
                       constants.PSYCHIC_TERRAIN, None)
        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(None, self.state.field)

    def test_apply_and_reverse_field(self):
        self.state.field = None
        instruction = (constants.MUTATOR_FIELD_START,
                       constants.PSYCHIC_TERRAIN, None)
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)
        if self.state.field != constants.PSYCHIC_TERRAIN:
            self.fail("Terrain was not set")
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(None, self.state.field)

    def test_apply_and_reverse_field_when_previous_field_exists(self):
        self.state.field = constants.GRASSY_TERRAIN
        instruction = (constants.MUTATOR_FIELD_START,
                       constants.PSYCHIC_TERRAIN, constants.GRASSY_TERRAIN)
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)
        if self.state.field != constants.PSYCHIC_TERRAIN:
            self.fail("Terrain was not set")
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(constants.GRASSY_TERRAIN, self.state.field)

    def test_end_active_field(self):
        self.state.field = constants.GRASSY_TERRAIN
        instruction = (constants.MUTATOR_FIELD_END, constants.GRASSY_TERRAIN)
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)
        if self.state.field is not None:
            self.fail("Terrain was not removed")
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(constants.GRASSY_TERRAIN, self.state.field)

    def test_reversing_end_active_field(self):
        self.state.field = None
        instruction = (constants.MUTATOR_FIELD_END, constants.GRASSY_TERRAIN)
        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)
        if self.state.field != constants.GRASSY_TERRAIN:
            self.fail("Terrain was not reset")
        self.mutator.apply(list_of_instructions)

        self.assertEqual(None, self.state.field)

    def test_toggle_trickroom_sets_trickroom(self):
        self.state.trick_room = False
        instruction = (constants.MUTATOR_TOGGLE_TRICKROOM, )
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertTrue(self.state.trick_room)

    def test_reverse_instruction_unsets_trickroom(self):
        self.state.trick_room = True
        instruction = (constants.MUTATOR_TOGGLE_TRICKROOM, )
        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertFalse(self.state.trick_room)

    def test_reverse_instruction_sets_trickroom(self):
        self.state.trick_room = False
        instruction = (constants.MUTATOR_TOGGLE_TRICKROOM, )
        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertTrue(self.state.trick_room)

    def test_toggle_trickroom_unsets_trickroom(self):
        self.state.trick_room = True
        instruction = (constants.MUTATOR_TOGGLE_TRICKROOM, )
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertFalse(self.state.trick_room)

    def test_apply_and_reverse_trickroom(self):
        self.state.trick_room = False
        instruction = (constants.MUTATOR_TOGGLE_TRICKROOM, )
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)
        if not self.state.trick_room:
            self.fail("Trickroom was not set")
        self.mutator.reverse(list_of_instructions)

        self.assertFalse(self.state.trick_room)

    def test_change_types_properly_changes_types(self):
        self.state.self.active.types = ['normal']
        instruction = (constants.MUTATOR_CHANGE_TYPE, constants.SELF,
                       ['water'], self.state.self.active.types)
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)

        self.assertEqual(['water'], self.state.self.active.types)

    def test_reverse_change_types(self):
        self.state.self.active.types = ['water']
        instruction = (constants.MUTATOR_CHANGE_TYPE, constants.SELF,
                       ['water'], ['normal'])
        list_of_instructions = [instruction]
        self.mutator.reverse(list_of_instructions)

        self.assertEqual(['normal'], self.state.self.active.types)

    def test_apply_and_reverse_change_types(self):
        self.state.self.active.types = ['normal']
        instruction = (constants.MUTATOR_CHANGE_TYPE, constants.SELF,
                       ['water', 'grass'], self.state.self.active.types)
        list_of_instructions = [instruction]
        self.mutator.apply(list_of_instructions)
        if self.state.self.active.types != ['water', 'grass']:
            self.fail('types were not changed')

        self.mutator.reverse(list_of_instructions)
        self.assertEqual(['normal'], self.state.self.active.types)
Example #12
0
                    'id': 'dragondance',
                    'disabled': False,
                    'current_pp': 32
                }, {
                    'id': 'earthquake',
                    'disabled': False,
                    'current_pp': 16
                }, {
                    'id': 'bounce',
                    'disabled': False,
                    'current_pp': 8
                }],
                'types': ['water', 'flying'],
                'canMegaEvo':
                False
            }
        },
        'side_conditions': {
            'toxic_count': 0
        },
        'trapped': False
    },
    'weather': None,
    'field': None,
    'trickroom': False,
    'forceSwitch': False,
    'wait': False
})
mutator = StateMutator(state)
state_instructions = get_payoff_matrix(mutator, depth=3)
    def setUp(self):
        self.state = State(
            Side(
                Pokemon.from_state_pokemon_dict(
                    StatePokemon("raichu", 73).to_dict()), {
                        "xatu":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("xatu", 81).to_dict()),
                        "starmie":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("starmie", 81).to_dict()),
                        "gyarados":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("gyarados", 81).to_dict()),
                        "dragonite":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("dragonite", 81).to_dict()),
                        "hitmonlee":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("hitmonlee", 81).to_dict()),
                    }, defaultdict(lambda: 0), False),
            Side(
                Pokemon.from_state_pokemon_dict(
                    StatePokemon("aromatisse", 81).to_dict()), {
                        "yveltal":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("yveltal", 73).to_dict()),
                        "slurpuff":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("slurpuff", 73).to_dict()),
                        "victini":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("victini", 73).to_dict()),
                        "toxapex":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("toxapex", 73).to_dict()),
                        "bronzong":
                        Pokemon.from_state_pokemon_dict(
                            StatePokemon("bronzong", 73).to_dict()),
                    }, defaultdict(lambda: 0), False), None, None, False,
            False, False)

        self.mutator = StateMutator(self.state)

        self.state.self.active.moves = [
            {
                constants.ID: 'tackle',
                constants.DISABLED: False
            },
            {
                constants.ID: 'charm',
                constants.DISABLED: False
            },
            {
                constants.ID: 'growl',
                constants.DISABLED: False
            },
            {
                constants.ID: 'stringshot',
                constants.DISABLED: False
            },
        ]
        self.state.opponent.active.moves = [
            {
                constants.ID: 'tackle',
                constants.DISABLED: False
            },
            {
                constants.ID: 'charm',
                constants.DISABLED: False
            },
            {
                constants.ID: 'growl',
                constants.DISABLED: False
            },
            {
                constants.ID: 'stringshot',
                constants.DISABLED: False
            },
        ]
Example #14
0
    def pick_move_from_battles(self, battles):
        # Only work on current battle
        # In practice the bot can play several at once, for now we simplified to one battle.
        battle = battles[0]
        root = Node("Root")

        state = battle.create_state()
        mutator = StateMutator(state)
        user_options, opponent_options = battle.get_all_options()
        logger.debug("Attempting to find best move from: {}".format(mutator.state))
        #get the scores from the "safest" algorithm provided by the starter code
        scores = get_payoff_matrix(mutator, user_options, opponent_options, depth=2, prune=False)

        # Create tree using payoff matrix from "Safest" algorithm
        checked_moves = {}
        for (myMove, opponentMove), score in scores.items():
            #checked moves keeps track of which nodes have been added to the tree, so we dont duplicate.
            if myMove not in checked_moves:
                child = Node(myMove, root)
                checked_moves[myMove] = child
            grandchild = Node(opponentMove, checked_moves[myMove])
            Node(score, grandchild)

        # a library function that prints our tree for readability.
        for pre, _, node in RenderTree(root):
            print("%s%s" % (pre, node.name))

        myTotalHP = 0.0 # max of 600, 100 points for full hp
        oppTotalHP = 0.0

        # calculate my total hp
        my_pokes = state.self
        # get active pokemon hp if it isn't dead
        if my_pokes.active.maxhp != 0:
            myTotalHP += my_pokes.active.hp / my_pokes.active.maxhp
        # get reserve pokmeons hps
        for p in my_pokes.reserve.values():
            if p.maxhp !=0:
                myTotalHP += p.hp / p.maxhp
        myTotalHP *= 100

        # calculate opp total hp
        opp_pokes = state.opponent
        # get active pokemon hp
        if opp_pokes.active.maxhp != 0:
            oppTotalHP += opp_pokes.active.hp / opp_pokes.active.maxhp
        # get reserve pokmeons hps
        for p in opp_pokes.reserve.values():
            if p.maxhp !=0:
                oppTotalHP += p.hp / p.maxhp
        
        #accounts for the pokemon of opponent that have not been revealed
        unseenPoke = 5-len(opp_pokes.reserve)
        oppTotalHP += unseenPoke
        oppTotalHP *=100

        possibleStatuses = {
            "psn" : .06,
            "frz" : .25,
            "tox" : .19,
            "par" : .16,
            "slp" : .16,
            "brn" : .20,
            None: 0,
        }

        statBuffs = {
            6 : .25,
            5 : .235,
            4 : .22,
            3 : .19,
            2 : .15,
            1 : .08,
            0 : 0,
            -1 : -.08,
            -2 : -.15,
            -3 : -.19,
            -4 : -.22,
            -5 : -.235,
            -6 : -.25,
        }

        # check how many status conditions we have
        myStatuses = 0
        # active pokemon
        myStatuses += possibleStatuses[my_pokes.active.status]
        # reserve pokemon
        for p in my_pokes.reserve.values():
            myStatuses += possibleStatuses[p.status]

        # check how many status conditions opponent has
        opponentStatuses = 0
        # active pokemon
        opponentStatuses += possibleStatuses[opp_pokes.active.status]
        # reserve pokemon
        for p in opp_pokes.reserve.values():
            opponentStatuses += possibleStatuses[p.status]

        status_aggression_multiplier = 1
        status_aggression_modifier = (opponentStatuses - myStatuses) * status_aggression_multiplier
        print(f"Status modifier:{status_aggression_modifier}")

        # Stat Buffs
        # check how many stat boosts/nerfs we have
        myBuffs = 0
        # active pokemon
        myBuffs += statBuffs[my_pokes.active.accuracy_boost]
        myBuffs += statBuffs[my_pokes.active.attack_boost]
        myBuffs += statBuffs[my_pokes.active.defense_boost]
        myBuffs += statBuffs[my_pokes.active.evasion_boost]
        myBuffs += statBuffs[my_pokes.active.special_attack_boost]
        myBuffs += statBuffs[my_pokes.active.special_defense_boost]
        myBuffs += statBuffs[my_pokes.active.speed_boost]
        
        # check how many stat boosts/nerfs opponent has
        oppBuffs = 0
        # active pokemon
        oppBuffs += statBuffs[opp_pokes.active.accuracy_boost]
        oppBuffs += statBuffs[opp_pokes.active.attack_boost]
        oppBuffs += statBuffs[opp_pokes.active.defense_boost]
        oppBuffs += statBuffs[opp_pokes.active.evasion_boost]
        oppBuffs += statBuffs[opp_pokes.active.special_attack_boost]
        oppBuffs += statBuffs[opp_pokes.active.special_defense_boost]
        oppBuffs += statBuffs[opp_pokes.active.speed_boost]

        buff_aggression_multiplier = 1
        buff_aggression_modifier = (myBuffs - oppBuffs) * buff_aggression_multiplier
        print(f"Buff modifier:{buff_aggression_modifier}")

        safety = (3 + status_aggression_modifier + buff_aggression_modifier) * myTotalHP/oppTotalHP
        if safety < 0:
            print("WARNING: safety constant is less than 0, changing to 0.1")
            safety = 0.1
        print(f"bot will play with safety constant of {safety}")
        bot_choice = self.aggressive_pick(root,safety)
        print(f"choice: {bot_choice}")
        print(f"the safest pick was {self.safest_pick(root)}")

        print("Choice: {}".format(bot_choice))
        return bot_choice