Initial work for fixing standard (basic only so far)

This commit is contained in:
aerinon
2020-01-17 16:35:18 -07:00
committed by compiling
parent 4f7aea7dde
commit c08fb4bd5e
13 changed files with 454 additions and 308 deletions

View File

@@ -184,6 +184,19 @@ class World(object):
return door return door
return None return None
def check_for_entrance(self, entrance, player):
if isinstance(entrance, Entrance):
return entrance
try:
return self._entrance_cache[(entrance, player)]
except KeyError:
for region in self.regions:
for ext in region.exits:
if ext.name == entrance and ext.player == player:
self._entrance_cache[(entrance, player)] = ext
return ext
return None
def get_room(self, room_idx, player): def get_room(self, room_idx, player):
if isinstance(room_idx, Room): if isinstance(room_idx, Room):
return room_idx return room_idx
@@ -882,6 +895,7 @@ class Entrance(object):
self.vanilla = None self.vanilla = None
self.access_rule = lambda state: True self.access_rule = lambda state: True
self.player = player self.player = player
self.door = None
def can_reach(self, state): def can_reach(self, state):
if self.parent_region.can_reach(state) and self.access_rule(state): if self.parent_region.can_reach(state) and self.access_rule(state):
@@ -1067,7 +1081,7 @@ class CrystalBarrier(Flag):
class Door(object): class Door(object):
def __init__(self, player, name, type): def __init__(self, player, name, type, entrance=None):
self.player = player self.player = player
self.name = name self.name = name
self.type = type self.type = type
@@ -1102,6 +1116,10 @@ class Door(object):
self.dependents = [] self.dependents = []
self.dead = False self.dead = False
self.entrance = entrance
if entrance is not None:
entrance.door = self
def getAddress(self): def getAddress(self):
if self.type == DoorType.Normal: if self.type == DoorType.Normal:
return 0x13A000 + normal_offset_table[self.roomIndex] * 24 + (self.doorIndex + self.direction.value * 3) * 2 return 0x13A000 + normal_offset_table[self.roomIndex] * 24 + (self.doorIndex + self.direction.value * 3) * 2

View File

@@ -1194,19 +1194,20 @@ def add_inaccessible_doors(world, player):
create_door(world, player, 'Death Mountain Return Cave (West)', 'Death Mountain Return Ledge') create_door(world, player, 'Death Mountain Return Cave (West)', 'Death Mountain Return Ledge')
if 'Desert Palace Lone Stairs' in world.inaccessible_regions[player]: if 'Desert Palace Lone Stairs' in world.inaccessible_regions[player]:
create_door(world, player, 'Desert Palace Entrance (East)', 'Desert Palace Lone Stairs') create_door(world, player, 'Desert Palace Entrance (East)', 'Desert Palace Lone Stairs')
if world.mode[player] == 'standard' and 'Hyrule Castle Ledge' in world.inaccessible_regions[player]: # if world.mode[player] == 'standard' and 'Hyrule Castle Ledge' in world.inaccessible_regions[player]:
create_door(world, player, 'Hyrule Castle Entrance (East)', 'Hyrule Castle Ledge') # create_door(world, player, 'Hyrule Castle Entrance (East)', 'Hyrule Castle Ledge')
create_door(world, player, 'Hyrule Castle Entrance (West)', 'Hyrule Castle Ledge') # create_door(world, player, 'Hyrule Castle Entrance (West)', 'Hyrule Castle Ledge')
def create_door(world, player, entName, region_name): def create_door(world, player, entName, region_name):
connect = world.get_entrance(entName, player).connected_region entrance = world.get_entrance(entName, player)
connect = entrance.connected_region
for ext in connect.exits: for ext in connect.exits:
if ext.connected_region is not None and ext.connected_region.name == region_name: if ext.connected_region is not None and ext.connected_region.name == region_name:
d = Door(player, ext.name, DoorType.Logical), d = Door(player, ext.name, DoorType.Logical, ext),
world.doors += d world.doors += d
connect_door_only(world, ext.name, ext.connected_region, player) connect_door_only(world, ext.name, ext.connected_region, player)
d = Door(player, entName, DoorType.Logical), d = Door(player, entName, DoorType.Logical, entrance),
world.doors += d world.doors += d
connect_door_only(world, entName, connect, player) connect_door_only(world, entName, connect, player)

View File

@@ -1069,6 +1069,10 @@ def create_doors(world, player):
world.get_door('Swamp Drain Right Switch', player).event('Swamp Drain') world.get_door('Swamp Drain Right Switch', player).event('Swamp Drain')
world.get_door('Swamp Flooded Room Ladder', player).event('Swamp Drain') world.get_door('Swamp Flooded Room Ladder', player).event('Swamp Drain')
# if world.mode[player] == 'standard': # todo: multi
if world.mode == 'standard':
world.get_door('Hyrule Castle Throne Room N', player).event('Zelda Pickup')
# crystal switches and barriers # crystal switches and barriers
world.get_door('Hera Lobby Down Stairs', player).c_switch() world.get_door('Hera Lobby Down Stairs', player).c_switch()
world.get_door('Hera Lobby Key Stairs', player).c_switch() world.get_door('Hera Lobby Key Stairs', player).c_switch()
@@ -1203,6 +1207,8 @@ def create_doors(world, player):
controller_door(east_controller, world.get_door('Ice Cross Bottom Push Block Right', player)) controller_door(east_controller, world.get_door('Ice Cross Bottom Push Block Right', player))
controller_door(east_controller, world.get_door('Ice Cross Top Push Block Right', player)) controller_door(east_controller, world.get_door('Ice Cross Top Push Block Right', player))
assign_entrances(world, player)
def create_paired_doors(world, player): def create_paired_doors(world, player):
world.paired_doors[player] = [ world.paired_doors[player] = [
@@ -1247,6 +1253,15 @@ def create_paired_doors(world, player):
] ]
def assign_entrances(world, player):
for door in world.doors:
if door.player == player:
entrance = world.check_for_entrance(door.name, player)
if entrance is not None:
door.entrance = entrance
entrance.door = door
def controller_door(controller, dependent): def controller_door(controller, dependent):
dependent.controller = controller dependent.controller = controller
controller.dependents.append(dependent) controller.dependents.append(dependent)

View File

