Bulk of Lobby randomization work

This commit is contained in:
aerinon
2020-08-28 12:42:20 -06:00
parent 18447cfe3e
commit 804309565b
16 changed files with 994 additions and 331 deletions

View File

@@ -78,6 +78,9 @@ class World(object):
self.key_logic = {}
self.pool_adjustment = {}
self.key_layout = defaultdict(dict)
self.dungeon_portals = defaultdict(list)
self._portal_cache = {}
self.sanc_portal = {}
self.fish = BabelFish()
for player in range(1, players + 1):
@@ -201,6 +204,18 @@ class World(object):
return door
raise RuntimeError('No such door %s for player %d' % (doorname, player))
def get_portal(self, portal_name, player):
if isinstance(portal_name, Portal):
return portal_name
try:
return self._portal_cache[(portal_name, player)]
except KeyError:
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
raise RuntimeError('No such portal %s for player %d' % (portal_name, player))
def check_for_door(self, doorname, player):
if isinstance(doorname, Door):
return doorname
@@ -933,9 +948,10 @@ class Entrance(object):
world = self.parent_region.world if self.parent_region else None
return world.get_name_string_for_object(self) if world else f'{self.name} (Player {self.player})'
class Dungeon(object):
def __init__(self, name, regions, big_key, small_keys, dungeon_items, player):
def __init__(self, name, regions, big_key, small_keys, dungeon_items, player, dungeon_id):
self.name = name
self.regions = regions
self.big_key = big_key
@@ -944,6 +960,7 @@ class Dungeon(object):
self.bosses = dict()
self.player = player
self.world = None
self.dungeon_id = dungeon_id
self.entrance_regions = []
@@ -1148,6 +1165,7 @@ class Door(object):
# 0-4 for spiral offset thing
self.doorIndex = -1
self.layer = -1 # 0 for normal floor, 1 for the inset layer
self.pseudo_bg = 0 # 0 for normal floor, 1 for pseudo bg
self.toggle = False
self.trapFlag = 0x0
self.quadrant = 2
@@ -1159,6 +1177,16 @@ class Door(object):
self.edge_id = None
self.edge_width = None
#portal items
self.portalAble = False
self.roomLayout = 0x22 # free scroll- both directions
self.entranceFlag = False
self.deadEnd = False
self.passage = True
self.dungeonLink = None
# self.incognitoPos = -1
# self.sectorLink = False
# logical properties
# self.connected = False # combine with Dest?
self.dest = None
@@ -1291,6 +1319,13 @@ class Door(object):
self.dead = True
return self
def portal(self, quadrant, roomLayout, pseudo_bg=0):
self.quadrant = quadrant
self.roomLayout = roomLayout
self.pseudo_bg = pseudo_bg
self.portalAble = True
return self
def __eq__(self, other):
return isinstance(other, self.__class__) and self.name == other.name
@@ -1420,6 +1455,109 @@ class Sector(object):
return f'{next(iter(self.region_set()))}'
class Portal(object):
def __init__(self, player, name, door, entrance_offset, exit_offset, boss_exit_idx):
self.player = player
self.name = name
self.door = door
self.ent_offset = entrance_offset
self.exit_offset = exit_offset
self.boss_exit_idx = boss_exit_idx
self.default = True
self.destination = False
self.deadEnd = False
def change_door(self, new_door):
if new_door != self.door:
self.default = False
self.door = new_door
def current_room(self):
return self.door.roomIndex
def relative_coords(self):
y_rel = (self.door.roomIndex & 0xf0) >> 3 #todo: fix the shift!!!!
x_rel = (self.door.roomIndex & 0x0f) * 2
quad = self.door.quadrant
if quad == 0:
return [y_rel, y_rel, y_rel, y_rel+1, x_rel, x_rel, x_rel, x_rel+1]
elif quad == 1:
return [y_rel, y_rel, y_rel, y_rel+1, x_rel+1, x_rel, x_rel+1, x_rel+1]
elif quad == 2:
return [y_rel+1, y_rel, y_rel+1, y_rel+1, x_rel, x_rel, x_rel, x_rel+1]
else:
return [y_rel+1, y_rel, y_rel+1, y_rel+1, x_rel+1, x_rel, x_rel+1, x_rel+1]
def scroll_x(self):
x_rel = (self.door.roomIndex & 0x0f) * 2
if self.door.doorIndex == 0:
return [0x00, x_rel]
elif self.door.doorIndex == 1:
return [0x80, x_rel]
else:
return [0x00, x_rel+1]
def scroll_y(self):
y_rel = ((self.door.roomIndex & 0xf0) >> 3) + 1
return [0x10, y_rel]
def link_y(self):
y_rel = ((self.door.roomIndex & 0xf0) >> 3) + 1
inset = False
if self.door.pseudo_bg == 1 or self.door.layer == 1:
inset = True
return [(0xd8 if not inset else 0xc0), y_rel]
def link_x(self):
x_rel = (self.door.roomIndex & 0x0f) * 2
if self.door.doorIndex == 0:
return [0x78, x_rel]
elif self.door.doorIndex == 1:
return [0xf8, x_rel]
else:
return [0x78, x_rel+1]
# def camera_y(self):
# return [0x87, 0x01]
def camera_x(self):
if self.door.doorIndex == 0:
return [0x7f, 0x00]
elif self.door.doorIndex == 1:
return [0xff, 0x00]
else:
return [0x7f, 0x01]
def bg_setting(self):
if self.door.layer == 0:
return 0x00 | self.door.pseudo_bg
else:
return 0x10 | self.door.pseudo_bg
def hv_scroll(self):
return self.door.roomLayout
def scroll_quad(self):
quad = self.door.quadrant
if quad == 0:
return 0x00
elif quad == 1:
return 0x10
elif quad == 2:
return 0x02
else:
return 0x12
class DungeonInfo(object):
def __init__(self, name):
self.name = name
self.total = 0
self.required_passage = {}
# self.dead_ends = 0 total - 1 - req = dead_ends possible
class Boss(object):
def __init__(self, name, enemizer_name, defeat_rule, player):
self.name = name

View File

