fix: specific fix for vanilla entrance shuffle with no doors to properly process dungeon in the correct order for key logic
This commit is contained in:
@@ -284,6 +284,16 @@ class World(object):
|
|||||||
return portal
|
return portal
|
||||||
raise RuntimeError('No such portal %s for player %d' % (portal_name, player))
|
raise RuntimeError('No such portal %s for player %d' % (portal_name, player))
|
||||||
|
|
||||||
|
def get_portal_unsafe(self, portal_name, player):
|
||||||
|
if (portal_name, player) in self._portal_cache:
|
||||||
|
return self._portal_cache[(portal_name, player)]
|
||||||
|
else:
|
||||||
|
for portal in self.dungeon_portals[player]:
|
||||||
|
if portal.name == portal_name and portal.player == player:
|
||||||
|
self._portal_cache[(portal_name, player)] = portal
|
||||||
|
return portal
|
||||||
|
return None
|
||||||
|
|
||||||
def is_atgt_swapped(self, player):
|
def is_atgt_swapped(self, player):
|
||||||
return self.mode[player] == 'inverted'
|
return self.mode[player] == 'inverted'
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ def link_doors_prep(world, player):
|
|||||||
world.get_portal('Turtle Rock Eye Bridge', player).destination = True
|
world.get_portal('Turtle Rock Eye Bridge', player).destination = True
|
||||||
else:
|
else:
|
||||||
analyze_portals(world, player)
|
analyze_portals(world, player)
|
||||||
|
if world.doorShuffle[player] == 'vanilla': # these are always not destinations
|
||||||
|
world.get_portal('Desert Back', player).destination = False
|
||||||
|
world.get_portal('Skull 3', player).destination = False
|
||||||
for portal in world.dungeon_portals[player]:
|
for portal in world.dungeon_portals[player]:
|
||||||
connect_portal(portal, world, player)
|
connect_portal(portal, world, player)
|
||||||
|
|
||||||
@@ -233,11 +236,21 @@ def vanilla_key_logic(world, player):
|
|||||||
enabled_entrances = world.enabled_entrances[player] = {}
|
enabled_entrances = world.enabled_entrances[player] = {}
|
||||||
builder_queue = deque(builders)
|
builder_queue = deque(builders)
|
||||||
last_key, loops = None, 0
|
last_key, loops = None, 0
|
||||||
|
|
||||||
|
# --- Precompute all potential portals for each builder using dungeon_portals ---
|
||||||
|
from DungeonGenerator import dungeon_portals
|
||||||
|
all_potential_portals_map = {}
|
||||||
|
for builder in builders:
|
||||||
|
portal_names = list(dungeon_portals.get(builder.name, []))
|
||||||
|
all_potential_portals_map[builder.name] = set(world.get_portal(portal_name, player).door.entrance.parent_region.name for portal_name in portal_names)
|
||||||
|
|
||||||
while len(builder_queue) > 0:
|
while len(builder_queue) > 0:
|
||||||
builder = builder_queue.popleft()
|
builder = builder_queue.popleft()
|
||||||
origin_list = entrances_map[builder.name]
|
origin_list = entrances_map[builder.name]
|
||||||
find_enabled_origins(builder.sectors, enabled_entrances, origin_list, entrances_map, builder.name)
|
find_enabled_origins(builder.sectors, enabled_entrances, origin_list, entrances_map, builder.name)
|
||||||
if len(origin_list) <= 0:
|
all_potential_origins = all_potential_portals_map[builder.name]
|
||||||
|
enabled = entrances_map[builder.name]
|
||||||
|
if len(origin_list) <= 0 or should_delay_processing(enabled, all_potential_origins, potentials, connections, world, player):
|
||||||
if last_key == builder.name or loops > 1000:
|
if last_key == builder.name or loops > 1000:
|
||||||
origin_name = (world.get_region(origin_list[0], player).entrances[0].parent_region.name
|
origin_name = (world.get_region(origin_list[0], player).entrances[0].parent_region.name
|
||||||
if len(origin_list) > 0 else 'no origin')
|
if len(origin_list) > 0 else 'no origin')
|
||||||
@@ -310,6 +323,33 @@ def validate_vanilla_reservation(dungeon, world, player):
|
|||||||
return validate_key_layout(world.key_layout[player][dungeon.name], world, player)
|
return validate_key_layout(world.key_layout[player][dungeon.name], world, player)
|
||||||
|
|
||||||
|
|
||||||
|
def should_delay_processing(enabled_origins, potential_origins, potentials, connections, world, player):
|
||||||
|
disabled_origins = potential_origins.difference(set(enabled_origins))
|
||||||
|
main_targets = []
|
||||||
|
for do in disabled_origins:
|
||||||
|
region = world.get_region(do, player)
|
||||||
|
portal = _find_portal_for_region(region, world, player)
|
||||||
|
if portal and not portal.destination:
|
||||||
|
main_targets.append(region)
|
||||||
|
if not main_targets:
|
||||||
|
return False # No non-destination disabled origins found
|
||||||
|
enabling_regions = {connections[r.name] for r in main_targets}
|
||||||
|
for enabling_region in enabling_regions:
|
||||||
|
dungeon_names = {
|
||||||
|
portal.door.entrance.parent_region.dungeon.name
|
||||||
|
for dungeon_r in potentials[enabling_region]
|
||||||
|
if (portal := _find_portal_for_region(world.get_region(dungeon_r, player), world, player))
|
||||||
|
}
|
||||||
|
if len(dungeon_names) > 1:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _find_portal_for_region(region, world, player):
|
||||||
|
return next((p for ent in region.entrances
|
||||||
|
if (p := world.get_portal_unsafe(ent.parent_region.name.rstrip(' Portal'), player))), None)
|
||||||
|
|
||||||
|
|
||||||
# some useful functions
|
# some useful functions
|
||||||
oppositemap = {
|
oppositemap = {
|
||||||
Direction.South: Direction.North,
|
Direction.South: Direction.North,
|
||||||
|
|||||||
Reference in New Issue
Block a user