Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pokemon Red&Blue: Cache which mons can learn HMs #4055

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion worlds/pokemon_rb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from .rom_addresses import rom_addresses
from .text import encode_text
from .rom import generate_output, get_base_rom_bytes, get_base_rom_path, RedDeltaPatch, BlueDeltaPatch
from .pokemon import process_pokemon_data, process_move_data, verify_hm_moves
from .pokemon import process_pokemon_data, process_move_data, rebuild_hm_mons_cache, verify_hm_moves
from .encounters import process_pokemon_locations, process_trainer_data
from .rules import set_rules
from .level_scaling import level_scaling
Expand Down Expand Up @@ -101,6 +101,7 @@ def __init__(self, multiworld: MultiWorld, player: int):
self.type_chart = None
self.local_poke_data = None
self.local_move_data = None
self.local_hm_mons_cache = None
self.local_tms = None
self.learnsets = None
self.trainer_name = None
Expand Down Expand Up @@ -261,6 +262,7 @@ def encode_name(name, t):

process_move_data(self)
process_pokemon_data(self)
rebuild_hm_mons_cache(self)

self.dexsanity_table = [
*(True for _ in range(round(self.options.dexsanity.value))),
Expand Down
7 changes: 2 additions & 5 deletions worlds/pokemon_rb/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,8 @@ def can_flash(state, world, player):


def can_learn_hm(state, world, move, player):
for pokemon, data in world.local_poke_data.items():
if state.has(pokemon, player) and data["tms"][6] & 1 << (["Cut", "Fly", "Surf", "Strength",
"Flash"].index(move) + 2):
return True
return False
hm_mons = world.local_hm_mons_cache[move]
return hm_mons and state.has_any(hm_mons, player)


def can_get_hidden_items(state, world, player):
Expand Down
16 changes: 14 additions & 2 deletions worlds/pokemon_rb/pokemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,21 @@ def roll_tm_compat(roll_move):
self.learnsets = learnsets


def rebuild_hm_mons_cache(world):
# Build a cache of which Pokémon can learn certain HMs
hm_mons_cache = {hm: [] for hm in poke_data.hm_moves}
for i, hm in enumerate(poke_data.hm_moves):
flag = i + 2 # same as can_learn_hm
for mon, data in world.local_poke_data.items():
if data["tms"][6] & flag:
hm_mons_cache[hm].append(mon)

world.local_hm_mons_cache = hm_mons_cache


def verify_hm_moves(multiworld, world, player):
def intervene(move, test_state):
move_bit = pow(2, poke_data.hm_moves.index(move) + 2)
viable_mons = [mon for mon in world.local_poke_data if world.local_poke_data[mon]["tms"][6] & move_bit]
viable_mons = world.local_hm_mons_cache[move]
if world.options.randomize_wild_pokemon and viable_mons:
accessible_slots = [loc for loc in multiworld.get_reachable_locations(test_state, player) if
loc.type == "Wild Encounter"]
Expand Down Expand Up @@ -427,6 +438,7 @@ def number_of_zones(mon):
if intervene_move == last_intervene:
raise Exception(f"Caught in infinite loop attempting to ensure {intervene_move} is available to player {player}")
intervene(intervene_move, test_state)
rebuild_hm_mons_cache(world)
last_intervene = intervene_move
else:
break