@@ -6,7 +6,7 @@ import time
from enum import unique, Flag
from functools import reduce
from BaseClasses import RegionType, Door, DoorType, Direction, Sector, CrystalBarrier
from BaseClasses import RegionType, Door, DoorType, Direction, Sector, CrystalBarrier, DungeonInfo
from Regions import key_only_locations
from Dungeons import dungeon_regions, region_starts, standard_starts, split_region_starts, flexible_starts
from Dungeons import dungeon_bigs, dungeon_keys, dungeon_hints
@@ -14,6 +14,7 @@ from Items import ItemFactory
from RoomData import DoorKind, PairedDoor
from DungeonGenerator import ExplorationState, convert_regions, generate_dungeon, pre_validate, determine_required_paths
from DungeonGenerator import create_dungeon_builders, split_dungeon_builder, simple_dungeon_builder, default_dungeon_entrances
from DungeonGenerator import dungeon_portals, dungeon_drops
from KeyDoorShuffle import analyze_dungeon, validate_vanilla_key_logic, build_key_layout, validate_key_layout
@@ -34,6 +35,8 @@ def link_doors(world, player):
for ent, ext in ladders:
connect_two_way(world, ent, ext, player)
choose_portals(world, player)
if world.doorShuffle[player] == 'vanilla':
for entrance, ext in open_edges:
connect_two_way(world, entrance, ext, player)
@@ -280,6 +283,7 @@ def remove_ugly_small_key_doors(world, player):
'TR Lava Escape SE', 'GT Hidden Spikes SE']:
door = world.get_door(d, player)
room = world.get_room(door.roomIndex, player)
if not door.entranceFlag:
room.change(door.doorListPos, DoorKind.Normal)
door.smallKey = False
door.ugly = False
@@ -308,14 +312,178 @@ def pair_existing_key_doors(world, player, door_a, door_b):
world.paired_doors[player].append(PairedDoor(door_a, door_b))
def choose_portals(world, player):
if world.doorShuffle[player] in ['basic', 'crossed']:
cross_flag = world.doorShuffle[player] == 'crossed'
# roast incognito doors
world.get_room(0x60, player).delete(5)
world.get_room(0x60, player).change(2, DoorKind.DungeonEntrance)
world.get_room(0x62, player).delete(5)
world.get_room(0x62, player).change(1, DoorKind.DungeonEntrance)
find_inaccessible_regions(world, player)
info_map = {}
for dungeon, portal_list in dungeon_portals.items():
info = DungeonInfo(dungeon)
region_map = defaultdict(list)
for portal in portal_list:
placeholder = world.get_region(portal + ' Placeholder', player)
portal_place = placeholder.exits[0].connected_region.name
if portal_place in world.inaccessible_regions[player]:
region_map[portal_place].append(portal)
info.total = len(portal_list)
info.required_passage = region_map
info_map[dungeon] = info
master_door_list = [x for x in world.doors if x.player == player and x.portalAble]
portal_assignment = defaultdict(list)
for dungeon, info in info_map.items():
outstanding_portals = list(dungeon_portals[dungeon])
if dungeon == 'Hyrule Castle' and world.mode[player] == 'Standard':
sanc = world.get_portal('Sanctuary', player)
sanc.destination = True
clean_up_portal_assignment(portal_assignment, dungeon, sanc, master_door_list, outstanding_portals)
for target_region, possible_portals in info.required_passage.items():
candidates = find_portal_candidates(master_door_list, dungeon, need_passage=True, crossed=cross_flag)
choice, portal = assign_portal(candidates, possible_portals, world, player)
portal.destination = True
clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals)
dead_end_choices = info.total - 1 - len(portal_assignment[dungeon])
for i in range(0, dead_end_choices):
candidates = find_portal_candidates(master_door_list, dungeon, dead_end_allowed=True, crossed=cross_flag)
choice, portal = assign_portal(candidates, outstanding_portals, world, player)
if choice.deadEnd:
portal.deadEnd = True
clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals)
the_rest = info.total - len(portal_assignment[dungeon])
for i in range(0, the_rest):
candidates = find_portal_candidates(master_door_list, dungeon, crossed=cross_flag)
choice, portal = assign_portal(candidates, outstanding_portals, world, player)
clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals)
for portal in world.dungeon_portals[player]:
connect_portal(portal, world, player)
hc_south = world.get_door('Hyrule Castle Lobby S', player)
if not hc_south.entranceFlag:
world.get_room(0x61, player).delete(6)
world.get_room(0x61, player).change(4, DoorKind.NormalLow)
sanctuary_door = world.get_door('Sanctuary S', player)
if not sanctuary_door.entranceFlag:
world.get_room(0x12, player).delete(3)
world.get_room(0x12, player).change(2, DoorKind.NormalLow)
if not world.swamp_patch_required[player]:
swamp_region = world.get_entrance('Swamp Palace', player).connected_region
if swamp_region.name != 'Swamp Lobby':
world.swamp_patch_required[player] = True
def connect_portal(portal, world, player):
ent, ext = portal_map[portal.name]
if world.mode[player] == 'inverted' and portal.name in ['Ganons Tower', 'Agahnims Tower']:
ext = 'Inverted ' + ext
ent = 'Inverted ' + ent
portal_entrance = world.get_entrance(portal.door.entrance.name, player) # ensures I get the right one for copying
target_exit = world.get_entrance(ext, player)
target_exit.parent_region = portal_entrance.parent_region
portal_entrance.connected_region = target_exit.connected_region
placeholder = world.get_region(portal.name + ' Placeholder', player)
if len(placeholder.entrances) > 0:
edit_entrance = placeholder.entrances[0]
else:
edit_entrance = world.get_entrance(ent, player)
entrance_region = portal_entrance.parent_region
edit_entrance.connected_region = entrance_region
entrance_region.exits.remove(portal_entrance)
entrance_region.exits.append(target_exit)
entrance_region.entrances.append(edit_entrance)
world.regions.remove(placeholder)
def find_portal_candidates(door_list, dungeon, need_passage=False, dead_end_allowed=False, crossed=False):
if need_passage:
if crossed:
ret = [x for x in door_list if x.passage and not x.deadEnd]
return [x for x in ret if x.dungeonLink is None or x.entrance.parent_region.dungeon.name == dungeon]
else:
return [x for x in door_list if x.passage and x.entrance.parent_region.dungeon.name == dungeon and not x.deadEnd]
elif dead_end_allowed:
if crossed:
return [x for x in door_list if x.dungeonLink is None or x.entrance.parent_region.dungeon.name == dungeon]
else:
return [x for x in door_list if x.entrance.parent_region.dungeon.name == dungeon]
else:
if crossed:
return [x for x in door_list if (not x.dungeonLink or x.entrance.parent_region.dungeon.name == dungeon) and not x.deadEnd]
else:
return [x for x in door_list if x.entrance.parent_region.dungeon.name == dungeon and not x.deadEnd]
def assign_portal(candidates, possible_portals, world, player):
candidate = random.choice(candidates)
portal_choice = random.choice(possible_portals)
portal = world.get_portal(portal_choice, player)
if candidate != portal.door:
if candidate.entranceFlag:
for other_portal in world.dungeon_portals[player]:
if other_portal.door == candidate:
other_portal.door = None
break
old_door = portal.door
if old_door:
old_door.entranceFlag = False
if old_door.name not in ['Hyrule Castle Lobby S', 'Sanctuary S']:
old_door_kind = DoorKind.NormalLow if old_door.layer or old_door.pseudo_bg else DoorKind.Normal
world.get_room(old_door.roomIndex, player).change(old_door.doorListPos, old_door_kind)
portal.change_door(candidate)
if candidate.name not in ['Hyrule Castle Lobby S', 'Sanctuary S']:
new_door_kind = DoorKind.DungeonEntranceLow if candidate.layer or candidate.pseudo_bg else DoorKind.DungeonEntrance
world.get_room(candidate.roomIndex, player).change(candidate.doorListPos, new_door_kind)
candidate.entranceFlag = True
return candidate, portal
def clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals):
portal_assignment[dungeon].append(portal)
master_door_list[:] = [x for x in master_door_list if x.roomIndex != portal.door.roomIndex]
if portal.door.dungeonLink and portal.door.dungeonLink.startswith('link'):
match_link = portal.door.dungeonLink
for door in master_door_list:
if door.dungeonLink == match_link:
door.dungeonLink = dungeon
outstanding_portals.remove(portal.name)
def create_dungeon_entrances(world, player):
entrance_map = defaultdict(list)
split_map = defaultdict(dict)
for key, portal_list in dungeon_portals.items():
if world.mode[player] == 'standard' and key in standard_starts.keys():
portal = world.get_portal('Hyrule Castle South', player)
entrance_map[key].append(portal.door.entrance.parent_region.name)
else:
if key in dungeon_drops.keys():
entrance_map[key].extend(dungeon_drops[key])
for portal_name in portal_list:
portal = world.get_portal(portal_name, player)
r_name = portal.door.entrance.parent_region.name
entrance_map[key].append(r_name)
if key in split_portals.keys():
for split_key in split_portals[key]:
split_map[key][split_key] = []
return entrance_map, split_map
# def unpair_all_doors(world, player):
# for paired_door in world.paired_doors[player]:
# paired_door.pair = False
def within_dungeon(world, player):
fix_big_key_doors_with_ugly_smalls(world, player)
overworld_prep(world, player)
entrances_map, potentials, connections = determine_entrance_list(world, player)
add_inaccessible_doors(world, player)
entrances_map, potentials, connections = determine_entrance_list_2(world, player)
connections_tuple = (entrances_map, potentials, connections)
dungeon_builders = {}
@@ -324,7 +492,8 @@ def within_dungeon(world, player):
dungeon_builders[key] = simple_dungeon_builder(key, sector_list)
dungeon_builders[key].entrance_list = list(entrances_map[key])
recombinant_builders = {}
builder_info = None, None, world, player
entrances, splits = create_dungeon_entrances(world, player)
builder_info = entrances, splits, world, player
handle_split_dungeons(dungeon_builders, recombinant_builders, entrances_map, builder_info)
main_dungeon_generation(dungeon_builders, recombinant_builders, connections_tuple, world, player)
@@ -346,7 +515,7 @@ def handle_split_dungeons(dungeon_builders, recombinant_builders, entrances_map,
dungeon_entrances = default_dungeon_entrances
if split_dungeon_entrances is None:
split_dungeon_entrances = split_region_starts
builder_info = dungeon_entrances, split_region_starts, world, player
builder_info = dungeon_entrances, split_dungeon_entrances, world, player
for name, split_list in split_dungeon_entrances.items():
builder = dungeon_builders.pop(name)
@@ -358,8 +527,8 @@ def handle_split_dungeons(dungeon_builders, recombinant_builders, entrances_map,
sub_builder = dungeon_builders[name+' '+sub_name]
sub_builder.split_flag = True
entrance_list = list(split_entrances)
if name in flexible_starts.keys():
add_shuffled_entrances(sub_builder.sectors, flexible_starts[name], entrance_list)
for ent in entrances_map[name]:
add_shuffled_entrances(sub_builder.sectors, ent, entrance_list)
filtered_entrance_list = [x for x in entrance_list if x in entrances_map[name]]
sub_builder.entrance_list = filtered_entrance_list
@@ -376,6 +545,9 @@ def main_dungeon_generation(dungeon_builders, recombinant_builders, connections_
name = builder.name
if split_dungeon:
name = ' '.join(builder.name.split(' ')[:-1])
if len(builder.sectors) == 0:
del dungeon_builders[builder.name]
continue
origin_list = list(builder.entrance_list)
find_enabled_origins(builder.sectors, enabled_entrances, origin_list, entrances_map, name)
if len(origin_list) <= 0 or not pre_validate(builder, origin_list, split_dungeon, world, player):
@@ -423,6 +595,37 @@ def determine_entrance_list(world, player):
return entrance_map, potential_entrances, connections
def determine_entrance_list_2(world, player):
entrance_map = {}
potential_entrances = {}
connections = {}
for key, portal_list in dungeon_portals.items():
entrance_map[key] = []
r_names = []
if world.mode[player] == 'standard' and key in standard_starts.keys():
portal = world.get_portal('Hyrule Castle South', player)
r_names.append(portal.door.entrance.parent_region.name)
else:
if key in dungeon_drops.keys():
r_names.extend(dungeon_drops[key])
for portal_name in portal_list:
portal = world.get_portal(portal_name, player)
r_names.append(portal.door.entrance.parent_region.name)
for region_name in r_names:
region = world.get_region(region_name, player)
for ent in region.entrances:
parent = ent.parent_region
if (parent.type != RegionType.Dungeon and parent.name != 'Menu') or parent.name == 'Sewer Drop':
if parent.name not in world.inaccessible_regions[player]:
entrance_map[key].append(region_name)
else:
if ent.parent_region not in potential_entrances.keys():
potential_entrances[parent] = []
potential_entrances[parent].append(region_name)
connections[region_name] = parent
return entrance_map, potential_entrances, connections
def add_shuffled_entrances(sectors, region_list, entrance_list):
for sector in sectors:
for region in sector.regions:
@@ -502,14 +705,15 @@ def aga_tower_enabled(enabled):
def cross_dungeon(world, player):
fix_big_key_doors_with_ugly_smalls(world, player)
overworld_prep(world, player)
entrances_map, potentials, connections = determine_entrance_list(world, player)
entrances_map, potentials, connections = determine_entrance_list_2(world, player)
connections_tuple = (entrances_map, potentials, connections)
all_sectors, all_regions = [], []
for key in dungeon_regions.keys():
all_regions += dungeon_regions[key]
all_sectors.extend(convert_to_sectors(all_regions, world, player))
dungeon_builders = create_dungeon_builders(all_sectors, connections_tuple, world, player)
entrances, splits = create_dungeon_entrances(world, player)
dungeon_builders = create_dungeon_builders(all_sectors, connections_tuple, world, player, entrances, splits)
for builder in dungeon_builders.values():
builder.entrance_list = list(entrances_map[builder.name])
dungeon_obj = world.get_dungeon(builder.name, player)
@@ -549,6 +753,32 @@ def cross_dungeon(world, player):
reassign_boss('GT Lanmolas 2', 'middle', builder, gt, world, player)
reassign_boss('GT Moldorm', 'top', builder, gt, world, player)
sanctuary = world.get_region('Sanctuary', player)
d_name = sanctuary.dungeon.name
if d_name != 'Hyrule Castle':
possible_portals = []
for portal_name in dungeon_portals[d_name]:
portal = world.get_portal(portal_name, player)
if portal.door == 'Sanctuary S':
possible_portals.clear()
possible_portals.append(portal)
break
if not portal.destination and not portal.deadEnd:
possible_portals.append(portal)
if len(possible_portals) == 1:
world.sanc_portal[player] = possible_portals[0]
else:
reachable_portals = []
for portal in possible_portals:
start_area = portal.door.entrance.parent_region
state = ExplorationState(dungeon=d_name)
state.visit_region(start_area)
state.add_all_doors_check_unattached(start_area, world, player)
explore_state(state, world, player)
if state.visited(sanctuary):
reachable_portals.append(portal)
world.sanc_portal[player] = random.choice(reachable_portals)
if world.hints[player]:
refine_hints(dungeon_builders)
@@ -683,7 +913,7 @@ def convert_to_sectors(region_names, world, player):
if existing not in matching_sectors:
matching_sectors.append(existing)
else:
if door is not None and door.controller is None and door.dest is None:
if door and not door.controller and not door.dest and not door.entranceFlag:
outstanding_doors.append(door)
sector = Sector()
if not new_sector:
@@ -718,7 +948,7 @@ def combine_layouts(recombinant_builders, dungeon_builders, entrances_map):
def valid_region_to_explore(region, world, player):
return region.type == RegionType.Dungeon or region.name in world.inaccessible_regions[player]
return region and (region.type == RegionType.Dungeon or region.name in world.inaccessible_regions[player])
def shuffle_key_doors(builder, world, player):
@@ -907,7 +1137,7 @@ def find_key_door_candidates(region, checked, world, player):
d = ext.door
if d and d.controller:
d = d.controller
if d is not None and not d.blocked and d.dest is not last_door and d.dest is not last_region and d not in checked_doors:
if d and not d.blocked and not d.entranceFlag and d.dest is not last_door and d.dest is not last_region and d not in checked_doors:
valid = False
if 0 <= d.doorListPos < 4 and d.type in [DoorType.Interior, DoorType.Normal, DoorType.SpiralStairs]:
room = world.get_room(d.roomIndex, player)
@@ -1038,7 +1268,7 @@ def smooth_door_pairs(world, player):
all_doors = [x for x in world.doors if x.player == player]
skip = set()
for door in all_doors:
if door.type in [DoorType.Normal, DoorType.Interior] and door not in skip:
if door.type in [DoorType.Normal, DoorType.Interior] and door not in skip and not door.entranceFlag:
partner = door.dest
skip.add(partner)
room_a = world.get_room(door.roomIndex, player)
@@ -1199,14 +1429,16 @@ def check_required_paths(paths, world, player):
if dungeon_name in world.dungeon_layouts[player].keys():
builder = world.dungeon_layouts[player][dungeon_name]
if len(paths[dungeon_name]) > 0:
states_to_explore = defaultdict(list)
states_to_explore = {}
for path in paths[dungeon_name]:
if type(path) is tuple:
states_to_explore[tuple([path[0]])].append(path[1])
states_to_explore[tuple([path[0]])] = path[1]
else:
states_to_explore[tuple(builder.path_entrances)].append(path)
states_to_explore[tuple(builder.path_entrances)] = path
cached_initial_state = None
for start_regs, dest_regs in states_to_explore.items():
if type(dest_regs) is not list:
dest_regs = [dest_regs]
check_paths = convert_regions(dest_regs, world, player)
start_regions = convert_regions(start_regs, world, player)
initial = start_regs == tuple(builder.path_entrances)
@@ -1231,10 +1463,8 @@ def check_required_paths(paths, world, player):
def determine_init_crystal(initial, state, start_regions):
if initial:
if initial or state is None:
return CrystalBarrier.Orange
if state is None:
raise Exception('Please start path checking from the entrances')
if len(start_regions) > 1:
raise NotImplementedError('Path checking for multiple start regions (not the entrances) not implemented, use more paths instead')
start_region = start_regions[0]
@@ -1258,13 +1488,14 @@ def explore_state(state, world, player):
def check_if_regions_visited(state, check_paths):
valid = True
valid = False
breaking_region = None
for region_target in check_paths:
if not state.visited_at_all(region_target):
valid = False
breaking_region = region_target
if state.visited_at_all(region_target):
valid = True
break
else:
breaking_region = region_target
return valid, breaking_region
@@ -1423,6 +1654,7 @@ logical_connections = [
('GT Hookshot South-North Path', 'GT Hookshot North Platform'),
('GT Hookshot Platform Blue Barrier', 'GT Hookshot South Entry'),
('GT Hookshot Entry Blue Barrier', 'GT Hookshot South Platform'),
('GT Hookshot Entry Boomerang Path', 'GT Hookshot South Platform'),
('GT Double Switch Orange Barrier', 'GT Double Switch Switches'),
('GT Double Switch Orange Barrier 2', 'GT Double Switch Key Spot'),
('GT Double Switch Transition Blue', 'GT Double Switch Exit'),
@@ -2072,3 +2304,70 @@ boss_indicator = {
'Turtle Rock': (0x18, 'TR Boss SW'),
'Ganons Tower': (0x1a, 'GT Agahnim 2 SW')
}
# For compass boss indicator
boss_indicator = {
'Eastern Palace': (0x04, 'Eastern Boss SE'),
'Desert Palace': (0x06, 'Desert Boss SW'),
'Agahnims Tower': (0x08, 'Tower Agahnim 1 SW'),
'Swamp Palace': (0x0a, 'Swamp Boss SW'),
'Palace of Darkness': (0x0c, 'PoD Boss SE'),
'Misery Mire': (0x0e, 'Mire Boss SW'),
'Skull Woods': (0x10, 'Skull Spike Corner SW'),
'Ice Palace': (0x12, 'Ice Antechamber NE'),
'Tower of Hera': (0x14, 'Hera Boss Down Stairs'),
'Thieves Town': (0x16, 'Thieves Boss SE'),
'Turtle Rock': (0x18, 'TR Boss SW'),
'Ganons Tower': (0x1a, 'GT Agahnim 2 SW')
}
# todo: inverted
portal_map = {
'Sanctuary': ('Sanctuary', 'Sanctuary Exit'),
'Hyrule Castle West': ('Hyrule Castle Entrance (West)', 'Hyrule Castle Exit (West)'),
'Hyrule Castle South': ('Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)'),
'Hyrule Castle East': ('Hyrule Castle Entrance (East)', 'Hyrule Castle Exit (East)'),
'Eastern': ('Eastern Palace', 'Eastern Palace Exit'),
'Desert West': ('Desert Palace Entrance (West)', 'Desert Palace Exit (West)'),
'Desert South': ('Desert Palace Entrance (South)', 'Desert Palace Exit (South)'),
'Desert East': ('Desert Palace Entrance (East)', 'Desert Palace Exit (East)'),
'Desert Back': ('Desert Palace Entrance (North)', 'Desert Palace Exit (North)'),
'Turtle Rock Lazy Eyes': ('Dark Death Mountain Ledge (West)', 'Turtle Rock Ledge Exit (West)'),
'Turtle Rock Eye Bridge': ('Turtle Rock Isolated Ledge Entrance', 'Turtle Rock Isolated Ledge Exit'),
'Turtle Rock Chest': ('Dark Death Mountain Ledge (East)', 'Turtle Rock Ledge Exit (East)'),
'Agahnims Tower': ('Agahnims Tower', 'Agahnims Tower Exit'),
'Swamp': ('Swamp Palace', 'Swamp Palace Exit'),
'Palace of Darkness': ('Palace of Darkness', 'Palace of Darkness Exit'),
'Mire': ('Misery Mire', 'Misery Mire Exit'),
'Skull 2 West': ('Skull Woods Second Section Door (West)', 'Skull Woods Second Section Exit (West)'),
'Skull 2 East': ('Skull Woods Second Section Door (East)', 'Skull Woods Second Section Exit (East)'),
'Skull 1': ('Skull Woods First Section Door', 'Skull Woods First Section Exit'),
'Skull 3': ('Skull Woods Final Section', 'Skull Woods Final Section Exit'),
'Ice': ('Ice Palace', 'Ice Palace Exit'),
'Hera': ('Tower of Hera', 'Tower of Hera Exit'),
'Thieves Town': ('Thieves Town', 'Thieves Town Exit'),
'Turtle Rock Main': ('Turtle Rock', 'Turtle Rock Exit (Front)'),
'Ganons Tower': ('Ganons Tower', 'Ganons Tower Exit'),
}
split_portals = {
'Desert Palace': ['Back', 'Main'],
'Skull Woods': ['1', '2', '3']
}
# split_portals = {
# 'Desert Palace': {
# 'Desert Back': 'Back',
# 'Desert South': 'Main',
# 'Desert West': 'Main',
# 'Desert East': 'Main'
# },
# 'Skull Woods': {
# 'Skull 1': '1',
# 'Skull 2 East': '2',
# 'Skull 2 West': '2',
# 'Skull 3': '3'
# }
# }

226
Doors.py
View File

@@ -1,5 +1,5 @@
from BaseClasses import Door, DoorType, Direction, CrystalBarrier
from BaseClasses import Door, DoorType, Direction, CrystalBarrier, Portal
from RoomData import PairedDoor
# constants
@@ -46,18 +46,21 @@ def create_doors(world, player):
create_door(player, 'Hyrule Castle Lobby W', Nrml).dir(We, 0x61, Mid, High).toggler().pos(0),
create_door(player, 'Hyrule Castle Lobby E', Nrml).dir(Ea, 0x61, Mid, High).toggler().pos(2),
create_door(player, 'Hyrule Castle Lobby WN', Nrml).dir(We, 0x61, Top, High).pos(1),
create_door(player, 'Hyrule Castle Lobby S', Nrml).dir(So, 0x61, Mid, High).pos(4).portal(Z, 0x22, 1),
create_door(player, 'Hyrule Castle Lobby North Stairs', StrS).dir(No, 0x61, Mid, High),
create_door(player, 'Hyrule Castle West Lobby E', Nrml).dir(Ea, 0x60, Mid, Low).toggler().pos(1),
create_door(player, 'Hyrule Castle West Lobby N', Nrml).dir(No, 0x60, Right, Low).pos(0),
create_door(player, 'Hyrule Castle West Lobby EN', Nrml).dir(Ea, 0x60, Top, High).pos(3),
create_door(player, 'Hyrule Castle West Lobby S', Nrml).dir(So, 0x60, Right, High).pos(2).portal(X, 0x02),
create_door(player, 'Hyrule Castle East Lobby W', Nrml).dir(We, 0x62, Mid, Low).toggler().pos(0),
create_door(player, 'Hyrule Castle East Lobby N', Nrml).dir(No, 0x62, Mid, High).pos(3),
create_door(player, 'Hyrule Castle East Lobby NW', Nrml).dir(No, 0x62, Left, Low).pos(2),
create_door(player, 'Hyrule Castle East Lobby S', Nrml).dir(So, 0x62, Left, High).pos(1).portal(Z, 0x22),
create_door(player, 'Hyrule Castle East Hall W', Nrml).dir(We, 0x52, Top, Low).pos(0),
create_door(player, 'Hyrule Castle East Hall S', Nrml).dir(So, 0x52, Mid, High).pos(2),
create_door(player, 'Hyrule Castle East Hall SW', Nrml).dir(So, 0x52, Left, Low).pos(1),
create_door(player, 'Hyrule Castle East Hall S', Nrml).dir(So, 0x52, Mid, High).pos(2).portal(Z, 0x22),
create_door(player, 'Hyrule Castle East Hall SW', Nrml).dir(So, 0x52, Left, Low).pos(1).portal(Z, 0x22, 1),
create_door(player, 'Hyrule Castle West Hall E', Nrml).dir(Ea, 0x50, Top, Low).pos(0),
create_door(player, 'Hyrule Castle West Hall S', Nrml).dir(So, 0x50, Right, Low).pos(1),
create_door(player, 'Hyrule Castle West Hall S', Nrml).dir(So, 0x50, Right, Low).pos(1).portal(X, 0x02, 1),
create_door(player, 'Hyrule Castle Back Hall W', Nrml).dir(We, 0x01, Top, Low).pos(0),
create_door(player, 'Hyrule Castle Back Hall E', Nrml).dir(Ea, 0x01, Top, Low).pos(1),
create_door(player, 'Hyrule Castle Back Hall Down Stairs', Sprl).dir(Dn, 0x01, 0, HTL).ss(A, 0x2a, 0x00),
@@ -80,7 +83,7 @@ def create_doors(world, player):
create_door(player, 'Hyrule Dungeon Guardroom Catwalk Edge', Open).dir(Ea, 0x81, None, High).edge(3, S, 0x10),
create_door(player, 'Hyrule Dungeon Guardroom Abyss Edge', Open).dir(Ea, 0x81, None, Low).edge(4, X, 0x18),
create_door(player, 'Hyrule Dungeon Guardroom N', Nrml).dir(No, 0x81, Left, Low).pos(0),
create_door(player, 'Hyrule Dungeon Armory S', Nrml).dir(So, 0x71, Left, Low).trap(0x2).pos(1),
create_door(player, 'Hyrule Dungeon Armory S', Nrml).dir(So, 0x71, Left, Low).trap(0x2).pos(1).portal(Z, 0x00, 1),
create_door(player, 'Hyrule Dungeon Armory ES', Intr).dir(Ea, 0x71, Left, Low).pos(2),
create_door(player, 'Hyrule Dungeon Armory Boomerang WS', Intr).dir(We, 0x71, Left, Low).pos(2),
create_door(player, 'Hyrule Dungeon Armory Interior Key Door N', Intr).dir(No, 0x71, Left, High).small_key().pos(0),
@@ -91,17 +94,17 @@ def create_doors(world, player):
create_door(player, 'Hyrule Dungeon Cellblock Up Stairs', Sprl).dir(Up, 0x80, 0, HTH).ss(A, 0x1a, 0x44),
# sewers
create_door(player, 'Sewers Behind Tapestry S', Nrml).dir(So, 0x41, Mid, High).no_exit().trap(0x4).pos(0),
create_door(player, 'Sewers Behind Tapestry S', Nrml).dir(So, 0x41, Mid, High).no_exit().trap(0x4).pos(0).portal(Z, 0x22),
create_door(player, 'Sewers Behind Tapestry Down Stairs', Sprl).dir(Dn, 0x41, 0, HTH).ss(S, 0x12, 0xb0),
create_door(player, 'Sewers Rope Room Up Stairs', Sprl).dir(Up, 0x42, 0, HTH).ss(S, 0x1b, 0x9c),
create_door(player, 'Sewers Rope Room North Stairs', StrS).dir(No, 0x42, Mid, High),
create_door(player, 'Sewers Dark Cross South Stairs', StrS).dir(So, 0x32, Mid, High),
create_door(player, 'Sewers Dark Cross Key Door N', Nrml).dir(No, 0x32, Mid, High).small_key().pos(0),
create_door(player, 'Sewers Water S', Nrml).dir(So, 0x22, Mid, High).small_key().pos(0),
create_door(player, 'Sewers Water S', Nrml).dir(So, 0x22, Mid, High).small_key().pos(0).portal(Z, 0x22),
create_door(player, 'Sewers Water W', Nrml).dir(We, 0x22, Bot, High).pos(1),
create_door(player, 'Sewers Key Rat E', Nrml).dir(Ea, 0x21, Bot, High).pos(1),
create_door(player, 'Sewers Key Rat Key Door N', Nrml).dir(No, 0x21, Right, High).small_key().pos(0),
create_door(player, 'Sewers Secret Room Key Door S', Nrml).dir(So, 0x11, Right, High).small_key().pos(2),
create_door(player, 'Sewers Secret Room Key Door S', Nrml).dir(So, 0x11, Right, High).small_key().pos(2).portal(X, 0x02),
create_door(player, 'Sewers Rat Path WS', Intr).dir(We, 0x11, Bot, High).pos(1),
create_door(player, 'Sewers Rat Path WN', Intr).dir(We, 0x11, Top, High).pos(0),
create_door(player, 'Sewers Secret Room ES', Intr).dir(Ea, 0x11, Bot, High).pos(1),
@@ -111,11 +114,13 @@ def create_doors(world, player):
create_door(player, 'Sewers Pull Switch Down Stairs', Sprl).dir(Dn, 0x02, 0, HTL).ss(S, 0x12, 0x80),
create_door(player, 'Sewers Yet More Rats S', Intr).dir(So, 0x02, Mid, Low).pos(1),
create_door(player, 'Sewers Pull Switch N', Intr).dir(No, 0x02, Mid, Low).pos(1),
create_door(player, 'Sewers Pull Switch S', Nrml).dir(So, 0x02, Mid, Low).trap(0x4).toggler().pos(0),
create_door(player, 'Sewers Pull Switch S', Nrml).dir(So, 0x02, Mid, Low).trap(0x4).toggler().pos(0).portal(Z, 0x20, 1),
# logically one way the sanc, but should be linked - also toggle
create_door(player, 'Sanctuary N', Nrml).dir(No, 0x12, Mid, High).no_exit().toggler().pos(0),
create_door(player, 'Sanctuary S', Nrml).dir(So, 0x12, Mid, High).pos(2).portal(Z, 0x22, 1),
# Eastern Palace
create_door(player, 'Eastern Lobby S', Nrml).dir(So, 0xc9, Mid, High).pos(4).portal(Z, 0x20),
create_door(player, 'Eastern Lobby N', Intr).dir(No, 0xc9, Mid, High).pos(0),
create_door(player, 'Eastern Lobby Bridge S', Intr).dir(So, 0xc9, Mid, High).pos(0),
create_door(player, 'Eastern Lobby NW', Intr).dir(No, 0xc9, Left, High).pos(2),
@@ -123,11 +128,11 @@ def create_doors(world, player):
create_door(player, 'Eastern Lobby NE', Intr).dir(No, 0xc9, Right, High).pos(3),
create_door(player, 'Eastern Lobby Right Ledge SE', Intr).dir(So, 0xc9, Right, High).pos(3),
create_door(player, 'Eastern Lobby Bridge N', Nrml).dir(No, 0xc9, Mid, High).pos(1).trap(0x2),
create_door(player, 'Eastern Cannonball S', Nrml).dir(So, 0xb9, Mid, High).pos(2),
create_door(player, 'Eastern Cannonball S', Nrml).dir(So, 0xb9, Mid, High).pos(2).portal(Z, 0x22),
create_door(player, 'Eastern Cannonball N', Nrml).dir(No, 0xb9, Mid, High).pos(1),
create_door(player, 'Eastern Cannonball Ledge WN', Nrml).dir(We, 0xb9, Top, High).pos(3),
create_door(player, 'Eastern Cannonball Ledge Key Door EN', Nrml).dir(Ea, 0xb9, Top, High).small_key().pos(0),
create_door(player, 'Eastern Courtyard Ledge S', Nrml).dir(So, 0xa9, Mid, High).pos(5),
create_door(player, 'Eastern Courtyard Ledge S', Nrml).dir(So, 0xa9, Mid, High).pos(5).portal(Z, 0x22),
create_door(player, 'Eastern Courtyard Ledge W', Nrml).dir(We, 0xa9, Mid, High).trap(0x4).pos(0),
create_door(player, 'Eastern Courtyard Ledge E', Nrml).dir(Ea, 0xa9, Mid, High).trap(0x2).pos(1),
create_door(player, 'Eastern East Wing W', Nrml).dir(We, 0xaa, Mid, High).pos(4),
@@ -147,7 +152,7 @@ def create_doors(world, player):
create_door(player, 'Eastern Compass Room EN', Intr).dir(Ea, 0xa8, Top, High).pos(3),
create_door(player, 'Eastern Hint Tile WN', Intr).dir(We, 0xa8, Top, High).pos(3),
create_door(player, 'Eastern Hint Tile EN', Nrml).dir(Ea, 0xa8, Top, Low).pos(4),
create_door(player, 'Eastern Hint Tile Blocked Path SE', Nrml).dir(So, 0xa8, Right, High).small_key().pos(2).kill(),
create_door(player, 'Eastern Hint Tile Blocked Path SE', Nrml).dir(So, 0xa8, Right, High).small_key().pos(2).kill().portal(X, 0x02),
create_door(player, 'Eastern Hint Tile Push Block', Lgcl),
create_door(player, 'Eastern Courtyard WN', Nrml).dir(We, 0xa9, Top, Low).pos(3),
create_door(player, 'Eastern Courtyard EN', Nrml).dir(Ea, 0xa9, Top, Low).pos(4),
@@ -155,14 +160,14 @@ def create_doors(world, player):
create_door(player, 'Eastern Courtyard Potholes', Hole),
create_door(player, 'Eastern Fairies\' Warp', Warp),
create_door(player, 'Eastern Map Valley WN', Nrml).dir(We, 0xaa, Top, Low).pos(1),
create_door(player, 'Eastern Map Valley SW', Nrml).dir(So, 0xaa, Left, High).pos(5),
create_door(player, 'Eastern Map Valley SW', Nrml).dir(So, 0xaa, Left, High).pos(5).portal(Z, 0x02),
create_door(player, 'Eastern Dark Square NW', Nrml).dir(No, 0xba, Left, High).trap(0x2).pos(1),
create_door(player, 'Eastern Dark Square Key Door WN', Nrml).dir(We, 0xba, Top, High).small_key().pos(0),
create_door(player, 'Eastern Dark Square EN', Intr).dir(Ea, 0xba, Top, High).pos(2),
create_door(player, 'Eastern Dark Pots WN', Intr).dir(We, 0xba, Top, High).pos(2),
create_door(player, 'Eastern Big Key EN', Nrml).dir(Ea, 0xb8, Top, High).pos(1),
create_door(player, 'Eastern Big Key NE', Nrml).dir(No, 0xb8, Right, High).big_key().pos(0),
create_door(player, 'Eastern Darkness S', Nrml).dir(So, 0x99, Mid, High).small_key().pos(1),
create_door(player, 'Eastern Darkness S', Nrml).dir(So, 0x99, Mid, High).small_key().pos(1).portal(Z, 0x20),
create_door(player, 'Eastern Darkness NE', Intr).dir(No, 0x99, Right, High).pos(2),
create_door(player, 'Eastern Rupees SE', Intr).dir(So, 0x99, Right, High).pos(2),
# Up is a keydoor and down is not. Only the up stairs should be considered a key door for now.
@@ -180,6 +185,7 @@ def create_doors(world, player):
create_door(player, 'Eastern Boss SE', Nrml).dir(So, 0xc8, Right, High).no_exit().trap(0x4).pos(0),
# Desert Palace
create_door(player, 'Desert Main Lobby S', Nrml).dir(So, 0x84, Mid, High).pos(0).portal(Z, 0x22),
create_door(player, 'Desert Main Lobby NW Edge', Open).dir(No, 0x84, None, High).edge(3, A, 0x20),
create_door(player, 'Desert Main Lobby N Edge', Open).dir(No, 0x84, None, High).edge(4, A, 0xa0),
create_door(player, 'Desert Main Lobby NE Edge', Open).dir(No, 0x84, None, High).edge(5, S, 0x20),
@@ -191,12 +197,13 @@ def create_doors(world, player):
create_door(player, 'Desert Dead End Edge', Open).dir(So, 0x74, None, High).edge(4, Z, 0xa0),
create_door(player, 'Desert East Wing W Edge', Open).dir(We, 0x85, None, High).edge(5, A, 0xa0),
create_door(player, 'Desert East Wing N Edge', Open).dir(No, 0x85, None, High).edge(6, A, 0x20),
create_door(player, 'Desert East Lobby S', Nrml).dir(So, 0x85, Right, High).pos(2).portal(X, 0x00),
create_door(player, 'Desert East Lobby WS', Intr).dir(We, 0x85, Bot, High).pos(3),
create_door(player, 'Desert East Wing ES', Intr).dir(Ea, 0x85, Bot, High).pos(3),
create_door(player, 'Desert East Wing Key Door EN', Intr).dir(Ea, 0x85, Top, High).small_key().pos(1),
create_door(player, 'Desert Compass Key Door WN', Intr).dir(We, 0x85, Top, High).small_key().pos(1),
create_door(player, 'Desert Compass NW', Nrml).dir(No, 0x85, Right, High).trap(0x4).pos(0),
create_door(player, 'Desert Cannonball S', Nrml).dir(So, 0x75, Right, High).pos(1),
create_door(player, 'Desert Cannonball S', Nrml).dir(So, 0x75, Right, High).pos(1).portal(Z, 0x02),
create_door(player, 'Desert Arrow Pot Corner S Edge', Open).dir(So, 0x75, None, High).edge(6, Z, 0x20),
create_door(player, 'Desert Arrow Pot Corner W Edge', Open).dir(We, 0x75, None, High).edge(2, Z, 0x20),
create_door(player, 'Desert Arrow Pot Corner NW', Intr).dir(No, 0x75, Left, High).pos(0),
@@ -219,10 +226,12 @@ def create_doors(world, player):
create_door(player, 'Desert Big Chest SW', Intr).dir(So, 0x73, Left, High).pos(0),
create_door(player, 'Desert West Wing N Edge', Open).dir(No, 0x83, None, High).edge(2, S, 0x20),
create_door(player, 'Desert West Wing WS', Intr).dir(We, 0x83, Bot, High).pos(2),
create_door(player, 'Desert West S', Nrml).dir(So, 0x83, Left, High).pos(1).portal(Z, 0x00),
create_door(player, 'Desert West Lobby ES', Intr).dir(Ea, 0x83, Bot, High).pos(2),
create_door(player, 'Desert West Lobby NW', Intr).dir(No, 0x83, Left, High).pos(0),
create_door(player, 'Desert Fairy Fountain SW', Intr).dir(So, 0x83, Left, High).pos(0),
# Desert Back
create_door(player, 'Desert Back Lobby S', Nrml).dir(So, 0x63, Left, High).pos(2).portal(Z, 0x00),
create_door(player, 'Desert Back Lobby NW', Intr).dir(No, 0x63, Left, High).pos(1),
create_door(player, 'Desert Tiles 1 SW', Intr).dir(So, 0x63, Left, High).pos(1),
create_door(player, 'Desert Tiles 1 Up Stairs', Sprl).dir(Up, 0x63, 0, HTH).ss(A, 0x1b, 0x6c, True).small_key().pos(0),
@@ -232,13 +241,14 @@ def create_doors(world, player):
create_door(player, 'Desert Four Statues ES', Intr).dir(Ea, 0x53, Bot, High).pos(1),
create_door(player, 'Desert Beamos Hall WS', Intr).dir(We, 0x53, Bot, High).pos(1),
create_door(player, 'Desert Beamos Hall NE', Nrml).dir(No, 0x53, Right, High).small_key().pos(2),
create_door(player, 'Desert Tiles 2 SE', Nrml).dir(So, 0x43, Right, High).small_key().pos(2).kill(),
create_door(player, 'Desert Tiles 2 SE', Nrml).dir(So, 0x43, Right, High).small_key().pos(2).kill().portal(X, 0x00),
create_door(player, 'Desert Tiles 2 NE', Intr).dir(No, 0x43, Right, High).small_key().pos(1),
create_door(player, 'Desert Wall Slide SE', Intr).dir(So, 0x43, Right, High).small_key().pos(1),
create_door(player, 'Desert Wall Slide NW', Nrml).dir(No, 0x43, Left, High).big_key().pos(0).no_entrance(),
create_door(player, 'Desert Boss SW', Nrml).dir(So, 0x33, Left, High).no_exit().trap(0x4).pos(0),
create_door(player, 'Desert Boss SW', Nrml).dir(So, 0x33, Left, High).no_exit().trap(0x4).pos(0).portal(Z, 0x00),
# Hera
create_door(player, 'Hera Lobby S', Nrml).dir(So, 0x77, Mid, Low).pos(0).portal(Z, 0x22, 1),
create_door(player, 'Hera Lobby Down Stairs', Sprl).dir(Dn, 0x77, 3, HTL).ss(Z, 0x21, 0x90, False, True),
create_door(player, 'Hera Lobby Key Stairs', Sprl).dir(Dn, 0x77, 1, HTL).ss(A, 0x12, 0x80).small_key().pos(1),
create_door(player, 'Hera Lobby Up Stairs', Sprl).dir(Up, 0x77, 2, HTL).ss(X, 0x2b, 0x5c, False, True),
@@ -274,6 +284,7 @@ def create_doors(world, player):
create_door(player, 'Hera Boss Inner Hole', Hole),
# Castle Tower
create_door(player, 'Tower Lobby S', Nrml).dir(So, 0xe0, Left, High).pos(3).portal(Z, 0x00),
create_door(player, 'Tower Lobby NW', Intr).dir(No, 0xe0, Left, High).pos(1),
create_door(player, 'Tower Gold Knights SW', Intr).dir(So, 0xe0, Left, High).pos(1),
create_door(player, 'Tower Gold Knights EN', Intr).dir(Ea, 0xe0, Top, High).pos(0),
@@ -310,6 +321,7 @@ def create_doors(world, player):
create_door(player, 'Tower Agahnim 1 SW', Nrml).dir(So, 0x20, Left, High).no_exit().trap(0x4).pos(0),
# Palace of Darkness
create_door(player, 'PoD Lobby S', Nrml).dir(So, 0x4a, Mid, High).pos(4).portal(Z, 0x20),
create_door(player, 'PoD Lobby N', Intr).dir(No, 0x4a, Mid, High).pos(3),
create_door(player, 'PoD Lobby NW', Intr).dir(No, 0x4a, Left, High).pos(0),
create_door(player, 'PoD Lobby NE', Intr).dir(No, 0x4a, Right, High).pos(1),
@@ -322,7 +334,7 @@ def create_doors(world, player):
create_door(player, 'PoD Shooter Room Up Stairs', Sprl).dir(Up, 0x09, 1, HTH).ss(A, 0x1b, 0x6c, True, True),
create_door(player, 'PoD Warp Room Up Stairs', Sprl).dir(Up, 0x09, 0, HTH).ss(S, 0x1a, 0x6c, True, True),
create_door(player, 'PoD Warp Room Warp', Warp),
create_door(player, 'PoD Pit Room S', Nrml).dir(So, 0x3a, Mid, High).small_key().pos(0),
create_door(player, 'PoD Pit Room S', Nrml).dir(So, 0x3a, Mid, High).small_key().pos(0).portal(Z, 0x22),
create_door(player, 'PoD Pit Room NW', Nrml).dir(No, 0x3a, Left, High).pos(1),
create_door(player, 'PoD Pit Room NE', Nrml).dir(No, 0x3a, Right, High).pos(2),
create_door(player, 'PoD Pit Room Freefall', Hole),
@@ -334,8 +346,8 @@ def create_doors(world, player):
create_door(player, 'PoD Basement Ledge Up Stairs', Sprl).dir(Up, 0x0a, 0, HTH).ss(A, 0x1a, 0xec).small_key().pos(0),
create_door(player, 'PoD Basement Ledge Drop Down', Lgcl),
create_door(player, 'PoD Stalfos Basement Warp', Warp),
create_door(player, 'PoD Arena Main SW', Nrml).dir(So, 0x2a, Left, High).pos(4),
create_door(player, 'PoD Arena Bridge SE', Nrml).dir(So, 0x2a, Right, High).pos(5),
create_door(player, 'PoD Arena Main SW', Nrml).dir(So, 0x2a, Left, High).pos(4).portal(Z, 0x22),
create_door(player, 'PoD Arena Bridge SE', Nrml).dir(So, 0x2a, Right, High).pos(5).portal(X, 0x22),
create_door(player, 'PoD Arena Main NW', Nrml).dir(No, 0x2a, Left, High).small_key().pos(1),
create_door(player, 'PoD Arena Main NE', Nrml).dir(No, 0x2a, Right, High).no_exit().trap(0x4).pos(0),
create_door(player, 'PoD Arena Main Crystal Path', Lgcl),
@@ -352,14 +364,14 @@ def create_doors(world, player):
create_door(player, 'PoD Map Balcony WS', Nrml).dir(We, 0x2b, Bot, High).pos(1),
create_door(player, 'PoD Map Balcony South Stairs', StrS).dir(So, 0x2b, Left, High),
create_door(player, 'PoD Conveyor North Stairs', StrS).dir(No, 0x3b, Left, High),
create_door(player, 'PoD Conveyor SW', Nrml).dir(So, 0x3b, Left, High).pos(0),
create_door(player, 'PoD Conveyor SW', Nrml).dir(So, 0x3b, Left, High).pos(0).portal(Z, 0x02),
create_door(player, 'PoD Mimics 1 NW', Nrml).dir(No, 0x4b, Left, High).trap(0x4).pos(0),
create_door(player, 'PoD Mimics 1 SW', Intr).dir(So, 0x4b, Left, High).pos(1),
create_door(player, 'PoD Jelly Hall NW', Intr).dir(No, 0x4b, Left, High).pos(1),
create_door(player, 'PoD Jelly Hall NE', Intr).dir(No, 0x4b, Right, High).pos(2),
create_door(player, 'PoD Warp Hint SE', Intr).dir(So, 0x4b, Right, High).pos(2),
create_door(player, 'PoD Warp Hint Warp', Warp),
create_door(player, 'PoD Falling Bridge SW', Nrml).dir(So, 0x1a, Left, High).small_key().pos(3),
create_door(player, 'PoD Falling Bridge SW', Nrml).dir(So, 0x1a, Left, High).small_key().pos(3).portal(Z, 0x02),
create_door(player, 'PoD Falling Bridge WN', Nrml).dir(We, 0x1a, Top, High).small_key().pos(1),
create_door(player, 'PoD Falling Bridge EN', Intr).dir(Ea, 0x1a, Top, High).pos(4),
create_door(player, 'PoD Falling Bridge Path N', Lgcl),
@@ -370,13 +382,13 @@ def create_doors(world, player):
create_door(player, 'PoD Compass Room WN', Intr).dir(We, 0x1a, Top, High).pos(4),
create_door(player, 'PoD Compass Room SE', Intr).dir(So, 0x1a, Mid, High).small_key().pos(0),
create_door(player, 'PoD Harmless Hellway NE', Intr).dir(No, 0x1a, Right, High).small_key().pos(0),
create_door(player, 'PoD Harmless Hellway SE', Nrml).dir(So, 0x1a, Right, High).pos(5),
create_door(player, 'PoD Harmless Hellway SE', Nrml).dir(So, 0x1a, Right, High).pos(5).portal(X, 0x00),
create_door(player, 'PoD Compass Room W Down Stairs', Sprl).dir(Dn, 0x1a, 0, HTH).ss(S, 0x12, 0x50, True, True),
create_door(player, 'PoD Compass Room E Down Stairs', Sprl).dir(Dn, 0x1a, 1, HTH).ss(S, 0x11, 0xb0, True, True),
create_door(player, 'PoD Dark Basement W Up Stairs', Sprl).dir(Up, 0x6a, 0, HTH).ss(S, 0x1b, 0x3c, True),
create_door(player, 'PoD Dark Basement E Up Stairs', Sprl).dir(Up, 0x6a, 1, HTH).ss(S, 0x1b, 0x9c, True),
create_door(player, 'PoD Dark Alley NE', Nrml).dir(No, 0x6a, Right, High).big_key().pos(0),
create_door(player, 'PoD Mimics 2 SW', Nrml).dir(So, 0x1b, Left, High).pos(1).kill(),
create_door(player, 'PoD Mimics 2 SW', Nrml).dir(So, 0x1b, Left, High).pos(1).kill().portal(X, 0x00),
create_door(player, 'PoD Mimics 2 NW', Intr).dir(No, 0x1b, Left, High).pos(0),
create_door(player, 'PoD Bow Statue SW', Intr).dir(So, 0x1b, Left, High).pos(0),
create_door(player, 'PoD Bow Statue Down Ladder', Lddr).no_entrance(),
@@ -390,6 +402,7 @@ def create_doors(world, player):
create_door(player, 'PoD Callback Warp', Warp),
create_door(player, 'PoD Boss SE', Nrml).dir(So, 0x5a, Right, High).no_exit().trap(0x4).pos(0),
create_door(player, 'Swamp Lobby S', Nrml).dir(So, 0x28, Mid, High).pos(1).portal(Z, 0x22),
create_door(player, 'Swamp Lobby Moat', Lgcl),
create_door(player, 'Swamp Entrance Down Stairs', Sprl).dir(Dn, 0x28, 0, HTH).ss(A, 0x11, 0x80).small_key().pos(0),
create_door(player, 'Swamp Entrance Moat', Lgcl),
@@ -416,7 +429,7 @@ def create_doors(world, player):
create_door(player, 'Swamp Hammer Switch SW', Intr).dir(So, 0x37, Left, High).small_key().pos(2),
create_door(player, 'Swamp Hammer Switch WN', Nrml).dir(We, 0x37, Top, High).pos(0),
create_door(player, 'Swamp Hub ES', Nrml).dir(Ea, 0x36, Bot, High).pos(4),
create_door(player, 'Swamp Hub S', Nrml).dir(So, 0x36, Mid, High).pos(5),
create_door(player, 'Swamp Hub S', Nrml).dir(So, 0x36, Mid, High).pos(5), # .portal(Z, 0x22, 1), couldn't figure this out
create_door(player, 'Swamp Hub WS', Nrml).dir(We, 0x36, Bot, High).pos(3),
create_door(player, 'Swamp Hub WN', Nrml).dir(We, 0x36, Top, High).small_key().pos(2),
create_door(player, 'Swamp Hub Hook Path', Lgcl),
@@ -457,7 +470,7 @@ def create_doors(world, player):
create_door(player, 'Swamp Attic Down Stairs', Sprl).dir(Dn, 0x54, 0, HTH).ss(Z, 0x12, 0x80).kill(),
create_door(player, 'Swamp Attic Left Pit', Hole),
create_door(player, 'Swamp Attic Right Pit', Hole),
create_door(player, 'Swamp Push Statue S', Nrml).dir(So, 0x26, Mid, High).small_key().pos(0),
create_door(player, 'Swamp Push Statue S', Nrml).dir(So, 0x26, Mid, High).small_key().pos(0).portal(Z, 0x20),
create_door(player, 'Swamp Push Statue NW', Intr).dir(No, 0x26, Left, High).pos(1),
create_door(player, 'Swamp Push Statue NE', Intr).dir(No, 0x26, Right, High).pos(2),
create_door(player, 'Swamp Push Statue Down Stairs', Sprl).dir(Dn, 0x26, 2, HTH).ss(X, 0x12, 0xc0, False, True),
@@ -478,7 +491,7 @@ def create_doors(world, player):
create_door(player, 'Swamp Basement Shallows NW', Nrml).dir(No, 0x76, Left, High).toggler().pos(2),
create_door(player, 'Swamp Basement Shallows EN', Intr).dir(Ea, 0x76, Top, High).pos(0),
create_door(player, 'Swamp Basement Shallows ES', Intr).dir(Ea, 0x76, Bot, High).pos(1),
create_door(player, 'Swamp Waterfall Room SW', Nrml).dir(So, 0x66, Left, Low).toggler().pos(1),
create_door(player, 'Swamp Waterfall Room SW', Nrml).dir(So, 0x66, Left, Low).toggler().pos(1).portal(Z, 0x20, 1),
create_door(player, 'Swamp Waterfall Room NW', Intr).dir(No, 0x66, Left, Low).pos(3),
create_door(player, 'Swamp Waterfall Room NE', Intr).dir(No, 0x66, Right, Low).pos(0),
create_door(player, 'Swamp Refill SW', Intr).dir(So, 0x66, Left, Low).pos(3),
@@ -494,10 +507,11 @@ def create_doors(world, player):
create_door(player, 'Swamp T NW', Nrml).dir(No, 0x16, Left, High).pos(3),
create_door(player, 'Swamp Boss SW', Nrml).dir(So, 0x06, Left, High).no_exit().trap(0x4).pos(0),
create_door(player, 'Skull 1 Lobby S', Nrml).dir(So, 0x58, Left, High).pos(4).portal(Z, 0x00),
create_door(player, 'Skull 1 Lobby WS', Nrml).dir(We, 0x58, Bot, High).small_key().pos(1),
create_door(player, 'Skull 1 Lobby ES', Intr).dir(Ea, 0x58, Bot, High).pos(5),
create_door(player, 'Skull Map Room WS', Intr).dir(We, 0x58, Bot, High).pos(5),
create_door(player, 'Skull Map Room SE', Nrml).dir(So, 0x58, Right, High).small_key().pos(2),
create_door(player, 'Skull Map Room SE', Nrml).dir(So, 0x58, Right, High).small_key().pos(2).portal(X, 0x02),
create_door(player, 'Skull Pot Circle WN', Intr).dir(We, 0x58, Top, High).pos(3),
create_door(player, 'Skull Pull Switch EN', Intr).dir(Ea, 0x58, Top, High).pos(3),
create_door(player, 'Skull Pot Circle Star Path', Lgcl),
@@ -511,7 +525,8 @@ def create_doors(world, player):
create_door(player, 'Skull Left Drop ES', Intr).dir(Ea, 0x67, Bot, High).pos(1),
create_door(player, 'Skull Compass Room WS', Intr).dir(We, 0x67, Bot, High).pos(1),
create_door(player, 'Skull Pot Prison ES', Nrml).dir(Ea, 0x57, Bot, High).small_key().pos(2),
create_door(player, 'Skull Pot Prison SE', Nrml).dir(So, 0x57, Right, High).pos(5),
create_door(player, 'Skull Pot Prison SE', Nrml).dir(So, 0x57, Right, High).pos(5).portal(X, 0x00),
create_door(player, 'Skull 2 East Lobby SW', Nrml).dir(So, 0x57, Left, High).pos(3).portal(Z, 0x00),
create_door(player, 'Skull 2 East Lobby WS', Nrml).dir(We, 0x57, Bot, High).pos(4),
create_door(player, 'Skull 2 East Lobby NW', Intr).dir(No, 0x57, Left, High).pos(1),
create_door(player, 'Skull Big Key SW', Intr).dir(So, 0x57, Left, High).pos(1),
@@ -519,26 +534,29 @@ def create_doors(world, player):
create_door(player, 'Skull Lone Pot EN', Intr).dir(Ea, 0x57, Top, High).pos(0),
create_door(player, 'Skull Small Hall ES', Nrml).dir(Ea, 0x56, Bot, High).pos(3),
create_door(player, 'Skull Small Hall WS', Intr).dir(We, 0x56, Bot, High).pos(2),
create_door(player, 'Skull 2 West Lobby S', Nrml).dir(So, 0x56, Left, High).pos(1).portal(Z, 0x00),
create_door(player, 'Skull 2 West Lobby ES', Intr).dir(Ea, 0x56, Bot, High).pos(2),
create_door(player, 'Skull 2 West Lobby NW', Intr).dir(No, 0x56, Left, High).small_key().pos(0),
create_door(player, 'Skull X Room SW', Intr).dir(So, 0x56, Left, High).small_key().pos(0),
create_door(player, 'Skull Back Drop Star Path', Lgcl),
create_door(player, 'Skull 3 Lobby SW', Nrml).dir(So, 0x59, Left, High).pos(1).portal(Z, 0x02),
create_door(player, 'Skull 3 Lobby NW', Nrml).dir(No, 0x59, Left, High).small_key().pos(0),
create_door(player, 'Skull 3 Lobby EN', Intr).dir(Ea, 0x59, Top, High).pos(2),
create_door(player, 'Skull East Bridge WN', Intr).dir(We, 0x59, Top, High).pos(2),
create_door(player, 'Skull East Bridge WS', Intr).dir(We, 0x59, Bot, High).pos(3),
create_door(player, 'Skull West Bridge Nook ES', Intr).dir(Ea, 0x59, Bot, High).pos(3),
create_door(player, 'Skull Star Pits SW', Nrml).dir(So, 0x49, Left, High).small_key().pos(2),
create_door(player, 'Skull Star Pits SW', Nrml).dir(So, 0x49, Left, High).small_key().pos(2).portal(Z, 0x00),
create_door(player, 'Skull Star Pits ES', Intr).dir(Ea, 0x49, Bot, High).pos(3),
create_door(player, 'Skull Torch Room WS', Intr).dir(We, 0x49, Bot, High).pos(3),
create_door(player, 'Skull Torch Room WN', Intr).dir(We, 0x49, Top, High).pos(1),
create_door(player, 'Skull Vines EN', Intr).dir(Ea, 0x49, Top, High).pos(1),
create_door(player, 'Skull Vines NW', Nrml).dir(No, 0x49, Left, High).pos(0),
create_door(player, 'Skull Spike Corner SW', Nrml).dir(So, 0x39, Left, High).no_exit().trap(0x4).pos(0),
create_door(player, 'Skull Spike Corner SW', Nrml).dir(So, 0x39, Left, High).no_exit().trap(0x4).pos(0).portal(Z, 0x00),
create_door(player, 'Skull Spike Corner ES', Intr).dir(Ea, 0x39, Bot, High).small_key().pos(1),
create_door(player, 'Skull Final Drop WS', Intr).dir(We, 0x39, Bot, High).small_key().pos(1),
create_door(player, 'Skull Final Drop Hole', Hole),
create_door(player, 'Thieves Lobby S', Nrml).dir(So, 0xdb, Mid, High).pos(1).portal(Z, 0x22),
create_door(player, 'Thieves Lobby N Edge', Open).dir(No, 0xdb, None, Low).edge(7, A, 0x10),
create_door(player, 'Thieves Lobby NE Edge', Open).dir(No, 0xdb, None, Low).edge(8, S, 0x18),
create_door(player, 'Thieves Lobby E', Nrml).dir(Ea, 0xdb, Mid, High).no_exit().trap(0x4).pos(0),
@@ -560,10 +578,10 @@ def create_doors(world, player):
create_door(player, 'Thieves Compass Room N Edge', Open).dir(No, 0xdc, None, Low).edge(10, A, 0x10),
create_door(player, 'Thieves Compass Room WS Edge', Open).dir(We, 0xdc, None, Low).edge(8, Z, 0x50),
create_door(player, 'Thieves Compass Room W', Nrml).dir(We, 0xdc, Mid, High).pos(0),
create_door(player, 'Thieves Hallway SE', Nrml).dir(So, 0xbc, Right, High).small_key().pos(1),
create_door(player, 'Thieves Hallway SE', Nrml).dir(So, 0xbc, Right, High).small_key().pos(1).portal(X, 0x02),
create_door(player, 'Thieves Hallway NE', Nrml).dir(No, 0xbc, Right, High).pos(7),
create_door(player, 'Thieves Pot Alcove Mid WS', Nrml).dir(We, 0xbc, Bot, High).pos(5),
create_door(player, 'Thieves Pot Alcove Bottom SW', Nrml).dir(So, 0xbc, Left, High).pos(3),
create_door(player, 'Thieves Pot Alcove Bottom SW', Nrml).dir(So, 0xbc, Left, High).pos(3).portal(Z, 0x00),
create_door(player, 'Thieves Conveyor Maze WN', Nrml).dir(We, 0xbc, Top, High).pos(4),
create_door(player, 'Thieves Hallway WS', Intr).dir(We, 0xbc, Bot, High).small_key().pos(0),
create_door(player, 'Thieves Pot Alcove Mid ES', Intr).dir(Ea, 0xbc, Bot, High).small_key().pos(0),
@@ -586,7 +604,7 @@ def create_doors(world, player):
create_door(player, 'Thieves Triple Bypass SE', Intr).dir(So, 0xbb, Right, High).pos(3),
create_door(player, 'Thieves Hellway Crystal EN', Intr).dir(Ea, 0xbb, Top, High).pos(1),
create_door(player, 'Thieves Triple Bypass WN', Intr).dir(We, 0xbb, Top, High).pos(1),
create_door(player, 'Thieves Spike Switch SW', Nrml).dir(So, 0xab, Left, High).pos(1),
create_door(player, 'Thieves Spike Switch SW', Nrml).dir(So, 0xab, Left, High).pos(1).portal(Z, 0x00),
create_door(player, 'Thieves Spike Switch Up Stairs', Sprl).dir(Up, 0xab, 0, HTH).ss(Z, 0x1a, 0x6c, True, True).small_key().pos(0),
create_door(player, 'Thieves Attic Down Stairs', Sprl).dir(Dn, 0x64, 0, HTH).ss(Z, 0x11, 0x80, True, True),
create_door(player, 'Thieves Attic ES', Intr).dir(Ea, 0x64, Bot, High).pos(0),
@@ -615,6 +633,7 @@ def create_doors(world, player):
create_door(player, 'Thieves Conveyor Block WN', Intr).dir(We, 0x44, Top, High).pos(0),
create_door(player, 'Thieves Trap EN', Intr).dir(Ea, 0x44, Left, Top).pos(0),
create_door(player, 'Ice Lobby SE', Nrml).dir(So, 0x0e, Right, High).pos(2).portal(X, 0x00),
create_door(player, 'Ice Lobby WS', Intr).dir(We, 0x0e, Bot, High).pos(1),
create_door(player, 'Ice Jelly Key ES', Intr).dir(Ea, 0x0e, Bot, High).pos(1),
create_door(player, 'Ice Jelly Key Down Stairs', Sprl).dir(Dn, 0x0e, 0, HTH).ss(Z, 0x11, 0x80, True, True).small_key().pos(0),
@@ -630,7 +649,7 @@ def create_doors(world, player):
create_door(player, 'Ice Cross Right Push Block Bottom', Lgcl), # dynamic
create_door(player, 'Ice Cross Top Push Block Bottom', Lgcl), # dynamic
create_door(player, 'Ice Cross Top Push Block Right', Lgcl), # dynamic
create_door(player, 'Ice Cross Bottom SE', Nrml).dir(So, 0x1e, Right, High).pos(3),
create_door(player, 'Ice Cross Bottom SE', Nrml).dir(So, 0x1e, Right, High).pos(3).portal(X, 0x00),
create_door(player, 'Ice Cross Right ES', Nrml).dir(Ea, 0x1e, Bot, High).trap(0x4).pos(0),
create_door(player, 'Ice Bomb Drop Hole', Hole),
create_door(player, 'Ice Compass Room NE', Nrml).dir(No, 0x2e, Right, High).pos(0),
@@ -641,7 +660,7 @@ def create_doors(world, player):
create_door(player, 'Ice Big Key Down Ladder', Lddr),
create_door(player, 'Ice Stalfos Hint SE', Intr).dir(So, 0x3e, Right, High).pos(0),
create_door(player, 'Ice Conveyor NE', Intr).dir(No, 0x3e, Right, High).no_exit().pos(0),
create_door(player, 'Ice Conveyor SW', Nrml).dir(So, 0x3e, Left, High).small_key().pos(1),
create_door(player, 'Ice Conveyor SW', Nrml).dir(So, 0x3e, Left, High).small_key().pos(1).portal(Z, 0x20),
create_door(player, 'Ice Bomb Jump NW', Nrml).dir(No, 0x4e, Left, High).small_key().pos(1),
create_door(player, 'Ice Bomb Jump Ledge Orange Barrier', Lgcl),
create_door(player, 'Ice Bomb Jump Catwalk Orange Barrier', Lgcl),
@@ -650,7 +669,7 @@ def create_doors(world, player):
create_door(player, 'Ice Narrow Corridor Down Stairs', Sprl).dir(Dn, 0x4e, 0, HTH).ss(S, 0x52, 0xc0, True, True),
create_door(player, 'Ice Pengator Trap Up Stairs', Sprl).dir(Up, 0x6e, 0, HTH).ss(S, 0x5a, 0xac, True, True),
create_door(player, 'Ice Pengator Trap NE', Nrml).dir(No, 0x6e, Right, High).trap(0x4).pos(0),
create_door(player, 'Ice Spike Cross SE', Nrml).dir(So, 0x5e, Right, High).pos(2),
create_door(player, 'Ice Spike Cross SE', Nrml).dir(So, 0x5e, Right, High).pos(2).portal(X, 0x00),
create_door(player, 'Ice Spike Cross ES', Nrml).dir(Ea, 0x5e, Bot, High).small_key().pos(0),
create_door(player, 'Ice Spike Cross WS', Intr).dir(We, 0x5e, Bot, High).pos(3),
create_door(player, 'Ice Firebar ES', Intr).dir(Ea, 0x5e, Bot, High).pos(3),
@@ -672,7 +691,7 @@ def create_doors(world, player):
create_door(player, 'Ice Freezors Ledge ES', Intr).dir(Ea, 0x7e, Bot, High).pos(2),
create_door(player, 'Ice Tall Hint WS', Intr).dir(We, 0x7e, Bot, High).pos(1),
create_door(player, 'Ice Tall Hint EN', Nrml).dir(Ea, 0x7e, Top, High).pos(2),
create_door(player, 'Ice Tall Hint SE', Nrml).dir(So, 0x7e, Right, High).small_key().pos(0),
create_door(player, 'Ice Tall Hint SE', Nrml).dir(So, 0x7e, Right, High).small_key().pos(0).portal(X, 0x02),
create_door(player, 'Ice Hookshot Ledge WN', Nrml).dir(We, 0x7f, Top, High).no_exit().trap(0x4).pos(0).kill(),
create_door(player, 'Ice Hookshot Ledge Path', Lgcl),
create_door(player, 'Ice Hookshot Balcony Path', Lgcl),
@@ -685,7 +704,7 @@ def create_doors(world, player):
create_door(player, 'Iced T Up Stairs', Sprl).dir(Up, 0xae, 0, HTH).ss(S, 0x1a, 0x3c, True, True),
create_door(player, 'Ice Catwalk WN', Nrml).dir(We, 0xaf, Top, High).pos(1),
create_door(player, 'Ice Catwalk NW', Nrml).dir(No, 0xaf, Left, High).pos(0),
create_door(player, 'Ice Many Pots SW', Nrml).dir(So, 0x9f, Left, High).trap(0x2).pos(1),
create_door(player, 'Ice Many Pots SW', Nrml).dir(So, 0x9f, Left, High).trap(0x2).pos(1).portal(Z, 0x00),
create_door(player, 'Ice Many Pots WS', Nrml).dir(We, 0x9f, Bot, High).trap(0x4).pos(0),
create_door(player, 'Ice Crystal Right ES', Nrml).dir(Ea, 0x9e, Bot, High).pos(3),
create_door(player, 'Ice Crystal Right Orange Barrier', Lgcl),
@@ -705,18 +724,19 @@ def create_doors(world, player):
create_door(player, 'Ice Anti-Fairy SE', Intr).dir(So, 0xbe, Right, High).pos(2),
create_door(player, 'Ice Switch Room NE', Intr).dir(No, 0xbe, Right, High).pos(2),
create_door(player, 'Ice Switch Room ES', Nrml).dir(Ea, 0xbe, Bot, High).small_key().pos(1),
create_door(player, 'Ice Switch Room SE', Nrml).dir(So, 0xbe, Right, High).trap(0x4).pos(0),
create_door(player, 'Ice Switch Room SE', Nrml).dir(So, 0xbe, Right, High).trap(0x4).pos(0).portal(X, 0x00),
create_door(player, 'Ice Refill WS', Nrml).dir(We, 0xbf, Bot, High).small_key().pos(0),
create_door(player, 'Ice Fairy Warp', Warp),
create_door(player, 'Ice Antechamber NE', Nrml).dir(No, 0xce, Right, High).trap(0x4).pos(0),
create_door(player, 'Ice Antechamber Hole', Hole),
create_door(player, 'Mire Lobby S', Nrml).dir(So, 0x98, Left, High).pos(0).portal(Z, 0x20),
create_door(player, 'Mire Lobby Gap', Lgcl),
create_door(player, 'Mire Post-Gap Gap', Lgcl),
create_door(player, 'Mire Post-Gap Down Stairs', Sprl).dir(Dn, 0x98, 0, HTH).ss(X, 0x11, 0x90, False, True),
create_door(player, 'Mire 2 Up Stairs', Sprl).dir(Up, 0xd2, 0, HTH).ss(X, 0x1a, 0x7c, False, True),
create_door(player, 'Mire 2 NE', Nrml).dir(No, 0xd2, Right, High).trap(0x4).pos(0),
create_door(player, 'Mire Hub SE', Nrml).dir(So, 0xc2, Right, High).pos(5),
create_door(player, 'Mire Hub SE', Nrml).dir(So, 0xc2, Right, High).pos(5).portal(X, 0x22),
create_door(player, 'Mire Hub ES', Nrml).dir(Ea, 0xc2, Bot, High).pos(6),
create_door(player, 'Mire Hub E', Nrml).dir(Ea, 0xc2, Mid, High).pos(4),
create_door(player, 'Mire Hub NE', Nrml).dir(No, 0xc2, Right, High).pos(7),
@@ -745,7 +765,7 @@ def create_doors(world, player):
create_door(player, 'Mire Map Spot Blue Barrier', Lgcl),
create_door(player, 'Mire Crystal Dead End Left Barrier', Lgcl),
create_door(player, 'Mire Crystal Dead End Right Barrier', Lgcl),
create_door(player, 'Mire Hidden Shooters SE', Nrml).dir(So, 0xb2, Right, High).pos(6),
create_door(player, 'Mire Hidden Shooters SE', Nrml).dir(So, 0xb2, Right, High).pos(6).portal(X, 0x00),
create_door(player, 'Mire Hidden Shooters ES', Nrml).dir(Ea, 0xb2, Bot, High).pos(7),
create_door(player, 'Mire Hidden Shooters WS', Intr).dir(We, 0xb2, Bot, High).pos(1),
create_door(player, 'Mire Cross ES', Intr).dir(Ea, 0xb2, Bot, High).pos(1),
@@ -753,22 +773,22 @@ def create_doors(world, player):
create_door(player, 'Mire Hidden Shooters Block Path N', Lgcl),
create_door(player, 'Mire Hidden Shooters NE', Intr).dir(No, 0xb2, Right, High).pos(2),
create_door(player, 'Mire Minibridge SE', Intr).dir(So, 0xb2, Right, High).pos(2),
create_door(player, 'Mire Cross SW', Nrml).dir(So, 0xb2, Left, High).pos(5),
create_door(player, 'Mire Cross SW', Nrml).dir(So, 0xb2, Left, High).pos(5).portal(Z, 0x00),
create_door(player, 'Mire Minibridge NE', Nrml).dir(No, 0xb2, Right, High).pos(4),
create_door(player, 'Mire BK Door Room EN', Nrml).dir(Ea, 0xb2, Top, Low).pos(3),
create_door(player, 'Mire BK Door Room N', Nrml).dir(No, 0xb2, Mid, High).big_key().pos(0),
create_door(player, 'Mire Spikes WS', Nrml).dir(We, 0xb3, Bot, High).pos(3),
create_door(player, 'Mire Spikes SW', Nrml).dir(So, 0xb3, Left, High).pos(4),
create_door(player, 'Mire Spikes SW', Nrml).dir(So, 0xb3, Left, High).pos(4).portal(Z, 0x00),
create_door(player, 'Mire Spikes NW', Intr).dir(No, 0xb3, Left, High).small_key().pos(0),
create_door(player, 'Mire Ledgehop SW', Intr).dir(So, 0xb3, Left, High).small_key().pos(0),
create_door(player, 'Mire Ledgehop WN', Nrml).dir(We, 0xb3, Top, Low).pos(1),
create_door(player, 'Mire Ledgehop NW', Nrml).dir(No, 0xb3, Left, High).pos(2),
create_door(player, 'Mire Bent Bridge SW', Nrml).dir(So, 0xa3, Left, High).pos(1),
create_door(player, 'Mire Bent Bridge SW', Nrml).dir(So, 0xa3, Left, High).pos(1).portal(Z, 0x02),
create_door(player, 'Mire Bent Bridge W', Nrml).dir(We, 0xa3, Mid, High).pos(0),
create_door(player, 'Mire Over Bridge E', Nrml).dir(Ea, 0xa2, Mid, High).pos(2),
create_door(player, 'Mire Over Bridge W', Nrml).dir(We, 0xa2, Mid, High).pos(1),
create_door(player, 'Mire Right Bridge SE', Nrml).dir(So, 0xa2, Right, High).pos(3),
create_door(player, 'Mire Left Bridge S', Nrml).dir(So, 0xa2, Mid, High).small_key().pos(0),
create_door(player, 'Mire Right Bridge SE', Nrml).dir(So, 0xa2, Right, High).pos(3).portal(X, 0x22),
create_door(player, 'Mire Left Bridge S', Nrml).dir(So, 0xa2, Mid, High).small_key().pos(0).portal(Z, 0x22),
create_door(player, 'Mire Left Bridge Hook Path', Lgcl),
create_door(player, 'Mire Left Bridge Down Stairs', Sprl).dir(Dn, 0xa2, 0, HTL).ss(A, 0x12, 0x00),
create_door(player, 'Mire Fishbone E', Nrml).dir(Ea, 0xa1, Mid, High).pos(1),
@@ -776,7 +796,7 @@ def create_doors(world, player):
create_door(player, 'Mire South Fish Blue Barrier', Lgcl),
create_door(player, 'Mire Fishbone SE', Nrml).dir(So, 0xa1, Right, High).small_key().pos(0),
create_door(player, 'Mire Spike Barrier NE', Nrml).dir(No, 0xb1, Right, High).small_key().pos(1),
create_door(player, 'Mire Spike Barrier SE', Nrml).dir(So, 0xb1, Right, High).pos(2),
create_door(player, 'Mire Spike Barrier SE', Nrml).dir(So, 0xb1, Right, High).pos(2).portal(X, 0x02),
create_door(player, 'Mire Spike Barrier ES', Intr).dir(Ea, 0xb1, Bot, High).pos(3),
create_door(player, 'Mire Square Rail WS', Intr).dir(We, 0xb1, Bot, High).pos(3),
create_door(player, 'Mire Square Rail NW', Intr).dir(No, 0xb1, Left, High).big_key().pos(0),
@@ -785,10 +805,10 @@ def create_doors(world, player):
create_door(player, 'Mire Wizzrobe Bypass EN', Nrml).dir(Ea, 0xc1, Top, High).pos(5),
create_door(player, 'Mire Wizzrobe Bypass NE', Nrml).dir(No, 0xc1, Right, High).pos(6),
create_door(player, 'Mire Conveyor Crystal ES', Nrml).dir(Ea, 0xc1, Bot, High).small_key().pos(1),
create_door(player, 'Mire Conveyor Crystal SE', Nrml).dir(So, 0xc1, Right, High).pos(7),
create_door(player, 'Mire Conveyor Crystal SE', Nrml).dir(So, 0xc1, Right, High).pos(7).portal(X, 0x00),
create_door(player, 'Mire Conveyor Crystal WS', Intr).dir(We, 0xc1, Bot, High).small_key().pos(0),
create_door(player, 'Mire Tile Room ES', Intr).dir(Ea, 0xc1, Bot, High).small_key().pos(0),
create_door(player, 'Mire Tile Room SW', Nrml).dir(So, 0xc1, Left, High).pos(4),
create_door(player, 'Mire Tile Room SW', Nrml).dir(So, 0xc1, Left, High).pos(4).portal(Z, 0x00),
create_door(player, 'Mire Tile Room NW', Intr).dir(No, 0xc1, Left, High).pos(3),
create_door(player, 'Mire Compass Room SW', Intr).dir(So, 0xc1, Left, High).pos(3),
create_door(player, 'Mire Compass Room EN', Intr).dir(Ea, 0xc1, Top, High).pos(2),
@@ -837,12 +857,13 @@ def create_doors(world, player):
create_door(player, 'Mire Antechamber NW', Nrml).dir(No, 0xa0, Left, High).big_key().pos(0),
create_door(player, 'Mire Boss SW', Nrml).dir(So, 0x90, Left, High).no_exit().trap(0x4).pos(0),
create_door(player, 'TR Main Lobby SE', Nrml).dir(So, 0xd6, Right, High).pos(1).portal(X, 0x02),
create_door(player, 'TR Lobby Ledge NE', Nrml).dir(No, 0xd6, Right, High).pos(2),
create_door(player, 'TR Main Lobby Gap', Lgcl),
create_door(player, 'TR Lobby Ledge Gap', Lgcl),
create_door(player, 'TR Compass Room NW', Nrml).dir(No, 0xd6, Left, High).pos(0),
create_door(player, 'TR Hub SW', Nrml).dir(So, 0xc6, Left, High).pos(4),
create_door(player, 'TR Hub SE', Nrml).dir(So, 0xc6, Right, High).pos(5),
create_door(player, 'TR Hub SW', Nrml).dir(So, 0xc6, Left, High).pos(4).portal(Z, 0x22),
create_door(player, 'TR Hub SE', Nrml).dir(So, 0xc6, Right, High).pos(5).portal(X, 0x22),
create_door(player, 'TR Hub ES', Nrml).dir(Ea, 0xc6, Bot, High).pos(3),
create_door(player, 'TR Hub EN', Nrml).dir(Ea, 0xc6, Top, High).pos(2),
create_door(player, 'TR Hub NW', Nrml).dir(No, 0xc6, Left, High).small_key().pos(0),
@@ -850,9 +871,9 @@ def create_doors(world, player):
create_door(player, 'TR Torches Ledge WS', Nrml).dir(We, 0xc7, Bot, High).pos(2),
create_door(player, 'TR Torches WN', Nrml).dir(We, 0xc7, Top, High).pos(1),
create_door(player, 'TR Torches NW', Nrml).dir(No, 0xc7, Left, High).trap(0x4).pos(0),
create_door(player, 'TR Roller Room SW', Nrml).dir(So, 0xb7, Left, High).pos(0),
create_door(player, 'TR Pokey 1 SW', Nrml).dir(So, 0xb6, Left, High).small_key().pos(2),
create_door(player, 'TR Tile Room SE', Nrml).dir(So, 0xb6, Right, High).pos(4),
create_door(player, 'TR Roller Room SW', Nrml).dir(So, 0xb7, Left, High).pos(0).portal(Z, 0x02),
create_door(player, 'TR Pokey 1 SW', Nrml).dir(So, 0xb6, Left, High).small_key().pos(2).portal(Z, 0x00),
create_door(player, 'TR Tile Room SE', Nrml).dir(So, 0xb6, Right, High).pos(4).portal(X, 0x00),
create_door(player, 'TR Tile Room NE', Intr).dir(No, 0xb6, Right, High).pos(1),
create_door(player, 'TR Refill SE', Intr).dir(So, 0xb6, Right, High).pos(1),
create_door(player, 'TR Pokey 1 NW', Intr).dir(No, 0xb6, Left, High).small_key().pos(3),
@@ -864,7 +885,7 @@ def create_doors(world, player):
create_door(player, 'TR Pipe Ledge Drop Down', Lgcl),
create_door(player, 'TR Lava Dual Pipes EN', Nrml).dir(Ea, 0x14, Top, High).pos(5),
create_door(player, 'TR Lava Dual Pipes WN', Nrml).dir(We, 0x14, Top, High).pos(3),
create_door(player, 'TR Lava Dual Pipes SW', Nrml).dir(So, 0x14, Left, High).pos(4),
create_door(player, 'TR Lava Dual Pipes SW', Nrml).dir(So, 0x14, Left, High).pos(4).portal(Z, 0x22),
create_door(player, 'TR Lava Island WS', Nrml).dir(We, 0x14, Bot, High).small_key().pos(1),
create_door(player, 'TR Lava Island ES', Nrml).dir(Ea, 0x14, Bot, High).pos(6),
create_door(player, 'TR Lava Escape SE', Nrml).dir(So, 0x14, Right, High).small_key().pos(0),
@@ -880,12 +901,14 @@ def create_doors(world, player):
create_door(player, 'TR Hallway ES', Intr).dir(Ea, 0x24, Bot, High).pos(7),
create_door(player, 'TR Big View WS', Intr).dir(We, 0x24, Bot, High).pos(7),
create_door(player, 'TR Big Chest Gap', Lgcl),
create_door(player, 'TR Big Chest Entrance SE', Nrml).dir(So, 0x24, Right, High).pos(4).kill().portal(X, 0x00),
create_door(player, 'TR Big Chest Entrance Gap', Lgcl),
create_door(player, 'TR Big Chest NE', Intr).dir(No, 0x24, Right, High).pos(3),
create_door(player, 'TR Dodgers SE', Intr).dir(So, 0x24, Right, High).no_exit().pos(3),
create_door(player, 'TR Dodgers NE', Nrml).dir(No, 0x24, Right, High).big_key().pos(0),
create_door(player, 'TR Lazy Eyes SE', Nrml).dir(So, 0x23, Right, High).pos(0).portal(X, 0x00),
create_door(player, 'TR Lazy Eyes ES', Nrml).dir(Ea, 0x23, Bot, High).pos(1),
create_door(player, 'TR Dash Room SW', Nrml).dir(So, 0x04, Left, High).pos(4),
create_door(player, 'TR Dash Room SW', Nrml).dir(So, 0x04, Left, High).pos(4).portal(Z, 0x00),
create_door(player, 'TR Dash Room ES', Intr).dir(Ea, 0x04, Bot, High).pos(2),
create_door(player, 'TR Tongue Pull WS', Intr).dir(We, 0x04, Bot, High).pos(2),
create_door(player, 'TR Tongue Pull NE', Intr).dir(No, 0x04, Right, High).pos(3),
@@ -894,11 +917,12 @@ def create_doors(world, player):
create_door(player, 'TR Crystaroller SW', Intr).dir(So, 0x04, Left, High).pos(1),
create_door(player, 'TR Crystaroller Down Stairs', Sprl).dir(Dn, 0x04, 0, HTH).ss(A, 0x12, 0x80, True, True).small_key().pos(0),
create_door(player, 'TR Dark Ride Up Stairs', Sprl).dir(Up, 0xb5, 0, HTH).ss(A, 0x1b, 0x6c),
create_door(player, 'TR Dark Ride SW', Nrml).dir(So, 0xb5, Left, High).trap(0x4).pos(0),
create_door(player, 'TR Dark Ride SW', Nrml).dir(So, 0xb5, Left, High).trap(0x4).pos(0).portal(Z, 0x22),
create_door(player, 'TR Dash Bridge NW', Nrml).dir(No, 0xc5, Left, High).pos(1),
create_door(player, 'TR Dash Bridge SW', Nrml).dir(So, 0xc5, Left, High).pos(2),
create_door(player, 'TR Dash Bridge SW', Nrml).dir(So, 0xc5, Left, High).pos(2).portal(Z, 0x02),
create_door(player, 'TR Dash Bridge WS', Nrml).dir(We, 0xc5, Bot, High).small_key().pos(0),
create_door(player, 'TR Eye Bridge NW', Nrml).dir(No, 0xd5, Left, High).pos(1),
create_door(player, 'TR Eye Bridge SW', Nrml).dir(So, 0xd5, Left, High).pos(0).portal(Z, 0x02),
create_door(player, 'TR Crystal Maze ES', Nrml).dir(Ea, 0xc4, Bot, High).small_key().pos(0),
create_door(player, 'TR Crystal Maze Forwards Path', Lgcl),
create_door(player, 'TR Crystal Maze Blue Path', Lgcl),
@@ -906,8 +930,9 @@ def create_doors(world, player):
create_door(player, 'TR Crystal Maze North Stairs', StrS).dir(No, 0xc4, Mid, High),
create_door(player, 'TR Final Abyss South Stairs', StrS).dir(So, 0xb4, Mid, High),
create_door(player, 'TR Final Abyss NW', Nrml).dir(No, 0xb4, Left, High).big_key().pos(0),
create_door(player, 'TR Boss SW', Nrml).dir(So, 0xa4, Left, High).no_exit().trap(0x4).pos(0),
create_door(player, 'TR Boss SW', Nrml).dir(So, 0xa4, Left, High).no_exit().trap(0x4).pos(0).portal(Z, 0x00),
create_door(player, 'GT Lobby S', Nrml).dir(So, 0x0c, Mid, High).pos(0).portal(Z, 0x22),
create_door(player, 'GT Lobby Left Down Stairs', Sprl).dir(Dn, 0x0c, 1, HTL).ss(A, 0x0f, 0x80),
create_door(player, 'GT Lobby Up Stairs', Sprl).dir(Up, 0x0c, 2, HTH).ss(A, 0x1b, 0xec),
create_door(player, 'GT Lobby Right Down Stairs', Sprl).dir(Dn, 0x0c, 0, HTL).ss(S, 0x12, 0x80),
@@ -921,8 +946,8 @@ def create_doors(world, player):
create_door(player, 'GT Big Chest NW', Intr).dir(No, 0x8c, Left, High).pos(1),
create_door(player, 'GT Blocked Stairs Down Stairs', Sprl).dir(Dn, 0x8c, 3, HTH).ss(Z, 0x12, 0x40, True, True).kill(),
create_door(player, 'GT Blocked Stairs Block Path', Lgcl),
create_door(player, 'GT Big Chest SW', Nrml).dir(So, 0x8c, Left, High).pos(4),
create_door(player, 'GT Bob\'s Room SE', Nrml).dir(So, 0x8c, Right, High).pos(5).kill(),
create_door(player, 'GT Big Chest SW', Nrml).dir(So, 0x8c, Left, High).pos(4).portal(Z, 0x00),
create_door(player, 'GT Bob\'s Room SE', Nrml).dir(So, 0x8c, Right, High).pos(5).kill().portal(X, 0x00),
create_door(player, 'GT Bob\'s Room Hole', Hole),
create_door(player, 'GT Tile Room WN', Nrml).dir(We, 0x8d, Top, High).pos(2),
create_door(player, 'GT Tile Room EN', Intr).dir(Ea, 0x8d, Top, High).small_key().pos(1),
@@ -932,7 +957,7 @@ def create_doors(world, player):
create_door(player, 'GT Speed Torch North Path', Lgcl),
create_door(player, 'GT Speed Torch WS', Intr).dir(We, 0x8d, Bot, High).pos(4),
create_door(player, 'GT Pots n Blocks ES', Intr).dir(Ea, 0x8d, Bot, High).pos(4),
create_door(player, 'GT Speed Torch SE', Nrml).dir(So, 0x8d, Right, High).trap(0x4).pos(0),
create_door(player, 'GT Speed Torch SE', Nrml).dir(So, 0x8d, Right, High).trap(0x4).pos(0).portal(X, 0x02),
create_door(player, 'GT Crystal Conveyor NE', Nrml).dir(No, 0x9d, Right, High).pos(0).kill(),
create_door(player, 'GT Crystal Conveyor WN', Intr).dir(We, 0x9d, Top, High).pos(2),
create_door(player, 'GT Compass Room EN', Intr).dir(Ea, 0x9d, Top, High).pos(2),
@@ -953,10 +978,11 @@ def create_doors(world, player):
create_door(player, 'GT Hookshot South-North Path', Lgcl),
create_door(player, 'GT Hookshot Platform Blue Barrier', Lgcl),
create_door(player, 'GT Hookshot Entry Blue Barrier', Lgcl),
create_door(player, 'GT Hookshot Entry Boomerang Path', Lgcl),
create_door(player, 'GT Hookshot NW', Nrml).dir(No, 0x8b, Left, High).pos(4),
create_door(player, 'GT Hookshot ES', Intr).dir(Ea, 0x8b, Bot, High).small_key().pos(1),
create_door(player, 'GT Map Room WS', Intr).dir(We, 0x8b, Bot, High).small_key().pos(1),
create_door(player, 'GT Hookshot SW', Nrml).dir(So, 0x8b, Left, High).pos(3),
create_door(player, 'GT Hookshot SW', Nrml).dir(So, 0x8b, Left, High).pos(3).portal(Z, 0x02),
create_door(player, 'GT Double Switch NW', Nrml).dir(No, 0x9b, Left, High).pos(1).kill(),
create_door(player, 'GT Double Switch Orange Barrier', Lgcl),
create_door(player, 'GT Double Switch Orange Barrier 2', Lgcl),
@@ -990,11 +1016,11 @@ def create_doors(world, player):
create_door(player, 'GT Warp Maze - Main Rails Right Mid Warp', Warp),
create_door(player, 'GT Warp Maze - Pot Rail Warp', Warp),
create_door(player, 'GT Warp Maze (Rails) WS', Nrml).dir(We, 0x7d, Bot, High).pos(1),
create_door(player, 'GT Petting Zoo SE', Nrml).dir(So, 0x7d, Right, High).trap(0x4).pos(0),
create_door(player, 'GT Petting Zoo SE', Nrml).dir(So, 0x7d, Right, High).trap(0x4).pos(0).portal(X, 0x00),
create_door(player, 'GT Conveyor Star Pits EN', Nrml).dir(Ea, 0x7b, Top, High).small_key().pos(1),
create_door(player, 'GT Hidden Star ES', Nrml).dir(Ea, 0x7b, Bot, High).pos(2).kill(),
create_door(player, 'GT Hidden Star Warp', Warp),
create_door(player, 'GT DMs Room SW', Nrml).dir(So, 0x7b, Left, High).trap(0x4).pos(0),
create_door(player, 'GT DMs Room SW', Nrml).dir(So, 0x7b, Left, High).trap(0x4).pos(0).portal(Z, 0x00),
create_door(player, 'GT Falling Bridge WN', Nrml).dir(We, 0x7c, Top, High).small_key().pos(2),
create_door(player, 'GT Falling Bridge WS', Nrml).dir(We, 0x7c, Bot, High).pos(3),
create_door(player, 'GT Randomizer Room ES', Nrml).dir(Ea, 0x7c, Bot, High).pos(1),
@@ -1013,7 +1039,7 @@ def create_doors(world, player):
create_door(player, 'GT Mimics 2 NE', Intr).dir(No, 0x6b, Right, High).pos(1),
create_door(player, 'GT Dash Hall SE', Intr).dir(So, 0x6b, Right, High).pos(1),
create_door(player, 'GT Dash Hall NE', Nrml).dir(No, 0x6b, Right, High).big_key().pos(0),
create_door(player, 'GT Hidden Spikes SE', Nrml).dir(So, 0x5b, Right, High).small_key().pos(0),
create_door(player, 'GT Hidden Spikes SE', Nrml).dir(So, 0x5b, Right, High).small_key().pos(0).portal(X, 0x02),
create_door(player, 'GT Hidden Spikes EN', Nrml).dir(Ea, 0x5b, Top, High).trap(0x2).pos(1),
create_door(player, 'GT Cannonball Bridge WN', Nrml).dir(We, 0x5c, Top, High).pos(1),
create_door(player, 'GT Cannonball Bridge SE', Intr).dir(So, 0x5c, Right, High).pos(0),
@@ -1024,7 +1050,7 @@ def create_doors(world, player):
create_door(player, 'GT Gauntlet 2 EN', Intr).dir(Ea, 0x5d, Top, High).pos(2),
create_door(player, 'GT Gauntlet 2 SW', Intr).dir(So, 0x5d, Left, High).pos(0),
create_door(player, 'GT Gauntlet 3 NW', Intr).dir(No, 0x5d, Left, High).pos(0),
create_door(player, 'GT Gauntlet 3 SW', Nrml).dir(So, 0x5d, Left, High).trap(0x2).pos(1),
create_door(player, 'GT Gauntlet 3 SW', Nrml).dir(So, 0x5d, Left, High).trap(0x2).pos(1).portal(Z, 0x00),
create_door(player, 'GT Gauntlet 4 NW', Nrml).dir(No, 0x6d, Left, High).trap(0x4).pos(0),
create_door(player, 'GT Gauntlet 4 SW', Intr).dir(So, 0x6d, Left, High).pos(1),
create_door(player, 'GT Gauntlet 5 NW', Intr).dir(No, 0x6d, Left, High).pos(1),
@@ -1041,7 +1067,7 @@ def create_doors(world, player):
create_door(player, 'GT Dashing Bridge NE', Intr).dir(No, 0xa5, Right, High).pos(1),
create_door(player, 'GT Wizzrobes 2 SE', Intr).dir(So, 0xa5, Right, High).pos(1),
create_door(player, 'GT Wizzrobes 2 NE', Nrml).dir(No, 0xa5, Right, High).trap(0x4).pos(0),
create_door(player, 'GT Conveyor Bridge SE', Nrml).dir(So, 0x95, Right, High).pos(0),
create_door(player, 'GT Conveyor Bridge SE', Nrml).dir(So, 0x95, Right, High).pos(0).portal(X, 0x02),
create_door(player, 'GT Conveyor Bridge EN', Nrml).dir(Ea, 0x95, Top, High).pos(1),
create_door(player, 'GT Torch Cross WN', Nrml).dir(We, 0x96, Top, High).pos(1),
create_door(player, 'GT Torch Cross ES', Intr).dir(Ea, 0x96, Bot, High).pos(0),
@@ -1055,7 +1081,7 @@ def create_doors(world, player):
create_door(player, 'GT Bomb Conveyor EN', Intr).dir(Ea, 0x3d, Top, High).small_key().pos(1),
create_door(player, 'GT Bomb Conveyor SW', Intr).dir(So, 0x3d, Left, High).pos(3),
create_door(player, 'GT Crystal Circles NW', Intr).dir(No, 0x3d, Left, High).pos(3),
create_door(player, 'GT Crystal Circles SW', Nrml).dir(So, 0x3d, Left, High).small_key().pos(2),
create_door(player, 'GT Crystal Circles SW', Nrml).dir(So, 0x3d, Left, High).small_key().pos(2).portal(Z, 0x00),
create_door(player, 'GT Left Moldorm Ledge NW', Nrml).dir(No, 0x4d, Left, High).small_key().pos(0).kill(),
create_door(player, 'GT Left Moldorm Ledge Drop Down', Lgcl),
create_door(player, 'GT Right Moldorm Ledge Drop Down', Lgcl),
@@ -1208,6 +1234,7 @@ def create_doors(world, player):
world.get_door('GT Hookshot South-East Path', player).c_switch()
world.get_door('GT Hookshot ES', player).c_switch()
world.get_door('GT Hookshot Platform Blue Barrier', player).c_switch()
world.get_door('GT Hookshot Entry Boomerang Path', player).c_switch()
world.get_door('GT Double Switch Orange Path', player).c_switch()
world.get_door('GT Double Switch Blue Path', player).c_switch()
world.get_door('GT Spike Crystals WN', player).c_switch()
@@ -1238,6 +1265,60 @@ def create_doors(world, player):
assign_entrances(world, player)
dungeon_portals = [
create_portal(player, 'Sanctuary', world.get_door('Sanctuary S', player), 0x02, 0x02),
create_portal(player, 'Hyrule Castle West', world.get_door('Hyrule Castle West Lobby S', player), 0x03, 0x04),
create_portal(player, 'Hyrule Castle South', world.get_door('Hyrule Castle Lobby S', player), 0x04, 0x06),
create_portal(player, 'Hyrule Castle East', world.get_door('Hyrule Castle East Lobby S', player), 0x05, 0x08),
create_portal(player, 'Eastern', world.get_door('Eastern Lobby S', player), 0x08, 0x12, 0),
create_portal(player, 'Desert South', world.get_door('Desert Main Lobby S', player), 0x09, 0x14),
create_portal(player, 'Desert East', world.get_door('Desert East Lobby S', player), 0x0a, 0x16),
create_portal(player, 'Desert West', world.get_door('Desert West S', player), 0x0b, 0x18),
create_portal(player, 'Desert Back', world.get_door('Desert Back Lobby S', player), 0x0c, 0x1a, 1),
create_portal(player, 'Turtle Rock Lazy Eyes', world.get_door('TR Lazy Eyes SE', player), 0x15, 0x2c),
create_portal(player, 'Turtle Rock Eye Bridge', world.get_door('TR Eye Bridge SW', player), 0x18, 0x32),
create_portal(player, 'Turtle Rock Chest', world.get_door('TR Big Chest Entrance SE', player), 0x19, 0x34),
create_portal(player, 'Agahnims Tower', world.get_door('Tower Lobby S', player), 0x24, 0x4a),
create_portal(player, 'Swamp', world.get_door('Swamp Lobby S', player), 0x25, 0x4c, 4),
create_portal(player, 'Palace of Darkness', world.get_door('PoD Lobby S', player), 0x26, 0x4e, 5),
create_portal(player, 'Mire', world.get_door('Mire Lobby S', player), 0x27, 0x50, 7),
create_portal(player, 'Skull 2 West', world.get_door('Skull 2 West Lobby S', player), 0x28, 0x52),
create_portal(player, 'Skull 2 East', world.get_door('Skull 2 East Lobby SW', player), 0x29, 0x54),
create_portal(player, 'Skull 1', world.get_door('Skull 1 Lobby S', player), 0x2a, 0x56),
create_portal(player, 'Skull 3', world.get_door('Skull 3 Lobby SW', player), 0x2b, 0x58, 6),
create_portal(player, 'Ice', world.get_door('Ice Lobby SE', player), 0x2d, 0x5c, 8),
create_portal(player, 'Hera', world.get_door('Hera Lobby S', player), 0x33, 0x5a, 2),
create_portal(player, 'Thieves Town', world.get_door('Thieves Lobby S', player), 0x34, 0x6a, 10),
create_portal(player, 'Turtle Rock Main', world.get_door('TR Main Lobby SE', player), 0x35, 0x68, 9),
create_portal(player, 'Ganons Tower', world.get_door('GT Lobby S', player), 0x37, 0x70),
]
world.dungeon_portals[player] += dungeon_portals
world.get_door('Sanctuary S', player).deadEnd = True
world.get_door('TR Big Chest Entrance SE', player).passage = False
world.get_door('Sewers Secret Room Key Door S', player).dungeonLink = 'Hyrule Castle'
world.get_door('Desert Cannonball S', player).deadEnd = True
world.get_door('Desert Boss SW', player).deadEnd = True
world.get_door('Desert Boss SW', player).dungeonLink = 'Desert Palace'
world.get_door('Skull 1 Lobby S', player).dungeonLink = 'Skull Woods'
world.get_door('Skull Map Room SE', player).dungeonLink = 'Skull Woods'
world.get_door('Skull Spike Corner SW', player).dungeonLink = 'Skull Woods'
world.get_door('Skull Spike Corner SW', player).deadEnd = True
world.get_door('Thieves Pot Alcove Bottom SW', player).deadEnd = True
world.get_door('Ice Conveyor SW', player).deadEnd = True
world.get_door('Mire Right Bridge SE', player).deadEnd = True
world.get_door('TR Roller Room SW', player).deadEnd = True
world.get_door('TR Tile Room SE', player).deadEnd = True
world.get_door('TR Boss SW', player).deadEnd = True
world.get_door('TR Boss SW', player).dungeonLink = 'Turtle Rock'
world.get_door('GT Petting Zoo SE', player).deadEnd = True
world.get_door('GT DMs Room SW', player).deadEnd = True
world.get_door("GT Bob\'s Room SE", player).passage = False
world.get_door('Ice Spike Cross SE', player).dungeonLink = 'linkIceFalls'
world.get_door('Ice Tall Hint SE', player).dungeonLink = 'linkIceFalls'
world.get_door('Ice Switch Room SE', player).dungeonLink = 'linkIceFalls'
def create_paired_doors(world, player):
world.paired_doors[player] = [
@@ -1303,3 +1384,8 @@ def create_door(player, name, door_type):
def ugly_door(door):
door.ugly = True
return door
def create_portal(player, name, door, ent, ext, boss_exit_idx=-1):
door.entranceFlag = True
return Portal(player, name, door, ent, ext, boss_exit_idx)

View File

@@ -9,7 +9,7 @@ import operator as op
import time
from typing import List
from BaseClasses import DoorType, Direction, CrystalBarrier, RegionType, Polarity, PolSlot, flooded_keys
from BaseClasses import DoorType, Direction, CrystalBarrier, RegionType, Polarity, PolSlot, flooded_keys, Sector
from BaseClasses import Hook, hook_from_door
from Regions import key_only_locations, dungeon_events, flooded_keys_reverse
from Dungeons import dungeon_regions, split_region_starts
@@ -41,11 +41,11 @@ def pre_validate(builder, entrance_region_names, split_dungeon, world, player):
all_regions.update(sector.regions)
bk_needed = bk_needed or determine_if_bk_needed(sector, split_dungeon, world, player)
bk_special = bk_special or check_for_special(sector)
paths = determine_required_paths(world, player, split_dungeon, all_regions, builder.name)[builder.name]
paths = determine_paths_for_dungeon(world, player, all_regions, builder.name)
dungeon, hangers, hooks = gen_dungeon_info(builder.name, builder.sectors, entrance_regions, all_regions,
proposed_map, doors_to_connect, bk_needed, bk_special, world, player)
return check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_regions,
bk_needed, paths, entrance_regions)
return check_valid(builder.name, dungeon, hangers, hooks, proposed_map, doors_to_connect, all_regions,
bk_needed, bk_special, paths, entrance_regions, world, player)
def generate_dungeon(builder, entrance_region_names, split_dungeon, world, player):
@@ -74,6 +74,8 @@ def generate_dungeon_main(builder, entrance_region_names, split_dungeon, world,
a, b = queue.popleft()
connect_doors(a, b)
queue.remove((b, a))
if len(builder.sectors) == 0:
return Sector()
available_sectors = list(builder.sectors)
master_sector = available_sectors.pop()
for sub_sector in available_sectors:
@@ -106,7 +108,7 @@ def generate_dungeon_find_proposal(builder, entrance_region_names, split_dungeon
attempt = 1
finished = False
# flag if standard and this is hyrule castle
paths = determine_required_paths(world, player, split_dungeon, all_regions, name)[name]
paths = determine_paths_for_dungeon(world, player, all_regions, name)
while not finished:
# what are my choices?
itr += 1
@@ -125,8 +127,8 @@ def generate_dungeon_find_proposal(builder, entrance_region_names, split_dungeon
dungeon, hangers, hooks = gen_dungeon_info(name, builder.sectors, entrance_regions, all_regions, proposed_map,
doors_to_connect, bk_needed, bk_special, world, player)
dungeon_cache[depth] = dungeon, hangers, hooks
valid = check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_regions,
bk_needed, paths, entrance_regions)
valid = check_valid(name, dungeon, hangers, hooks, proposed_map, doors_to_connect, all_regions,
bk_needed, bk_special, paths, entrance_regions, world, player)
else:
dungeon, hangers, hooks = dungeon_cache[depth]
valid = True
@@ -385,8 +387,8 @@ def filter_choices(next_hanger, door, orig_hang, prev_choices, hook_candidates):
return next_hanger != door and orig_hang != next_hanger and door not in hook_candidates
def check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_regions,
bk_needed, paths, entrance_regions):
def check_valid(name, dungeon, hangers, hooks, proposed_map, doors_to_connect, all_regions,
bk_needed, bk_special, paths, entrance_regions, world, player):
# evaluate if everything is still plausible
# only origin is left in the dungeon and not everything is connected
@@ -434,7 +436,8 @@ def check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_reg
return False
if not bk_possible:
return False
if not valid_paths(paths, entrance_regions, doors_to_connect, all_regions, proposed_map):
if not valid_paths(name, paths, entrance_regions, doors_to_connect, all_regions, proposed_map,
bk_needed, bk_special, world, player):
return False
new_hangers_found = True
accessible_hook_types = []
@@ -463,7 +466,8 @@ def check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_reg
return len(all_hangers.difference(hanger_matching)) == 0
def valid_paths(paths, entrance_regions, valid_doors, all_regions, proposed_map):
def valid_paths(name, paths, entrance_regions, valid_doors, all_regions, proposed_map,
bk_needed, bk_special, world, player):
for path in paths:
if type(path) is tuple:
target = path[1]
@@ -475,76 +479,81 @@ def valid_paths(paths, entrance_regions, valid_doors, all_regions, proposed_map)
else:
target = path
start_regions = entrance_regions
if not valid_path(start_regions, target, valid_doors, proposed_map):
if not valid_path(name, start_regions, target, valid_doors, proposed_map, all_regions,
bk_needed, bk_special, world, player):
return False
return True
def valid_path(starting_regions, target, valid_doors, proposed_map):
queue = deque(starting_regions)
visited = set(starting_regions)
while len(queue) > 0:
region = queue.popleft()
if region.name == target:
return True
for ext in region.exits:
connect = ext.connected_region
if connect is None and ext.name in valid_doors:
door = valid_doors[ext.name]
if not door.blocked:
if door in proposed_map:
new_region = proposed_map[door].entrance.parent_region
if new_region not in visited:
visited.add(new_region)
queue.append(new_region)
def valid_path(name, starting_regions, target, valid_doors, proposed_map, all_regions,
bk_needed, bk_special, world, player):
target_regions = set()
if type(target) is not list:
for region in all_regions:
if target == region.name:
target_regions.add(region)
break
else:
for region in all_regions:
if region.name in target:
target_regions.add(region)
start = ExplorationState(dungeon=name)
start.big_key_special = bk_special
def exception(d):
return name == 'Skull Woods 2' and d.name == 'Skull Pinball WS'
original_state = extend_reachable_state_improved(starting_regions, start, proposed_map, all_regions,
valid_doors, bk_needed, world, player, exception)
for exp_door in original_state.unattached_doors:
if not exp_door.door.blocked:
return True # outstanding connection possible
elif connect is not None:
door = ext.door
if door is not None and not door.blocked and connect not in visited:
visited.add(connect)
queue.append(connect)
for target in target_regions:
if original_state.visited_at_all(target):
return True
return False # couldn't find an outstanding door or the target
def determine_required_paths(world, player, split_dungeon=False, all_regions=None, name=None):
if all_regions is None:
all_regions = set()
paths = {
'Hyrule Castle': ['Hyrule Castle Lobby', 'Hyrule Castle West Lobby', 'Hyrule Castle East Lobby'],
'Eastern Palace': ['Eastern Boss'],
'Desert Palace': ['Desert Main Lobby', 'Desert East Lobby', 'Desert West Lobby', 'Desert Boss'],
'Tower of Hera': ['Hera Boss'],
'Agahnims Tower': ['Tower Agahnim 1'],
'Palace of Darkness': ['PoD Boss'],
'Swamp Palace': ['Swamp Boss'],
'Skull Woods': ['Skull 1 Lobby', 'Skull 2 East Lobby', 'Skull 2 West Lobby', 'Skull Boss'],
'Thieves Town': ['Thieves Boss', ('Thieves Blind\'s Cell', 'Thieves Boss')],
'Ice Palace': ['Ice Boss'],
'Misery Mire': ['Mire Boss'],
'Turtle Rock': ['TR Main Lobby', 'TR Lazy Eyes', 'TR Big Chest Entrance', 'TR Eye Bridge', 'TR Boss'],
'Ganons Tower': ['GT Agahnim 2'],
'Skull Woods 1': ['Skull 1 Lobby'],
'Skull Woods 2': ['Skull 2 East Lobby', 'Skull 2 West Lobby'],
'Skull Woods 3': [],
'Desert Palace Main': ['Desert Main Lobby', 'Desert East Lobby', 'Desert West Lobby'],
'Desert Palace Back': []
}
if world.mode[player] == 'standard':
paths['Hyrule Castle'].append('Hyrule Dungeon Cellblock')
# noinspection PyTypeChecker
paths['Hyrule Castle'].append(('Hyrule Dungeon Cellblock', 'Sanctuary'))
if world.doorShuffle[player] in ['basic']:
paths['Thieves Town'].append('Thieves Attic Window')
if split_dungeon:
if world.get_region('Desert Boss', player) in all_regions:
paths[name].append('Desert Boss')
if world.get_region('Skull Boss', player) in all_regions:
paths[name].append('Skull Boss')
def determine_required_paths(world, player):
paths = {}
for name, builder in world.dungeon_layouts[player].items():
all_regions = builder.master_sector.regions
paths[name] = determine_paths_for_dungeon(world, player, all_regions, name)
return paths
boss_path_checks = ['Eastern Boss', 'Desert Boss', 'Hera Boss', 'Tower Agahnim 1', 'PoD Boss', 'Swamp Boss',
'Skull Boss', 'Ice Boss', 'Mire Boss', 'TR Boss', 'GT Agahnim 2']
# pinball is allowed to orphan you
drop_path_checks = ['Skull Pot Circle', 'Skull Left Drop', 'Skull Back Drop', 'Sewers Rat Path']
def determine_paths_for_dungeon(world, player, all_regions, name):
all_r_names = set(x.name for x in all_regions)
paths = []
non_hole_portals = []
for portal in world.dungeon_portals[player]:
if portal.door.entrance.parent_region in all_regions:
non_hole_portals.append(portal.door.entrance.parent_region.name)
if portal.destination:
paths.append(portal.door.entrance.parent_region.name)
if world.mode[player] == 'standard' and name == 'Hyrule Castle':
paths.append('Hyrule Dungeon Cellblock')
paths.append(('Hyrule Dungeon Cellblock', 'Sanctuary'))
if world.doorShuffle[player] in ['basic'] and name == 'Thieves Town':
paths.append('Thieves Attic Window')
for boss in boss_path_checks:
if boss in all_r_names:
paths.append(boss)
if 'Thieves Boss' in all_r_names:
paths.append('Thieves Boss')
paths.append(('Thieves Blind\'s Cell', 'Thieves Boss'))
for drop_check in drop_path_checks:
if drop_check in all_r_names:
paths.append((drop_check, non_hole_portals))
return paths
def winnow_hangers(hangers, hooks):
@@ -1775,16 +1784,6 @@ def loop_present(hook, opp, h_mag, other_mag):
return h_mag[opp] >= h_mag[hook.value] - other_mag[opp]
def is_entrance_sector(builder, sector):
if builder is None:
return False
for entrance in builder.all_entrances:
r_set = sector.region_set()
if entrance in r_set:
return True
return False
def is_satisfied(door_dict_list):
for door_dict in door_dict_list:
for door_list in door_dict.values():
@@ -2604,7 +2603,11 @@ def valid_c_switch(builder, sector_list):
def valid_connected_assignment(builder, sector_list):
full_list = sector_list + builder.sectors
if len(full_list) == 1 and sum_magnitude(full_list) == [0, 0, 0]:
return True
for sector in full_list:
if sector.is_entrance_sector():
continue
others = [x for x in full_list if x != sector]
other_mag = sum_magnitude(others)
sector_mag = sector.magnitude()
@@ -2831,6 +2834,8 @@ def check_for_forced_crystal_single(builder, candidate_sectors):
for sector in builder.sectors:
for door in sector.outstanding_doors:
builder_doors[hook_from_door(door)][door] = sector
if len(builder_doors) == 0:
return False
candidate_doors = defaultdict(dict)
for sector in candidate_sectors:
for door in sector.outstanding_doors:
@@ -3124,15 +3129,27 @@ def check_for_valid_layout(builder, sector_list, builder_info):
temp_builder = DungeonBuilder(builder.name)
for s in sector_list + builder.sectors:
assign_sector_helper(s, temp_builder)
split_list = split_region_starts[builder.name]
split_list = split_dungeon_entrances[builder.name]
builder.split_dungeon_map = split_dungeon_builder(temp_builder, split_list, builder_info)
builder.valid_proposal = {}
possible_regions = set()
for portal in world.dungeon_portals[player]:
if not portal.destination and portal.name in dungeon_portals[builder.name]:
possible_regions.add(portal.door.entrance.parent_region.name)
if builder.name in dungeon_drops.keys():
possible_regions.update(dungeon_drops[builder.name])
for name, split_build in builder.split_dungeon_map.items():
name_bits = name.split(" ")
orig_name = " ".join(name_bits[:-1])
entrance_regions = split_dungeon_entrances[orig_name][name_bits[-1]]
# todo: this is hardcoded information for random entrances
entrance_regions = [x for x in entrance_regions if x not in split_check_entrance_invalid]
for sector in split_build.sectors:
match_set = set(sector.region_set()).intersection(possible_regions)
if len(match_set) > 0:
for r_name in match_set:
if r_name not in entrance_regions:
entrance_regions.append(r_name)
# entrance_regions = [x for x in entrance_regions if x not in split_check_entrance_invalid]
proposal = generate_dungeon_find_proposal(split_build, entrance_regions, True, world, player)
# record split proposals
builder.valid_proposal[name] = proposal
@@ -3150,7 +3167,7 @@ def check_for_valid_layout(builder, sector_list, builder_info):
def resolve_equations(builder, sector_list):
unreached_doors = defaultdict(list)
equations = copy_door_equations(builder, sector_list)
equations = {x: y for x, y in copy_door_equations(builder, sector_list).items() if len(y) > 0}
current_access = {}
sector_split = {} # those sectors that belong to a certain sector
if builder.name in split_region_starts.keys():
@@ -3531,7 +3548,7 @@ def copy_door_equations(builder, sector_list):
def calc_sector_equations(sector, builder):
equations = []
is_entrance = is_entrance_sector(builder, sector) and not sector.destination_entrance
is_entrance = sector.is_entrance_sector() and not sector.destination_entrance
if is_entrance:
flagged_equations = []
for door in sector.outstanding_doors:
@@ -3734,4 +3751,24 @@ split_check_entrance_invalid = [
'Desert East Lobby', 'Skull 2 West Lobby'
]
dungeon_portals = {
'Hyrule Castle': ['Hyrule Castle South', 'Hyrule Castle West', 'Hyrule Castle East', 'Sanctuary'],
'Eastern Palace': ['Eastern'],
'Desert Palace': ['Desert Back', 'Desert South', 'Desert West', 'Desert East'],
'Tower of Hera': ['Hera'],
'Agahnims Tower': ['Agahnims Tower'],
'Palace of Darkness': ['Palace of Darkness'],
'Swamp Palace': ['Swamp'],
'Skull Woods': ['Skull 1', 'Skull 2 East', 'Skull 2 West', 'Skull 3'],
'Thieves Town': ['Thieves Town'],
'Ice Palace': ['Ice'],
'Misery Mire': ['Mire'],
'Turtle Rock': ['Turtle Rock Main', 'Turtle Rock Lazy Eyes', 'Turtle Rock Chest', 'Turtle Rock Eye Bridge'],
'Ganons Tower': ['Ganons Tower']
}
dungeon_drops = {
'Hyrule Castle': ['Sewers Rat Path'],
'Skull Woods': ['Skull Pot Circle', 'Skull Pinball', 'Skull Left Drop', 'Skull Back Drop'],
}

View File

@@ -7,27 +7,28 @@ from Items import ItemFactory
def create_dungeons(world, player):
def make_dungeon(name, default_boss, dungeon_regions, big_key, small_keys, dungeon_items):
dungeon = Dungeon(name, dungeon_regions, big_key, [] if world.retro[player] else small_keys, dungeon_items, player)
def make_dungeon(name, id, default_boss, dungeon_regions, big_key, small_keys, dungeon_items):
dungeon = Dungeon(name, dungeon_regions, big_key, [] if world.retro[player] else small_keys,
dungeon_items, player, id)
dungeon.boss = BossFactory(default_boss, player)
for region in dungeon.regions:
world.get_region(region, player).dungeon = dungeon
dungeon.world = world
return dungeon
ES = make_dungeon('Hyrule Castle', None, hyrule_castle_regions, None, [ItemFactory('Small Key (Escape)', player)], [ItemFactory('Map (Escape)', player)])
EP = make_dungeon('Eastern Palace', 'Armos Knights', eastern_regions, ItemFactory('Big Key (Eastern Palace)', player), [], ItemFactory(['Map (Eastern Palace)', 'Compass (Eastern Palace)'], player))
DP = make_dungeon('Desert Palace', 'Lanmolas', desert_regions, ItemFactory('Big Key (Desert Palace)', player), [ItemFactory('Small Key (Desert Palace)', player)], ItemFactory(['Map (Desert Palace)', 'Compass (Desert Palace)'], player))
ToH = make_dungeon('Tower of Hera', 'Moldorm', hera_regions, ItemFactory('Big Key (Tower of Hera)', player), [ItemFactory('Small Key (Tower of Hera)', player)], ItemFactory(['Map (Tower of Hera)', 'Compass (Tower of Hera)'], player))
PoD = make_dungeon('Palace of Darkness', 'Helmasaur King', pod_regions, ItemFactory('Big Key (Palace of Darkness)', player), ItemFactory(['Small Key (Palace of Darkness)'] * 6, player), ItemFactory(['Map (Palace of Darkness)', 'Compass (Palace of Darkness)'], player))
TT = make_dungeon('Thieves Town', 'Blind', thieves_regions, ItemFactory('Big Key (Thieves Town)', player), [ItemFactory('Small Key (Thieves Town)', player)], ItemFactory(['Map (Thieves Town)', 'Compass (Thieves Town)'], player))
SW = make_dungeon('Skull Woods', 'Mothula', skull_regions, ItemFactory('Big Key (Skull Woods)', player), ItemFactory(['Small Key (Skull Woods)'] * 3, player), ItemFactory(['Map (Skull Woods)', 'Compass (Skull Woods)'], player))
SP = make_dungeon('Swamp Palace', 'Arrghus', swamp_regions, ItemFactory('Big Key (Swamp Palace)', player), [ItemFactory('Small Key (Swamp Palace)', player)], ItemFactory(['Map (Swamp Palace)', 'Compass (Swamp Palace)'], player))
IP = make_dungeon('Ice Palace', 'Kholdstare', ice_regions, ItemFactory('Big Key (Ice Palace)', player), ItemFactory(['Small Key (Ice Palace)'] * 2, player), ItemFactory(['Map (Ice Palace)', 'Compass (Ice Palace)'], player))
MM = make_dungeon('Misery Mire', 'Vitreous', mire_regions, ItemFactory('Big Key (Misery Mire)', player), ItemFactory(['Small Key (Misery Mire)'] * 3, player), ItemFactory(['Map (Misery Mire)', 'Compass (Misery Mire)'], player))
TR = make_dungeon('Turtle Rock', 'Trinexx', tr_regions, ItemFactory('Big Key (Turtle Rock)', player), ItemFactory(['Small Key (Turtle Rock)'] * 4, player), ItemFactory(['Map (Turtle Rock)', 'Compass (Turtle Rock)'], player))
AT = make_dungeon('Agahnims Tower', 'Agahnim', tower_regions, None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), [])
GT = make_dungeon('Ganons Tower', 'Agahnim2', gt_regions, ItemFactory('Big Key (Ganons Tower)', player), ItemFactory(['Small Key (Ganons Tower)'] * 4, player), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'], player))
ES = make_dungeon('Hyrule Castle', 1, None, hyrule_castle_regions, None, [ItemFactory('Small Key (Escape)', player)], [ItemFactory('Map (Escape)', player)])
EP = make_dungeon('Eastern Palace', 2, 'Armos Knights', eastern_regions, ItemFactory('Big Key (Eastern Palace)', player), [], ItemFactory(['Map (Eastern Palace)', 'Compass (Eastern Palace)'], player))
DP = make_dungeon('Desert Palace', 3, 'Lanmolas', desert_regions, ItemFactory('Big Key (Desert Palace)', player), [ItemFactory('Small Key (Desert Palace)', player)], ItemFactory(['Map (Desert Palace)', 'Compass (Desert Palace)'], player))
ToH = make_dungeon('Tower of Hera', 10, 'Moldorm', hera_regions, ItemFactory('Big Key (Tower of Hera)', player), [ItemFactory('Small Key (Tower of Hera)', player)], ItemFactory(['Map (Tower of Hera)', 'Compass (Tower of Hera)'], player))
PoD = make_dungeon('Palace of Darkness', 6, 'Helmasaur King', pod_regions, ItemFactory('Big Key (Palace of Darkness)', player), ItemFactory(['Small Key (Palace of Darkness)'] * 6, player), ItemFactory(['Map (Palace of Darkness)', 'Compass (Palace of Darkness)'], player))
TT = make_dungeon('Thieves Town', 11, 'Blind', thieves_regions, ItemFactory('Big Key (Thieves Town)', player), [ItemFactory('Small Key (Thieves Town)', player)], ItemFactory(['Map (Thieves Town)', 'Compass (Thieves Town)'], player))
SW = make_dungeon('Skull Woods', 8, 'Mothula', skull_regions, ItemFactory('Big Key (Skull Woods)', player), ItemFactory(['Small Key (Skull Woods)'] * 3, player), ItemFactory(['Map (Skull Woods)', 'Compass (Skull Woods)'], player))
SP = make_dungeon('Swamp Palace', 5, 'Arrghus', swamp_regions, ItemFactory('Big Key (Swamp Palace)', player), [ItemFactory('Small Key (Swamp Palace)', player)], ItemFactory(['Map (Swamp Palace)', 'Compass (Swamp Palace)'], player))
IP = make_dungeon('Ice Palace', 9, 'Kholdstare', ice_regions, ItemFactory('Big Key (Ice Palace)', player), ItemFactory(['Small Key (Ice Palace)'] * 2, player), ItemFactory(['Map (Ice Palace)', 'Compass (Ice Palace)'], player))
MM = make_dungeon('Misery Mire', 7, 'Vitreous', mire_regions, ItemFactory('Big Key (Misery Mire)', player), ItemFactory(['Small Key (Misery Mire)'] * 3, player), ItemFactory(['Map (Misery Mire)', 'Compass (Misery Mire)'], player))
TR = make_dungeon('Turtle Rock', 12, 'Trinexx', tr_regions, ItemFactory('Big Key (Turtle Rock)', player), ItemFactory(['Small Key (Turtle Rock)'] * 4, player), ItemFactory(['Map (Turtle Rock)', 'Compass (Turtle Rock)'], player))
AT = make_dungeon('Agahnims Tower', 4, 'Agahnim', tower_regions, None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), [])
GT = make_dungeon('Ganons Tower', 13, 'Agahnim2', gt_regions, ItemFactory('Big Key (Ganons Tower)', player), ItemFactory(['Small Key (Ganons Tower)'] * 4, player), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'], player))
GT.bosses['bottom'] = BossFactory('Armos Knights', player)
GT.bosses['middle'] = BossFactory('Lanmolas', player)

View File

@@ -325,7 +325,6 @@ def link_entrances(world, player):
elif world.doorShuffle[player] != 'vanilla':
connect_caves(world, lw_entrances, [], [('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)', 'Hyrule Castle Exit (South)')], player)
# place old man, has limited options
# exit has to come from specific set of doors, the entrance is free to move about
old_man_entrances = [door for door in old_man_entrances if door in lw_entrances]
@@ -711,7 +710,7 @@ def link_entrances(world, player):
# handle remaining caves
while caves:
# connect highest exit count caves first, prevent issue where we have 2 or 3 exits accross worlds left to fill
# connect highest exit count caves first, prevent issue where we have 2 or 3 exits across worlds left to fill
cave_candidate = (None, 0)
for i, cave in enumerate(caves):
if isinstance(cave, str):
@@ -1062,7 +1061,7 @@ def link_entrances(world, player):
raise NotImplementedError('Shuffling not supported yet')
# check for swamp palace fix
if world.get_entrance('Dam', player).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', player).connected_region.name != 'Swamp Lobby':
if world.get_entrance('Dam', player).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', player).connected_region.name != 'Swamp Placeholder':
world.swamp_patch_required[player] = True
# check for potion shop location
@@ -1074,7 +1073,7 @@ def link_entrances(world, player):
world.ganon_at_pyramid[player] = False
# check for Ganon's Tower location
if world.get_entrance('Ganons Tower', player).connected_region.name != 'GT Lobby':
if world.get_entrance('Ganons Tower', player).connected_region.name != 'Ganons Tower Placeholder':
world.ganonstower_vanilla[player] = False
def link_inverted_entrances(world, player):
@@ -3165,7 +3164,7 @@ default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'),
('Two Brothers House Exit (East)', 'Light World'),
('Two Brothers House Exit (West)', 'Maze Race Ledge'),
('Sanctuary', 'Sanctuary'),
('Sanctuary', 'Sanctuary Placeholder'),
('Sanctuary Grave', 'Sewer Drop'),
('Sanctuary Exit', 'Light World'),
@@ -3400,62 +3399,62 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
('Inverted Pyramid Entrance', 'Bottom of Pyramid')]
# non shuffled dungeons
default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert Main Lobby'),
('Desert Palace Entrance (West)', 'Desert West Lobby'),
('Desert Palace Entrance (North)', 'Desert Back Lobby'),
('Desert Palace Entrance (East)', 'Desert East Lobby'),
default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert South Placeholder'),
('Desert Palace Entrance (West)', 'Desert West Placeholder'),
('Desert Palace Entrance (North)', 'Desert Back Placeholder'),
('Desert Palace Entrance (East)', 'Desert East Placeholder'),
('Desert Palace Exit (South)', 'Desert Palace Stairs'),
('Desert Palace Exit (West)', 'Desert Ledge'),
('Desert Palace Exit (East)', 'Desert Palace Lone Stairs'),
('Desert Palace Exit (North)', 'Desert Palace Entrance (North) Spot'),
('Eastern Palace', 'Eastern Lobby'),
('Eastern Palace', 'Eastern Placeholder'),
('Eastern Palace Exit', 'Light World'),
('Tower of Hera', 'Hera Lobby'),
('Tower of Hera', 'Hera Placeholder'),
('Tower of Hera Exit', 'Death Mountain (Top)'),
('Hyrule Castle Entrance (South)', 'Hyrule Castle Lobby'),
('Hyrule Castle Entrance (West)', 'Hyrule Castle West Lobby'),
('Hyrule Castle Entrance (East)', 'Hyrule Castle East Lobby'),
('Hyrule Castle Entrance (South)', 'Hyrule Castle South Placeholder'),
('Hyrule Castle Entrance (West)', 'Hyrule Castle West Placeholder'),
('Hyrule Castle Entrance (East)', 'Hyrule Castle East Placeholder'),
('Hyrule Castle Exit (South)', 'Hyrule Castle Courtyard'),
('Hyrule Castle Exit (West)', 'Hyrule Castle Ledge'),
('Hyrule Castle Exit (East)', 'Hyrule Castle Ledge'),
('Agahnims Tower', 'Tower Lobby'),
('Agahnims Tower', 'Agahnims Tower Placeholder'),
('Agahnims Tower Exit', 'Hyrule Castle Ledge'),
('Thieves Town', 'Thieves Lobby'),
('Thieves Town', 'Thieves Town Placeholder'),
('Thieves Town Exit', 'West Dark World'),
('Skull Woods First Section Hole (East)', 'Skull Pinball'),
('Skull Woods First Section Hole (West)', 'Skull Left Drop'),
('Skull Woods First Section Hole (North)', 'Skull Pot Circle'),
('Skull Woods First Section Door', 'Skull 1 Lobby'),
('Skull Woods First Section Door', 'Skull 1 Placeholder'),
('Skull Woods First Section Exit', 'Skull Woods Forest'),
('Skull Woods Second Section Hole', 'Skull Back Drop'),
('Skull Woods Second Section Door (East)', 'Skull 2 East Lobby'),
('Skull Woods Second Section Door (West)', 'Skull 2 West Lobby'),
('Skull Woods Second Section Door (East)', 'Skull 2 East Placeholder'),
('Skull Woods Second Section Door (West)', 'Skull 2 West Placeholder'),
('Skull Woods Second Section Exit (East)', 'Skull Woods Forest'),
('Skull Woods Second Section Exit (West)', 'Skull Woods Forest (West)'),
('Skull Woods Final Section', 'Skull 3 Lobby'),
('Skull Woods Final Section', 'Skull 3 Placeholder'),
('Skull Woods Final Section Exit', 'Skull Woods Forest (West)'),
('Ice Palace', 'Ice Lobby'),
('Ice Palace', 'Ice Placeholder'),
('Ice Palace Exit', 'Dark Lake Hylia Central Island'),
('Misery Mire', 'Mire Lobby'),
('Misery Mire', 'Mire Placeholder'),
('Misery Mire Exit', 'Dark Desert'),
('Palace of Darkness', 'PoD Lobby'),
('Palace of Darkness', 'Palace of Darkness Placeholder'),
('Palace of Darkness Exit', 'East Dark World'),
('Swamp Palace', 'Swamp Lobby'), # requires additional patch for flooding moat if moved
('Swamp Palace', 'Swamp Placeholder'), # requires additional patch for flooding moat if moved
('Swamp Palace Exit', 'South Dark World'),
('Turtle Rock', 'TR Main Lobby'),
('Turtle Rock', 'Turtle Rock Main Placeholder'),
('Turtle Rock Exit (Front)', 'Dark Death Mountain (Top)'),
('Turtle Rock Ledge Exit (West)', 'Dark Death Mountain Ledge'),
('Turtle Rock Ledge Exit (East)', 'Dark Death Mountain Ledge'),
('Dark Death Mountain Ledge (West)', 'TR Lazy Eyes'),
('Dark Death Mountain Ledge (East)', 'TR Big Chest Entrance'),
('Dark Death Mountain Ledge (West)', 'Turtle Rock Lazy Eyes Placeholder'),
('Dark Death Mountain Ledge (East)', 'Turtle Rock Chest Placeholder'),
('Turtle Rock Isolated Ledge Exit', 'Dark Death Mountain Isolated Ledge'),
('Turtle Rock Isolated Ledge Entrance', 'TR Eye Bridge'),
('Turtle Rock Isolated Ledge Entrance', 'Turtle Rock Eye Bridge Placeholder'),
('Ganons Tower', 'GT Lobby'),
('Ganons Tower', 'Ganons Tower Placeholder'),
('Ganons Tower Exit', 'Dark Death Mountain (Top)')
]

View File

@@ -16,7 +16,7 @@ from InvertedRegions import create_inverted_regions, mark_dark_world_regions
from EntranceShuffle import link_entrances, link_inverted_entrances
from Rom import patch_rom, patch_race_rom, patch_enemizer, apply_rom_settings, LocalRom, JsonRom, get_hash_string
from Doors import create_doors
from DoorShuffle import link_doors
from DoorShuffle import link_doors, connect_portal
from RoomData import create_rooms
from Rules import set_rules
from Dungeons import create_dungeons, fill_dungeons, fill_dungeons_restrictive
@@ -434,6 +434,11 @@ def copy_world(world):
ret.inaccessible_regions = world.inaccessible_regions
ret.dungeon_layouts = world.dungeon_layouts
ret.key_logic = world.key_logic
ret.dungeon_portals = world.dungeon_portals
for player, portals in world.dungeon_portals.items():
for portal in portals:
connect_portal(portal, ret, player)
ret.sanc_portal = world.sanc_portal
for player in range(1, world.players + 1):
set_rules(ret, player)

View File

@@ -198,18 +198,45 @@ def create_regions(world, player):
create_dw_region(player, 'Pyramid Ledge', None, ['Pyramid Entrance', 'Pyramid Drop']),
]
def create_dungeon_regions(world, player):
std_flag = world.mode[player] == 'standard'
inv_flag = world.mode[player] == 'inverted'
world.regions += [
create_dungeon_region(player, 'Hyrule Castle Lobby', 'Hyrule Castle', None, ['Hyrule Castle Lobby W', 'Hyrule Castle Lobby E',
'Hyrule Castle Lobby WN', 'Hyrule Castle Lobby North Stairs', 'Hyrule Castle Exit (South)']),
create_dungeon_region(player, 'Hyrule Castle West Lobby', 'Hyrule Castle', None, ['Hyrule Castle West Lobby E', 'Hyrule Castle West Lobby N',
'Hyrule Castle West Lobby EN', 'Hyrule Castle Exit (West)']),
create_dungeon_region(player, 'Hyrule Castle East Lobby', 'Hyrule Castle', None, ['Hyrule Castle East Lobby W', 'Hyrule Castle East Lobby N',
'Hyrule Castle East Lobby NW', 'Hyrule Castle Exit (East)']),
create_dungeon_region(player, 'Hyrule Castle East Hall', 'Hyrule Castle', None, ['Hyrule Castle East Hall W', 'Hyrule Castle East Hall S',
'Hyrule Castle East Hall SW']),
create_dungeon_region(player, 'Sanctuary Placeholder', 'Twilight Zone', None, ['Sanctuary Exit']),
create_dungeon_region(player, 'Hyrule Castle West Placeholder', 'Twilight Zone', None, ['Hyrule Castle Exit (West)']),
create_dungeon_region(player, 'Hyrule Castle South Placeholder', 'Twilight Zone', None, ['Hyrule Castle Exit (South)']),
create_dungeon_region(player, 'Hyrule Castle East Placeholder', 'Twilight Zone', None, ['Hyrule Castle Exit (East)']),
create_dungeon_region(player, 'Eastern Placeholder', 'Twilight Zone', None, ['Eastern Palace Exit']),
create_dungeon_region(player, 'Desert West Placeholder', 'Twilight Zone', None, ['Desert Palace Exit (West)']),
create_dungeon_region(player, 'Desert South Placeholder', 'Twilight Zone', None, ['Desert Palace Exit (South)']),
create_dungeon_region(player, 'Desert East Placeholder', 'Twilight Zone', None, ['Desert Palace Exit (East)']),
create_dungeon_region(player, 'Desert Back Placeholder', 'Twilight Zone', None, ['Desert Palace Exit (North)']),
create_dungeon_region(player, 'Hera Placeholder', 'Twilight Zone', None, ['Tower of Hera Exit']),
create_dungeon_region(player, 'Agahnims Tower Placeholder', 'Twilight Zone', None, [inv_flag and 'Inverted Agahnims Tower Exit' or 'Agahnims Tower Exit']),
create_dungeon_region(player, 'Palace of Darkness Placeholder', 'Twilight Zone', None, ['Palace of Darkness Exit']),
create_dungeon_region(player, 'Swamp Placeholder', 'Twilight Zone', None, ['Swamp Palace Exit']),
create_dungeon_region(player, 'Skull 1 Placeholder', 'Twilight Zone', None, ['Skull Woods First Section Exit']),
create_dungeon_region(player, 'Skull 2 East Placeholder', 'Twilight Zone', None, ['Skull Woods Second Section Exit (East)']),
create_dungeon_region(player, 'Skull 2 West Placeholder', 'Twilight Zone', None, ['Skull Woods Second Section Exit (West)']),
create_dungeon_region(player, 'Skull 3 Placeholder', 'Twilight Zone', None, ['Skull Woods Final Section Exit']),
create_dungeon_region(player, 'Thieves Town Placeholder', 'Twilight Zone', None, ['Thieves Town Exit']),
create_dungeon_region(player, 'Ice Placeholder', 'Twilight Zone', None, ['Ice Palace Exit']),
create_dungeon_region(player, 'Mire Placeholder', 'Twilight Zone', None, ['Misery Mire Exit']),
create_dungeon_region(player, 'Turtle Rock Main Placeholder', 'Twilight Zone', None, ['Turtle Rock Exit (Front)']),
create_dungeon_region(player, 'Turtle Rock Lazy Eyes Placeholder', 'Twilight Zone', None, ['Turtle Rock Ledge Exit (West)']),
create_dungeon_region(player, 'Turtle Rock Chest Placeholder', 'Twilight Zone', None, ['Turtle Rock Ledge Exit (East)']),
create_dungeon_region(player, 'Turtle Rock Eye Bridge Placeholder', 'Twilight Zone', None, ['Turtle Rock Isolated Ledge Exit']),
create_dungeon_region(player, 'Ganons Tower Placeholder', 'Twilight Zone', None, [inv_flag and 'Inverted Ganons Tower Exit' or 'Ganons Tower Exit']),
create_dungeon_region(player, 'Hyrule Castle Lobby', 'Hyrule Castle', None,
['Hyrule Castle Lobby W', 'Hyrule Castle Lobby E', 'Hyrule Castle Lobby WN', 'Hyrule Castle Lobby North Stairs', 'Hyrule Castle Lobby S']),
create_dungeon_region(player, 'Hyrule Castle West Lobby', 'Hyrule Castle', None,
['Hyrule Castle West Lobby E', 'Hyrule Castle West Lobby N', 'Hyrule Castle West Lobby EN', 'Hyrule Castle West Lobby S']),
create_dungeon_region(player, 'Hyrule Castle East Lobby', 'Hyrule Castle', None,
['Hyrule Castle East Lobby W', 'Hyrule Castle East Lobby N', 'Hyrule Castle East Lobby NW', 'Hyrule Castle East Lobby S']),
create_dungeon_region(player, 'Hyrule Castle East Hall', 'Hyrule Castle', None,
['Hyrule Castle East Hall W', 'Hyrule Castle East Hall S', 'Hyrule Castle East Hall SW']),
create_dungeon_region(player, 'Hyrule Castle West Hall', 'Hyrule Castle', None, ['Hyrule Castle West Hall E', 'Hyrule Castle West Hall S']),
create_dungeon_region(player, 'Hyrule Castle Back Hall', 'Hyrule Castle', None, ['Hyrule Castle Back Hall E', 'Hyrule Castle Back Hall W', 'Hyrule Castle Back Hall Down Stairs']),
create_dungeon_region(player, 'Hyrule Castle Throne Room', 'Hyrule Castle', None, ['Hyrule Castle Throne Room Tapestry', 'Hyrule Castle Throne Room South Stairs']),
@@ -244,10 +271,10 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Sewers Pull Switch', 'Hyrule Castle', None, ['Sewers Pull Switch N', 'Sewers Pull Switch S']),
create_dungeon_region(player, 'Sanctuary', 'Hyrule Castle',
['Sanctuary'] if not std_flag else ['Sanctuary', 'Zelda Drop Off'],
['Sanctuary Exit', 'Sanctuary N']),
['Sanctuary S', 'Sanctuary N']),
# Eastern Palace
create_dungeon_region(player, 'Eastern Lobby', 'Eastern Palace', None, ['Eastern Lobby N', 'Eastern Palace Exit', 'Eastern Lobby NW', 'Eastern Lobby NE']),
create_dungeon_region(player, 'Eastern Lobby', 'Eastern Palace', None, ['Eastern Lobby N', 'Eastern Lobby S', 'Eastern Lobby NW', 'Eastern Lobby NE']),
create_dungeon_region(player, 'Eastern Lobby Bridge', 'Eastern Palace', None, ['Eastern Lobby Bridge S', 'Eastern Lobby Bridge N']),
create_dungeon_region(player, 'Eastern Lobby Left Ledge', 'Eastern Palace', None, ['Eastern Lobby Left Ledge SW']),
create_dungeon_region(player, 'Eastern Lobby Right Ledge', 'Eastern Palace', None, ['Eastern Lobby Right Ledge SE']),
@@ -279,11 +306,11 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Eastern Boss', 'Eastern Palace', ['Eastern Palace - Boss', 'Eastern Palace - Prize'], ['Eastern Boss SE']),
# Desert Palace
create_dungeon_region(player, 'Desert Main Lobby', 'Desert Palace', None, ['Desert Palace Exit (South)', 'Desert Main Lobby N Edge', 'Desert Main Lobby Left Path', 'Desert Main Lobby Right Path']),
create_dungeon_region(player, 'Desert Main Lobby', 'Desert Palace', None, ['Desert Main Lobby S', 'Desert Main Lobby N Edge', 'Desert Main Lobby Left Path', 'Desert Main Lobby Right Path']),
create_dungeon_region(player, 'Desert Left Alcove', 'Desert Palace', None, ['Desert Main Lobby NW Edge', 'Desert Left Alcove Path']),
create_dungeon_region(player, 'Desert Right Alcove', 'Desert Palace', None, ['Desert Main Lobby NE Edge', 'Desert Main Lobby E Edge', 'Desert Right Alcove Path']),
create_dungeon_region(player, 'Desert Dead End', 'Desert Palace', None, ['Desert Dead End Edge']),
create_dungeon_region(player, 'Desert East Lobby', 'Desert Palace', None, ['Desert East Lobby WS', 'Desert Palace Exit (East)']),
create_dungeon_region(player, 'Desert East Lobby', 'Desert Palace', None, ['Desert East Lobby WS', 'Desert East Lobby S']),
create_dungeon_region(player, 'Desert East Wing', 'Desert Palace', None, ['Desert East Wing ES', 'Desert East Wing Key Door EN', 'Desert East Wing W Edge', 'Desert East Wing N Edge']),
create_dungeon_region(player, 'Desert Compass Room', 'Desert Palace', ['Desert Palace - Compass Chest'], ['Desert Compass Key Door WN', 'Desert Compass NW']),
create_dungeon_region(player, 'Desert Cannonball', 'Desert Palace', ['Desert Palace - Big Key Chest'], ['Desert Cannonball S']),
@@ -296,9 +323,9 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Desert Circle of Pots', 'Desert Palace', None, ['Desert Circle of Pots ES', 'Desert Circle of Pots NW']),
create_dungeon_region(player, 'Desert Big Chest Room', 'Desert Palace', ['Desert Palace - Big Chest'], ['Desert Big Chest SW']),
create_dungeon_region(player, 'Desert West Wing', 'Desert Palace', None, ['Desert West Wing N Edge', 'Desert West Wing WS']),
create_dungeon_region(player, 'Desert West Lobby', 'Desert Palace', None, ['Desert West Lobby ES', 'Desert Palace Exit (West)', 'Desert West Lobby NW']),
create_dungeon_region(player, 'Desert West Lobby', 'Desert Palace', None, ['Desert West Lobby ES', 'Desert West S', 'Desert West Lobby NW']),
create_dungeon_region(player, 'Desert Fairy Fountain', 'Desert Palace', None, ['Desert Fairy Fountain SW']),
create_dungeon_region(player, 'Desert Back Lobby', 'Desert Palace', None, ['Desert Palace Exit (North)', 'Desert Back Lobby NW']),
create_dungeon_region(player, 'Desert Back Lobby', 'Desert Palace', None, ['Desert Back Lobby S', 'Desert Back Lobby NW']),
create_dungeon_region(player, 'Desert Tiles 1', 'Desert Palace', ['Desert Palace - Desert Tiles 1 Pot Key'], ['Desert Tiles 1 SW', 'Desert Tiles 1 Up Stairs']),
create_dungeon_region(player, 'Desert Bridge', 'Desert Palace', None, ['Desert Bridge Down Stairs', 'Desert Bridge SW']),
create_dungeon_region(player, 'Desert Four Statues', 'Desert Palace', None, ['Desert Four Statues NW', 'Desert Four Statues ES']),
@@ -308,7 +335,7 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Desert Boss', 'Desert Palace', ['Desert Palace - Boss', 'Desert Palace - Prize'], ['Desert Boss SW']),
# Hera
create_dungeon_region(player, 'Hera Lobby', 'Tower of Hera', ['Tower of Hera - Map Chest'], ['Hera Lobby Down Stairs', 'Hera Lobby Key Stairs', 'Hera Lobby Up Stairs', 'Tower of Hera Exit']),
create_dungeon_region(player, 'Hera Lobby', 'Tower of Hera', ['Tower of Hera - Map Chest'], ['Hera Lobby Down Stairs', 'Hera Lobby Key Stairs', 'Hera Lobby Up Stairs', 'Hera Lobby S']),
create_dungeon_region(player, 'Hera Basement Cage', 'Tower of Hera', ['Tower of Hera - Basement Cage'], ['Hera Basement Cage Up Stairs']),
create_dungeon_region(player, 'Hera Tile Room', 'Tower of Hera', None, ['Hera Tile Room Up Stairs', 'Hera Tile Room EN']),
create_dungeon_region(player, 'Hera Tridorm', 'Tower of Hera', None, ['Hera Tridorm WN', 'Hera Tridorm SE']),
@@ -323,7 +350,7 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Hera Boss', 'Tower of Hera', ['Tower of Hera - Boss', 'Tower of Hera - Prize'], ['Hera Boss Down Stairs', 'Hera Boss Outer Hole', 'Hera Boss Inner Hole']),
# AgaTower
create_dungeon_region(player, 'Tower Lobby', 'Castle Tower', None, ['Tower Lobby NW', inv_flag and 'Inverted Agahnims Tower Exit' or 'Agahnims Tower Exit']),
create_dungeon_region(player, 'Tower Lobby', 'Castle Tower', None, ['Tower Lobby NW', 'Tower Lobby S']),
create_dungeon_region(player, 'Tower Gold Knights', 'Castle Tower', None, ['Tower Gold Knights SW', 'Tower Gold Knights EN']),
create_dungeon_region(player, 'Tower Room 03', 'Castle Tower', ['Castle Tower - Room 03'], ['Tower Room 03 WN', 'Tower Room 03 Up Stairs']),
create_dungeon_region(player, 'Tower Lone Statue', 'Castle Tower', None, ['Tower Lone Statue Down Stairs', 'Tower Lone Statue WN']),
@@ -343,7 +370,7 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Tower Agahnim 1', 'Castle Tower', ['Agahnim 1'], ['Tower Agahnim 1 SW']),
# pod
create_dungeon_region(player, 'PoD Lobby', 'Palace of Darkness', None, ['PoD Lobby N', 'PoD Lobby NW', 'PoD Lobby NE', 'Palace of Darkness Exit']),
create_dungeon_region(player, 'PoD Lobby', 'Palace of Darkness', None, ['PoD Lobby N', 'PoD Lobby NW', 'PoD Lobby NE', 'PoD Lobby S']),
create_dungeon_region(player, 'PoD Left Cage', 'Palace of Darkness', None, ['PoD Left Cage SW', 'PoD Left Cage Down Stairs']),
create_dungeon_region(player, 'PoD Middle Cage', 'Palace of Darkness', None, ['PoD Middle Cage S', 'PoD Middle Cage SE', 'PoD Middle Cage N', 'PoD Middle Cage Down Stairs']),
create_dungeon_region(player, 'PoD Shooter Room', 'Palace of Darkness', ['Palace of Darkness - Shooter Room'], ['PoD Shooter Room Up Stairs']),
@@ -381,7 +408,7 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'PoD Boss', 'Palace of Darkness', ['Palace of Darkness - Boss', 'Palace of Darkness - Prize'], ['PoD Boss SE']),
# swamp
create_dungeon_region(player, 'Swamp Lobby', 'Swamp Palace', None, ['Swamp Palace Exit', 'Swamp Lobby Moat']),
create_dungeon_region(player, 'Swamp Lobby', 'Swamp Palace', None, ['Swamp Lobby S', 'Swamp Lobby Moat']),
create_dungeon_region(player, 'Swamp Entrance', 'Swamp Palace', ['Swamp Palace - Entrance'], ['Swamp Entrance Down Stairs', 'Swamp Entrance Moat']),
create_dungeon_region(player, 'Swamp Pot Row', 'Swamp Palace', ['Swamp Palace - Pot Row Pot Key'], ['Swamp Pot Row Up Stairs', 'Swamp Pot Row WN', 'Swamp Pot Row WS']),
create_dungeon_region(player, 'Swamp Map Ledge', 'Swamp Palace', ['Swamp Palace - Map Chest'], ['Swamp Map Ledge EN']),
@@ -430,7 +457,7 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Swamp Boss', 'Swamp Palace', ['Swamp Palace - Boss', 'Swamp Palace - Prize'], ['Swamp Boss SW']),
# sw
create_dungeon_region(player, 'Skull 1 Lobby', 'Skull Woods', None, ['Skull Woods First Section Exit', 'Skull 1 Lobby WS', 'Skull 1 Lobby ES']),
create_dungeon_region(player, 'Skull 1 Lobby', 'Skull Woods', None, ['Skull 1 Lobby S', 'Skull 1 Lobby WS', 'Skull 1 Lobby ES']),
create_dungeon_region(player, 'Skull Map Room', 'Skull Woods', ['Skull Woods - Map Chest'], ['Skull Map Room WS', 'Skull Map Room SE']),
create_dungeon_region(player, 'Skull Pot Circle', 'Skull Woods', None, ['Skull Pot Circle WN', 'Skull Pot Circle Star Path']),
create_dungeon_region(player, 'Skull Pull Switch', 'Skull Woods', None, ['Skull Pull Switch EN', 'Skull Pull Switch S']),
@@ -439,14 +466,14 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Skull Pot Prison', 'Skull Woods', ['Skull Woods - Pot Prison'], ['Skull Pot Prison ES', 'Skull Pot Prison SE']),
create_dungeon_region(player, 'Skull Compass Room', 'Skull Woods', ['Skull Woods - Compass Chest'], ['Skull Compass Room NE', 'Skull Compass Room ES', 'Skull Compass Room WS']),
create_dungeon_region(player, 'Skull Left Drop', 'Skull Woods', None, ['Skull Left Drop ES']),
create_dungeon_region(player, 'Skull 2 East Lobby', 'Skull Woods', None, ['Skull 2 East Lobby NW', 'Skull 2 East Lobby WS', 'Skull Woods Second Section Exit (East)']),
create_dungeon_region(player, 'Skull 2 East Lobby', 'Skull Woods', None, ['Skull 2 East Lobby NW', 'Skull 2 East Lobby WS', 'Skull 2 East Lobby SW']),
create_dungeon_region(player, 'Skull Big Key', 'Skull Woods', ['Skull Woods - Big Key Chest'], ['Skull Big Key SW', 'Skull Big Key WN']),
create_dungeon_region(player, 'Skull Lone Pot', 'Skull Woods', None, ['Skull Lone Pot EN']),
create_dungeon_region(player, 'Skull Small Hall', 'Skull Woods', None, ['Skull Small Hall ES', 'Skull Small Hall WS']),
create_dungeon_region(player, 'Skull Back Drop', 'Skull Woods', None, ['Skull Back Drop Star Path', ]),
create_dungeon_region(player, 'Skull 2 West Lobby', 'Skull Woods', ['Skull Woods - West Lobby Pot Key'], ['Skull 2 West Lobby ES', 'Skull 2 West Lobby NW', 'Skull Woods Second Section Exit (West)']),
create_dungeon_region(player, 'Skull 2 West Lobby', 'Skull Woods', ['Skull Woods - West Lobby Pot Key'], ['Skull 2 West Lobby ES', 'Skull 2 West Lobby NW', 'Skull 2 West Lobby S']),
create_dungeon_region(player, 'Skull X Room', 'Skull Woods', None, ['Skull X Room SW']),
create_dungeon_region(player, 'Skull 3 Lobby', 'Skull Woods', None, ['Skull 3 Lobby NW', 'Skull 3 Lobby EN', 'Skull Woods Final Section Exit']),
create_dungeon_region(player, 'Skull 3 Lobby', 'Skull Woods', None, ['Skull 3 Lobby NW', 'Skull 3 Lobby EN', 'Skull 3 Lobby SW']),
create_dungeon_region(player, 'Skull East Bridge', 'Skull Woods', None, ['Skull East Bridge WN', 'Skull East Bridge WS']),
create_dungeon_region(player, 'Skull West Bridge Nook', 'Skull Woods', ['Skull Woods - Bridge Room'], ['Skull West Bridge Nook ES']),
create_dungeon_region(player, 'Skull Star Pits', 'Skull Woods', None, ['Skull Star Pits SW', 'Skull Star Pits ES']),
@@ -457,7 +484,7 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Skull Boss', 'Skull Woods', ['Skull Woods - Boss', 'Skull Woods - Prize']),
# tt
create_dungeon_region(player, 'Thieves Lobby', 'Thieves\' Town', ['Thieves\' Town - Map Chest'], ['Thieves Town Exit', 'Thieves Lobby N Edge', 'Thieves Lobby NE Edge', 'Thieves Lobby E']),
create_dungeon_region(player, 'Thieves Lobby', 'Thieves\' Town', ['Thieves\' Town - Map Chest'], ['Thieves Lobby S', 'Thieves Lobby N Edge', 'Thieves Lobby NE Edge', 'Thieves Lobby E']),
create_dungeon_region(player, 'Thieves Ambush', 'Thieves\' Town', ['Thieves\' Town - Ambush Chest'], ['Thieves Ambush S Edge', 'Thieves Ambush SE Edge', 'Thieves Ambush ES Edge', 'Thieves Ambush EN Edge', 'Thieves Ambush E']),
create_dungeon_region(player, 'Thieves Rail Ledge', 'Thieves\' Town', None, ['Thieves Rail Ledge NW', 'Thieves Rail Ledge W', 'Thieves Rail Ledge Drop Down']),
create_dungeon_region(player, 'Thieves BK Corner', 'Thieves\' Town', None, ['Thieves BK Corner WN Edge', 'Thieves BK Corner WS Edge', 'Thieves BK Corner S Edge', 'Thieves BK Corner SW Edge', 'Thieves BK Corner NE']),
@@ -490,7 +517,7 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Thieves Trap', 'Thieves\' Town', None, ['Thieves Trap EN']),
# ice
create_dungeon_region(player, 'Ice Lobby', 'Ice Palace', None, ['Ice Palace Exit', 'Ice Lobby WS']),
create_dungeon_region(player, 'Ice Lobby', 'Ice Palace', None, ['Ice Lobby SE', 'Ice Lobby WS']),
create_dungeon_region(player, 'Ice Jelly Key', 'Ice Palace', ['Ice Palace - Jelly Key Drop'], ['Ice Jelly Key ES', 'Ice Jelly Key Down Stairs']),
create_dungeon_region(player, 'Ice Floor Switch', 'Ice Palace', None, ['Ice Floor Switch Up Stairs', 'Ice Floor Switch ES']),
create_dungeon_region(player, 'Ice Cross Left', 'Ice Palace', None, ['Ice Cross Left WS', 'Ice Cross Left Push Block']),
@@ -538,7 +565,7 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Ice Boss', 'Ice Palace', ['Ice Palace - Boss', 'Ice Palace - Prize']),
# mire
create_dungeon_region(player, 'Mire Lobby', 'Misery Mire', None, ['Misery Mire Exit', 'Mire Lobby Gap']),
create_dungeon_region(player, 'Mire Lobby', 'Misery Mire', None, ['Mire Lobby S', 'Mire Lobby Gap']),
create_dungeon_region(player, 'Mire Post-Gap', 'Misery Mire', None, ['Mire Post-Gap Gap', 'Mire Post-Gap Down Stairs']),
create_dungeon_region(player, 'Mire 2', 'Misery Mire', None, ['Mire 2 Up Stairs', 'Mire 2 NE']),
create_dungeon_region(player, 'Mire Hub', 'Misery Mire', None, ['Mire Hub SE', 'Mire Hub ES', 'Mire Hub E', 'Mire Hub NE', 'Mire Hub WN', 'Mire Hub WS', 'Mire Hub Upper Blue Barrier', 'Mire Hub Lower Blue Barrier']),
@@ -595,7 +622,7 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'Mire Boss', 'Misery Mire', ['Misery Mire - Boss', 'Misery Mire - Prize'], ['Mire Boss SW']),
# tr
create_dungeon_region(player, 'TR Main Lobby', 'Turtle Rock', None, ['TR Main Lobby Gap', 'Turtle Rock Exit (Front)']),
create_dungeon_region(player, 'TR Main Lobby', 'Turtle Rock', None, ['TR Main Lobby Gap', 'TR Main Lobby SE']),
create_dungeon_region(player, 'TR Lobby Ledge', 'Turtle Rock', None, ['TR Lobby Ledge NE', 'TR Lobby Ledge Gap']),
create_dungeon_region(player, 'TR Compass Room', 'Turtle Rock', ['Turtle Rock - Compass Chest'], ['TR Compass Room NW']),
create_dungeon_region(player, 'TR Hub', 'Turtle Rock', None, ['TR Hub SW', 'TR Hub SE', 'TR Hub ES', 'TR Hub EN', 'TR Hub NW', 'TR Hub NE']),
@@ -617,8 +644,8 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'TR Dodgers', 'Turtle Rock', None, ['TR Dodgers WN', 'TR Dodgers SE', 'TR Dodgers NE']),
create_dungeon_region(player, 'TR Big View', 'Turtle Rock', None, ['TR Big View WS']),
create_dungeon_region(player, 'TR Big Chest', 'Turtle Rock', ['Turtle Rock - Big Chest'], ['TR Big Chest Gap', 'TR Big Chest NE']),
create_dungeon_region(player, 'TR Big Chest Entrance', 'Turtle Rock', None, ['Turtle Rock Ledge Exit (East)', 'TR Big Chest Entrance Gap']),
create_dungeon_region(player, 'TR Lazy Eyes', 'Turtle Rock', None, ['Turtle Rock Ledge Exit (West)', 'TR Lazy Eyes ES']),
create_dungeon_region(player, 'TR Big Chest Entrance', 'Turtle Rock', None, ['TR Big Chest Entrance SE', 'TR Big Chest Entrance Gap']),
create_dungeon_region(player, 'TR Lazy Eyes', 'Turtle Rock', None, ['TR Lazy Eyes SE', 'TR Lazy Eyes ES']),
create_dungeon_region(player, 'TR Dash Room', 'Turtle Rock', None, ['TR Dash Room SW', 'TR Dash Room ES', 'TR Dash Room NW']),
create_dungeon_region(player, 'TR Tongue Pull', 'Turtle Rock', None, ['TR Tongue Pull WS', 'TR Tongue Pull NE']),
create_dungeon_region(player, 'TR Rupees', 'Turtle Rock', None, ['TR Rupees SE']),
@@ -627,14 +654,14 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'TR Dash Bridge', 'Turtle Rock', None, ['TR Dash Bridge NW', 'TR Dash Bridge SW', 'TR Dash Bridge WS']),
create_dungeon_region(player, 'TR Eye Bridge', 'Turtle Rock', ['Turtle Rock - Eye Bridge - Bottom Left', 'Turtle Rock - Eye Bridge - Bottom Right',
'Turtle Rock - Eye Bridge - Top Left', 'Turtle Rock - Eye Bridge - Top Right'],
['Turtle Rock Isolated Ledge Exit', 'TR Eye Bridge NW']),
['TR Eye Bridge SW', 'TR Eye Bridge NW']),
create_dungeon_region(player, 'TR Crystal Maze', 'Turtle Rock', None, ['TR Crystal Maze ES', 'TR Crystal Maze Forwards Path']),
create_dungeon_region(player, 'TR Crystal Maze End', 'Turtle Rock', None, ['TR Crystal Maze Blue Path', 'TR Crystal Maze Cane Path', 'TR Crystal Maze North Stairs']),
create_dungeon_region(player, 'TR Final Abyss', 'Turtle Rock', None, ['TR Final Abyss South Stairs', 'TR Final Abyss NW']),
create_dungeon_region(player, 'TR Boss', 'Turtle Rock', ['Turtle Rock - Boss', 'Turtle Rock - Prize'], ['TR Boss SW']),
# gt
create_dungeon_region(player, 'GT Lobby', 'Ganon\'s Tower', None, ['GT Lobby Left Down Stairs', 'GT Lobby Up Stairs', 'GT Lobby Right Down Stairs', inv_flag and 'Inverted Ganons Tower Exit' or 'Ganons Tower Exit']),
create_dungeon_region(player, 'GT Lobby', 'Ganon\'s Tower', None, ['GT Lobby Left Down Stairs', 'GT Lobby Up Stairs', 'GT Lobby Right Down Stairs', 'GT Lobby S']),
create_dungeon_region(player, 'GT Bob\'s Torch', 'Ganon\'s Tower', ['Ganons Tower - Bob\'s Torch'], ['GT Torch Up Stairs', 'GT Torch WN', 'GT Torch EN', 'GT Torch SW']),
create_dungeon_region(player, 'GT Hope Room', 'Ganon\'s Tower', ['Ganons Tower - Hope Room - Left', 'Ganons Tower - Hope Room - Right'], ['GT Hope Room Up Stairs', 'GT Hope Room WN', 'GT Hope Room EN']),
create_dungeon_region(player, 'GT Big Chest', 'Ganon\'s Tower', ['Ganons Tower - Big Chest'], ['GT Big Chest NW', 'GT Big Chest SW']),
@@ -653,13 +680,13 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'GT Hookshot East Platform', 'Ganon\'s Tower', None, ['GT Hookshot EN', 'GT Hookshot East-North Path', 'GT Hookshot East-South Path']),
create_dungeon_region(player, 'GT Hookshot North Platform', 'Ganon\'s Tower', None, ['GT Hookshot NW', 'GT Hookshot North-East Path', 'GT Hookshot North-South Path']),
create_dungeon_region(player, 'GT Hookshot South Platform', 'Ganon\'s Tower', None, ['GT Hookshot ES', 'GT Hookshot South-East Path', 'GT Hookshot South-North Path', 'GT Hookshot Platform Blue Barrier']),
create_dungeon_region(player, 'GT Hookshot South Entry', 'Ganon\'s Tower', None, ['GT Hookshot SW', 'GT Hookshot Entry Blue Barrier']),
create_dungeon_region(player, 'GT Hookshot South Entry', 'Ganon\'s Tower', None, ['GT Hookshot SW', 'GT Hookshot Entry Blue Barrier', ]),
create_dungeon_region(player, 'GT Map Room', 'Ganon\'s Tower', ['Ganons Tower - Map Chest'], ['GT Map Room WS']),
create_dungeon_region(player, 'GT Double Switch Entry', 'Ganon\'s Tower', None, ['GT Double Switch NW', 'GT Double Switch Orange Barrier', 'GT Double Switch Orange Barrier 2']),
create_dungeon_region(player, 'GT Double Switch Switches', 'Ganon\'s Tower', None, ['GT Double Switch Blue Path', 'GT Double Switch Orange Path']),
create_dungeon_region(player, 'GT Double Switch Transition', 'Ganon\'s Tower', None, ['GT Double Switch Transition Blue']),
create_dungeon_region(player, 'GT Double Switch Key Spot', 'Ganon\'s Tower', ['Ganons Tower - Double Switch Pot Key'], ['GT Double Switch Key Blue Path', 'GT Double Switch Key Orange Path']),
create_dungeon_region(player, 'GT Double Switch Exit', 'Ganon\'s Tower', None, ['GT Double Switch EN', 'GT Double Switch Blue Barrier']),
create_dungeon_region(player, 'GT Double Switch Exit', 'Ganon\'s Tower', None, ['GT Double Switch EN', 'GT Double Switch Blue Barrier', 'GT Hookshot Entry Boomerang Path']),
create_dungeon_region(player, 'GT Spike Crystals', 'Ganon\'s Tower', None, ['GT Spike Crystals WN', 'GT Spike Crystals Warp']),
create_dungeon_region(player, 'GT Warp Maze - Left Section', 'Ganon\'s Tower', None, ['GT Warp Maze - Left Section Warp']),
create_dungeon_region(player, 'GT Warp Maze - Mid Section', 'Ganon\'s Tower', None, ['GT Warp Maze - Mid Section Left Warp', 'GT Warp Maze - Mid Section Right Warp']),

