Fixed problem with Inverted+ER

Fixed problem with Vanilla doors+Retro
Fixed Keylock issue with Ice Cross
Merged in compiling's fix for keyshuffle
ER Infinite Loop detection
This commit is contained in:
aerinon
2020-03-11 12:25:49 -06:00
parent 90e6e8762e
commit c67cd478a1
4 changed files with 99 additions and 29 deletions

View File

@@ -139,7 +139,7 @@ def vanilla_key_logic(world, player):
enabled_entrances = {} enabled_entrances = {}
sector_queue = deque(builders) sector_queue = deque(builders)
last_key = None last_key, loops = None, 0
while len(sector_queue) > 0: while len(sector_queue) > 0:
builder = sector_queue.popleft() builder = sector_queue.popleft()
@@ -147,12 +147,14 @@ def vanilla_key_logic(world, player):
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)
origin_list_sans_drops = remove_drop_origins(origin_list) origin_list_sans_drops = remove_drop_origins(origin_list)
if len(origin_list_sans_drops) <= 0: if len(origin_list_sans_drops) <= 0:
if last_key == builder.name: if last_key == builder.name or loops > 1000:
raise Exception('Infinte loop detected %s' % builder.name) origin_name = world.get_region(origin_list[0], player).entrances[0].parent_region.name
raise Exception('Infinite loop detected for "%s" located at %s' % builder.name, origin_name)
sector_queue.append(builder) sector_queue.append(builder)
last_key = builder.name last_key = builder.name
loops += 1
else: else:
find_new_entrances(builder.master_sector, connections, potentials, enabled_entrances, world, player) find_new_entrances(builder.master_sector, entrances_map, connections, potentials, enabled_entrances, world, player)
start_regions = convert_regions(origin_list, world, player) start_regions = convert_regions(origin_list, world, player)
doors = convert_key_doors(default_small_key_doors[builder.name], world, player) doors = convert_key_doors(default_small_key_doors[builder.name], world, player)
key_layout = build_key_layout(builder, start_regions, doors, world, player) key_layout = build_key_layout(builder, start_regions, doors, world, player)
@@ -165,7 +167,7 @@ def vanilla_key_logic(world, player):
world.key_logic[player][builder.name] = key_layout.key_logic world.key_logic[player][builder.name] = key_layout.key_logic
log_key_logic(builder.name, key_layout.key_logic) log_key_logic(builder.name, key_layout.key_logic)
last_key = None last_key = None
if world.shuffle[player] == 'vanilla' and world.accessibility[player] == 'items': if world.shuffle[player] == 'vanilla' and world.accessibility[player] == 'items' and not world.retro[player]:
validate_vanilla_key_logic(world, player) validate_vanilla_key_logic(world, player)
@@ -350,7 +352,7 @@ def main_dungeon_generation(dungeon_builders, recombinant_builders, connections_
entrances_map, potentials, connections = connections_tuple entrances_map, potentials, connections = connections_tuple
enabled_entrances = {} enabled_entrances = {}
sector_queue = deque(dungeon_builders.values()) sector_queue = deque(dungeon_builders.values())
last_key = None last_key, loops = None, 0
while len(sector_queue) > 0: while len(sector_queue) > 0:
builder = sector_queue.popleft() builder = sector_queue.popleft()
split_dungeon = builder.name.startswith('Desert Palace') or builder.name.startswith('Skull Woods') split_dungeon = builder.name.startswith('Desert Palace') or builder.name.startswith('Skull Woods')
@@ -361,14 +363,16 @@ def main_dungeon_generation(dungeon_builders, recombinant_builders, connections_
find_enabled_origins(builder.sectors, enabled_entrances, origin_list, entrances_map, name) find_enabled_origins(builder.sectors, enabled_entrances, origin_list, entrances_map, name)
origin_list_sans_drops = remove_drop_origins(origin_list) origin_list_sans_drops = remove_drop_origins(origin_list)
if len(origin_list_sans_drops) <= 0 or name == "Turtle Rock" and not validate_tr(builder, origin_list_sans_drops, world, player): if len(origin_list_sans_drops) <= 0 or name == "Turtle Rock" and not validate_tr(builder, origin_list_sans_drops, world, player):
if last_key == builder.name: if last_key == builder.name or loops > 1000:
raise Exception('Infinte loop detected %s' % builder.name) origin_name = world.get_region(origin_list[0], player).entrances[0].parent_region.name
raise Exception('Infinite loop detected for "%s" located at %s' % builder.name, origin_name)
sector_queue.append(builder) sector_queue.append(builder)
last_key = builder.name last_key = builder.name
loops += 1
else: else:
logging.getLogger('').info('Generating dungeon: %s', builder.name) logging.getLogger('').info('Generating dungeon: %s', builder.name)
ds = generate_dungeon(builder, origin_list_sans_drops, split_dungeon, world, player) ds = generate_dungeon(builder, origin_list_sans_drops, split_dungeon, world, player)
find_new_entrances(ds, connections, potentials, enabled_entrances, world, player) find_new_entrances(ds, entrances_map, connections, potentials, enabled_entrances, world, player)
ds.name = name ds.name = name
builder.master_sector = ds builder.master_sector = ds
builder.layout_starts = origin_list if len(builder.entrance_list) <= 0 else builder.entrance_list builder.layout_starts = origin_list if len(builder.entrance_list) <= 0 else builder.entrance_list
@@ -432,27 +436,50 @@ def remove_drop_origins(entrance_list):
return [x for x in entrance_list if x not in drop_entrances] return [x for x in entrance_list if x not in drop_entrances]
def find_new_entrances(sector, connections, potentials, enabled, world, player): def find_new_entrances(sector, entrances_map, connections, potentials, enabled, world, player):
for region in sector.regions: for region in sector.regions:
if region.name in connections.keys() and (connections[region.name] in potentials.keys() or connections[region.name].name in world.inaccessible_regions[player]): if region.name in connections.keys() and (connections[region.name] in potentials.keys() or connections[region.name].name in world.inaccessible_regions[player]):
new_region = connections[region.name] enable_new_entrances(region, connections, potentials, enabled, world, player)
if new_region in potentials.keys(): inverted_aga_check(entrances_map, connections, potentials, enabled, world, player)
for potential in potentials.pop(new_region):
enabled[potential] = (region.name, region.dungeon)
# see if this unexplored region connects elsewhere def enable_new_entrances(region, connections, potentials, enabled, world, player):
queue = deque(new_region.exits) new_region = connections[region.name]
visited = set() if new_region in potentials.keys():
while len(queue) > 0: for potential in potentials.pop(new_region):
ext = queue.popleft() enabled[potential] = (region.name, region.dungeon)
visited.add(ext) # see if this unexplored region connects elsewhere
region_name = ext.connected_region.name queue = deque(new_region.exits)
if region_name in connections.keys() and connections[region_name] in potentials.keys(): visited = set()
for potential in potentials.pop(connections[region_name]): while len(queue) > 0:
enabled[potential] = (region.name, region.dungeon) ext = queue.popleft()
if ext.connected_region.name in world.inaccessible_regions[player]: visited.add(ext)
for new_exit in ext.connected_region.exits: region_name = ext.connected_region.name
if new_exit not in visited: if region_name in connections.keys() and connections[region_name] in potentials.keys():
queue.append(new_exit) for potential in potentials.pop(connections[region_name]):
enabled[potential] = (region.name, region.dungeon)
if ext.connected_region.name in world.inaccessible_regions[player]:
for new_exit in ext.connected_region.exits:
if new_exit not in visited:
queue.append(new_exit)
def inverted_aga_check(entrances_map, connections, potentials, enabled, world, player):
if world.mode[player] == 'inverted':
if 'Agahnims Tower' in entrances_map.keys() or aga_tower_enabled(enabled):
for region in list(potentials.keys()):
if region.name == 'Hyrule Castle Ledge':
for r_name in potentials[region]:
new_region = world.get_region(r_name, player)
enable_new_entrances(new_region, connections, potentials, enabled, world, player)
def aga_tower_enabled(enabled):
for region_name, enabled_tuple in enabled.items():
entrance, dungeon = enabled_tuple
if dungeon.name == 'Agahnims Tower':
return True
return False
def within_dungeon_legacy(world, player): def within_dungeon_legacy(world, player):

View File

@@ -836,6 +836,8 @@ class ExplorationState(object):
def add_all_doors_check_keys(self, region, key_door_proposal, world, player): def add_all_doors_check_keys(self, region, key_door_proposal, world, player):
for door in get_doors(world, region, player): for door in get_doors(world, region, player):
if self.can_traverse(door): if self.can_traverse(door):
if door.controller:
door = door.controller
if door in key_door_proposal and door not in self.opened_doors: if door in key_door_proposal and door not in self.opened_doors:
if not self.in_door_list(door, self.small_doors): if not self.in_door_list(door, self.small_doors):
self.append_door_to_list(door, self.small_doors) self.append_door_to_list(door, self.small_doors)

View File

@@ -24,7 +24,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute
from ItemList import generate_itempool, difficulties, fill_prizes from ItemList import generate_itempool, difficulties, fill_prizes
from Utils import output_path, parse_player_names from Utils import output_path, parse_player_names
__version__ = '0.0.18.4d' __version__ = '0.0.18.5d'
def main(args, seed=None): def main(args, seed=None):

View File

@@ -3,6 +3,7 @@ import os
import re import re
import subprocess import subprocess
import sys import sys
import xml.etree.ElementTree as ET
def int16_as_bytes(value): def int16_as_bytes(value):
value = value & 0xFFFF value = value & 0xFFFF
@@ -241,6 +242,46 @@ def print_wiki_doors(d_regions, world, player):
print('|}') print('|}')
def print_xml_doors(d_regions, world, player):
root = ET.Element('root')
for d, region_list in d_regions.items():
tile_map = {}
for region in region_list:
tile = None
r = world.get_region(region, player)
for ext in r.exits:
door = world.check_for_door(ext.name, player)
if door is not None and door.roomIndex != -1:
tile = door.roomIndex
break
if tile is not None:
if tile not in tile_map:
tile_map[tile] = []
tile_map[tile].append(r)
dungeon = ET.SubElement(root, 'dungeon', {'name': d})
for tile, r_list in tile_map.items():
supertile = ET.SubElement(dungeon, 'supertile', {'id': str(tile)})
for region in r_list:
room = ET.SubElement(supertile, 'room', {'name': region.name})
for ext in region.exits:
ET.SubElement(room, 'door', {'name': ext.name})
ET.dump(root)
def print_graph(world):
root = ET.Element('root')
for region in world.regions:
r = ET.SubElement(root, 'region', {'name': region.name})
for ext in region.exits:
attribs = {'name': ext.name}
if ext.connected_region:
attribs['connected_region'] = ext.connected_region.name
if ext.door and ext.door.dest:
attribs['dest'] = ext.door.dest.name
ET.SubElement(r, 'exit', attribs)
ET.dump(root)
if __name__ == '__main__': if __name__ == '__main__':
pass pass
# make_new_base2current() # make_new_base2current()