@@ -1,6 +1,6 @@
import random import random
import collections import collections
from collections import defaultdict from collections import defaultdict, deque
from enum import Enum, unique from enum import Enum, unique
import logging import logging
from functools import reduce from functools import reduce
@@ -34,13 +34,13 @@ class GraphPiece:
def generate_dungeon(name, available_sectors, entrance_region_names, split_dungeon, world, player): def generate_dungeon(name, available_sectors, entrance_region_names, split_dungeon, world, player):
logger = logging.getLogger('') logger = logging.getLogger('')
entrance_regions = convert_regions(entrance_region_names, world, player) entrance_regions = convert_regions(entrance_region_names, world, player)
doors_to_connect = set() doors_to_connect = {}
all_regions = set() all_regions = set()
bk_needed = False bk_needed = False
bk_special = False bk_special = False
for sector in available_sectors: for sector in available_sectors:
for door in sector.outstanding_doors: for door in sector.outstanding_doors:
doors_to_connect.add(door) doors_to_connect[door.name] = door
all_regions.update(sector.regions) all_regions.update(sector.regions)
bk_needed = bk_needed or determine_if_bk_needed(sector, split_dungeon, world, player) bk_needed = bk_needed or determine_if_bk_needed(sector, split_dungeon, world, player)
bk_special = bk_special or check_for_special(sector) bk_special = bk_special or check_for_special(sector)
@@ -51,7 +51,9 @@ def generate_dungeon(name, available_sectors, entrance_region_names, split_dunge
backtrack = False backtrack = False
itr = 0 itr = 0
finished = False finished = False
# last_choice = None # flag if standard and this is hyrule castle
# std_flag = world.mode[player] == 'standard' and bk_special # todo: multi
std_flag = world.mode == 'standard' and bk_special
while not finished: while not finished:
# what are my choices? # what are my choices?
itr += 1 itr += 1
@@ -61,7 +63,7 @@ def generate_dungeon(name, available_sectors, entrance_region_names, split_dunge
dungeon, hangers, hooks = gen_dungeon_info(name, available_sectors, entrance_regions, proposed_map, dungeon, hangers, hooks = gen_dungeon_info(name, available_sectors, entrance_regions, proposed_map,
doors_to_connect, bk_needed, bk_special, world, player) doors_to_connect, bk_needed, bk_special, world, player)
dungeon_cache[depth] = dungeon, hangers, hooks dungeon_cache[depth] = dungeon, hangers, hooks
valid = check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_regions, bk_needed) valid = check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_regions, bk_needed, std_flag)
else: else:
dungeon, hangers, hooks = dungeon_cache[depth] dungeon, hangers, hooks = dungeon_cache[depth]
valid = True valid = True
@@ -98,7 +100,7 @@ def generate_dungeon(name, available_sectors, entrance_region_names, split_dunge
queue = collections.deque(proposed_map.items()) queue = collections.deque(proposed_map.items())
while len(queue) > 0: while len(queue) > 0:
a, b = queue.pop() a, b = queue.pop()
connect_doors(a, b, world, player) connect_doors(a, b)
queue.remove((b, a)) queue.remove((b, a))
master_sector = available_sectors.pop() master_sector = available_sectors.pop()
for sub_sector in available_sectors: for sub_sector in available_sectors:
@@ -136,7 +138,7 @@ def gen_dungeon_info(name, available_sectors, entrance_regions, proposed_map, va
for door in sector.outstanding_doors: for door in sector.outstanding_doors:
if not door.stonewall and door not in proposed_map.keys(): if not door.stonewall and door not in proposed_map.keys():
hanger_set.add(door) hanger_set.add(door)
parent = parent_region(door, world, player).parent_region parent = door.entrance.parent_region
init_state = ExplorationState(dungeon=name) init_state = ExplorationState(dungeon=name)
init_state.big_key_special = start.big_key_special init_state.big_key_special = start.big_key_special
o_state = extend_reachable_state_improved([parent], init_state, proposed_map, o_state = extend_reachable_state_improved([parent], init_state, proposed_map,
@@ -198,7 +200,7 @@ def check_blue_states(hanger_set, dungeon, o_state_cache, proposed_map, valid_do
def explore_blue_state(door, dungeon, o_state, proposed_map, valid_doors, world, player): def explore_blue_state(door, dungeon, o_state, proposed_map, valid_doors, world, player):
parent = parent_region(door, world, player).parent_region parent = door.entrance.parent_region
blue_start = ExplorationState(CrystalBarrier.Blue, o_state.dungeon) blue_start = ExplorationState(CrystalBarrier.Blue, o_state.dungeon)
blue_start.big_key_special = o_state.big_key_special blue_start.big_key_special = o_state.big_key_special
b_state = extend_reachable_state_improved([parent], blue_start, proposed_map, valid_doors, False, world, player) b_state = extend_reachable_state_improved([parent], blue_start, proposed_map, valid_doors, False, world, player)
@@ -269,7 +271,7 @@ 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 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): def check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_regions, bk_needed, std_flag):
# evaluate if everything is still plausible # evaluate if everything is still plausible
# only origin is left in the dungeon and not everything is connected # only origin is left in the dungeon and not everything is connected
@@ -300,7 +302,7 @@ def check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_reg
if len(must_hang[key]) > len(hooks[key]): if len(must_hang[key]) > len(hooks[key]):
return False return False
outstanding_doors = defaultdict(list) outstanding_doors = defaultdict(list)
for d in doors_to_connect: for d in doors_to_connect.values():
if d not in proposed_map.keys(): if d not in proposed_map.keys():
outstanding_doors[hook_from_door(d)].append(d) outstanding_doors[hook_from_door(d)].append(d)
for key in outstanding_doors.keys(): for key in outstanding_doors.keys():
@@ -317,6 +319,8 @@ def check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_reg
return False return False
if not bk_possible: if not bk_possible:
return False return False
if std_flag and not cellblock_valid(doors_to_connect, all_regions, proposed_map):
return False
new_hangers_found = True new_hangers_found = True
accessible_hook_types = [] accessible_hook_types = []
hanger_matching = set() hanger_matching = set()
@@ -344,6 +348,41 @@ def check_valid(dungeon, hangers, hooks, proposed_map, doors_to_connect, all_reg
return len(all_hangers.difference(hanger_matching)) == 0 return len(all_hangers.difference(hanger_matching)) == 0
def cellblock_valid(valid_doors, all_regions, proposed_map):
cellblock = None
for region in all_regions:
if 'Hyrule Dungeon Cellblock' == region.name:
cellblock = region
break
queue = deque([cellblock])
visited = {cellblock}
while len(queue) > 0:
region = queue.popleft()
if region.name == 'Sanctuary':
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)
else:
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)
return False # couldn't find an outstanding door or the sanctuary
def winnow_hangers(hangers, hooks): def winnow_hangers(hangers, hooks):
removal_info = [] removal_info = []
for hanger, door_set in hangers.items(): for hanger, door_set in hangers.items():
@@ -406,10 +445,6 @@ def filter_for_potential_bk_locations(locations):
and x.name not in key_only_locations.keys() and x.name not in ['Agahnim 1', 'Agahnim 2']] and x.name not in key_only_locations.keys() and x.name not in ['Agahnim 1', 'Agahnim 2']]
def parent_region(door, world, player):
return world.get_entrance(door.name, player)
def opposite_h_type(h_type): def opposite_h_type(h_type):
type_map = { type_map = {
Hook.Stairs: Hook.Stairs, Hook.Stairs: Hook.Stairs,
@@ -450,7 +485,7 @@ def hanger_from_door(door):
return None return None
def connect_doors(a, b, world, player): def connect_doors(a, b):
# Return on unsupported types. # Return on unsupported types.
if a.type in [DoorType.Open, DoorType.StraightStairs, DoorType.Hole, DoorType.Warp, DoorType.Ladder, if a.type in [DoorType.Open, DoorType.StraightStairs, DoorType.Hole, DoorType.Warp, DoorType.Ladder,
DoorType.Interior, DoorType.Logical]: DoorType.Interior, DoorType.Logical]:
@@ -458,28 +493,26 @@ def connect_doors(a, b, world, player):
# Connect supported types # Connect supported types
if a.type == DoorType.Normal or a.type == DoorType.SpiralStairs: if a.type == DoorType.Normal or a.type == DoorType.SpiralStairs:
if a.blocked: if a.blocked:
connect_one_way(world, b.name, a.name, player) connect_one_way(b.entrance, a.entrance)
elif b.blocked: elif b.blocked:
connect_one_way(world, a.name, b.name, player) connect_one_way(a.entrance, b.entrance)
else: else:
connect_two_way(world, a.name, b.name, player) connect_two_way(a.entrance, b.entrance)
dep_doors, target = [], None dep_doors, target = [], None
if len(a.dependents) > 0: if len(a.dependents) > 0:
dep_doors, target = a.dependents, b dep_doors, target = a.dependents, b
elif len(b.dependents) > 0: elif len(b.dependents) > 0:
dep_doors, target = b.dependents, a dep_doors, target = b.dependents, a
if target is not None: if target is not None:
target_region = world.get_entrance(target.name, player).parent_region target_region = target.entrance.parent_region
for dep in dep_doors: for dep in dep_doors:
connect_simple_door(dep, target_region, world, player) connect_simple_door(dep, target_region)
return return
# If we failed to account for a type, panic # If we failed to account for a type, panic
raise RuntimeError('Unknown door type ' + a.type.name) raise RuntimeError('Unknown door type ' + a.type.name)
def connect_two_way(world, entrancename, exitname, player): def connect_two_way(entrance, ext):
entrance = world.get_entrance(entrancename, player)
ext = world.get_entrance(exitname, player)
# if these were already connected somewhere, remove the backreference # if these were already connected somewhere, remove the backreference
if entrance.connected_region is not None: if entrance.connected_region is not None:
@@ -491,17 +524,15 @@ def connect_two_way(world, entrancename, exitname, player):
ext.connect(entrance.parent_region) ext.connect(entrance.parent_region)
if entrance.parent_region.dungeon: if entrance.parent_region.dungeon:
ext.parent_region.dungeon = entrance.parent_region.dungeon ext.parent_region.dungeon = entrance.parent_region.dungeon
x = world.check_for_door(entrancename, player) x = entrance.door
y = world.check_for_door(exitname, player) y = ext.door
if x is not None: if x is not None:
x.dest = y x.dest = y
if y is not None: if y is not None:
y.dest = x y.dest = x
def connect_one_way(world, entrancename, exitname, player): def connect_one_way(entrance, ext):
entrance = world.get_entrance(entrancename, player)
ext = world.get_entrance(exitname, player)
# if these were already connected somewhere, remove the backreference # if these were already connected somewhere, remove the backreference
if entrance.connected_region is not None: if entrance.connected_region is not None:
@@ -512,16 +543,16 @@ def connect_one_way(world, entrancename, exitname, player):
entrance.connect(ext.parent_region) entrance.connect(ext.parent_region)
if entrance.parent_region.dungeon: if entrance.parent_region.dungeon:
ext.parent_region.dungeon = entrance.parent_region.dungeon ext.parent_region.dungeon = entrance.parent_region.dungeon
x = world.check_for_door(entrancename, player) x = entrance.door
y = world.check_for_door(exitname, player) y = ext.door
if x is not None: if x is not None:
x.dest = y x.dest = y
if y is not None: if y is not None:
y.dest = x y.dest = x
def connect_simple_door(exit_door, region, world, player): def connect_simple_door(exit_door, region):
world.get_entrance(exit_door.name, player).connect(region) exit_door.entrance.connect(region)
exit_door.dest = region exit_door.dest = region
@@ -679,7 +710,7 @@ class ExplorationState(object):
if self.can_traverse(door): if self.can_traverse(door):
if door.controller is not None: if door.controller is not None:
door = door.controller door = door.controller
if door.dest is None and door not in proposed_map.keys() and door in valid_doors: if door.dest is None and door not in proposed_map.keys() and door.name in valid_doors.keys():
if not self.in_door_list_ic(door, self.unattached_doors): if not self.in_door_list_ic(door, self.unattached_doors):
self.append_door_to_list(door, self.unattached_doors, flag) self.append_door_to_list(door, self.unattached_doors, flag)
else: else:

View File

@@ -255,7 +255,9 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
fill_locations.reverse() fill_locations.reverse()
# Make sure the escape small key is placed first in standard with key shuffle to prevent running out of spots # Make sure the escape small key is placed first in standard with key shuffle to prevent running out of spots
progitempool.sort(key=lambda item: 1 if item.name == 'Small Key (Escape)' and world.mode[item.player] == 'standard' and world.keyshuffle[item.player] else 0) # todo: crossed
if world.keyshuffle[item.player] and world.mode == 'standard':
progitempool.sort(key=lambda item: 1 if item.name == 'Small Key (Escape)' else 0)
fill_restrictive(world, world.state, fill_locations, progitempool) fill_restrictive(world, world.state, fill_locations, progitempool)

View File

@@ -192,6 +192,15 @@ def generate_itempool(world, player):
world.push_item(world.get_location('Ice Block Drop', player), ItemFactory('Convenient Block', player), False) world.push_item(world.get_location('Ice Block Drop', player), ItemFactory('Convenient Block', player), False)
world.get_location('Ice Block Drop', player).event = True world.get_location('Ice Block Drop', player).event = True
world.get_location('Ice Block Drop', player).locked = True world.get_location('Ice Block Drop', player).locked = True
# if world.mode[player] == 'standard': todo: multi
if world.mode == 'standard':
world.push_item(world.get_location('Zelda Pickup', player), ItemFactory('Zelda Herself', player), False)
world.get_location('Zelda Pickup', player).event = True
world.get_location('Zelda Pickup', player).locked = True
world.push_item(world.get_location('Zelda Drop Off', player), ItemFactory('Zelda Delivered', player), False)
world.get_location('Zelda Drop Off', player).event = True
world.get_location('Zelda Drop Off', player).locked = True
# set up item pool # set up item pool
if world.custom: if world.custom:

View File

@@ -183,4 +183,6 @@ item_table = {'Bow': (True, False, None, 0x0B, 'You have\nchosen the\narcher cla
'Maiden Rescued': (True, False, 'Event', None, None, None, None, None, None, None, None), 'Maiden Rescued': (True, False, 'Event', None, None, None, None, None, None, None, None),
'Maiden Unmasked': (True, False, 'Event', None, None, None, None, None, None, None, None), 'Maiden Unmasked': (True, False, 'Event', None, None, None, None, None, None, None, None),
'Convenient Block': (True, False, 'Event', None, None, None, None, None, None, None, None), 'Convenient Block': (True, False, 'Event', None, None, None, None, None, None, None, None),
'Zelda Herself': (True, False, 'Event', None, None, None, None, None, None, None, None),
'Zelda Delivered': (True, False, 'Event', None, None, None, None, None, None, None, None),
} }

View File

@@ -3,7 +3,8 @@ from BaseClasses import Region, Location, Entrance, RegionType, Shop, ShopType
def create_regions(world, player): def create_regions(world, player):
# std_flag = world.mode[player] == 'standard' # todo: multi
std_flag = world.mode == 'standard'
world.regions += [ world.regions += [
create_lw_region(player, 'Light World', ['Mushroom', 'Bottle Merchant', 'Flute Spot', 'Sunken Treasure', 'Purple Chest'], create_lw_region(player, 'Light World', ['Mushroom', 'Bottle Merchant', 'Flute Spot', 'Sunken Treasure', 'Purple Chest'],
["Blinds Hideout", "Hyrule Castle Secret Entrance Drop", 'Zoras River', 'Kings Grave Outer Rocks', 'Dam', ["Blinds Hideout", "Hyrule Castle Secret Entrance Drop", 'Zoras River', 'Kings Grave Outer Rocks', 'Dam',
@@ -219,7 +220,10 @@ def create_regions(world, player):
create_dungeon_region(player, 'Hyrule Dungeon Armory Boomerang', 'Hyrule Castle', ['Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Boomerang Guard Key Drop'], ['Hyrule Dungeon Armory Boomerang WS']), create_dungeon_region(player, 'Hyrule Dungeon Armory Boomerang', 'Hyrule Castle', ['Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Boomerang Guard Key Drop'], ['Hyrule Dungeon Armory Boomerang WS']),
create_dungeon_region(player, 'Hyrule Dungeon Armory North Branch', 'Hyrule Castle', None, ['Hyrule Dungeon Armory Interior Key Door S', 'Hyrule Dungeon Armory Down Stairs']), create_dungeon_region(player, 'Hyrule Dungeon Armory North Branch', 'Hyrule Castle', None, ['Hyrule Dungeon Armory Interior Key Door S', 'Hyrule Dungeon Armory Down Stairs']),
create_dungeon_region(player, 'Hyrule Dungeon Staircase', 'Hyrule Castle', None, ['Hyrule Dungeon Staircase Up Stairs', 'Hyrule Dungeon Staircase Down Stairs']), create_dungeon_region(player, 'Hyrule Dungeon Staircase', 'Hyrule Castle', None, ['Hyrule Dungeon Staircase Up Stairs', 'Hyrule Dungeon Staircase Down Stairs']),
create_dungeon_region(player, 'Hyrule Dungeon Cellblock', 'Hyrule Castle', ['Hyrule Castle - Big Key Drop', 'Hyrule Castle - Zelda\'s Chest'], ['Hyrule Dungeon Cellblock Up Stairs']), create_dungeon_region(player, 'Hyrule Dungeon Cellblock', 'Hyrule Castle',
['Hyrule Castle - Big Key Drop', 'Hyrule Castle - Zelda\'s Chest'] if not std_flag else
['Hyrule Castle - Big Key Drop', 'Hyrule Castle - Zelda\'s Chest', 'Zelda Pickup'],
['Hyrule Dungeon Cellblock Up Stairs']),
create_dungeon_region(player, 'Sewers Behind Tapestry', 'Hyrule Castle', None, ['Sewers Behind Tapestry S', 'Sewers Behind Tapestry Down Stairs']), create_dungeon_region(player, 'Sewers Behind Tapestry', 'Hyrule Castle', None, ['Sewers Behind Tapestry S', 'Sewers Behind Tapestry Down Stairs']),
@@ -233,7 +237,9 @@ def create_regions(world, player):
['Sewers Secret Room ES', 'Sewers Secret Room EN']), ['Sewers Secret Room ES', 'Sewers Secret Room EN']),
create_dungeon_region(player, 'Sewers Yet More Rats', 'Hyrule Castle', None, ['Sewers Pull Switch Down Stairs', 'Sewers Yet More Rats S']), create_dungeon_region(player, 'Sewers Yet More Rats', 'Hyrule Castle', None, ['Sewers Pull Switch Down Stairs', 'Sewers Yet More Rats S']),
create_dungeon_region(player, 'Sewers Pull Switch', 'Hyrule Castle', None, ['Sewers Pull Switch N', 'Sewers Pull Switch S']), 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'], ['Sanctuary Exit', 'Sanctuary N']), create_dungeon_region(player, 'Sanctuary', 'Hyrule Castle',
['Sanctuary'] if not std_flag else ['Sanctuary', 'Zelda Drop Off'],
['Sanctuary Exit', 'Sanctuary N']),
# Eastern Palace # 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 Palace Exit', 'Eastern Lobby NW', 'Eastern Lobby NE']),
@@ -848,243 +854,246 @@ flooded_keys_reverse = {
'Swamp Palace - Trench 1 Pot Key': 'Trench 1 Switch', 'Swamp Palace - Trench 1 Pot Key': 'Trench 1 Switch',
'Swamp Palace - Trench 2 Pot Key': 'Trench 2 Switch' 'Swamp Palace - Trench 2 Pot Key': 'Trench 2 Switch'
} }
location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'),
'Bottle Merchant': (0x2eb18, 0x186339, False, 'with a merchant'), location_table = {'Mushroom': (0x180013, False, 'in the woods'),
'Flute Spot': (0x18014a, 0x18633d, False, 'underground'), 'Bottle Merchant': (0x2eb18, False, 'with a merchant'),
'Sunken Treasure': (0x180145, 0x186354, False, 'underwater'), 'Flute Spot': (0x18014a, False, 'underground'),
'Purple Chest': (0x33d68, 0x186359, False, 'from a box'), 'Sunken Treasure': (0x180145, False, 'underwater'),
"Blind's Hideout - Top": (0xeb0f, 0x1862e3, False, 'in a basement'), 'Purple Chest': (0x33d68, False, 'from a box'),
"Blind's Hideout - Left": (0xeb12, 0x1862e6, False, 'in a basement'), "Blind's Hideout - Top": (0xeb0f, False, 'in a basement'),
"Blind's Hideout - Right": (0xeb15, 0x1862e9, False, 'in a basement'), "Blind's Hideout - Left": (0xeb12, False, 'in a basement'),
"Blind's Hideout - Far Left": (0xeb18, 0x1862ec, False, 'in a basement'), "Blind's Hideout - Right": (0xeb15, False, 'in a basement'),
"Blind's Hideout - Far Right": (0xeb1b, 0x1862ef, False, 'in a basement'), "Blind's Hideout - Far Left": (0xeb18, False, 'in a basement'),
"Link's Uncle": (0x2df45, 0x18635f, False, 'with your uncle'), "Blind's Hideout - Far Right": (0xeb1b, False, 'in a basement'),
'Secret Passage': (0xe971, 0x186145, False, 'near your uncle'), "Link's Uncle": (0x2df45, False, 'with your uncle'),
'King Zora': (0xee1c3, 0x186360, False, 'at a high price'), 'Secret Passage': (0xe971, False, 'near your uncle'),
"Zora's Ledge": (0x180149, 0x186358, False, 'near Zora'), 'King Zora': (0xee1c3, False, 'at a high price'),
'Waterfall Fairy - Left': (0xe9b0, 0x186184, False, 'near a fairy'), "Zora's Ledge": (0x180149, False, 'near Zora'),
'Waterfall Fairy - Right': (0xe9d1, 0x1861a5, False, 'near a fairy'), 'Waterfall Fairy - Left': (0xe9b0, False, 'near a fairy'),
"King's Tomb": (0xe97a, 0x18614e, False, 'alone in a cave'), 'Waterfall Fairy - Right': (0xe9d1, False, 'near a fairy'),
'Floodgate Chest': (0xe98c, 0x186160, False, 'in the dam'), "King's Tomb": (0xe97a, False, 'alone in a cave'),
"Link's House": (0xe9bc, 0x186190, False, 'in your home'), 'Floodgate Chest': (0xe98c, False, 'in the dam'),
'Kakariko Tavern': (0xe9ce, 0x1861a2, False, 'in the bar'), "Link's House": (0xe9bc, False, 'in your home'),
'Chicken House': (0xe9e9, 0x1861bd, False, 'near poultry'), 'Kakariko Tavern': (0xe9ce, False, 'in the bar'),
"Aginah's Cave": (0xe9f2, 0x1861c6, False, 'with Aginah'), 'Chicken House': (0xe9e9, False, 'near poultry'),
"Sahasrahla's Hut - Left": (0xea82, 0x186256, False, 'near the elder'), "Aginah's Cave": (0xe9f2, False, 'with Aginah'),
"Sahasrahla's Hut - Middle": (0xea85, 0x186259, False, 'near the elder'), "Sahasrahla's Hut - Left": (0xea82, False, 'near the elder'),
"Sahasrahla's Hut - Right": (0xea88, 0x18625c, False, 'near the elder'), "Sahasrahla's Hut - Middle": (0xea85, False, 'near the elder'),
'Sahasrahla': (0x2f1fc, 0x186365, False, 'with the elder'), "Sahasrahla's Hut - Right": (0xea88, False, 'near the elder'),
'Kakariko Well - Top': (0xea8e, 0x186262, False, 'in a well'), 'Sahasrahla': (0x2f1fc, False, 'with the elder'),
'Kakariko Well - Left': (0xea91, 0x186265, False, 'in a well'), 'Kakariko Well - Top': (0xea8e, False, 'in a well'),
'Kakariko Well - Middle': (0xea94, 0x186268, False, 'in a well'), 'Kakariko Well - Left': (0xea91, False, 'in a well'),
'Kakariko Well - Right': (0xea97, 0x18626b, False, 'in a well'), 'Kakariko Well - Middle': (0xea94, False, 'in a well'),
'Kakariko Well - Bottom': (0xea9a, 0x18626e, False, 'in a well'), 'Kakariko Well - Right': (0xea97, False, 'in a well'),
'Blacksmith': (0x18002a, 0x186366, False, 'with the smith'), 'Kakariko Well - Bottom': (0xea9a, False, 'in a well'),
'Magic Bat': (0x180015, 0x18635e, False, 'with the bat'), 'Blacksmith': (0x18002a, False, 'with the smith'),
'Sick Kid': (0x339cf, 0x186367, False, 'with the sick'), 'Magic Bat': (0x180015, False, 'with the bat'),
'Hobo': (0x33e7d, 0x186368, False, 'with the hobo'), 'Sick Kid': (0x339cf, False, 'with the sick'),
'Lost Woods Hideout': (0x180000, 0x186348, False, 'near a thief'), 'Hobo': (0x33e7d, False, 'with the hobo'),
'Lumberjack Tree': (0x180001, 0x186349, False, 'in a hole'), 'Lost Woods Hideout': (0x180000, False, 'near a thief'),
'Cave 45': (0x180003, 0x18634b, False, 'alone in a cave'), 'Lumberjack Tree': (0x180001, False, 'in a hole'),
'Graveyard Cave': (0x180004, 0x18634c, False, 'alone in a cave'), 'Cave 45': (0x180003, False, 'alone in a cave'),
'Checkerboard Cave': (0x180005, 0x18634d, False, 'alone in a cave'), 'Graveyard Cave': (0x180004, False, 'alone in a cave'),
'Mini Moldorm Cave - Far Left': (0xeb42, 0x186316, False, 'near Moldorms'), 'Checkerboard Cave': (0x180005, False, 'alone in a cave'),
'Mini Moldorm Cave - Left': (0xeb45, 0x186319, False, 'near Moldorms'), 'Mini Moldorm Cave - Far Left': (0xeb42, False, 'near Moldorms'),
'Mini Moldorm Cave - Right': (0xeb48, 0x18631c, False, 'near Moldorms'), 'Mini Moldorm Cave - Left': (0xeb45, False, 'near Moldorms'),
'Mini Moldorm Cave - Far Right': (0xeb4b, 0x18631f, False, 'near Moldorms'), 'Mini Moldorm Cave - Right': (0xeb48, False, 'near Moldorms'),
'Mini Moldorm Cave - Generous Guy': (0x180010, 0x18635a, False, 'near Moldorms'), 'Mini Moldorm Cave - Far Right': (0xeb4b, False, 'near Moldorms'),
'Ice Rod Cave': (0xeb4e, 0x186322, False, 'in a frozen cave'), 'Mini Moldorm Cave - Generous Guy': (0x180010, False, 'near Moldorms'),
'Bonk Rock Cave': (0xeb3f, 0x186313, False, 'alone in a cave'), 'Ice Rod Cave': (0xeb4e, False, 'in a frozen cave'),
'Library': (0x180012, 0x18635c, False, 'near books'), 'Bonk Rock Cave': (0xeb3f, False, 'alone in a cave'),
'Potion Shop': (0x180014, 0x18635d, False, 'near potions'), 'Library': (0x180012, False, 'near books'),
'Lake Hylia Island': (0x180144, 0x186353, False, 'on an island'), 'Potion Shop': (0x180014, False, 'near potions'),
'Maze Race': (0x180142, 0x186351, False, 'at the race'), 'Lake Hylia Island': (0x180144, False, 'on an island'),
'Desert Ledge': (0x180143, 0x186352, False, 'in the desert'), 'Maze Race': (0x180142, False, 'at the race'),
'Desert Palace - Big Chest': (0xe98f, 0x186163, False, 'in Desert Palace'), 'Desert Ledge': (0x180143, False, 'in the desert'),
'Desert Palace - Torch': (0x180160, 0x186362, False, 'in Desert Palace'), 'Desert Palace - Big Chest': (0xe98f, False, 'in Desert Palace'),
'Desert Palace - Map Chest': (0xe9b6, 0x18618a, False, 'in Desert Palace'), 'Desert Palace - Torch': (0x180160, False, 'in Desert Palace'),
'Desert Palace - Compass Chest': (0xe9cb, 0x18619f, False, 'in Desert Palace'), 'Desert Palace - Map Chest': (0xe9b6, False, 'in Desert Palace'),
'Desert Palace - Big Key Chest': (0xe9c2, 0x186196, False, 'in Desert Palace'), 'Desert Palace - Compass Chest': (0xe9cb, False, 'in Desert Palace'),
'Desert Palace - Boss': (0x180151, 0x18633f, False, 'with Lanmolas'), 'Desert Palace - Big Key Chest': (0xe9c2, False, 'in Desert Palace'),
'Eastern Palace - Compass Chest': (0xe977, 0x18614b, False, 'in Eastern Palace'), 'Desert Palace - Boss': (0x180151, False, 'with Lanmolas'),
'Eastern Palace - Big Chest': (0xe97d, 0x186151, False, 'in Eastern Palace'), 'Eastern Palace - Compass Chest': (0xe977, False, 'in Eastern Palace'),
'Eastern Palace - Cannonball Chest': (0xe9b3, 0x186187, False, 'in Eastern Palace'), 'Eastern Palace - Big Chest': (0xe97d, False, 'in Eastern Palace'),
'Eastern Palace - Big Key Chest': (0xe9b9, 0x18618d, False, 'in Eastern Palace'), 'Eastern Palace - Cannonball Chest': (0xe9b3, False, 'in Eastern Palace'),
'Eastern Palace - Map Chest': (0xe9f5, 0x1861c9, False, 'in Eastern Palace'), 'Eastern Palace - Big Key Chest': (0xe9b9, False, 'in Eastern Palace'),
'Eastern Palace - Boss': (0x180150, 0x18633e, False, 'with the Armos'), 'Eastern Palace - Map Chest': (0xe9f5, False, 'in Eastern Palace'),
'Master Sword Pedestal': (0x289b0, 0x186369, False, 'at the pedestal'), 'Eastern Palace - Boss': (0x180150, False, 'with the Armos'),
'Hyrule Castle - Boomerang Chest': (0xe974, 0x186148, False, 'in Hyrule Castle'), 'Master Sword Pedestal': (0x289b0, False, 'at the pedestal'),
'Hyrule Castle - Map Chest': (0xeb0c, 0x1862e0, False, 'in Hyrule Castle'), 'Hyrule Castle - Boomerang Chest': (0xe974, False, 'in Hyrule Castle'),
"Hyrule Castle - Zelda's Chest": (0xeb09, 0x1862dd, False, 'in Hyrule Castle'), 'Hyrule Castle - Map Chest': (0xeb0c, False, 'in Hyrule Castle'),
'Sewers - Dark Cross': (0xe96e, 0x186142, False, 'in the sewers'), "Hyrule Castle - Zelda's Chest": (0xeb09, False, 'in Hyrule Castle'),
'Sewers - Secret Room - Left': (0xeb5d, 0x186331, False, 'in the sewers'), 'Sewers - Dark Cross': (0xe96e, False, 'in the sewers'),
'Sewers - Secret Room - Middle': (0xeb60, 0x186334, False, 'in the sewers'), 'Sewers - Secret Room - Left': (0xeb5d, False, 'in the sewers'),
'Sewers - Secret Room - Right': (0xeb63, 0x186337, False, 'in the sewers'), 'Sewers - Secret Room - Middle': (0xeb60, False, 'in the sewers'),
'Sanctuary': (0xea79, 0x18624d, False, 'in Sanctuary'), 'Sewers - Secret Room - Right': (0xeb63, False, 'in the sewers'),
'Castle Tower - Room 03': (0xeab5, 0x186289, False, 'in Castle Tower'), 'Sanctuary': (0xea79, False, 'in Sanctuary'),
'Castle Tower - Dark Maze': (0xeab2, 0x186286, False, 'in Castle Tower'), 'Castle Tower - Room 03': (0xeab5, False, 'in Castle Tower'),
'Old Man': (0xf69fa, 0x186364, False, 'with the old man'), 'Castle Tower - Dark Maze': (0xeab2, False, 'in Castle Tower'),
'Spectacle Rock Cave': (0x180002, 0x18634a, False, 'alone in a cave'), 'Old Man': (0xf69fa, False, 'with the old man'),
'Paradox Cave Lower - Far Left': (0xeb2a, 0x1862fe, False, 'in a cave with seven chests'), 'Spectacle Rock Cave': (0x180002, False, 'alone in a cave'),
'Paradox Cave Lower - Left': (0xeb2d, 0x186301, False, 'in a cave with seven chests'), 'Paradox Cave Lower - Far Left': (0xeb2a, False, 'in a cave with seven chests'),
'Paradox Cave Lower - Right': (0xeb30, 0x186304, False, 'in a cave with seven chests'), 'Paradox Cave Lower - Left': (0xeb2d, False, 'in a cave with seven chests'),
'Paradox Cave Lower - Far Right': (0xeb33, 0x186307, False, 'in a cave with seven chests'), 'Paradox Cave Lower - Right': (0xeb30, False, 'in a cave with seven chests'),
'Paradox Cave Lower - Middle': (0xeb36, 0x18630a, False, 'in a cave with seven chests'), 'Paradox Cave Lower - Far Right': (0xeb33, False, 'in a cave with seven chests'),
'Paradox Cave Upper - Left': (0xeb39, 0x18630d, False, 'in a cave with seven chests'), 'Paradox Cave Lower - Middle': (0xeb36, False, 'in a cave with seven chests'),
'Paradox Cave Upper - Right': (0xeb3c, 0x186310, False, 'in a cave with seven chests'), 'Paradox Cave Upper - Left': (0xeb39, False, 'in a cave with seven chests'),
'Spiral Cave': (0xe9bf, 0x186193, False, 'in spiral cave'), 'Paradox Cave Upper - Right': (0xeb3c, False, 'in a cave with seven chests'),
'Ether Tablet': (0x180016, 0x18633b, False, 'at a monolith'), 'Spiral Cave': (0xe9bf, False, 'in spiral cave'),
'Spectacle Rock': (0x180140, 0x18634f, False, 'atop a rock'), 'Ether Tablet': (0x180016, False, 'at a monolith'),
'Tower of Hera - Basement Cage': (0x180162, 0x18633a, False, 'in Tower of Hera'), 'Spectacle Rock': (0x180140, False, 'atop a rock'),
'Tower of Hera - Map Chest': (0xe9ad, 0x186181, False, 'in Tower of Hera'), 'Tower of Hera - Basement Cage': (0x180162, False, 'in Tower of Hera'),
'Tower of Hera - Big Key Chest': (0xe9e6, 0x1861ba, False, 'in Tower of Hera'), 'Tower of Hera - Map Chest': (0xe9ad, False, 'in Tower of Hera'),
'Tower of Hera - Compass Chest': (0xe9fb, 0x1861cf, False, 'in Tower of Hera'), 'Tower of Hera - Big Key Chest': (0xe9e6, False, 'in Tower of Hera'),
'Tower of Hera - Big Chest': (0xe9f8, 0x1861cc, False, 'in Tower of Hera'), 'Tower of Hera - Compass Chest': (0xe9fb, False, 'in Tower of Hera'),
'Tower of Hera - Boss': (0x180152, 0x186340, False, 'with Moldorm'), 'Tower of Hera - Big Chest': (0xe9f8, False, 'in Tower of Hera'),
'Pyramid': (0x180147, 0x186356, False, 'on the pyramid'), 'Tower of Hera - Boss': (0x180152, False, 'with Moldorm'),
'Catfish': (0xee185, 0x186361, False, 'with a catfish'), 'Pyramid': (0x180147, False, 'on the pyramid'),
'Stumpy': (0x330c7, 0x18636a, False, 'with tree boy'), 'Catfish': (0xee185, False, 'with a catfish'),
'Digging Game': (0x180148, 0x186357, False, 'underground'), 'Stumpy': (0x330c7, False, 'with tree boy'),
'Bombos Tablet': (0x180017, 0x18633c, False, 'at a monolith'), 'Digging Game': (0x180148, False, 'underground'),
'Hype Cave - Top': (0xeb1e, 0x1862f2, False, 'near a bat-like man'), 'Bombos Tablet': (0x180017, False, 'at a monolith'),
'Hype Cave - Middle Right': (0xeb21, 0x1862f5, False, 'near a bat-like man'), 'Hype Cave - Top': (0xeb1e, False, 'near a bat-like man'),
'Hype Cave - Middle Left': (0xeb24, 0x1862f8, False, 'near a bat-like man'), 'Hype Cave - Middle Right': (0xeb21, False, 'near a bat-like man'),
'Hype Cave - Bottom': (0xeb27, 0x1862fb, False, 'near a bat-like man'), 'Hype Cave - Middle Left': (0xeb24, False, 'near a bat-like man'),
'Hype Cave - Generous Guy': (0x180011, 0x18635b, False, 'with a bat-like man'), 'Hype Cave - Bottom': (0xeb27, False, 'near a bat-like man'),
'Peg Cave': (0x180006, 0x18634e, False, 'alone in a cave'), 'Hype Cave - Generous Guy': (0x180011, False, 'with a bat-like man'),
'Pyramid Fairy - Left': (0xe980, 0x186154, False, 'near a fairy'), 'Peg Cave': (0x180006, False, 'alone in a cave'),
'Pyramid Fairy - Right': (0xe983, 0x186157, False, 'near a fairy'), 'Pyramid Fairy - Left': (0xe980, False, 'near a fairy'),
'Brewery': (0xe9ec, 0x1861c0, False, 'alone in a home'), 'Pyramid Fairy - Right': (0xe983, False, 'near a fairy'),
'C-Shaped House': (0xe9ef, 0x1861c3, False, 'alone in a home'), 'Brewery': (0xe9ec, False, 'alone in a home'),
'Chest Game': (0xeda8, 0x18636b, False, 'as a prize'), 'C-Shaped House': (0xe9ef, False, 'alone in a home'),
'Bumper Cave Ledge': (0x180146, 0x186355, False, 'on a ledge'), 'Chest Game': (0xeda8, False, 'as a prize'),
'Mire Shed - Left': (0xea73, 0x186247, False, 'near sparks'), 'Bumper Cave Ledge': (0x180146, False, 'on a ledge'),
'Mire Shed - Right': (0xea76, 0x18624a, False, 'near sparks'), 'Mire Shed - Left': (0xea73, False, 'near sparks'),
'Superbunny Cave - Top': (0xea7c, 0x186250, False, 'in a connection'), 'Mire Shed - Right': (0xea76, False, 'near sparks'),
'Superbunny Cave - Bottom': (0xea7f, 0x186253, False, 'in a connection'), 'Superbunny Cave - Top': (0xea7c, False, 'in a connection'),
'Spike Cave': (0xea8b, 0x18625f, False, 'beyond spikes'), 'Superbunny Cave - Bottom': (0xea7f, False, 'in a connection'),
'Hookshot Cave - Top Right': (0xeb51, 0x186325, False, 'across pits'), 'Spike Cave': (0xea8b, False, 'beyond spikes'),
'Hookshot Cave - Top Left': (0xeb54, 0x186328, False, 'across pits'), 'Hookshot Cave - Top Right': (0xeb51, False, 'across pits'),
'Hookshot Cave - Bottom Right': (0xeb5a, 0x18632e, False, 'across pits'), 'Hookshot Cave - Top Left': (0xeb54, False, 'across pits'),
'Hookshot Cave - Bottom Left': (0xeb57, 0x18632b, False, 'across pits'), 'Hookshot Cave - Bottom Right': (0xeb5a, False, 'across pits'),
'Floating Island': (0x180141, 0x186350, False, 'on an island'), 'Hookshot Cave - Bottom Left': (0xeb57, False, 'across pits'),
'Mimic Cave': (0xe9c5, 0x186199, False, 'in a cave of mimicry'), 'Floating Island': (0x180141, False, 'on an island'),
'Swamp Palace - Entrance': (0xea9d, 0x186271, False, 'in Swamp Palace'), 'Mimic Cave': (0xe9c5, False, 'in a cave of mimicry'),
'Swamp Palace - Map Chest': (0xe986, 0x18615a, False, 'in Swamp Palace'), 'Swamp Palace - Entrance': (0xea9d, False, 'in Swamp Palace'),
'Swamp Palace - Big Chest': (0xe989, 0x18615d, False, 'in Swamp Palace'), 'Swamp Palace - Map Chest': (0xe986, False, 'in Swamp Palace'),
'Swamp Palace - Compass Chest': (0xeaa0, 0x186274, False, 'in Swamp Palace'), 'Swamp Palace - Big Chest': (0xe989, False, 'in Swamp Palace'),
'Swamp Palace - Big Key Chest': (0xeaa6, 0x18627a, False, 'in Swamp Palace'), 'Swamp Palace - Compass Chest': (0xeaa0, False, 'in Swamp Palace'),
'Swamp Palace - West Chest': (0xeaa3, 0x186277, False, 'in Swamp Palace'), 'Swamp Palace - Big Key Chest': (0xeaa6, False, 'in Swamp Palace'),
'Swamp Palace - Flooded Room - Left': (0xeaa9, 0x18627d, False, 'in Swamp Palace'), 'Swamp Palace - West Chest': (0xeaa3, False, 'in Swamp Palace'),
'Swamp Palace - Flooded Room - Right': (0xeaac, 0x186280, False, 'in Swamp Palace'), 'Swamp Palace - Flooded Room - Left': (0xeaa9, False, 'in Swamp Palace'),
'Swamp Palace - Waterfall Room': (0xeaaf, 0x186283, False, 'in Swamp Palace'), 'Swamp Palace - Flooded Room - Right': (0xeaac, False, 'in Swamp Palace'),
'Swamp Palace - Boss': (0x180154, 0x186342, False, 'with Arrghus'), 'Swamp Palace - Waterfall Room': (0xeaaf, False, 'in Swamp Palace'),
"Thieves' Town - Big Key Chest": (0xea04, 0x1861d8, False, "in Thieves' Town"), 'Swamp Palace - Boss': (0x180154, False, 'with Arrghus'),
"Thieves' Town - Map Chest": (0xea01, 0x1861d5, False, "in Thieves' Town"), "Thieves' Town - Big Key Chest": (0xea04, False, "in Thieves' Town"),
"Thieves' Town - Compass Chest": (0xea07, 0x1861db, False, "in Thieves' Town"), "Thieves' Town - Map Chest": (0xea01, False, "in Thieves' Town"),
"Thieves' Town - Ambush Chest": (0xea0a, 0x1861de, False, "in Thieves' Town"), "Thieves' Town - Compass Chest": (0xea07, False, "in Thieves' Town"),
"Thieves' Town - Attic": (0xea0d, 0x1861e1, False, "in Thieves' Town"), "Thieves' Town - Ambush Chest": (0xea0a, False, "in Thieves' Town"),
"Thieves' Town - Big Chest": (0xea10, 0x1861e4, False, "in Thieves' Town"), "Thieves' Town - Attic": (0xea0d, False, "in Thieves' Town"),
"Thieves' Town - Blind's Cell": (0xea13, 0x1861e7, False, "in Thieves' Town"), "Thieves' Town - Big Chest": (0xea10, False, "in Thieves' Town"),
"Thieves' Town - Boss": (0x180156, 0x186344, False, 'with Blind'), "Thieves' Town - Blind's Cell": (0xea13, False, "in Thieves' Town"),
'Skull Woods - Compass Chest': (0xe992, 0x186166, False, 'in Skull Woods'), "Thieves' Town - Boss": (0x180156, False, 'with Blind'),
'Skull Woods - Map Chest': (0xe99b, 0x18616f, False, 'in Skull Woods'), 'Skull Woods - Compass Chest': (0xe992, False, 'in Skull Woods'),
'Skull Woods - Big Chest': (0xe998, 0x18616c, False, 'in Skull Woods'), 'Skull Woods - Map Chest': (0xe99b, False, 'in Skull Woods'),
'Skull Woods - Pot Prison': (0xe9a1, 0x186175, False, 'in Skull Woods'), 'Skull Woods - Big Chest': (0xe998, False, 'in Skull Woods'),
'Skull Woods - Pinball Room': (0xe9c8, 0x18619c, False, 'in Skull Woods'), 'Skull Woods - Pot Prison': (0xe9a1, False, 'in Skull Woods'),
'Skull Woods - Big Key Chest': (0xe99e, 0x186172, False, 'in Skull Woods'), 'Skull Woods - Pinball Room': (0xe9c8, False, 'in Skull Woods'),
'Skull Woods - Bridge Room': (0xe9fe, 0x1861d2, False, 'near Mothula'), 'Skull Woods - Big Key Chest': (0xe99e, False, 'in Skull Woods'),
'Skull Woods - Boss': (0x180155, 0x186343, False, 'with Mothula'), 'Skull Woods - Bridge Room': (0xe9fe, False, 'near Mothula'),
'Ice Palace - Compass Chest': (0xe9d4, 0x1861a8, False, 'in Ice Palace'), 'Skull Woods - Boss': (0x180155, False, 'with Mothula'),
'Ice Palace - Freezor Chest': (0xe995, 0x186169, False, 'in Ice Palace'), 'Ice Palace - Compass Chest': (0xe9d4, False, 'in Ice Palace'),
'Ice Palace - Big Chest': (0xe9aa, 0x18617e, False, 'in Ice Palace'), 'Ice Palace - Freezor Chest': (0xe995, False, 'in Ice Palace'),
'Ice Palace - Iced T Room': (0xe9e3, 0x1861b7, False, 'in Ice Palace'), 'Ice Palace - Big Chest': (0xe9aa, False, 'in Ice Palace'),
'Ice Palace - Spike Room': (0xe9e0, 0x1861b4, False, 'in Ice Palace'), 'Ice Palace - Iced T Room': (0xe9e3, False, 'in Ice Palace'),
'Ice Palace - Big Key Chest': (0xe9a4, 0x186178, False, 'in Ice Palace'), 'Ice Palace - Spike Room': (0xe9e0, False, 'in Ice Palace'),
'Ice Palace - Map Chest': (0xe9dd, 0x1861b1, False, 'in Ice Palace'), 'Ice Palace - Big Key Chest': (0xe9a4, False, 'in Ice Palace'),
'Ice Palace - Boss': (0x180157, 0x186345, False, 'with Kholdstare'), 'Ice Palace - Map Chest': (0xe9dd, False, 'in Ice Palace'),
'Misery Mire - Big Chest': (0xea67, 0x18623b, False, 'in Misery Mire'), 'Ice Palace - Boss': (0x180157, False, 'with Kholdstare'),
'Misery Mire - Map Chest': (0xea6a, 0x18623e, False, 'in Misery Mire'), 'Misery Mire - Big Chest': (0xea67, False, 'in Misery Mire'),
'Misery Mire - Main Lobby': (0xea5e, 0x186232, False, 'in Misery Mire'), 'Misery Mire - Map Chest': (0xea6a, False, 'in Misery Mire'),
'Misery Mire - Bridge Chest': (0xea61, 0x186235, False, 'in Misery Mire'), 'Misery Mire - Main Lobby': (0xea5e, False, 'in Misery Mire'),
'Misery Mire - Spike Chest': (0xe9da, 0x1861ae, False, 'in Misery Mire'), 'Misery Mire - Bridge Chest': (0xea61, False, 'in Misery Mire'),
'Misery Mire - Compass Chest': (0xea64, 0x186238, False, 'in Misery Mire'), 'Misery Mire - Spike Chest': (0xe9da, False, 'in Misery Mire'),
'Misery Mire - Big Key Chest': (0xea6d, 0x186241, False, 'in Misery Mire'), 'Misery Mire - Compass Chest': (0xea64, False, 'in Misery Mire'),
'Misery Mire - Boss': (0x180158, 0x186346, False, 'with Vitreous'), 'Misery Mire - Big Key Chest': (0xea6d, False, 'in Misery Mire'),
'Turtle Rock - Compass Chest': (0xea22, 0x1861f6, False, 'in Turtle Rock'), 'Misery Mire - Boss': (0x180158, False, 'with Vitreous'),
'Turtle Rock - Roller Room - Left': (0xea1c, 0x1861f0, False, 'in Turtle Rock'), 'Turtle Rock - Compass Chest': (0xea22, False, 'in Turtle Rock'),
'Turtle Rock - Roller Room - Right': (0xea1f, 0x1861f3, False, 'in Turtle Rock'), 'Turtle Rock - Roller Room - Left': (0xea1c, False, 'in Turtle Rock'),
'Turtle Rock - Chain Chomps': (0xea16, 0x1861ea, False, 'in Turtle Rock'), 'Turtle Rock - Roller Room - Right': (0xea1f, False, 'in Turtle Rock'),
'Turtle Rock - Big Key Chest': (0xea25, 0x1861f9, False, 'in Turtle Rock'), 'Turtle Rock - Chain Chomps': (0xea16, False, 'in Turtle Rock'),
'Turtle Rock - Big Chest': (0xea19, 0x1861ed, False, 'in Turtle Rock'), 'Turtle Rock - Big Key Chest': (0xea25, False, 'in Turtle Rock'),
'Turtle Rock - Crystaroller Room': (0xea34, 0x186208, False, 'in Turtle Rock'), 'Turtle Rock - Big Chest': (0xea19, False, 'in Turtle Rock'),
'Turtle Rock - Eye Bridge - Bottom Left': (0xea31, 0x186205, False, 'in Turtle Rock'), 'Turtle Rock - Crystaroller Room': (0xea34, False, 'in Turtle Rock'),
'Turtle Rock - Eye Bridge - Bottom Right': (0xea2e, 0x186202, False, 'in Turtle Rock'), 'Turtle Rock - Eye Bridge - Bottom Left': (0xea31, False, 'in Turtle Rock'),
'Turtle Rock - Eye Bridge - Top Left': (0xea2b, 0x1861ff, False, 'in Turtle Rock'), 'Turtle Rock - Eye Bridge - Bottom Right': (0xea2e, False, 'in Turtle Rock'),
'Turtle Rock - Eye Bridge - Top Right': (0xea28, 0x1861fc, False, 'in Turtle Rock'), 'Turtle Rock - Eye Bridge - Top Left': (0xea2b, False, 'in Turtle Rock'),
'Turtle Rock - Boss': (0x180159, 0x186347, False, 'with Trinexx'), 'Turtle Rock - Eye Bridge - Top Right': (0xea28, False, 'in Turtle Rock'),
'Palace of Darkness - Shooter Room': (0xea5b, 0x18622f, False, 'in Palace of Darkness'), 'Turtle Rock - Boss': (0x180159, False, 'with Trinexx'),
'Palace of Darkness - The Arena - Bridge': (0xea3d, 0x186211, False, 'in Palace of Darkness'), 'Palace of Darkness - Shooter Room': (0xea5b, False, 'in Palace of Darkness'),
'Palace of Darkness - Stalfos Basement': (0xea49, 0x18621d, False, 'in Palace of Darkness'), 'Palace of Darkness - The Arena - Bridge': (0xea3d, False, 'in Palace of Darkness'),
'Palace of Darkness - Big Key Chest': (0xea37, 0x18620b, False, 'in Palace of Darkness'), 'Palace of Darkness - Stalfos Basement': (0xea49, False, 'in Palace of Darkness'),
'Palace of Darkness - The Arena - Ledge': (0xea3a, 0x18620e, False, 'in Palace of Darkness'), 'Palace of Darkness - Big Key Chest': (0xea37, False, 'in Palace of Darkness'),
'Palace of Darkness - Map Chest': (0xea52, 0x186226, False, 'in Palace of Darkness'), 'Palace of Darkness - The Arena - Ledge': (0xea3a, False, 'in Palace of Darkness'),
'Palace of Darkness - Compass Chest': (0xea43, 0x186217, False, 'in Palace of Darkness'), 'Palace of Darkness - Map Chest': (0xea52, False, 'in Palace of Darkness'),
'Palace of Darkness - Dark Basement - Left': (0xea4c, 0x186220, False, 'in Palace of Darkness'), 'Palace of Darkness - Compass Chest': (0xea43, False, 'in Palace of Darkness'),
'Palace of Darkness - Dark Basement - Right': (0xea4f, 0x186223, False, 'in Palace of Darkness'), 'Palace of Darkness - Dark Basement - Left': (0xea4c, False, 'in Palace of Darkness'),
'Palace of Darkness - Dark Maze - Top': (0xea55, 0x186229, False, 'in Palace of Darkness'), 'Palace of Darkness - Dark Basement - Right': (0xea4f, False, 'in Palace of Darkness'),
'Palace of Darkness - Dark Maze - Bottom': (0xea58, 0x18622c, False, 'in Palace of Darkness'), 'Palace of Darkness - Dark Maze - Top': (0xea55, False, 'in Palace of Darkness'),
'Palace of Darkness - Big Chest': (0xea40, 0x186214, False, 'in Palace of Darkness'), 'Palace of Darkness - Dark Maze - Bottom': (0xea58, False, 'in Palace of Darkness'),
'Palace of Darkness - Harmless Hellway': (0xea46, 0x18621a, False, 'in Palace of Darkness'), 'Palace of Darkness - Big Chest': (0xea40, False, 'in Palace of Darkness'),
'Palace of Darkness - Boss': (0x180153, 0x186341, False, 'with Helmasaur King'), 'Palace of Darkness - Harmless Hellway': (0xea46, False, 'in Palace of Darkness'),
"Ganons Tower - Bob's Torch": (0x180161, 0x186363, False, "in Ganon's Tower"), 'Palace of Darkness - Boss': (0x180153, False, 'with Helmasaur King'),
'Ganons Tower - Hope Room - Left': (0xead9, 0x1862ad, False, "in Ganon's Tower"), "Ganons Tower - Bob's Torch": (0x180161, False, "in Ganon's Tower"),
'Ganons Tower - Hope Room - Right': (0xeadc, 0x1862b0, False, "in Ganon's Tower"), 'Ganons Tower - Hope Room - Left': (0xead9, False, "in Ganon's Tower"),
'Ganons Tower - Tile Room': (0xeae2, 0x1862b6, False, "in Ganon's Tower"), 'Ganons Tower - Hope Room - Right': (0xeadc, False, "in Ganon's Tower"),
'Ganons Tower - Compass Room - Top Left': (0xeae5, 0x1862b9, False, "in Ganon's Tower"), 'Ganons Tower - Tile Room': (0xeae2, False, "in Ganon's Tower"),
'Ganons Tower - Compass Room - Top Right': (0xeae8, 0x1862bc, False, "in Ganon's Tower"), 'Ganons Tower - Compass Room - Top Left': (0xeae5, False, "in Ganon's Tower"),
'Ganons Tower - Compass Room - Bottom Left': (0xeaeb, 0x1862bf, False, "in Ganon's Tower"), 'Ganons Tower - Compass Room - Top Right': (0xeae8, False, "in Ganon's Tower"),
'Ganons Tower - Compass Room - Bottom Right': (0xeaee, 0x1862c2, False, "in Ganon's Tower"), 'Ganons Tower - Compass Room - Bottom Left': (0xeaeb, False, "in Ganon's Tower"),
'Ganons Tower - DMs Room - Top Left': (0xeab8, 0x18628c, False, "in Ganon's Tower"), 'Ganons Tower - Compass Room - Bottom Right': (0xeaee, False, "in Ganon's Tower"),
'Ganons Tower - DMs Room - Top Right': (0xeabb, 0x18628f, False, "in Ganon's Tower"), 'Ganons Tower - DMs Room - Top Left': (0xeab8, False, "in Ganon's Tower"),
'Ganons Tower - DMs Room - Bottom Left': (0xeabe, 0x186292, False, "in Ganon's Tower"), 'Ganons Tower - DMs Room - Top Right': (0xeabb, False, "in Ganon's Tower"),
'Ganons Tower - DMs Room - Bottom Right': (0xeac1, 0x186295, False, "in Ganon's Tower"), 'Ganons Tower - DMs Room - Bottom Left': (0xeabe, False, "in Ganon's Tower"),
'Ganons Tower - Map Chest': (0xead3, 0x1862a7, False, "in Ganon's Tower"), 'Ganons Tower - DMs Room - Bottom Right': (0xeac1, False, "in Ganon's Tower"),
'Ganons Tower - Firesnake Room': (0xead0, 0x1862a4, False, "in Ganon's Tower"), 'Ganons Tower - Map Chest': (0xead3, False, "in Ganon's Tower"),
'Ganons Tower - Randomizer Room - Top Left': (0xeac4, 0x186298, False, "in Ganon's Tower"), 'Ganons Tower - Firesnake Room': (0xead0, False, "in Ganon's Tower"),
'Ganons Tower - Randomizer Room - Top Right': (0xeac7, 0x18629b, False, "in Ganon's Tower"), 'Ganons Tower - Randomizer Room - Top Left': (0xeac4, False, "in Ganon's Tower"),
'Ganons Tower - Randomizer Room - Bottom Left': (0xeaca, 0x18629e, False, "in Ganon's Tower"), 'Ganons Tower - Randomizer Room - Top Right': (0xeac7, False, "in Ganon's Tower"),
'Ganons Tower - Randomizer Room - Bottom Right': (0xeacd, 0x1862a1, False, "in Ganon's Tower"), 'Ganons Tower - Randomizer Room - Bottom Left': (0xeaca, False, "in Ganon's Tower"),
"Ganons Tower - Bob's Chest": (0xeadf, 0x1862b3, False, "in Ganon's Tower"), 'Ganons Tower - Randomizer Room - Bottom Right': (0xeacd, False, "in Ganon's Tower"),
'Ganons Tower - Big Chest': (0xead6, 0x1862aa, False, "in Ganon's Tower"), "Ganons Tower - Bob's Chest": (0xeadf, False, "in Ganon's Tower"),
'Ganons Tower - Big Key Room - Left': (0xeaf4, 0x1862c8, False, "in Ganon's Tower"), 'Ganons Tower - Big Chest': (0xead6, False, "in Ganon's Tower"),
'Ganons Tower - Big Key Room - Right': (0xeaf7, 0x1862cb, False, "in Ganon's Tower"), 'Ganons Tower - Big Key Room - Left': (0xeaf4, False, "in Ganon's Tower"),
'Ganons Tower - Big Key Chest': (0xeaf1, 0x1862c5, False, "in Ganon's Tower"), 'Ganons Tower - Big Key Room - Right': (0xeaf7, False, "in Ganon's Tower"),
'Ganons Tower - Mini Helmasaur Room - Left': (0xeafd, 0x1862d1, False, "atop Ganon's Tower"), 'Ganons Tower - Big Key Chest': (0xeaf1, False, "in Ganon's Tower"),
'Ganons Tower - Mini Helmasaur Room - Right': (0xeb00, 0x1862d4, False, "atop Ganon's Tower"), 'Ganons Tower - Mini Helmasaur Room - Left': (0xeafd, False, "atop Ganon's Tower"),
'Ganons Tower - Pre-Moldorm Chest': (0xeb03, 0x1862d7, False, "atop Ganon's Tower"), 'Ganons Tower - Mini Helmasaur Room - Right': (0xeb00, False, "atop Ganon's Tower"),
'Ganons Tower - Validation Chest': (0xeb06, 0x1862da, False, "atop Ganon's Tower"), 'Ganons Tower - Pre-Moldorm Chest': (0xeb03, False, "atop Ganon's Tower"),
'Ganon': (None, None, False, 'from me'), 'Ganons Tower - Validation Chest': (0xeb06, False, "atop Ganon's Tower"),
'Agahnim 1': (None, None, False, 'from Ganon\'s wizardry form'), 'Ganon': (None, False, 'from me'),
'Agahnim 2': (None, None, False, 'from Ganon\'s wizardry form'), 'Agahnim 1': (None, False, 'from Ganon\'s wizardry form'),
'Floodgate': (None, None, False, None), 'Agahnim 2': (None, False, 'from Ganon\'s wizardry form'),
'Frog': (None, None, False, None), 'Floodgate': (None, False, None),
'Missing Smith': (None, None, False, None), 'Frog': (None, False, None),
'Dark Blacksmith Ruins': (None, None, False, None), 'Missing Smith': (None, False, None),
'Trench 1 Switch': (None, None, False, None), 'Dark Blacksmith Ruins': (None, False, None),
'Trench 2 Switch': (None, None, False, None), 'Trench 1 Switch': (None, False, None),
'Swamp Drain': (None, None, False, None), 'Trench 2 Switch': (None, False, None),
'Attic Cracked Floor': (None, None, False, None), 'Swamp Drain': (None, False, None),
'Suspicious Maiden': (None, None, False, None), 'Attic Cracked Floor': (None, False, None),
'Revealing Light': (None, None, False, None), 'Suspicious Maiden': (None, False, None),
'Ice Block Drop': (None, None, False, None), 'Revealing Light': (None, False, None),
'Eastern Palace - Prize': ([0x1209D, 0x53EF8, 0x53EF9, 0x180052, 0x18007C, 0xC6FE], None, True, 'Eastern Palace'), 'Ice Block Drop': (None, False, None),
'Desert Palace - Prize': ([0x1209E, 0x53F1C, 0x53F1D, 0x180053, 0x180078, 0xC6FF], None, True, 'Desert Palace'), 'Zelda Pickup': (None, False, None),
'Tower of Hera - Prize': ([0x120A5, 0x53F0A, 0x53F0B, 0x18005A, 0x18007A, 0xC706], None, True, 'Tower of Hera'), 'Zelda Drop Off': (None, False, None),
'Palace of Darkness - Prize': ([0x120A1, 0x53F00, 0x53F01, 0x180056, 0x18007D, 0xC702], None, True, 'Palace of Darkness'), 'Eastern Palace - Prize': ([0x1209D, 0x53EF8, 0x53EF9, 0x180052, 0x18007C, 0xC6FE], True, 'Eastern Palace'),
'Swamp Palace - Prize': ([0x120A0, 0x53F6C, 0x53F6D, 0x180055, 0x180071, 0xC701], None, True, 'Swamp Palace'), 'Desert Palace - Prize': ([0x1209E, 0x53F1C, 0x53F1D, 0x180053, 0x180078, 0xC6FF], True, 'Desert Palace'),
'Thieves\' Town - Prize': ([0x120A6, 0x53F36, 0x53F37, 0x18005B, 0x180077, 0xC707], None, True, 'Thieves\' Town'), 'Tower of Hera - Prize': ([0x120A5, 0x53F0A, 0x53F0B, 0x18005A, 0x18007A, 0xC706], True, 'Tower of Hera'),
'Skull Woods - Prize': ([0x120A3, 0x53F12, 0x53F13, 0x180058, 0x18007B, 0xC704], None, True, 'Skull Woods'), 'Palace of Darkness - Prize': ([0x120A1, 0x53F00, 0x53F01, 0x180056, 0x18007D, 0xC702], True, 'Palace of Darkness'),
'Ice Palace - Prize': ([0x120A4, 0x53F5A, 0x53F5B, 0x180059, 0x180073, 0xC705], None, True, 'Ice Palace'), 'Swamp Palace - Prize': ([0x120A0, 0x53F6C, 0x53F6D, 0x180055, 0x180071, 0xC701], True, 'Swamp Palace'),
'Misery Mire - Prize': ([0x120A2, 0x53F48, 0x53F49, 0x180057, 0x180075, 0xC703], None, True, 'Misery Mire'), 'Thieves\' Town - Prize': ([0x120A6, 0x53F36, 0x53F37, 0x18005B, 0x180077, 0xC707], True, 'Thieves\' Town'),
'Turtle Rock - Prize': ([0x120A7, 0x53F24, 0x53F25, 0x18005C, 0x180079, 0xC708], None, True, 'Turtle Rock')} 'Skull Woods - Prize': ([0x120A3, 0x53F12, 0x53F13, 0x180058, 0x18007B, 0xC704], True, 'Skull Woods'),
'Ice Palace - Prize': ([0x120A4, 0x53F5A, 0x53F5B, 0x180059, 0x180073, 0xC705], True, 'Ice Palace'),
'Misery Mire - Prize': ([0x120A2, 0x53F48, 0x53F49, 0x180057, 0x180075, 0xC703], True, 'Misery Mire'),
'Turtle Rock - Prize': ([0x120A7, 0x53F24, 0x53F25, 0x18005C, 0x180079, 0xC708], True, 'Turtle Rock')}

2
Rom.py
View File

@@ -21,7 +21,7 @@ from EntranceShuffle import door_addresses, exit_ids
JAP10HASH = '03a63945398191337e896e5771f77173' JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = 'a5ae693acf449264533429d4dbd217e4' #RANDOMIZERBASEHASH = '4e291b6f6227de32db2735423889a780'
class JsonRom(object): class JsonRom(object):

View File

@@ -369,9 +369,10 @@ def global_rules(world, player):
def default_rules(world, player): def default_rules(world, player):
if world.mode[player] == 'standard': if world.mode[player] == 'standard':
# Links house requires reaching Sanc so skipping that chest isn't a softlock.
world.get_region('Hyrule Castle Secret Entrance', player).can_reach_private = lambda state: True world.get_region('Hyrule Castle Secret Entrance', player).can_reach_private = lambda state: True
old_rule = world.get_region('Links House', player).can_reach_private old_rule = world.get_region('Links House', player).can_reach_private
world.get_region('Links House', player).can_reach_private = lambda state: state.can_reach('Sanctuary', 'Region', player) or old_rule(state) world.get_region('Links House', player).can_reach_private = lambda state: state.has('Zelda Delivered', player) or old_rule(state)
else: else:
# these are default save&quit points and always accessible # these are default save&quit points and always accessible
world.get_region('Links House', player).can_reach_private = lambda state: True world.get_region('Links House', player).can_reach_private = lambda state: True
@@ -644,21 +645,21 @@ def inverted_rules(world, player):
def no_glitches_rules(world, player): def no_glitches_rules(world, player):
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
set_rule(world.get_entrance('Zoras River', player), lambda state: state.has('Flippers', player) or state.can_lift_rocks(player)) add_rule(world.get_entrance('Zoras River', player), lambda state: state.has('Flippers', player) or state.can_lift_rocks(player))
set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has('Flippers', player)) # can be fake flippered to add_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has('Flippers', player)) # can be fake flippered to
set_rule(world.get_entrance('Hobo Bridge', player), lambda state: state.has('Flippers', player)) add_rule(world.get_entrance('Hobo Bridge', player), lambda state: state.has('Flippers', player))
set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) add_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player))
set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) add_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player)))
set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) add_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player))
else: else:
set_rule(world.get_entrance('Zoras River', player), lambda state: state.has_Pearl(player) and (state.has('Flippers', player) or state.can_lift_rocks(player))) add_rule(world.get_entrance('Zoras River', player), lambda state: state.has_Pearl(player) and (state.has('Flippers', player) or state.can_lift_rocks(player)))
set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # can be fake flippered to add_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # can be fake flippered to
set_rule(world.get_entrance('Lake Hylia Island', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) add_rule(world.get_entrance('Lake Hylia Island', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player))
set_rule(world.get_entrance('Hobo Bridge', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) add_rule(world.get_entrance('Hobo Bridge', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player))
set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has('Flippers', player)) add_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has('Flippers', player))
set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) add_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player)))
set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has('Flippers', player)) add_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has('Flippers', player))
set_rule(world.get_entrance('East Dark World Pier', player), lambda state: state.has('Flippers', player)) add_rule(world.get_entrance('East Dark World Pier', player), lambda state: state.has('Flippers', player))
# todo: move some dungeon rules to no glictes logic - see these for examples # todo: move some dungeon rules to no glictes logic - see these for examples
# add_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player)) # add_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
@@ -800,23 +801,28 @@ def swordless_rules(world, player):
def standard_rules(world, player): def standard_rules(world, player):
# add_rule(world.get_entrance('Sewers Door', player), lambda state: state.can_kill_most_things(player)) # these are because of rails
set_rule(world.get_entrance('Hyrule Castle Exit (East)', player), lambda state: state.has('Zelda Delivered', player))
set_rule(world.get_entrance('Hyrule Castle Exit (East)', player), lambda state: state.can_reach('Sanctuary', 'Region', player)) set_rule(world.get_entrance('Hyrule Castle Exit (West)', player), lambda state: state.has('Zelda Delivered', player))
set_rule(world.get_entrance('Hyrule Castle Exit (West)', player), lambda state: state.can_reach('Sanctuary', 'Region', player))
# too restrictive for crossed?
def uncle_item_rule(item): def uncle_item_rule(item):
copy_state = CollectionState(world) copy_state = CollectionState(world)
copy_state.collect(item) copy_state.collect(item)
copy_state.sweep_for_events() copy_state.sweep_for_events()
return copy_state.can_reach('Sanctuary', 'Region', player) return copy_state.has('Zelda Delivered', player)
add_item_rule(world.get_location('Link\'s Uncle', player), uncle_item_rule) add_item_rule(world.get_location('Link\'s Uncle', player), uncle_item_rule)
# easiest way to enforce key placement not relevant for open # ensures the required weapon for escape lands on uncle (unless player has it pre-equipped)
set_rule(world.get_location('Sewers - Dark Cross', player), lambda state: state.can_kill_most_things(player)) for location in ['Link\'s House', 'Sanctuary', 'Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle',
'Sewers - Secret Room - Right']:
add_rule(world.get_location(location, player), lambda state: state.can_kill_most_things(player))
add_rule(world.get_location('Secret Passage', player), lambda state: state.can_kill_most_things(player))
# todo: in crossed these chest/key drops are not necessarily present
add_rule(world.get_location('Hyrule Castle - Map Chest', player), lambda state: state.can_kill_most_things(player))
set_rule(world.get_location('Sewers - Dark Cross', player), lambda state: state.can_kill_most_things(player))
set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), lambda state: state.can_kill_most_things(player)) set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), lambda state: state.can_kill_most_things(player))
set_rule(world.get_location('Hyrule Castle - Zelda\'s Chest', player), lambda state: state.can_kill_most_things(player)) set_rule(world.get_location('Hyrule Castle - Zelda\'s Chest', player), lambda state: state.can_kill_most_things(player))
@@ -825,6 +831,31 @@ def standard_rules(world, player):
set_rule(world.get_location('Hyrule Castle - Key Rat Key Drop', player), lambda state: state.can_kill_most_things(player)) set_rule(world.get_location('Hyrule Castle - Key Rat Key Drop', player), lambda state: state.can_kill_most_things(player))
set_rule(world.get_entrance('Hyrule Dungeon Armory S', player), lambda state: state.can_kill_most_things(player)) set_rule(world.get_entrance('Hyrule Dungeon Armory S', player), lambda state: state.can_kill_most_things(player))
set_rule(world.get_location('Hyrule Castle - Big Key Drop', player), lambda state: state.can_kill_most_things(player))
set_rule(world.get_location('Zelda Pickup', player), lambda state: state.has('Big Key (Escape)', player))
set_rule(world.get_entrance('Hyrule Castle Throne Room N', player), lambda state: state.has('Zelda Herself', player))
set_rule(world.get_location('Zelda Drop Off', player), lambda state: state.has('Zelda Herself', player))
for location in ['Mushroom', 'Bottle Merchant', 'Flute Spot', 'Sunken Treasure', 'Purple Chest']:
add_rule(world.get_location(location, player), lambda state: state.has('Zelda Delivered', player))
# Bonk Fairy (Light) is a notable omission in ER shuffles/Retro
for entrance in ['Blinds Hideout', 'Zoras River', 'Kings Grave Outer Rocks', 'Dam', 'Tavern North', 'Chicken House',
'Aginahs Cave', 'Sahasrahlas Hut', 'Kakariko Well Drop', 'Kakariko Well Cave', 'Blacksmiths Hut',
'Bat Cave Drop Ledge', 'Bat Cave Cave', 'Sick Kids House', 'Hobo Bridge',
'Lost Woods Hideout Drop', 'Lost Woods Hideout Stump', 'Lumberjack Tree Tree',
'Lumberjack Tree Cave', 'Mini Moldorm Cave', 'Ice Rod Cave', 'Lake Hylia Central Island Pier',
'Bonk Rock Cave', 'Library', 'Potion Shop', 'Two Brothers House (East)', 'Desert Palace Stairs',
'Eastern Palace', 'Master Sword Meadow', 'Sanctuary', 'Sanctuary Grave',
'Death Mountain Entrance Rock', 'Flute Spot 1', 'Dark Desert Teleporter', 'East Hyrule Teleporter',
'South Hyrule Teleporter', 'Kakariko Teleporter', 'Elder House (East)', 'Elder House (West)',
'North Fairy Cave', 'North Fairy Cave Drop', 'Lost Woods Gamble', 'Snitch Lady (East)',
'Snitch Lady (West)', 'Tavern (Front)', 'Bush Covered House', 'Light World Bomb Hut',
'Kakariko Shop', 'Long Fairy Cave', 'Good Bee Cave', '20 Rupee Cave', 'Cave Shop (Lake Hylia)',
'Waterfall of Wishing', 'Hyrule Castle Main Gate', '50 Rupee Cave',
'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy',
'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid']:
add_rule(world.get_entrance(entrance, player), lambda state: state.has('Zelda Delivered', player))
def set_trock_key_rules(world, player): def set_trock_key_rules(world, player):