37
Rom.py
View File

@@ -22,7 +22,7 @@ from EntranceShuffle import door_addresses, exit_ids
JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '82a102fee15ed0718257d92cd7ba031b'
RANDOMIZERBASEHASH = '7d7ea5b59d05926be23a3963e31cb0f0'
class JsonRom(object):
@@ -615,7 +615,10 @@ def patch_rom(world, rom, player, team, enemized):
rom.write_byte(0x13f038+offset*2, bk_status)
rom.write_byte(0x151f1, 2)
rom.write_byte(0x15270, 2)
rom.write_byte(0x1597b, 2)
sanctuary = world.get_region('Sanctuary', player)
rom.write_byte(0x1597b, sanctuary.dungeon.dungeon_id*2)
if world.sanc_portal[player]:
rom.write_byte(0x159a6, world.sanc_portal[player].ent_offset)
if compass_code_good(rom):
update_compasses(rom, world, player)
else:
@@ -626,13 +629,11 @@ def patch_rom(world, rom, player, team, enemized):
if door.dest is not None and door.player == player and door.type in [DoorType.Normal, DoorType.SpiralStairs,
DoorType.Open, DoorType.StraightStairs]:
rom.write_bytes(door.getAddress(), door.dest.getTarget(door))
for room in world.rooms:
if room.player == player and room.modified:
rom.write_bytes(room.address(), room.rom_data())
for paired_door in world.paired_doors[player]:
rom.write_bytes(paired_door.address_a(world, player), paired_door.rom_data_a(world, player))
rom.write_bytes(paired_door.address_b(world, player), paired_door.rom_data_b(world, player))
if world.doorShuffle[player] != 'vanilla':
for builder in world.dungeon_layouts[player].values():
if builder.pre_open_stonewall:
if builder.pre_open_stonewall.name == 'Desert Wall Slide NW':
@@ -640,7 +641,7 @@ def patch_rom(world, rom, player, team, enemized):
for name, pair in boss_indicator.items():
dungeon_id, boss_door = pair
opposite_door = world.get_door(boss_door, player).dest
if opposite_door.roomIndex > -1:
if opposite_door and opposite_door.roomIndex > -1:
dungeon_name = opposite_door.entrance.parent_region.dungeon.name
dungeon_id = boss_indicator[dungeon_name][0]
rom.write_byte(0x13f000+dungeon_id, opposite_door.roomIndex)
@@ -648,6 +649,23 @@ def patch_rom(world, rom, player, team, enemized):
if dr_flags & DROptions.Town_Portal and world.mode[player] == 'inverted':
rom.write_byte(0x139008, 1)
for portal in world.dungeon_portals[player]:
if not portal.default:
offset = portal.ent_offset
rom.write_byte(0x14577 + offset*2, portal.current_room())
rom.write_bytes(0x14681 + offset*8, portal.relative_coords())
rom.write_bytes(0x14aa9 + offset*2, portal.scroll_x())
rom.write_bytes(0x14bb3 + offset*2, portal.scroll_y())
rom.write_bytes(0x14cbd + offset*2, portal.link_y())
rom.write_bytes(0x14dc7 + offset*2, portal.link_x())
rom.write_bytes(0x14fdb + offset*2, portal.camera_x())
rom.write_byte(0x152f9 + offset, portal.bg_setting())
rom.write_byte(0x1537e + offset, portal.hv_scroll())
rom.write_byte(0x15403 + offset, portal.scroll_quad())
rom.write_byte(0x15aee + portal.exit_offset, portal.current_room())
if portal.boss_exit_idx > -1:
rom.write_byte(0x7939 + portal.boss_exit_idx, portal.current_room())
# fix skull woods exit, if not fixed during exit patching
if world.fix_skullwoods_exit[player] and world.shuffle[player] == 'vanilla':
write_int16(rom, 0x15DB5 + 2 * exit_ids['Skull Woods Final Section Exit'][1], 0x00F8)
@@ -1311,6 +1329,10 @@ def patch_rom(world, rom, player, team, enemized):
rom.write_byte(0xFED31, 0x2A) # preopen bombable exit
rom.write_byte(0xFEE41, 0x2A) # preopen bombable exit
for room in world.rooms:
if room.player == player and room.modified:
rom.write_bytes(room.address(), room.rom_data())
write_strings(rom, world, player, team)
rom.write_byte(0x18636C, 1 if world.remote_items[player] else 0)
@@ -2139,7 +2161,8 @@ def patch_shuffled_dark_sanc(world, rom, player):
# 24B118 and 20BB32
compass_r_addr = 0x123118 # a9 90 24 8f 9a c7 7e
compass_w_addr = 0x103b32 # e2 20 ad 0c 04 c9 00 d0
# compass_w_addr = 0x103b32 # e2 20 ad 0c 04 c9 00 d0
compass_w_addr = 0x103b42 # e2 20 ad 0c 04 c9 00 d0
def compass_code_good(rom):

