diff --git a/modules/battle_action_selection.py b/modules/battle_action_selection.py index 0bb24d8f..c333f1bf 100644 --- a/modules/battle_action_selection.py +++ b/modules/battle_action_selection.py @@ -168,7 +168,7 @@ def battle_action_use_item(item: Item, target_index: int = 0): if target_index is not None: battle_state = get_battle_state() in_battle_index = battle_state.map_battle_party_index(target_index) - + yield from scroll_to_party_menu_index(in_battle_index) context.emulator.press_button("A") yield diff --git a/modules/battle_strategies/catch.py b/modules/battle_strategies/catch.py index 89f86607..e903d8a4 100644 --- a/modules/battle_strategies/catch.py +++ b/modules/battle_strategies/catch.py @@ -7,12 +7,13 @@ from modules.pokedex import get_pokedex from modules.pokemon import Pokemon, get_type_by_name, StatusCondition, get_party, get_party_alive + class CatchStrategy(BattleStrategy): - + def __init__(self): super().__init__() - self._first_pokemon_sent_index = self.get_first_valid_pokemon_index() - + self._first_pokemon_sent_index = self.get_first_valid_pokemon_index() + def party_can_battle(self) -> bool: return True @@ -115,16 +116,16 @@ def choose_new_lead_after_faint(self, battle_state: BattleState) -> int: for index, pokemon in enumerate(party): if not pokemon.is_egg and pokemon.current_hp > 0: # Ignore eggs and fainted Pokémon - return index + return index def decide_turn(self, battle_state: BattleState) -> tuple["TurnAction", any]: """Determines the next action depending on the mode and current battle state.""" mode = context.config.battle.catch_revive_mode - + party = get_party() lead_pokemon_index = self._first_pokemon_sent_index lead_pokemon = party[lead_pokemon_index] - + if get_party_alive() == 1: return TurnAction.switch_to_manual() @@ -148,8 +149,7 @@ def get_first_valid_pokemon_index(self) -> int | None: if not pokemon.is_egg and not pokemon.current_hp == 0: return index return None - - + def get_first_valid_pokemon(self, party: list) -> Pokemon | None: """Returns the first valid Pokémon that is not an egg.""" for pokemon in party: @@ -182,4 +182,4 @@ def handle_catch_logic(self, battle_state: BattleState): return TurnAction.use_move(status_move) # Otherwise, throw the best available Poké Ball - return TurnAction.use_item(ball_to_throw) \ No newline at end of file + return TurnAction.use_item(ball_to_throw) diff --git a/modules/battle_strategies/run_away.py b/modules/battle_strategies/run_away.py index 7b9e0fcf..b938f28f 100644 --- a/modules/battle_strategies/run_away.py +++ b/modules/battle_strategies/run_away.py @@ -1,6 +1,6 @@ from modules.battle_state import BattleState from modules.battle_strategies import BattleStrategy, TurnAction, SafariTurnAction -from modules.pokemon import Pokemon, Move +from modules.pokemon import Pokemon, Move, get_party class RunAwayStrategy(BattleStrategy): @@ -23,7 +23,12 @@ def choose_new_lead_after_battle(self) -> int | None: return False def choose_new_lead_after_faint(self, battle_state: BattleState) -> int: - return 0 + """Selects the first non egg Pokemon to become the new lead.""" + party = get_party() + + for index, pokemon in enumerate(party): + if not pokemon.is_egg and pokemon.current_hp > 0: # Ignore eggs and fainted Pokémon + return index def decide_turn(self, battle_state: BattleState) -> tuple["TurnAction", any]: return TurnAction.run_away() diff --git a/modules/config/schemas_v1.py b/modules/config/schemas_v1.py index 5deb056d..f6bdf029 100644 --- a/modules/config/schemas_v1.py +++ b/modules/config/schemas_v1.py @@ -22,7 +22,7 @@ class Battle(BaseConfig): hp_threshold: Annotated[float, Field(ge=0, le=100)] = 20 lead_cannot_battle_action: Literal["stop", "flee", "rotate"] = "flee" faint_action: Literal["stop", "flee", "rotate"] = "flee" - catch_revive_mode: Literal ["always_revive_lead", "no_revive"] = "always_revive_lead" + catch_revive_mode: Literal["always_revive_lead", "no_revive"] = "always_revive_lead" new_move: Literal["stop", "cancel", "learn_best"] = "stop" stop_evolution: bool = True switch_strategy: Literal["first_available", "lowest_level"] = "first_available" diff --git a/modules/memory.py b/modules/memory.py index 2851ae34..78a54b6c 100644 --- a/modules/memory.py +++ b/modules/memory.py @@ -21,8 +21,6 @@ def unpack_uint16(bytes: bytes) -> int: def unpack_uint32(bytes: bytes) -> int: return struct.unpack(" int: - return struct.unpack('<6B', bytes[:6]) def pack_uint16(int: int) -> bytes: return struct.pack(" str: @staticmethod def is_selectable() -> bool: return get_player_avatar().map_location.has_encounters - + def run(self) -> Generator: yield from apply_white_flute_if_available() - yield from spin() \ No newline at end of file + yield from spin() diff --git a/modules/pokemon.py b/modules/pokemon.py index 790ba9d3..7bf77b30 100644 --- a/modules/pokemon.py +++ b/modules/pokemon.py @@ -1383,6 +1383,7 @@ def get_party() -> list[Pokemon]: return party + def get_party_alive() -> int: """ :return: The current number of Pokémon alive in our party @@ -1393,9 +1394,10 @@ def get_party_alive() -> int: # Check if the Pokémon is valid, not an egg, and has HP greater than 0 (i.e., it is alive) if pokemon.is_valid and not pokemon.is_egg and pokemon.current_hp > 0: alive_count += 1 - + return alive_count + def get_party_repel_level() -> int: """ :return: The minimum level that wild encounters can have, given the current Repel