View File

@@ -16,6 +16,8 @@ incsrc normal.asm
incsrc spiral.asm incsrc spiral.asm
incsrc gfx.asm incsrc gfx.asm
incsrc keydoors.asm incsrc keydoors.asm
incsrc overrides.asm
warnpc $279000
; Data Section ; Data Section
org $279000 org $279000

View File

@@ -59,6 +59,9 @@ org $1bece4
Palette_SpriteAux1: Palette_SpriteAux1:
org $0DFA53
jsl.l LampCheckOverride
; These two, if enabled together, have implications for vanilla BK doors in IP/Hera/Mire ; 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 ; IPBJ is common enough to consider not doing this. Mire is not a concern for vanilla - maybe glitched modes
; Hera BK door back can be seen with Pot clipping - likely useful for no logic seeds ; Hera BK door back can be seen with Pot clipping - likely useful for no logic seeds

23
asm/overrides.asm Normal file
View File

@@ -0,0 +1,23 @@
;================================================================================
; Lamp Mantle & Light Cone Fix
;--------------------------------------------------------------------------------
; Output: 0 for darkness, 1 for lamp cone
;--------------------------------------------------------------------------------
LampCheckOverride:
LDA $7F50C4 : CMP.b #$01 : BNE + : RTL : +
CMP.b #$FF : BNE + : INC : RTL : +
LDA $7EF34A : BNE .done ; skip if we already have lantern
LDA $7EF3CA : BNE +
.lightWorld
LDA $040C : CMP.b #$02 : BNE ++ ; check if we're in HC
LDA LampConeSewers : BRA .done
++
LDA LampConeLightWorld : BRA .done
+
.darkWorld
LDA LampConeDarkWorld
.done
;BNE + : STZ $1D : + ; remember to turn cone off after a torch
RTL