View File

@@ -297,6 +297,7 @@ def global_rules(world, player):
set_rule(world.get_entrance('GT Hookshot East-South Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
set_rule(world.get_entrance('GT Hookshot North-East Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
set_rule(world.get_entrance('GT Hookshot North-South Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
set_rule(world.get_entrance('GT Hookshot Entry Boomerang Path', player), lambda state: state.has('Blue Boomerang', player) or state.has('Red Boomerang', player))
set_rule(world.get_entrance('GT Firesnake Room Hook Path', player), lambda state: state.has('Hookshot', player))
# I am tempted to stick an invincibility rule for getting across falling bridge
set_rule(world.get_entrance('GT Ice Armos NE', player), lambda state: world.get_region('GT Ice Armos', player).dungeon.bosses['bottom'].can_defeat(state))
@@ -1527,10 +1528,10 @@ bunny_impassible_doors = {
'Ice Backwards Room Hole', 'Ice Switch Room SE', 'Ice Antechamber NE', 'Ice Antechamber Hole', 'Mire Lobby Gap',
'Mire Post-Gap Gap', 'Mire 2 NE', 'Mire Hub Upper Blue Barrier', 'Mire Hub Lower Blue Barrier',
'Mire Hub Right Blue Barrier', 'Mire Hub Top Blue Barrier', 'Mire Hub Switch Blue Barrier N',
'Mire Hub Switch Blue Barrier S', 'Mire Falling Bridge WN',
'Mire Map Spike Side Blue Barrier', 'Mire Map Spot Blue Barrier', 'Mire Crystal Dead End Left Barrier',
'Mire Crystal Dead End Right Barrier', 'Mire Cross ES', 'Mire Hidden Shooters Block Path S',
'Mire Hidden Shooters Block Path N', 'Mire Left Bridge Hook Path', 'Mire Fishbone Blue Barrier',
'Mire Hub Switch Blue Barrier S', 'Mire Falling Bridge WN', 'Mire Map Spike Side Blue Barrier',
'Mire Map Spot Blue Barrier', 'Mire Crystal Dead End Left Barrier', 'Mire Crystal Dead End Right Barrier',
'Mire Cross ES', 'Mire Hidden Shooters Block Path S', 'Mire Hidden Shooters Block Path N',
'Mire Left Bridge Hook Path', 'Mire Fishbone Blue Barrier',
'Mire South Fish Blue Barrier', 'Mire Tile Room NW', 'Mire Compass Blue Barrier', 'Mire Attic Hint Hole',
'Mire Dark Shooters SW', 'Mire Crystal Mid Blue Barrier', 'Mire Crystal Left Blue Barrier', 'TR Main Lobby Gap',
'TR Lobby Ledge Gap', 'TR Hub SW', 'TR Hub SE', 'TR Hub ES', 'TR Hub EN', 'TR Hub NW', 'TR Hub NE', 'TR Torches NW',
@@ -1542,14 +1543,15 @@ bunny_impassible_doors = {
'GT Crystal Conveyor NE', 'GT Crystal Conveyor WN', 'GT Conveyor Cross EN', 'GT Conveyor Cross WN',
'GT Hookshot East-North Path', 'GT Hookshot East-South Path', 'GT Hookshot North-East Path',
'GT Hookshot North-South Path', 'GT Hookshot South-East Path', 'GT Hookshot South-North Path',
'GT Hookshot Platform Blue Barrier', 'GT Hookshot Entry Blue Barrier', 'GT Double Switch Blue Path',
'GT Double Switch Key Blue Path', 'GT Double Switch Blue Barrier', 'GT Double Switch Transition Blue',
'GT Firesnake Room Hook Path', 'GT Falling Bridge WN', 'GT Falling Bridge WS', 'GT Ice Armos NE', 'GT Ice Armos WS',
'GT Crystal Paths SW', 'GT Mimics 1 NW', 'GT Mimics 1 ES', 'GT Mimics 2 WS', 'GT Mimics 2 NE',
'GT Hidden Spikes EN', 'GT Cannonball Bridge SE', 'GT Gauntlet 1 WN', 'GT Gauntlet 2 EN', 'GT Gauntlet 2 SW',
'GT Gauntlet 3 NW', 'GT Gauntlet 3 SW', 'GT Gauntlet 4 NW', 'GT Gauntlet 4 SW', 'GT Gauntlet 5 NW',
'GT Gauntlet 5 WS', 'GT Lanmolas 2 ES', 'GT Lanmolas 2 NW', 'GT Wizzrobes 1 SW', 'GT Wizzrobes 2 SE',
'GT Wizzrobes 2 NE', 'GT Torch Cross ES', 'GT Falling Torches NE', 'GT Moldorm Gap', 'GT Validation Block Path'
'GT Hookshot Platform Blue Barrier', 'GT Hookshot Entry Blue Barrier', 'GT Hookshot Entry Boomerang Path',
'GT Double Switch Blue Path', 'GT Double Switch Key Blue Path', 'GT Double Switch Blue Barrier',
'GT Double Switch Transition Blue', 'GT Firesnake Room Hook Path', 'GT Falling Bridge WN', 'GT Falling Bridge WS',
'GT Ice Armos NE', 'GT Ice Armos WS', 'GT Crystal Paths SW', 'GT Mimics 1 NW', 'GT Mimics 1 ES', 'GT Mimics 2 WS',
'GT Mimics 2 NE', 'GT Hidden Spikes EN', 'GT Cannonball Bridge SE', 'GT Gauntlet 1 WN', 'GT Gauntlet 2 EN',
'GT Gauntlet 2 SW', 'GT Gauntlet 3 NW', 'GT Gauntlet 3 SW', 'GT Gauntlet 4 NW', 'GT Gauntlet 4 SW',
'GT Gauntlet 5 NW', 'GT Gauntlet 5 WS', 'GT Lanmolas 2 ES', 'GT Lanmolas 2 NW', 'GT Wizzrobes 1 SW',
'GT Wizzrobes 2 SE', 'GT Wizzrobes 2 NE', 'GT Torch Cross ES', 'GT Falling Torches NE', 'GT Moldorm Gap',
'GT Validation Block Path'
}

View File

@@ -20,7 +20,10 @@ normal_offset_table = {
0xc1: 0x81, 0xc2: 0x82, 0xc3: 0x83, 0xc4: 0x84, 0xc5: 0x85, 0xc6: 0x86, 0xc7: 0x87, 0xc8: 0x88,
0xc9: 0x89, 0xcb: 0x8A, 0xcc: 0x8B, 0xce: 0x8C, 0xd1: 0x8D, 0xd2: 0x8E, 0xd5: 0x8F, 0xd6: 0x90,
0xd8: 0x91, 0xd9: 0x92, 0xda: 0x93, 0xdb: 0x94, 0xdc: 0x95,
0x40: 0x96, 0x42: 0x97 # newcomers for str stairs
0x40: 0x96, 0x42: 0x97, # newcomers for str stairs
# newcomers for entrances
0x28: 0x98, 0x0e: 0x99, 0x0c: 0x9a, 0x98: 0x9b, 0x83: 0x9c, 0x84: 0x9d, 0x77: 0x9e, 0xe0: 0x9f,
0x63: 0xa0
}

View File

@@ -39,21 +39,22 @@ db $70
org $279F00
DoorOffset:
db $00,$01,$02,$00,$03,$00,$04,$00,$00,$00,$00,$00,$00,$05,$00,$00
db $00,$01,$02,$00,$03,$00,$04,$00,$00,$00,$00,$00,$9A,$05,$99,$00
db $00,$06,$07,$08,$09,$0A,$0B,$00,$00,$0C,$0D,$0E,$00,$0F,$10,$11
db $12,$13,$14,$15,$16,$00,$17,$00,$00,$00,$18,$19,$00,$00,$1A,$00
db $12,$13,$14,$15,$16,$00,$17,$00,$98,$00,$18,$19,$00,$00,$1A,$00
db $1B,$00,$1C,$1D,$1E,$1F,$20,$21,$22,$23,$24,$25,$00,$26,$27,$00
db $96,$28,$97,$29,$2A,$2B,$2C,$00,$00,$2D,$2E,$2F,$30,$31,$32,$00
db $33,$34,$35,$36,$00,$00,$37,$38,$39,$3A,$3B,$3C,$3D,$3E,$3F,$40
db $41,$42,$43,$00,$00,$00,$44,$45,$46,$00,$47,$48,$49,$4A,$4B,$00
db $00,$4C,$00,$00,$00,$4D,$4E,$00,$00,$00,$00,$4F,$50,$51,$52,$53
db $00,$54,$00,$00,$00,$55,$00,$00,$00,$00,$00,$56,$57,$58,$59,$00
db $5A,$5B,$5C,$5D,$00,$5E,$5F,$00,$00,$60,$00,$61,$62,$63,$64,$65
db $41,$42,$43,$A0,$00,$00,$44,$45,$46,$00,$47,$48,$49,$4A,$4B,$00
; 0 1 2 3 4 5 6 7 8 9 a b c d e f --Offset Ruler
db $00,$4C,$00,$00,$00,$4D,$4E,$9E,$00,$00,$00,$4F,$50,$51,$52,$53
db $00,$54,$00,$9C,$9D,$55,$00,$00,$00,$00,$00,$56,$57,$58,$59,$00
db $5A,$5B,$5C,$5D,$00,$5E,$5F,$00,$9B,$60,$00,$61,$62,$63,$64,$65
db $66,$67,$68,$69,$6A,$6B,$00,$00,$6C,$6D,$6E,$6F,$70,$00,$71,$72
db $00,$73,$74,$75,$76,$77,$78,$79,$7A,$7B,$7C,$7D,$7E,$00,$7F,$80
db $00,$81,$82,$83,$84,$85,$86,$87,$88,$89,$00,$8A,$8B,$00,$8C,$00
db $00,$8D,$8E,$00,$00,$8F,$90,$00,$91,$92,$93,$94,$95,$00,$00,$00
db $00
db $9f
org $27A000
DoorTable:
@@ -210,7 +211,16 @@ dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003,
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TT SE Quad
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Aga 6F
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Sewers Rope
; this should end at 27AE40 about (152 * 24 bytes = 3648 or E40)
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Swamp Lobby
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Lobby
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Lobby
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Lobby
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Desert West Lobby
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Desert Main Lobby
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Hera Lobby
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Tower Lobby
dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Desert Back Lobby
; this should end at 27AF18 about (160 * 24 bytes = 3840 or F18)
; some values you can hardcode for spirals
;dw $0070, $36a0 ; ->HC Stairwell
;dw $0072, $4ff8 ; ->HC Map Room

View File

@@ -101,9 +101,11 @@ nop : stz $0dd0, X : rts
.not_in_ganons_tower
org $208206
;org $208206
org $20820E
jsl MirrorCheckOverride2
org $208270
;org $208270
org $208278
jsl MirrorCheckOverride2
org $07a955 ; <- Bank07.asm : around 6564 (JP is a bit different) (STZ $05FC : STZ $05FD)
jsl BlockEraseFix
@@ -123,19 +125,27 @@ nop #3
org $028fc9
nop #2 : jsl BlindAtticFix
org $028409
jsl SuctionOverworldFix
; also rando's hooks.asm line 1360
; 106e4e -> goes to a0ee4e
org $a0ee8a ; <- 6FC4C - headsup_display.asm : 836 (LDA $7EF36E : AND.w #$00FF : ADD.w #$0007 : AND.w #$FFF8 : TAX)
;org $a0ee8a ; <- 6FC4C - headsup_display.asm : 836 (LDA $7EF36E : AND.w #$00FF : ADD.w #$0007 : AND.w #$FFF8 : TAX)
org $a0ee9a
jsl DrHudOverride
org $0ded04 ; <- rando's hooks.asm line 2192 - 6ED04 - equipment.asm : 1963 (REP #$30)
jsl DrHudDungeonItemsAdditions
org $098638 ; rando's hooks.asm line 2192
jsl CountChestKeys
;org $098638 ; rando's hooks.asm line 2192
;jsl CountChestKeys
org $06D192 ; rando's hooks.asm line 457
jsl CountAbsorbedKeys
; rando's hooks.asm line 1020
org $05FC7E ; <- 2FC7E - sprite_dash_item.asm : 118 (LDA $7EF36F : INC A : STA $7EF36F)
jsl CountBonkItem
;org $05FC7E ; <- 2FC7E - sprite_dash_item.asm : 118 (LDA $7EF36F : INC A : STA $7EF36F)
;jsl CountBonkItem
org $019dbd ; <- Bank01.asm : 4465 of Object_Draw8xN (LDA $9B52, Y : STA $7E2000, X)
jsl CutoffEntranceRug : bra .nextTile : nop
.nextTile
; These two, if enabled together, have implications for vanilla BK doors in IP/Hera/Mire
; IPBJ is common enough to consider not doing this. Mire is not a concern for vanilla - maybe glitched modes

View File

@@ -126,27 +126,27 @@ ConvertToDisplay2:
+ !add #$2816 : rts
++ lda #$2483 : rts ; 0/O for 0 or placeholder digit
CountChestKeys:
jsl ItemDowngradeFix
jsr CountChest
rtl
;CountChestKeys:
; jsl ItemDowngradeFix
; jsr CountChest
; rtl
CountChest:
lda !MULTIWORLD_ITEM_PLAYER_ID : bne .end
cpy #$24 : beq +
cpy #$a0 : !blt .end
cpy #$ae : !bge .end
pha : phx
tya : and #$0f : bne ++
inc a
++ tax : bra .count
+ pha : phx
lda $040c : lsr : tax
.count
lda $7ef4b0, x : inc : sta $7ef4b0, x
lda $7ef4e0, x : inc : sta $7ef4e0, x
.restore plx : pla
.end rts
;CountChest:
; lda !MULTIWORLD_ITEM_PLAYER_ID : bne .end
; cpy #$24 : beq +
; cpy #$a0 : !blt .end
; cpy #$ae : !bge .end
; pha : phx
; tya : and #$0f : bne ++
; inc a
; ++ tax : bra .count
; + pha : phx
; lda $040c : lsr : tax
; .count
; lda $7ef4b0, x : inc : sta $7ef4b0, x
; lda $7ef4e0, x : inc : sta $7ef4e0, x
; .restore plx : pla
; .end rts
CountAbsorbedKeys:
jsl IncrementSmallKeysNoPrimary : phx
@@ -155,19 +155,19 @@ CountAbsorbedKeys:
lda $7ef4b0, x : inc : sta $7ef4b0, x
+ plx : rtl
CountBonkItem:
jsl GiveBonkItem
lda $a0 ; check room ID - only bonk keys in 2 rooms so we're just checking the lower byte
cmp #115 : bne + ; Desert Bonk Key
lda.l BonkKey_Desert
bra ++
+ : cmp #140 : bne + ; GTower Bonk Key
lda.l BonkKey_GTower
bra ++
+ lda.b #$24 ; default to small key
++ cmp #$24 : bne +
phy : tay : jsr CountChest : ply
+ rtl
;CountBonkItem:
; jsl GiveBonkItem
; lda $a0 ; check room ID - only bonk keys in 2 rooms so we're just checking the lower byte
; cmp #115 : bne + ; Desert Bonk Key
; lda.l BonkKey_Desert
; bra ++
; + : cmp #140 : bne + ; GTower Bonk Key
; lda.l BonkKey_GTower
; bra ++
; + lda.b #$24 ; default to small key
; ++ cmp #$24 : bne +
; phy : tay : jsr CountChest : ply
; + rtl
;================================================================================
; 16-bit A, 8-bit X

View File

@@ -80,3 +80,26 @@ BlindAtticFix:
lda #$01 : rtl
+ lda $7EF3CC : cmp.b #$06
rtl
SuctionOverworldFix:
stz $50 : stz $5e
lda.l DRMode : beq +
stz $49
+ rtl
CutoffEntranceRug:
pha
lda.l DRMode : beq +
lda $04 : cmp #$000A : bne +
lda $a0 : cmp #$00BC : beq .check ;; TT Alcove
cmp #$00A2 : beq .check ; Mire Bridges
cmp #$00C2 : bne + ; Mire Hub
.check
lda $0c : cmp #$0007 : !bge .skip
lda $0e : cmp #$0009 : !bge .skip
cmp #$0003 : !blt .skip
bra +
.skip pla : rtl
+ pla : lda $9B52, y : sta $7E2000, x ; what we wrote over
rtl

File diff suppressed because one or more lines are too long