mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Pokemon R/B: Version 5 Update (#3566)
* Quiz updates * Enable Partial Trainersanity * Losable Key Items Still Count * New options api * Type Chart Seed * Continue switching to new options API * Level Scaling and Quiz fixes * Level Scaling and Quiz fixes * Clarify that palettes are only for Super Gameboy * Type chart seed groups use one random players' options * remove goal option again * Text updates * Trainersanity Trainers ignore Blind Trainers setting * Re-order simple connecting interiors so that directions are preserved when possible * Dexsanity exact number * Year update * Dexsanity Doc update * revert accidental file deletion * Fixes * Add world parameter to logic calls * restore correct seeded random object * missing world.options changes * Trainersanity table bug fix * delete entrances as well as exits when restarting door shuffle * Do not collect route 25 item for level scaling if trainer is trainersanity * world.options in level_scaling.py * Update worlds/pokemon_rb/level_scaling.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/pokemon_rb/encounters.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/pokemon_rb/encounters.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * world -> multiworld * Fix Cerulean Cave Hidden Item Center Rocks region * Fix Cerulean Cave Hidden Item Center Rocks region for real * Remove "self-locking" rules * Update worlds/pokemon_rb/regions.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Fossil events * Update worlds/pokemon_rb/level_scaling.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --------- Co-authored-by: alchav <alchav@jalchavware.com> Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com>
This commit is contained in:
@@ -3,8 +3,8 @@ from . import poke_data, logic
|
||||
from .rom_addresses import rom_addresses
|
||||
|
||||
|
||||
def set_mon_palettes(self, random, data):
|
||||
if self.multiworld.randomize_pokemon_palettes[self.player] == "vanilla":
|
||||
def set_mon_palettes(world, random, data):
|
||||
if world.options.randomize_pokemon_palettes == "vanilla":
|
||||
return
|
||||
pallet_map = {
|
||||
"Poison": 0x0F,
|
||||
@@ -25,9 +25,9 @@ def set_mon_palettes(self, random, data):
|
||||
}
|
||||
palettes = []
|
||||
for mon in poke_data.pokemon_data:
|
||||
if self.multiworld.randomize_pokemon_palettes[self.player] == "primary_type":
|
||||
pallet = pallet_map[self.local_poke_data[mon]["type1"]]
|
||||
elif (self.multiworld.randomize_pokemon_palettes[self.player] == "follow_evolutions" and mon in
|
||||
if world.options.randomize_pokemon_palettes == "primary_type":
|
||||
pallet = pallet_map[world.local_poke_data[mon]["type1"]]
|
||||
elif (world.options.randomize_pokemon_palettes == "follow_evolutions" and mon in
|
||||
poke_data.evolves_from and poke_data.evolves_from[mon] != "Eevee"):
|
||||
pallet = palettes[-1]
|
||||
else: # completely_random or follow_evolutions and it is not an evolved form (except eeveelutions)
|
||||
@@ -93,40 +93,41 @@ def move_power(move_data):
|
||||
return power
|
||||
|
||||
|
||||
def process_move_data(self):
|
||||
self.local_move_data = deepcopy(poke_data.moves)
|
||||
def process_move_data(world):
|
||||
world.local_move_data = deepcopy(poke_data.moves)
|
||||
|
||||
if self.multiworld.randomize_move_types[self.player]:
|
||||
for move, data in self.local_move_data.items():
|
||||
if world.options.randomize_move_types:
|
||||
for move, data in world.local_move_data.items():
|
||||
if move == "No Move":
|
||||
continue
|
||||
# The chance of randomized moves choosing a normal type move is high, so we want to retain having a higher
|
||||
# rate of normal type moves
|
||||
data["type"] = self.multiworld.random.choice(list(poke_data.type_ids) + (["Normal"] * 4))
|
||||
data["type"] = world.random.choice(list(poke_data.type_ids) + (["Normal"] * 4))
|
||||
|
||||
if self.multiworld.move_balancing[self.player]:
|
||||
self.local_move_data["Sing"]["accuracy"] = 30
|
||||
self.local_move_data["Sleep Powder"]["accuracy"] = 40
|
||||
self.local_move_data["Spore"]["accuracy"] = 50
|
||||
self.local_move_data["Sonicboom"]["effect"] = 0
|
||||
self.local_move_data["Sonicboom"]["power"] = 50
|
||||
self.local_move_data["Dragon Rage"]["effect"] = 0
|
||||
self.local_move_data["Dragon Rage"]["power"] = 80
|
||||
self.local_move_data["Horn Drill"]["effect"] = 0
|
||||
self.local_move_data["Horn Drill"]["power"] = 70
|
||||
self.local_move_data["Horn Drill"]["accuracy"] = 90
|
||||
self.local_move_data["Guillotine"]["effect"] = 0
|
||||
self.local_move_data["Guillotine"]["power"] = 70
|
||||
self.local_move_data["Guillotine"]["accuracy"] = 90
|
||||
self.local_move_data["Fissure"]["effect"] = 0
|
||||
self.local_move_data["Fissure"]["power"] = 70
|
||||
self.local_move_data["Fissure"]["accuracy"] = 90
|
||||
self.local_move_data["Blizzard"]["accuracy"] = 70
|
||||
if self.multiworld.randomize_tm_moves[self.player]:
|
||||
self.local_tms = self.multiworld.random.sample([move for move in poke_data.moves.keys() if move not in
|
||||
["No Move"] + poke_data.hm_moves], 50)
|
||||
if world.options.move_balancing:
|
||||
world.local_move_data["Sing"]["accuracy"] = 30
|
||||
world.local_move_data["Sleep Powder"]["accuracy"] = 40
|
||||
world.local_move_data["Spore"]["accuracy"] = 50
|
||||
world.local_move_data["Sonicboom"]["effect"] = 0
|
||||
world.local_move_data["Sonicboom"]["power"] = 50
|
||||
world.local_move_data["Dragon Rage"]["effect"] = 0
|
||||
world.local_move_data["Dragon Rage"]["power"] = 80
|
||||
world.local_move_data["Horn Drill"]["effect"] = 0
|
||||
world.local_move_data["Horn Drill"]["power"] = 70
|
||||
world.local_move_data["Horn Drill"]["accuracy"] = 90
|
||||
world.local_move_data["Guillotine"]["effect"] = 0
|
||||
world.local_move_data["Guillotine"]["power"] = 70
|
||||
world.local_move_data["Guillotine"]["accuracy"] = 90
|
||||
world.local_move_data["Fissure"]["effect"] = 0
|
||||
world.local_move_data["Fissure"]["power"] = 70
|
||||
world.local_move_data["Fissure"]["accuracy"] = 90
|
||||
world.local_move_data["Blizzard"]["accuracy"] = 70
|
||||
|
||||
if world.options.randomize_tm_moves:
|
||||
world.local_tms = world.random.sample([move for move in poke_data.moves.keys() if move not in
|
||||
["No Move"] + poke_data.hm_moves], 50)
|
||||
else:
|
||||
self.local_tms = poke_data.tm_moves.copy()
|
||||
world.local_tms = poke_data.tm_moves.copy()
|
||||
|
||||
|
||||
def process_pokemon_data(self):
|
||||
@@ -138,12 +139,12 @@ def process_pokemon_data(self):
|
||||
compat_hms = set()
|
||||
|
||||
for mon, mon_data in local_poke_data.items():
|
||||
if self.multiworld.randomize_pokemon_stats[self.player] == "shuffle":
|
||||
if self.options.randomize_pokemon_stats == "shuffle":
|
||||
stats = [mon_data["hp"], mon_data["atk"], mon_data["def"], mon_data["spd"], mon_data["spc"]]
|
||||
if mon in poke_data.evolves_from:
|
||||
stat_shuffle_map = local_poke_data[poke_data.evolves_from[mon]]["stat_shuffle_map"]
|
||||
else:
|
||||
stat_shuffle_map = self.multiworld.random.sample(range(0, 5), 5)
|
||||
stat_shuffle_map = self.random.sample(range(0, 5), 5)
|
||||
|
||||
mon_data["stat_shuffle_map"] = stat_shuffle_map
|
||||
mon_data["hp"] = stats[stat_shuffle_map[0]]
|
||||
@@ -151,7 +152,7 @@ def process_pokemon_data(self):
|
||||
mon_data["def"] = stats[stat_shuffle_map[2]]
|
||||
mon_data["spd"] = stats[stat_shuffle_map[3]]
|
||||
mon_data["spc"] = stats[stat_shuffle_map[4]]
|
||||
elif self.multiworld.randomize_pokemon_stats[self.player] == "randomize":
|
||||
elif self.options.randomize_pokemon_stats == "randomize":
|
||||
first_run = True
|
||||
while (mon_data["hp"] > 255 or mon_data["atk"] > 255 or mon_data["def"] > 255 or mon_data["spd"] > 255
|
||||
or mon_data["spc"] > 255 or first_run):
|
||||
@@ -168,9 +169,9 @@ def process_pokemon_data(self):
|
||||
mon_data[stat] = 10
|
||||
total_stats -= 10
|
||||
assert total_stats >= 0, f"Error distributing stats for {mon} for player {self.player}"
|
||||
dist = [self.multiworld.random.randint(1, 101) / 100, self.multiworld.random.randint(1, 101) / 100,
|
||||
self.multiworld.random.randint(1, 101) / 100, self.multiworld.random.randint(1, 101) / 100,
|
||||
self.multiworld.random.randint(1, 101) / 100]
|
||||
dist = [self.random.randint(1, 101) / 100, self.random.randint(1, 101) / 100,
|
||||
self.random.randint(1, 101) / 100, self.random.randint(1, 101) / 100,
|
||||
self.random.randint(1, 101) / 100]
|
||||
total_dist = sum(dist)
|
||||
|
||||
mon_data["hp"] += int(round(dist[0] / total_dist * total_stats))
|
||||
@@ -178,30 +179,30 @@ def process_pokemon_data(self):
|
||||
mon_data["def"] += int(round(dist[2] / total_dist * total_stats))
|
||||
mon_data["spd"] += int(round(dist[3] / total_dist * total_stats))
|
||||
mon_data["spc"] += int(round(dist[4] / total_dist * total_stats))
|
||||
if self.multiworld.randomize_pokemon_types[self.player]:
|
||||
if self.multiworld.randomize_pokemon_types[self.player].value == 1 and mon in poke_data.evolves_from:
|
||||
if self.options.randomize_pokemon_types:
|
||||
if self.options.randomize_pokemon_types.value == 1 and mon in poke_data.evolves_from:
|
||||
type1 = local_poke_data[poke_data.evolves_from[mon]]["type1"]
|
||||
type2 = local_poke_data[poke_data.evolves_from[mon]]["type2"]
|
||||
if type1 == type2:
|
||||
if self.multiworld.secondary_type_chance[self.player].value == -1:
|
||||
if self.options.secondary_type_chance.value == -1:
|
||||
if mon_data["type1"] != mon_data["type2"]:
|
||||
while type2 == type1:
|
||||
type2 = self.multiworld.random.choice(list(poke_data.type_names.values()))
|
||||
elif self.multiworld.random.randint(1, 100) <= self.multiworld.secondary_type_chance[self.player].value:
|
||||
type2 = self.multiworld.random.choice(list(poke_data.type_names.values()))
|
||||
type2 = self.random.choice(list(poke_data.type_names.values()))
|
||||
elif self.random.randint(1, 100) <= self.options.secondary_type_chance.value:
|
||||
type2 = self.random.choice(list(poke_data.type_names.values()))
|
||||
else:
|
||||
type1 = self.multiworld.random.choice(list(poke_data.type_names.values()))
|
||||
type1 = self.random.choice(list(poke_data.type_names.values()))
|
||||
type2 = type1
|
||||
if ((self.multiworld.secondary_type_chance[self.player].value == -1 and mon_data["type1"]
|
||||
!= mon_data["type2"]) or self.multiworld.random.randint(1, 100)
|
||||
<= self.multiworld.secondary_type_chance[self.player].value):
|
||||
if ((self.options.secondary_type_chance.value == -1 and mon_data["type1"]
|
||||
!= mon_data["type2"]) or self.random.randint(1, 100)
|
||||
<= self.options.secondary_type_chance.value):
|
||||
while type2 == type1:
|
||||
type2 = self.multiworld.random.choice(list(poke_data.type_names.values()))
|
||||
type2 = self.random.choice(list(poke_data.type_names.values()))
|
||||
|
||||
mon_data["type1"] = type1
|
||||
mon_data["type2"] = type2
|
||||
if self.multiworld.randomize_pokemon_movesets[self.player]:
|
||||
if self.multiworld.randomize_pokemon_movesets[self.player] == "prefer_types":
|
||||
if self.options.randomize_pokemon_movesets:
|
||||
if self.options.randomize_pokemon_movesets == "prefer_types":
|
||||
if mon_data["type1"] == "Normal" and mon_data["type2"] == "Normal":
|
||||
chances = [[75, "Normal"]]
|
||||
elif mon_data["type1"] == "Normal" or mon_data["type2"] == "Normal":
|
||||
@@ -219,9 +220,9 @@ def process_pokemon_data(self):
|
||||
moves = list(poke_data.moves.keys())
|
||||
for move in ["No Move"] + poke_data.hm_moves:
|
||||
moves.remove(move)
|
||||
if self.multiworld.confine_transform_to_ditto[self.player]:
|
||||
if self.options.confine_transform_to_ditto:
|
||||
moves.remove("Transform")
|
||||
if self.multiworld.start_with_four_moves[self.player]:
|
||||
if self.options.start_with_four_moves:
|
||||
num_moves = 4
|
||||
else:
|
||||
num_moves = len([i for i in [mon_data["start move 1"], mon_data["start move 2"],
|
||||
@@ -231,12 +232,12 @@ def process_pokemon_data(self):
|
||||
non_power_moves = []
|
||||
learnsets[mon] = []
|
||||
for i in range(num_moves):
|
||||
if i == 0 and mon == "Ditto" and self.multiworld.confine_transform_to_ditto[self.player]:
|
||||
if i == 0 and mon == "Ditto" and self.options.confine_transform_to_ditto:
|
||||
move = "Transform"
|
||||
else:
|
||||
move = get_move(self.local_move_data, moves, chances, self.multiworld.random)
|
||||
while move == "Transform" and self.multiworld.confine_transform_to_ditto[self.player]:
|
||||
move = get_move(self.local_move_data, moves, chances, self.multiworld.random)
|
||||
move = get_move(self.local_move_data, moves, chances, self.random)
|
||||
while move == "Transform" and self.options.confine_transform_to_ditto:
|
||||
move = get_move(self.local_move_data, moves, chances, self.random)
|
||||
if self.local_move_data[move]["power"] < 5:
|
||||
non_power_moves.append(move)
|
||||
else:
|
||||
@@ -244,59 +245,58 @@ def process_pokemon_data(self):
|
||||
learnsets[mon].sort(key=lambda move: move_power(self.local_move_data[move]))
|
||||
if learnsets[mon]:
|
||||
for move in non_power_moves:
|
||||
learnsets[mon].insert(self.multiworld.random.randint(1, len(learnsets[mon])), move)
|
||||
learnsets[mon].insert(self.random.randint(1, len(learnsets[mon])), move)
|
||||
else:
|
||||
learnsets[mon] = non_power_moves
|
||||
for i in range(1, 5):
|
||||
if mon_data[f"start move {i}"] != "No Move" or self.multiworld.start_with_four_moves[self.player]:
|
||||
if mon_data[f"start move {i}"] != "No Move" or self.options.start_with_four_moves:
|
||||
mon_data[f"start move {i}"] = learnsets[mon].pop(0)
|
||||
|
||||
if self.multiworld.randomize_pokemon_catch_rates[self.player]:
|
||||
mon_data["catch rate"] = self.multiworld.random.randint(self.multiworld.minimum_catch_rate[self.player],
|
||||
255)
|
||||
if self.options.randomize_pokemon_catch_rates:
|
||||
mon_data["catch rate"] = self.random.randint(self.options.minimum_catch_rate, 255)
|
||||
else:
|
||||
mon_data["catch rate"] = max(self.multiworld.minimum_catch_rate[self.player], mon_data["catch rate"])
|
||||
mon_data["catch rate"] = max(self.options.minimum_catch_rate, mon_data["catch rate"])
|
||||
|
||||
def roll_tm_compat(roll_move):
|
||||
if self.local_move_data[roll_move]["type"] in [mon_data["type1"], mon_data["type2"]]:
|
||||
if roll_move in poke_data.hm_moves:
|
||||
if self.multiworld.hm_same_type_compatibility[self.player].value == -1:
|
||||
if self.options.hm_same_type_compatibility.value == -1:
|
||||
return mon_data["tms"][int(flag / 8)] & 1 << (flag % 8)
|
||||
r = self.multiworld.random.randint(1, 100) <= self.multiworld.hm_same_type_compatibility[self.player].value
|
||||
r = self.random.randint(1, 100) <= self.options.hm_same_type_compatibility.value
|
||||
if r and mon not in poke_data.legendary_pokemon:
|
||||
compat_hms.add(roll_move)
|
||||
return r
|
||||
else:
|
||||
if self.multiworld.tm_same_type_compatibility[self.player].value == -1:
|
||||
if self.options.tm_same_type_compatibility.value == -1:
|
||||
return mon_data["tms"][int(flag / 8)] & 1 << (flag % 8)
|
||||
return self.multiworld.random.randint(1, 100) <= self.multiworld.tm_same_type_compatibility[self.player].value
|
||||
return self.random.randint(1, 100) <= self.options.tm_same_type_compatibility.value
|
||||
elif self.local_move_data[roll_move]["type"] == "Normal" and "Normal" not in [mon_data["type1"], mon_data["type2"]]:
|
||||
if roll_move in poke_data.hm_moves:
|
||||
if self.multiworld.hm_normal_type_compatibility[self.player].value == -1:
|
||||
if self.options.hm_normal_type_compatibility.value == -1:
|
||||
return mon_data["tms"][int(flag / 8)] & 1 << (flag % 8)
|
||||
r = self.multiworld.random.randint(1, 100) <= self.multiworld.hm_normal_type_compatibility[self.player].value
|
||||
r = self.random.randint(1, 100) <= self.options.hm_normal_type_compatibility.value
|
||||
if r and mon not in poke_data.legendary_pokemon:
|
||||
compat_hms.add(roll_move)
|
||||
return r
|
||||
else:
|
||||
if self.multiworld.tm_normal_type_compatibility[self.player].value == -1:
|
||||
if self.options.tm_normal_type_compatibility.value == -1:
|
||||
return mon_data["tms"][int(flag / 8)] & 1 << (flag % 8)
|
||||
return self.multiworld.random.randint(1, 100) <= self.multiworld.tm_normal_type_compatibility[self.player].value
|
||||
return self.random.randint(1, 100) <= self.options.tm_normal_type_compatibility.value
|
||||
else:
|
||||
if roll_move in poke_data.hm_moves:
|
||||
if self.multiworld.hm_other_type_compatibility[self.player].value == -1:
|
||||
if self.options.hm_other_type_compatibility.value == -1:
|
||||
return mon_data["tms"][int(flag / 8)] & 1 << (flag % 8)
|
||||
r = self.multiworld.random.randint(1, 100) <= self.multiworld.hm_other_type_compatibility[self.player].value
|
||||
r = self.random.randint(1, 100) <= self.options.hm_other_type_compatibility.value
|
||||
if r and mon not in poke_data.legendary_pokemon:
|
||||
compat_hms.add(roll_move)
|
||||
return r
|
||||
else:
|
||||
if self.multiworld.tm_other_type_compatibility[self.player].value == -1:
|
||||
if self.options.tm_other_type_compatibility.value == -1:
|
||||
return mon_data["tms"][int(flag / 8)] & 1 << (flag % 8)
|
||||
return self.multiworld.random.randint(1, 100) <= self.multiworld.tm_other_type_compatibility[self.player].value
|
||||
return self.random.randint(1, 100) <= self.options.tm_other_type_compatibility.value
|
||||
|
||||
for flag, tm_move in enumerate(tms_hms):
|
||||
if mon in poke_data.evolves_from and self.multiworld.inherit_tm_hm_compatibility[self.player]:
|
||||
if mon in poke_data.evolves_from and self.options.inherit_tm_hm_compatibility:
|
||||
|
||||
if local_poke_data[poke_data.evolves_from[mon]]["tms"][int(flag / 8)] & 1 << (flag % 8):
|
||||
# always inherit learnable tms/hms
|
||||
@@ -310,7 +310,7 @@ def process_pokemon_data(self):
|
||||
# so this gets full chance roll
|
||||
bit = roll_tm_compat(tm_move)
|
||||
# otherwise 50% reduced chance to add compatibility over pre-evolved form
|
||||
elif self.multiworld.random.randint(1, 100) > 50 and roll_tm_compat(tm_move):
|
||||
elif self.random.randint(1, 100) > 50 and roll_tm_compat(tm_move):
|
||||
bit = 1
|
||||
else:
|
||||
bit = 0
|
||||
@@ -322,15 +322,13 @@ def process_pokemon_data(self):
|
||||
mon_data["tms"][int(flag / 8)] &= ~(1 << (flag % 8))
|
||||
|
||||
hm_verify = ["Surf", "Strength"]
|
||||
if self.multiworld.accessibility[self.player] != "minimal" or ((not
|
||||
self.multiworld.badgesanity[self.player]) and max(self.multiworld.elite_four_badges_condition[self.player],
|
||||
self.multiworld.route_22_gate_condition[self.player], self.multiworld.victory_road_condition[self.player])
|
||||
> 7) or (self.multiworld.door_shuffle[self.player] not in ("off", "simple")):
|
||||
if self.options.accessibility != "minimal" or ((not
|
||||
self.options.badgesanity) and max(self.options.elite_four_badges_condition,
|
||||
self.options.route_22_gate_condition, self.options.victory_road_condition)
|
||||
> 7) or (self.options.door_shuffle not in ("off", "simple")):
|
||||
hm_verify += ["Cut"]
|
||||
if self.multiworld.accessibility[self.player] != "minimal" or (not
|
||||
self.multiworld.dark_rock_tunnel_logic[self.player]) and ((self.multiworld.trainersanity[self.player] or
|
||||
self.multiworld.extra_key_items[self.player])
|
||||
or self.multiworld.door_shuffle[self.player]):
|
||||
if (self.options.accessibility != "minimal" or (not self.options.dark_rock_tunnel_logic) and
|
||||
((self.options.trainersanity or self.options.extra_key_items) or self.options.door_shuffle)):
|
||||
hm_verify += ["Flash"]
|
||||
# Fly does not need to be verified. Full/Insanity/Decoupled door shuffle connects reachable regions to unreachable
|
||||
# regions, so if Fly is available and can be learned, the towns you can fly to would be considered reachable for
|
||||
@@ -339,8 +337,7 @@ def process_pokemon_data(self):
|
||||
|
||||
for hm_move in hm_verify:
|
||||
if hm_move not in compat_hms:
|
||||
mon = self.multiworld.random.choice([mon for mon in poke_data.pokemon_data if mon not in
|
||||
poke_data.legendary_pokemon])
|
||||
mon = self.random.choice([mon for mon in poke_data.pokemon_data if mon not in poke_data.legendary_pokemon])
|
||||
flag = tms_hms.index(hm_move)
|
||||
local_poke_data[mon]["tms"][int(flag / 8)] |= 1 << (flag % 8)
|
||||
|
||||
@@ -352,7 +349,7 @@ 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]
|
||||
if multiworld.randomize_wild_pokemon[player] and viable_mons:
|
||||
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"]
|
||||
|
||||
@@ -364,7 +361,7 @@ def verify_hm_moves(multiworld, world, player):
|
||||
|
||||
placed_mons = [slot.item.name for slot in accessible_slots]
|
||||
|
||||
if multiworld.area_1_to_1_mapping[player]:
|
||||
if world.options.area_1_to_1_mapping:
|
||||
placed_mons.sort(key=lambda i: number_of_zones(i))
|
||||
else:
|
||||
# this sort method doesn't work if you reference the same list being sorted in the lambda
|
||||
@@ -372,10 +369,10 @@ def verify_hm_moves(multiworld, world, player):
|
||||
placed_mons.sort(key=lambda i: placed_mons_copy.count(i))
|
||||
|
||||
placed_mon = placed_mons.pop()
|
||||
replace_mon = multiworld.random.choice(viable_mons)
|
||||
replace_slot = multiworld.random.choice([slot for slot in accessible_slots if slot.item.name
|
||||
replace_mon = world.random.choice(viable_mons)
|
||||
replace_slot = world.random.choice([slot for slot in accessible_slots if slot.item.name
|
||||
== placed_mon])
|
||||
if multiworld.area_1_to_1_mapping[player]:
|
||||
if world.options.area_1_to_1_mapping:
|
||||
zone = " - ".join(replace_slot.name.split(" - ")[:-1])
|
||||
replace_slots = [slot for slot in accessible_slots if slot.name.startswith(zone) and slot.item.name
|
||||
== placed_mon]
|
||||
@@ -387,7 +384,7 @@ def verify_hm_moves(multiworld, world, player):
|
||||
tms_hms = world.local_tms + poke_data.hm_moves
|
||||
flag = tms_hms.index(move)
|
||||
mon_list = [mon for mon in poke_data.pokemon_data.keys() if test_state.has(mon, player)]
|
||||
multiworld.random.shuffle(mon_list)
|
||||
world.random.shuffle(mon_list)
|
||||
mon_list.sort(key=lambda mon: world.local_move_data[move]["type"] not in
|
||||
[world.local_poke_data[mon]["type1"], world.local_poke_data[mon]["type2"]])
|
||||
for mon in mon_list:
|
||||
@@ -399,31 +396,31 @@ def verify_hm_moves(multiworld, world, player):
|
||||
while True:
|
||||
intervene_move = None
|
||||
test_state = multiworld.get_all_state(False)
|
||||
if not logic.can_learn_hm(test_state, "Surf", player):
|
||||
if not logic.can_learn_hm(test_state, world, "Surf", player):
|
||||
intervene_move = "Surf"
|
||||
elif not logic.can_learn_hm(test_state, "Strength", player):
|
||||
elif not logic.can_learn_hm(test_state, world, "Strength", player):
|
||||
intervene_move = "Strength"
|
||||
# cut may not be needed if accessibility is minimal, unless you need all 8 badges and badgesanity is off,
|
||||
# as you will require cut to access celadon gyn
|
||||
elif ((not logic.can_learn_hm(test_state, "Cut", player)) and
|
||||
(multiworld.accessibility[player] != "minimal" or ((not
|
||||
multiworld.badgesanity[player]) and max(
|
||||
multiworld.elite_four_badges_condition[player],
|
||||
multiworld.route_22_gate_condition[player],
|
||||
multiworld.victory_road_condition[player])
|
||||
> 7) or (multiworld.door_shuffle[player] not in ("off", "simple")))):
|
||||
elif ((not logic.can_learn_hm(test_state, world, "Cut", player)) and
|
||||
(world.options.accessibility != "minimal" or ((not
|
||||
world.options.badgesanity) and max(
|
||||
world.options.elite_four_badges_condition,
|
||||
world.options.route_22_gate_condition,
|
||||
world.options.victory_road_condition)
|
||||
> 7) or (world.options.door_shuffle not in ("off", "simple")))):
|
||||
intervene_move = "Cut"
|
||||
elif ((not logic.can_learn_hm(test_state, "Flash", player))
|
||||
and multiworld.dark_rock_tunnel_logic[player]
|
||||
and (multiworld.accessibility[player] != "minimal"
|
||||
or multiworld.door_shuffle[player])):
|
||||
elif ((not logic.can_learn_hm(test_state, world, "Flash", player))
|
||||
and world.options.dark_rock_tunnel_logic
|
||||
and (world.options.accessibility != "minimal"
|
||||
or world.options.door_shuffle)):
|
||||
intervene_move = "Flash"
|
||||
# If no Pokémon can learn Fly, then during door shuffle it would simply not treat the free fly maps
|
||||
# as reachable, and if on no door shuffle or simple, fly is simply never necessary.
|
||||
# We only intervene if a Pokémon is able to learn fly but none are reachable, as that would have been
|
||||
# considered in door shuffle.
|
||||
elif ((not logic.can_learn_hm(test_state, "Fly", player))
|
||||
and multiworld.door_shuffle[player] not in
|
||||
elif ((not logic.can_learn_hm(test_state, world, "Fly", player))
|
||||
and world.options.door_shuffle not in
|
||||
("off", "simple") and [world.fly_map, world.town_map_fly_map] != ["Pallet Town", "Pallet Town"]):
|
||||
intervene_move = "Fly"
|
||||
if intervene_move:
|
||||
@@ -432,4 +429,4 @@ def verify_hm_moves(multiworld, world, player):
|
||||
intervene(intervene_move, test_state)
|
||||
last_intervene = intervene_move
|
||||
else:
|
||||
break
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user