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)