Key checking in dungeons limited to single player for speed

Spoiler traversal fixes and speed
Bug with boss shuffle spoiler in MW fixed
Perf enhancement fix for pot shuffle
This commit is contained in:
aerinon
2021-08-04 12:08:17 -06:00
parent 4b29408911
commit d7e326f71d
3 changed files with 16 additions and 9 deletions

View File

@@ -518,7 +518,8 @@ class CollectionState(object):
connection, crystal_state = queue.popleft()
new_region = connection.connected_region
if not self.should_visit(new_region, rrp, crystal_state, player):
bc.pop(connection, None)
if not self.dungeon_limits or self.possibly_connected_to_dungeon(new_region, player):
bc.pop(connection, None)
elif connection.can_reach(self):
bc.pop(connection, None)
if new_region.type == RegionType.Dungeon:
@@ -643,9 +644,12 @@ class CollectionState(object):
while not done:
rrp_ = child_state.reachable_regions[player]
bc_ = child_state.blocked_connections[player]
self.set_dungeon_limits(player, dungeon_name)
child_state.set_dungeon_limits(player, dungeon_name)
child_queue.extend([(x, y) for x, y in bc_.items()
if child_state.possibly_connected_to_dungeon(x.parent_region,
player)])
child_state.traverse_world(child_queue, rrp_, bc_, player)
new_events = child_state.sweep_for_events_once()
new_events = child_state.sweep_for_events_once(player)
child_state.stale[player] = False
if new_events:
for conn in bc_:
@@ -890,8 +894,8 @@ class CollectionState(object):
return spot.can_reach(self)
def sweep_for_events_once(self):
locations = self.world.get_filled_locations()
def sweep_for_events_once(self, player):
locations = self.world.get_filled_locations(player)
checked_locations = set([l for l in locations if l in self.locations_checked])
reachable_events = [location for location in locations if location.event and location.can_reach(self)]
reachable_events = self._do_not_flood_the_keys(reachable_events)
@@ -2520,7 +2524,7 @@ class Spoiler(object):
for player in range(1, self.world.players + 1):
if self.world.boss_shuffle[player] != 'none':
bossmap = self.bosses[player] if self.world.players > 1 else self.bosses
bossmap = self.bosses[str(player)] if self.world.players > 1 else self.bosses
outfile.write(f'\n\nBosses ({self.world.get_player_names(player)}):\n\n')
outfile.write('\n'.join([f'{x}: {y}' for x, y in bossmap.items() if y not in ['Agahnim', 'Agahnim 2', 'Ganon']]))

View File

@@ -573,7 +573,7 @@ def create_playthrough(world):
old_item = location.item
location.item = None
# todo: this is not very efficient, but I'm not sure how else to do it for this backwards logic
world.clear_exp_cache()
# world.clear_exp_cache()
if world.can_beat_game(state_cache[num]):
# logging.getLogger('').debug(f'{old_item.name} (Player {old_item.player}) is not required')
to_delete.add(location)
@@ -615,7 +615,10 @@ def create_playthrough(world):
logging.getLogger('').debug(world.fish.translate("cli","cli","building.final.spheres"), len(collection_spheres), len(sphere), len(required_locations))
if not sphere:
raise RuntimeError(world.fish.translate("cli","cli","cannot.reach.required"))
if world.has_beaten_game(state):
required_locations.clear()
else:
raise RuntimeError(world.fish.translate("cli","cli","cannot.reach.required"))
# store the required locations for statistical analysis
old_world.required_locations = [(location.name, location.player) for sphere in collection_spheres for location in sphere]

2
Rom.py
View File

@@ -2795,7 +2795,7 @@ def write_pots_to_rom(rom, pot_contents):
pots = [pot for pot in pot_contents[i] if pot.item != PotItem.Nothing]
if len(pots) > 0:
write_int16(rom, pot_item_room_table_lookup + 2*i, n)
rom.write_bytes(n, itertools.chain(*((pot.x,pot.y,pot.item) for pot in pots)))
rom.write_bytes(n, list(itertools.chain.from_iterable(((pot.x, pot.y, pot.item) for pot in pots))))
n += 3*len(pots) + 2
rom.write_bytes(n - 2, [0xFF,0xFF])
else: