Merge branch 'KrisDavie-hmg_logic' into DoorDevVolatile
This commit is contained in:
+49
-4
@@ -133,7 +133,7 @@ class World(object):
|
|||||||
set_player_attr('can_access_trock_front', None)
|
set_player_attr('can_access_trock_front', None)
|
||||||
set_player_attr('can_access_trock_big_chest', None)
|
set_player_attr('can_access_trock_big_chest', None)
|
||||||
set_player_attr('can_access_trock_middle', None)
|
set_player_attr('can_access_trock_middle', None)
|
||||||
set_player_attr('fix_fake_world', logic[player] not in ['owglitches', 'nologic']
|
set_player_attr('fix_fake_world', logic[player] not in ['owglitches', 'hybridglitches', 'nologic']
|
||||||
or shuffle[player] in ['lean', 'swapped', 'crossed', 'insanity'])
|
or shuffle[player] in ['lean', 'swapped', 'crossed', 'insanity'])
|
||||||
set_player_attr('mapshuffle', False)
|
set_player_attr('mapshuffle', False)
|
||||||
set_player_attr('compassshuffle', False)
|
set_player_attr('compassshuffle', False)
|
||||||
@@ -603,6 +603,42 @@ class CollectionState(object):
|
|||||||
self.placing_items = None
|
self.placing_items = None
|
||||||
# self.trace = None
|
# self.trace = None
|
||||||
|
|
||||||
|
def can_reach_from(self, spot, start, player=None):
|
||||||
|
old_state = self.copy()
|
||||||
|
# old_state.path = {old_state.world.get_region(start, player)}
|
||||||
|
old_state.stale[player] = False
|
||||||
|
old_state.reachable_regions[player] = dict()
|
||||||
|
old_state.blocked_connections[player] = dict()
|
||||||
|
rrp = old_state.reachable_regions[player]
|
||||||
|
bc = old_state.blocked_connections[player]
|
||||||
|
|
||||||
|
# init on first call - this can't be done on construction since the regions don't exist yet
|
||||||
|
start = self.world.get_region(start, player)
|
||||||
|
if start in self.reachable_regions[player]:
|
||||||
|
rrp[start] = self.reachable_regions[player][start]
|
||||||
|
for conn in start.exits:
|
||||||
|
bc[conn] = self.blocked_connections[player][conn]
|
||||||
|
else:
|
||||||
|
rrp[start] = CrystalBarrier.Orange
|
||||||
|
for conn in start.exits:
|
||||||
|
bc[conn] = CrystalBarrier.Orange
|
||||||
|
|
||||||
|
queue = deque(old_state.blocked_connections[player].items())
|
||||||
|
|
||||||
|
old_state.traverse_world(queue, rrp, bc, player)
|
||||||
|
if old_state.world.key_logic_algorithm[player] == 'default':
|
||||||
|
unresolved_events = [x for y in old_state.reachable_regions[player] for x in y.locations
|
||||||
|
if x.event and x.item and (x.item.smallkey or x.item.bigkey or x.item.advancement)
|
||||||
|
and x not in old_state.locations_checked and x.can_reach(old_state)]
|
||||||
|
unresolved_events = old_state._do_not_flood_the_keys(unresolved_events)
|
||||||
|
if len(unresolved_events) == 0:
|
||||||
|
old_state.check_key_doors_in_dungeons(rrp, player)
|
||||||
|
|
||||||
|
if self.world.get_region(spot, player) in rrp:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def update_reachable_regions(self, player):
|
def update_reachable_regions(self, player):
|
||||||
self.stale[player] = False
|
self.stale[player] = False
|
||||||
rrp = self.reachable_regions[player]
|
rrp = self.reachable_regions[player]
|
||||||
@@ -1020,7 +1056,7 @@ class CollectionState(object):
|
|||||||
# try to resolve a name
|
# try to resolve a name
|
||||||
if resolution_hint == 'Location':
|
if resolution_hint == 'Location':
|
||||||
spot = self.world.get_location(spot, player)
|
spot = self.world.get_location(spot, player)
|
||||||
elif resolution_hint in ['Entrance', 'OWEdge', 'OWTerrain', 'Ledge', 'Portal', 'Whirlpool', 'Mirror', 'Flute']:
|
elif resolution_hint in ['Entrance', 'OWEdge', 'OWTerrain', 'OpenTerrain', 'Ledge', 'OWG', 'Portal', 'Whirlpool', 'Mirror', 'Flute']:
|
||||||
spot = self.world.get_entrance(spot, player)
|
spot = self.world.get_entrance(spot, player)
|
||||||
else:
|
else:
|
||||||
# default to Region
|
# default to Region
|
||||||
@@ -1169,6 +1205,12 @@ class CollectionState(object):
|
|||||||
def can_lift_rocks(self, player):
|
def can_lift_rocks(self, player):
|
||||||
return self.has('Power Glove', player) or self.has('Titans Mitts', player)
|
return self.has('Power Glove', player) or self.has('Titans Mitts', player)
|
||||||
|
|
||||||
|
def can_bomb_clip(self, region, player: int) -> bool:
|
||||||
|
return self.is_not_bunny(region, player) and self.has('Pegasus Boots', player) and self.can_use_bombs(player)
|
||||||
|
|
||||||
|
def can_dash_clip(self, region, player: int) -> bool:
|
||||||
|
return self.is_not_bunny(region, player) and self.has('Pegasus Boots', player)
|
||||||
|
|
||||||
def has_bottle(self, player):
|
def has_bottle(self, player):
|
||||||
return self.bottle_count(player) > 0
|
return self.bottle_count(player) > 0
|
||||||
|
|
||||||
@@ -1348,6 +1390,9 @@ class CollectionState(object):
|
|||||||
def can_superbunny_mirror_with_sword(self, player):
|
def can_superbunny_mirror_with_sword(self, player):
|
||||||
return self.has_Mirror(player) and self.has_sword(player)
|
return self.has_Mirror(player) and self.has_sword(player)
|
||||||
|
|
||||||
|
def can_bunny_pocket(self, player):
|
||||||
|
return self.has_Boots(player) and (self.has_Mirror(player) or self.has_bottle(player))
|
||||||
|
|
||||||
def collect(self, item, event=False, location=None):
|
def collect(self, item, event=False, location=None):
|
||||||
if location:
|
if location:
|
||||||
self.locations_checked.add(location)
|
self.locations_checked.add(location)
|
||||||
@@ -1631,7 +1676,7 @@ class Entrance(object):
|
|||||||
if region not in explored_regions:
|
if region not in explored_regions:
|
||||||
explored_regions[region] = path
|
explored_regions[region] = path
|
||||||
for exit in region.exits:
|
for exit in region.exits:
|
||||||
if exit.connected_region and (not ignore_ledges or exit.spot_type != 'Ledge') \
|
if exit.connected_region and (not ignore_ledges or exit.spot_type not in ['Ledge', 'OWG']) \
|
||||||
and exit.name not in ['Dig Game To Ledge Drop'] \
|
and exit.name not in ['Dig Game To Ledge Drop'] \
|
||||||
and exit.access_rule(state):
|
and exit.access_rule(state):
|
||||||
if exit.connected_region == destination:
|
if exit.connected_region == destination:
|
||||||
@@ -3422,7 +3467,7 @@ er_mode = {"vanilla": 0, "simple": 1, "restricted": 2, "full": 3, "crossed": 4,
|
|||||||
'lean': 9, "dungeonsfull": 7, "dungeonssimple": 6, "swapped": 10}
|
'lean': 9, "dungeonsfull": 7, "dungeonssimple": 6, "swapped": 10}
|
||||||
|
|
||||||
# byte 1: LLLW WSS? (logic, mode, sword)
|
# byte 1: LLLW WSS? (logic, mode, sword)
|
||||||
logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4}
|
logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4, "hybridglitches": 5}
|
||||||
world_mode = {"open": 0, "standard": 1, "inverted": 2}
|
world_mode = {"open": 0, "standard": 1, "inverted": 2}
|
||||||
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3}
|
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -814,7 +814,7 @@ def connect_mandatory_exits(world, entrances, caves, must_be_exits, player, must
|
|||||||
# Keeps track of entrances that cannot be used to access each exit / cave
|
# Keeps track of entrances that cannot be used to access each exit / cave
|
||||||
invalid_cave_connections = defaultdict(set)
|
invalid_cave_connections = defaultdict(set)
|
||||||
|
|
||||||
# if world.logic[player] in ['owglitches', 'nologic']:
|
# if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
|
||||||
# import OverworldGlitchRules
|
# import OverworldGlitchRules
|
||||||
# for entrance in OverworldGlitchRules.get_non_mandatory_exits(world, player):
|
# for entrance in OverworldGlitchRules.get_non_mandatory_exits(world, player):
|
||||||
# if entrance in must_be_exits:
|
# if entrance in must_be_exits:
|
||||||
|
|||||||
@@ -175,6 +175,9 @@ def valid_key_placement(item, location, key_pool, collection_state, world):
|
|||||||
if dungeon:
|
if dungeon:
|
||||||
if dungeon.name not in item.name and (dungeon.name != 'Hyrule Castle' or 'Escape' not in item.name):
|
if dungeon.name not in item.name and (dungeon.name != 'Hyrule Castle' or 'Escape' not in item.name):
|
||||||
return True
|
return True
|
||||||
|
# Small key and big key in Swamp and Hera are placed without logic
|
||||||
|
if world.logic[item.player] == 'hybridglitches' and dungeon.name in ['Tower of Hera', 'Swamp Palace'] and dungeon.name in item.name:
|
||||||
|
return True
|
||||||
key_logic = world.key_logic[item.player][dungeon.name]
|
key_logic = world.key_logic[item.player][dungeon.name]
|
||||||
unplaced_keys = len([x for x in key_pool if x.name == key_logic.small_key_name and x.player == item.player])
|
unplaced_keys = len([x for x in key_pool if x.name == key_logic.small_key_name and x.player == item.player])
|
||||||
prize_loc = None
|
prize_loc = None
|
||||||
@@ -420,7 +423,7 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
|||||||
# fill in gtower locations with trash first
|
# fill in gtower locations with trash first
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
if (not gftower_trash or not world.ganonstower_vanilla[player]
|
if (not gftower_trash or not world.ganonstower_vanilla[player]
|
||||||
or world.logic[player] in ['owglitches', 'nologic']):
|
or world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']):
|
||||||
continue
|
continue
|
||||||
gt_count, total_count = calc_trash_locations(world, player)
|
gt_count, total_count = calc_trash_locations(world, player)
|
||||||
scale_factor = .75 * (world.crystals_needed_for_gt[player] / 7)
|
scale_factor = .75 * (world.crystals_needed_for_gt[player] / 7)
|
||||||
|
|||||||
+9
-4
@@ -327,6 +327,11 @@ def generate_itempool(world, player):
|
|||||||
for _ in range(0, amt):
|
for _ in range(0, amt):
|
||||||
pool.append('Rupees (20)')
|
pool.append('Rupees (20)')
|
||||||
|
|
||||||
|
if world.logic[player] == 'hybridglitches' and world.pottery[player] not in ['none', 'cave']:
|
||||||
|
# In HMG force swamp smalls in pots to allow getting out of swamp palace
|
||||||
|
placed_items['Swamp Palace - Trench 1 Pot Key'] = 'Small Key (Swamp Palace)'
|
||||||
|
placed_items['Swamp Palace - Pot Row Pot Key'] = 'Small Key (Swamp Palace)'
|
||||||
|
|
||||||
start_inventory = list(world.precollected_items)
|
start_inventory = list(world.precollected_items)
|
||||||
for item in precollected_items:
|
for item in precollected_items:
|
||||||
world.push_precollected(ItemFactory(item, player))
|
world.push_precollected(ItemFactory(item, player))
|
||||||
@@ -1056,7 +1061,7 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt
|
|||||||
return random.choice([True, False]) if progressive == 'random' else progressive == 'on'
|
return random.choice([True, False]) if progressive == 'random' else progressive == 'on'
|
||||||
|
|
||||||
# provide boots to boots glitch dependent modes
|
# provide boots to boots glitch dependent modes
|
||||||
if logic in ['owglitches', 'nologic']:
|
if logic in ['owglitches', 'hybridglitches', 'nologic']:
|
||||||
precollected_items.append('Pegasus Boots')
|
precollected_items.append('Pegasus Boots')
|
||||||
pool.remove('Pegasus Boots')
|
pool.remove('Pegasus Boots')
|
||||||
pool.extend(['Rupees (20)'])
|
pool.extend(['Rupees (20)'])
|
||||||
@@ -1362,12 +1367,12 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer
|
|||||||
|
|
||||||
start_inventory = [x for x in world.precollected_items if x.player == player]
|
start_inventory = [x for x in world.precollected_items if x.player == player]
|
||||||
if not start_inventory:
|
if not start_inventory:
|
||||||
if world.logic[player] in ['owglitches', 'nologic']:
|
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic'] and all(x.name != 'Pegasus Boots' for x in start_inventory):
|
||||||
precollected_items.append('Pegasus Boots')
|
precollected_items.append('Pegasus Boots')
|
||||||
if 'Pegasus Boots' in pool:
|
if 'Pegasus Boots' in pool:
|
||||||
pool.remove('Pegasus Boots')
|
pool.remove('Pegasus Boots')
|
||||||
pool.append('Rupees (20)')
|
pool.append('Rupees (20)')
|
||||||
if world.swords[player] == 'assured':
|
if world.swords[player] == 'assured' and all(' Sword' not in x.name for x in start_inventory):
|
||||||
precollected_items.append('Progressive Sword')
|
precollected_items.append('Progressive Sword')
|
||||||
if 'Progressive Sword' in pool:
|
if 'Progressive Sword' in pool:
|
||||||
pool.remove('Progressive Sword')
|
pool.remove('Progressive Sword')
|
||||||
@@ -1503,7 +1508,7 @@ def make_customizer_pool(world, player):
|
|||||||
sphere_0 = world.customizer.get_start_inventory()
|
sphere_0 = world.customizer.get_start_inventory()
|
||||||
no_start_inventory = not sphere_0 or not sphere_0[player]
|
no_start_inventory = not sphere_0 or not sphere_0[player]
|
||||||
init_equip = [] if no_start_inventory else sphere_0[player]
|
init_equip = [] if no_start_inventory else sphere_0[player]
|
||||||
if (world.logic[player] in ['owglitches', 'nologic']
|
if (world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']
|
||||||
and (no_start_inventory or all(x != 'Pegasus Boots' for x in init_equip))):
|
and (no_start_inventory or all(x != 'Pegasus Boots' for x in init_equip))):
|
||||||
precollected_items.append('Pegasus Boots')
|
precollected_items.append('Pegasus Boots')
|
||||||
if 'Pegasus Boots' in pool:
|
if 'Pegasus Boots' in pool:
|
||||||
|
|||||||
@@ -2106,6 +2106,22 @@ def validate_key_placement(key_layout, world, player):
|
|||||||
if i.player == player and i.name == smallkey_name:
|
if i.player == player and i.name == smallkey_name:
|
||||||
keys_outside += 1
|
keys_outside += 1
|
||||||
|
|
||||||
|
if world.logic[player] == 'hybridglitches':
|
||||||
|
# Swamp keylogic
|
||||||
|
if smallkey_name.endswith('(Swamp Palace)'):
|
||||||
|
swamp_entrance = world.get_location('Swamp Palace - Entrance', player)
|
||||||
|
# Swamp small not vanilla
|
||||||
|
if swamp_entrance.item is None or (swamp_entrance.item.name != smallkey_name or swamp_entrance.item.player != player):
|
||||||
|
mire_keylayout = world.key_layout[player]['Misery Mire']
|
||||||
|
mire_smallkey_name = dungeon_keys[mire_keylayout.sector.name]
|
||||||
|
# Check if any mire keys are in swamp (excluding entrance), if none then add one to keys_outside
|
||||||
|
mire_keys_in_swamp = sum([1 if x.item.name == mire_smallkey_name else 0 for x in key_layout.item_locations if x.item is not None and x != swamp_entrance])
|
||||||
|
if mire_keys_in_swamp == 0:
|
||||||
|
keys_outside +=1
|
||||||
|
# Mire keylogic
|
||||||
|
if smallkey_name.endswith('(Tower of Hera)'):
|
||||||
|
# TODO: Make sure that mire medallion isn't in hera basement, or if it is, the small key is available downstairs
|
||||||
|
big_key_outside = True
|
||||||
for code, counter in key_layout.key_counters.items():
|
for code, counter in key_layout.key_counters.items():
|
||||||
if len(counter.child_doors) == 0:
|
if len(counter.child_doors) == 0:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ from Fill import distribute_items_restrictive, promote_dungeon_items, fill_dunge
|
|||||||
from Fill import dungeon_tracking
|
from Fill import dungeon_tracking
|
||||||
from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations, set_prize_drops
|
from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations, set_prize_drops
|
||||||
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops, fill_specific_items, create_farm_locations
|
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops, fill_specific_items, create_farm_locations
|
||||||
|
from UnderworldGlitchRules import create_hybridmajor_connections, create_hybridmajor_connectors
|
||||||
from Utils import output_path, parse_player_names
|
from Utils import output_path, parse_player_names
|
||||||
|
|
||||||
from source.item.District import init_districts
|
from source.item.District import init_districts
|
||||||
@@ -78,6 +79,11 @@ def main(args, seed=None, fish=None):
|
|||||||
seeded = True
|
seeded = True
|
||||||
world.customizer.adjust_args(args)
|
world.customizer.adjust_args(args)
|
||||||
world = init_world(args, fish)
|
world = init_world(args, fish)
|
||||||
|
|
||||||
|
for i in zip(args.logic.values(), args.door_shuffle.values()):
|
||||||
|
if i[0] == 'hybridglitches' and i[1] != 'vanilla':
|
||||||
|
raise RuntimeError(BabelFish().translate("cli","cli","hybridglitches.door.shuffle"))
|
||||||
|
|
||||||
if seed is None:
|
if seed is None:
|
||||||
random.seed(None)
|
random.seed(None)
|
||||||
world.seed = random.randint(0, 999999999)
|
world.seed = random.randint(0, 999999999)
|
||||||
@@ -166,6 +172,8 @@ def main(args, seed=None, fish=None):
|
|||||||
create_dungeons(world, player)
|
create_dungeons(world, player)
|
||||||
adjust_locations(world, player)
|
adjust_locations(world, player)
|
||||||
place_bosses(world, player)
|
place_bosses(world, player)
|
||||||
|
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||||
|
create_hybridmajor_connections(world, player)
|
||||||
|
|
||||||
if any(world.potshuffle.values()):
|
if any(world.potshuffle.values()):
|
||||||
logger.info(world.fish.translate("cli", "cli", "shuffling.pots"))
|
logger.info(world.fish.translate("cli", "cli", "shuffling.pots"))
|
||||||
@@ -191,6 +199,8 @@ def main(args, seed=None, fish=None):
|
|||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
link_entrances_new(world, player)
|
link_entrances_new(world, player)
|
||||||
|
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||||
|
create_hybridmajor_connectors(world, player)
|
||||||
|
|
||||||
logger.info(world.fish.translate("cli", "cli", "shuffling.prep"))
|
logger.info(world.fish.translate("cli", "cli", "shuffling.prep"))
|
||||||
|
|
||||||
@@ -594,8 +604,10 @@ def copy_world(world):
|
|||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
create_regions(ret, player)
|
create_regions(ret, player)
|
||||||
update_world_regions(ret, player)
|
update_world_regions(ret, player)
|
||||||
if world.logic[player] in ('owglitches', 'nologic'):
|
if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'):
|
||||||
create_owg_connections(ret, player)
|
create_owg_connections(ret, player)
|
||||||
|
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||||
|
create_hybridmajor_connections(ret, player)
|
||||||
create_dynamic_exits(ret, player)
|
create_dynamic_exits(ret, player)
|
||||||
create_dungeon_regions(ret, player)
|
create_dungeon_regions(ret, player)
|
||||||
create_owedges(ret, player)
|
create_owedges(ret, player)
|
||||||
@@ -703,6 +715,8 @@ def copy_world(world):
|
|||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
categorize_world_regions(ret, player)
|
categorize_world_regions(ret, player)
|
||||||
create_farm_locations(ret, player)
|
create_farm_locations(ret, player)
|
||||||
|
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||||
|
create_hybridmajor_connectors(ret, player)
|
||||||
set_rules(ret, player)
|
set_rules(ret, player)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
@@ -782,8 +796,10 @@ def copy_world_premature(world, player):
|
|||||||
|
|
||||||
create_regions(ret, player)
|
create_regions(ret, player)
|
||||||
update_world_regions(ret, player)
|
update_world_regions(ret, player)
|
||||||
if world.logic[player] in ('owglitches', 'nologic'):
|
if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'):
|
||||||
create_owg_connections(ret, player)
|
create_owg_connections(ret, player)
|
||||||
|
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||||
|
create_hybridmajor_connections(ret, player)
|
||||||
create_dynamic_exits(ret, player)
|
create_dynamic_exits(ret, player)
|
||||||
create_dungeon_regions(ret, player)
|
create_dungeon_regions(ret, player)
|
||||||
create_owedges(ret, player)
|
create_owedges(ret, player)
|
||||||
@@ -844,6 +860,9 @@ def copy_world_premature(world, player):
|
|||||||
for portal in world.dungeon_portals[player]:
|
for portal in world.dungeon_portals[player]:
|
||||||
connect_portal(portal, ret, player)
|
connect_portal(portal, ret, player)
|
||||||
|
|
||||||
|
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||||
|
create_hybridmajor_connectors(ret, player)
|
||||||
|
|
||||||
set_rules(ret, player)
|
set_rules(ret, player)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
+25
-24
@@ -1558,23 +1558,39 @@ OWExitTypes = {
|
|||||||
'Ice Lake Southeast Water Drop',
|
'Ice Lake Southeast Water Drop',
|
||||||
'Bomber Corner Waterfall Water Drop'
|
'Bomber Corner Waterfall Water Drop'
|
||||||
],
|
],
|
||||||
'OWTerrain': ['Lost Woods Bush (West)',
|
'OpenTerrain': ['Old Man Drop Off',
|
||||||
'Lost Woods Bush (East)',
|
|
||||||
'Old Man Drop Off',
|
|
||||||
'Spectacle Rock Approach',
|
'Spectacle Rock Approach',
|
||||||
'Spectacle Rock Leave',
|
'Spectacle Rock Leave',
|
||||||
'DM Hammer Bridge (West)',
|
|
||||||
'DM Hammer Bridge (East)',
|
|
||||||
'Floating Island Bridge (East)',
|
'Floating Island Bridge (East)',
|
||||||
'Fairy Ascension Rocks (Inner)',
|
|
||||||
'DM Broken Bridge (West)',
|
|
||||||
'DM Broken Bridge (East)',
|
|
||||||
'Spiral Mimic Bridge (West)',
|
'Spiral Mimic Bridge (West)',
|
||||||
'Spiral Mimic Bridge (East)',
|
'Spiral Mimic Bridge (East)',
|
||||||
'Spiral Ledge Approach',
|
'Spiral Ledge Approach',
|
||||||
'Mimic Ledge Approach',
|
'Mimic Ledge Approach',
|
||||||
'Fairy Ascension Rocks (Outer)',
|
|
||||||
'Floating Island Bridge (West)',
|
'Floating Island Bridge (West)',
|
||||||
|
'Graveyard Ladder (Bottom)',
|
||||||
|
'Graveyard Ladder (Top)',
|
||||||
|
'Hyrule Castle Main Gate (South)',
|
||||||
|
'Hyrule Castle Main Gate (North)',
|
||||||
|
'Stone Bridge (Northbound)',
|
||||||
|
'Stone Bridge (Southbound)',
|
||||||
|
'Checkerboard Ledge Approach',
|
||||||
|
'Checkerboard Ledge Leave',
|
||||||
|
'Cave 45 Approach',
|
||||||
|
'Cave 45 Leave',
|
||||||
|
'Middle Aged Man',
|
||||||
|
'Desert Pass Ladder (South)',
|
||||||
|
'Desert Pass Ladder (North)',
|
||||||
|
'GT Approach',
|
||||||
|
'GT Leave',
|
||||||
|
],
|
||||||
|
'OWTerrain': ['Lost Woods Bush (West)',
|
||||||
|
'Lost Woods Bush (East)',
|
||||||
|
'DM Hammer Bridge (West)',
|
||||||
|
'DM Hammer Bridge (East)',
|
||||||
|
'Fairy Ascension Rocks (Inner)',
|
||||||
|
'DM Broken Bridge (West)',
|
||||||
|
'DM Broken Bridge (East)',
|
||||||
|
'Fairy Ascension Rocks (Outer)',
|
||||||
'TR Pegs Ledge Entry',
|
'TR Pegs Ledge Entry',
|
||||||
'TR Pegs Ledge Leave',
|
'TR Pegs Ledge Leave',
|
||||||
'Mountain Pass Rock (Outer)',
|
'Mountain Pass Rock (Outer)',
|
||||||
@@ -1587,8 +1603,6 @@ OWExitTypes = {
|
|||||||
'Lost Woods Pass Rock (North)',
|
'Lost Woods Pass Rock (North)',
|
||||||
'Lost Woods Pass Rock (South)',
|
'Lost Woods Pass Rock (South)',
|
||||||
'Kings Grave Rocks (Outer)',
|
'Kings Grave Rocks (Outer)',
|
||||||
'Graveyard Ladder (Bottom)',
|
|
||||||
'Graveyard Ladder (Top)',
|
|
||||||
'Kings Grave Rocks (Inner)',
|
'Kings Grave Rocks (Inner)',
|
||||||
'River Bend Water Drop',
|
'River Bend Water Drop',
|
||||||
'River Bend West Pier',
|
'River Bend West Pier',
|
||||||
@@ -1602,12 +1616,10 @@ OWExitTypes = {
|
|||||||
'Kakariko Yard Bush (South)',
|
'Kakariko Yard Bush (South)',
|
||||||
'Kakariko Southwest Bush (South)',
|
'Kakariko Southwest Bush (South)',
|
||||||
'Kakariko Yard Bush (North)',
|
'Kakariko Yard Bush (North)',
|
||||||
'Hyrule Castle Main Gate (South)',
|
|
||||||
'Hyrule Castle East Rock (Inner)',
|
'Hyrule Castle East Rock (Inner)',
|
||||||
'Hyrule Castle Southwest Bush (North)',
|
'Hyrule Castle Southwest Bush (North)',
|
||||||
'Hyrule Castle Southwest Bush (South)',
|
'Hyrule Castle Southwest Bush (South)',
|
||||||
'Hyrule Castle Courtyard Bush (South)',
|
'Hyrule Castle Courtyard Bush (South)',
|
||||||
'Hyrule Castle Main Gate (North)',
|
|
||||||
'Hyrule Castle Courtyard Bush (North)',
|
'Hyrule Castle Courtyard Bush (North)',
|
||||||
'Hyrule Castle East Rock (Outer)',
|
'Hyrule Castle East Rock (Outer)',
|
||||||
'Wooden Bridge Bush (South)',
|
'Wooden Bridge Bush (South)',
|
||||||
@@ -1615,17 +1627,11 @@ OWExitTypes = {
|
|||||||
'Blacksmith Ledge Peg (West)',
|
'Blacksmith Ledge Peg (West)',
|
||||||
'Blacksmith Ledge Peg (East)',
|
'Blacksmith Ledge Peg (East)',
|
||||||
'Maze Race Game',
|
'Maze Race Game',
|
||||||
'Stone Bridge (Northbound)',
|
|
||||||
'Stone Bridge (Southbound)',
|
|
||||||
'Desert Statue Move',
|
'Desert Statue Move',
|
||||||
'Checkerboard Ledge Approach',
|
|
||||||
'Desert Ledge Rocks (Outer)',
|
'Desert Ledge Rocks (Outer)',
|
||||||
'Desert Ledge Rocks (Inner)',
|
'Desert Ledge Rocks (Inner)',
|
||||||
'Checkerboard Ledge Leave',
|
|
||||||
'Flute Boy Bush (South)',
|
'Flute Boy Bush (South)',
|
||||||
'Cave 45 Approach',
|
|
||||||
'Flute Boy Bush (North)',
|
'Flute Boy Bush (North)',
|
||||||
'Cave 45 Leave',
|
|
||||||
'C Whirlpool Rock (Bottom)',
|
'C Whirlpool Rock (Bottom)',
|
||||||
'C Whirlpool Rock (Top)',
|
'C Whirlpool Rock (Top)',
|
||||||
'C Whirlpool Pegs (Outer)',
|
'C Whirlpool Pegs (Outer)',
|
||||||
@@ -1644,19 +1650,14 @@ OWExitTypes = {
|
|||||||
'Lake Hylia Water D Approach',
|
'Lake Hylia Water D Approach',
|
||||||
'Lake Hylia Water D Leave',
|
'Lake Hylia Water D Leave',
|
||||||
'Ice Cave Pier',
|
'Ice Cave Pier',
|
||||||
'Desert Pass Ladder (South)',
|
|
||||||
'Desert Pass Rocks (North)',
|
'Desert Pass Rocks (North)',
|
||||||
'Desert Pass Rocks (South)',
|
'Desert Pass Rocks (South)',
|
||||||
'Desert Pass Ladder (North)',
|
|
||||||
'Middle Aged Man',
|
|
||||||
'Octoballoon Water Drop',
|
'Octoballoon Water Drop',
|
||||||
'Octoballoon Pier',
|
'Octoballoon Pier',
|
||||||
'Skull Woods Rock (East)',
|
'Skull Woods Rock (East)',
|
||||||
'Skull Woods Rock (West)',
|
'Skull Woods Rock (West)',
|
||||||
'Skull Woods Forgotten Bush (West)',
|
'Skull Woods Forgotten Bush (West)',
|
||||||
'Skull Woods Forgotten Bush (East)',
|
'Skull Woods Forgotten Bush (East)',
|
||||||
'GT Approach',
|
|
||||||
'GT Leave',
|
|
||||||
'East Dark Death Mountain Bushes',
|
'East Dark Death Mountain Bushes',
|
||||||
'Bumper Cave Rock (Outer)',
|
'Bumper Cave Rock (Outer)',
|
||||||
'Bumper Cave Rock (Inner)',
|
'Bumper Cave Rock (Inner)',
|
||||||
|
|||||||
+89
-90
@@ -5,102 +5,86 @@ Helper functions to deliver entrance/exit/region sets to OWG rules.
|
|||||||
from BaseClasses import Entrance
|
from BaseClasses import Entrance
|
||||||
from OWEdges import OWTileRegions
|
from OWEdges import OWTileRegions
|
||||||
|
|
||||||
|
# Cave regions that superbunny can get through - but only with a sword.
|
||||||
|
sword_required_superbunny_mirror_regions = ["Spiral Cave (Top)"]
|
||||||
|
|
||||||
def get_sword_required_superbunny_mirror_regions():
|
# Cave regions that superbunny can get through - but only with boots.
|
||||||
"""
|
boots_required_superbunny_mirror_regions = ["Two Brothers House"]
|
||||||
Cave regions that superbunny can get through - but only with a sword.
|
|
||||||
"""
|
|
||||||
yield 'Spiral Cave (Top)'
|
|
||||||
|
|
||||||
def get_boots_required_superbunny_mirror_regions():
|
# Cave locations that superbunny can access - but only with boots.
|
||||||
"""
|
boots_required_superbunny_mirror_locations = [
|
||||||
Cave regions that superbunny can get through - but only with boots.
|
"Sahasrahla's Hut - Left",
|
||||||
"""
|
"Sahasrahla's Hut - Middle",
|
||||||
yield 'Two Brothers House'
|
"Sahasrahla's Hut - Right",
|
||||||
|
]
|
||||||
|
|
||||||
def get_boots_required_superbunny_mirror_locations():
|
# Entrances that can't be superbunny-mirrored into.
|
||||||
"""
|
invalid_mirror_bunny_entrances = [
|
||||||
Cave locations that superbunny can access - but only with boots.
|
"Hype Cave",
|
||||||
"""
|
"Bonk Fairy (Dark)",
|
||||||
yield 'Sahasrahla\'s Hut - Left'
|
"Thieves Town",
|
||||||
yield 'Sahasrahla\'s Hut - Middle'
|
"Hammer Peg Cave",
|
||||||
yield 'Sahasrahla\'s Hut - Right'
|
"Brewery",
|
||||||
|
"Hookshot Cave",
|
||||||
|
"Dark Lake Hylia Ledge Fairy",
|
||||||
|
"Dark Lake Hylia Ledge Spike Cave",
|
||||||
|
"Palace of Darkness",
|
||||||
|
"Misery Mire",
|
||||||
|
"Turtle Rock",
|
||||||
|
"Bonk Rock Cave",
|
||||||
|
"Bonk Fairy (Light)",
|
||||||
|
"50 Rupee Cave",
|
||||||
|
"20 Rupee Cave",
|
||||||
|
"Checkerboard Cave",
|
||||||
|
"Light Hype Fairy",
|
||||||
|
"Waterfall of Wishing",
|
||||||
|
"Light World Bomb Hut",
|
||||||
|
"Mini Moldorm Cave",
|
||||||
|
"Ice Rod Cave",
|
||||||
|
"Sanctuary Grave",
|
||||||
|
"Kings Grave",
|
||||||
|
"Sanctuary Grave",
|
||||||
|
"Hyrule Castle Secret Entrance Drop",
|
||||||
|
"Skull Woods Second Section Hole",
|
||||||
|
"Skull Woods First Section Hole (North)",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Interior locations that can be accessed with superbunny state.
|
||||||
|
superbunny_accessible_locations = [
|
||||||
|
"Waterfall of Wishing - Left",
|
||||||
|
"Waterfall of Wishing - Right",
|
||||||
|
"King's Tomb",
|
||||||
|
"Floodgate",
|
||||||
|
"Floodgate Chest",
|
||||||
|
"Cave 45",
|
||||||
|
"Bonk Rock Cave",
|
||||||
|
"Brewery",
|
||||||
|
"C-Shaped House",
|
||||||
|
"Chest Game",
|
||||||
|
"Mire Shed - Left",
|
||||||
|
"Mire Shed - Right",
|
||||||
|
"Secret Passage",
|
||||||
|
"Ice Rod Cave",
|
||||||
|
"Pyramid Fairy - Left",
|
||||||
|
"Pyramid Fairy - Right",
|
||||||
|
"Superbunny Cave - Top",
|
||||||
|
"Superbunny Cave - Bottom",
|
||||||
|
"Blind's Hideout - Left",
|
||||||
|
"Blind's Hideout - Right",
|
||||||
|
"Blind's Hideout - Far Left",
|
||||||
|
"Blind's Hideout - Far Right",
|
||||||
|
"Kakariko Well - Left",
|
||||||
|
"Kakariko Well - Middle",
|
||||||
|
"Kakariko Well - Right",
|
||||||
|
"Kakariko Well - Bottom",
|
||||||
|
"Kakariko Tavern",
|
||||||
|
"Library",
|
||||||
|
"Spiral Cave",
|
||||||
|
] + boots_required_superbunny_mirror_locations
|
||||||
|
|
||||||
# TODO: Add pottery locations
|
# TODO: Add pottery locations
|
||||||
|
|
||||||
|
|
||||||
def get_invalid_mirror_bunny_entrances():
|
|
||||||
"""
|
|
||||||
Entrances that can't be superbunny-mirrored into.
|
|
||||||
"""
|
|
||||||
yield 'Skull Woods Final Section'
|
|
||||||
yield 'Hype Cave'
|
|
||||||
yield 'Bonk Fairy (Dark)'
|
|
||||||
yield 'Thieves Town'
|
|
||||||
yield 'Hammer Peg Cave'
|
|
||||||
yield 'Brewery'
|
|
||||||
yield 'Hookshot Cave'
|
|
||||||
yield 'Dark Lake Hylia Ledge Fairy'
|
|
||||||
yield 'Dark Lake Hylia Ledge Spike Cave'
|
|
||||||
yield 'Palace of Darkness'
|
|
||||||
yield 'Misery Mire'
|
|
||||||
yield 'Turtle Rock'
|
|
||||||
yield 'Bonk Rock Cave'
|
|
||||||
yield 'Bonk Fairy (Light)'
|
|
||||||
yield '50 Rupee Cave'
|
|
||||||
yield '20 Rupee Cave'
|
|
||||||
yield 'Checkerboard Cave'
|
|
||||||
yield 'Light Hype Fairy'
|
|
||||||
yield 'Waterfall of Wishing'
|
|
||||||
yield 'Light World Bomb Hut'
|
|
||||||
yield 'Mini Moldorm Cave'
|
|
||||||
yield 'Ice Rod Cave'
|
|
||||||
yield 'Sanctuary Grave'
|
|
||||||
yield 'Kings Grave'
|
|
||||||
yield 'Sanctuary Grave'
|
|
||||||
yield 'Hyrule Castle Secret Entrance Drop'
|
|
||||||
yield 'Skull Woods Second Section Hole'
|
|
||||||
yield 'Skull Woods First Section Hole (North)'
|
|
||||||
|
|
||||||
|
|
||||||
def get_superbunny_accessible_locations():
|
|
||||||
"""
|
|
||||||
Interior locations that can be accessed with superbunny state.
|
|
||||||
"""
|
|
||||||
|
|
||||||
yield 'Waterfall of Wishing - Left'
|
|
||||||
yield 'Waterfall of Wishing - Right'
|
|
||||||
yield 'King\'s Tomb'
|
|
||||||
yield 'Floodgate'
|
|
||||||
yield 'Floodgate Chest'
|
|
||||||
yield 'Cave 45'
|
|
||||||
yield 'Bonk Rock Cave'
|
|
||||||
yield 'Brewery'
|
|
||||||
yield 'C-Shaped House'
|
|
||||||
yield 'Chest Game'
|
|
||||||
yield 'Mire Shed - Left'
|
|
||||||
yield 'Mire Shed - Right'
|
|
||||||
yield 'Secret Passage'
|
|
||||||
yield 'Ice Rod Cave'
|
|
||||||
yield 'Pyramid Fairy - Left'
|
|
||||||
yield 'Pyramid Fairy - Right'
|
|
||||||
yield 'Superbunny Cave - Top'
|
|
||||||
yield 'Superbunny Cave - Bottom'
|
|
||||||
yield 'Blind\'s Hideout - Left'
|
|
||||||
yield 'Blind\'s Hideout - Right'
|
|
||||||
yield 'Blind\'s Hideout - Far Left'
|
|
||||||
yield 'Blind\'s Hideout - Far Right'
|
|
||||||
yield 'Kakariko Well - Left'
|
|
||||||
yield 'Kakariko Well - Middle'
|
|
||||||
yield 'Kakariko Well - Right'
|
|
||||||
yield 'Kakariko Well - Bottom'
|
|
||||||
yield 'Kakariko Tavern'
|
|
||||||
yield 'Library'
|
|
||||||
yield 'Spiral Cave'
|
|
||||||
for location in get_boots_required_superbunny_mirror_locations():
|
|
||||||
yield location
|
|
||||||
|
|
||||||
|
|
||||||
def get_non_mandatory_exits(world, player):
|
def get_non_mandatory_exits(world, player):
|
||||||
"""
|
"""
|
||||||
Entrances that can be reached with full equipment using overworld glitches and don't need to be an exit.
|
Entrances that can be reached with full equipment using overworld glitches and don't need to be an exit.
|
||||||
@@ -295,6 +279,7 @@ def overworld_glitches_rules(world, player):
|
|||||||
#set_owg_rules(player, world, get_glitched_speed_drops_dw(world, player), lambda state: state.can_get_glitched_speed_dw(player))
|
#set_owg_rules(player, world, get_glitched_speed_drops_dw(world, player), lambda state: state.can_get_glitched_speed_dw(player))
|
||||||
|
|
||||||
# Mirror clip spots.
|
# Mirror clip spots.
|
||||||
|
# TODO: Should this also require can_boots_clip
|
||||||
set_owg_rules(player, world, get_mirror_clip_spots(world, player), lambda state: state.has_Mirror(player))
|
set_owg_rules(player, world, get_mirror_clip_spots(world, player), lambda state: state.has_Mirror(player))
|
||||||
|
|
||||||
# Mirror offset spots.
|
# Mirror offset spots.
|
||||||
@@ -319,6 +304,18 @@ def overworld_glitches_rules(world, player):
|
|||||||
add_additional_rule(world.get_entrance('Tree Line Water Clip', player), lambda state: state.has('Flippers', player))
|
add_additional_rule(world.get_entrance('Tree Line Water Clip', player), lambda state: state.has('Flippers', player))
|
||||||
add_additional_rule(world.get_entrance('Dark Tree Line Water Clip', player), lambda state: state.has('Flippers', player))
|
add_additional_rule(world.get_entrance('Dark Tree Line Water Clip', player), lambda state: state.has('Flippers', player))
|
||||||
|
|
||||||
|
# Bunny pocket
|
||||||
|
if not world.is_tile_swapped(0x00, player):
|
||||||
|
add_alternate_rule(world.get_entrance("Skull Woods Final Section", player), lambda state: state.can_bunny_pocket(player) and state.has("Fire Rod", player))
|
||||||
|
if world.is_tile_swapped(0x05, player):
|
||||||
|
add_alternate_rule(world.get_entrance("DM Hammer Bridge (West)", player), lambda state: state.can_bunny_pocket(player) and state.has("Hammer", player))
|
||||||
|
add_alternate_rule(world.get_entrance("DM Hammer Bridge (East)", player), lambda state: state.can_bunny_pocket(player) and state.has("Hammer", player))
|
||||||
|
if not world.is_tile_swapped(0x18, player):
|
||||||
|
add_alternate_rule(world.get_entrance("Bush Yard Pegs (Inner)", player), lambda state: state.can_bunny_pocket(player) and state.has("Hammer", player))
|
||||||
|
add_alternate_rule(world.get_entrance("Bush Yard Pegs (Outer)", player), lambda state: state.can_bunny_pocket(player) and state.has("Hammer", player))
|
||||||
|
if world.is_tile_swapped(0x22, player):
|
||||||
|
add_alternate_rule(world.get_entrance("Blacksmith Ledge Peg (West)", player), lambda state: state.can_bunny_pocket(player) and state.has("Hammer", player))
|
||||||
|
|
||||||
|
|
||||||
def add_alternate_rule(entrance, rule):
|
def add_alternate_rule(entrance, rule):
|
||||||
old_rule = entrance.access_rule
|
old_rule = entrance.access_rule
|
||||||
@@ -335,7 +332,7 @@ def create_no_logic_connections(player, world, connections):
|
|||||||
parent = world.get_region(parent_region, player)
|
parent = world.get_region(parent_region, player)
|
||||||
target = world.get_region(target_region, player)
|
target = world.get_region(target_region, player)
|
||||||
connection = Entrance(player, entrance, parent)
|
connection = Entrance(player, entrance, parent)
|
||||||
connection.spot_type = 'Ledge'
|
connection.spot_type = 'OWG'
|
||||||
parent.exits.append(connection)
|
parent.exits.append(connection)
|
||||||
connection.connect(target)
|
connection.connect(target)
|
||||||
|
|
||||||
@@ -387,6 +384,8 @@ boots_clips_local = [ # (name, from_region, to_region)
|
|||||||
|
|
||||||
('Maze Race Item Get Ledge Clip', 'Maze Race Area', 'Maze Race Prize'),
|
('Maze Race Item Get Ledge Clip', 'Maze Race Area', 'Maze Race Prize'),
|
||||||
|
|
||||||
|
#('Hobo Water Clip', 'Stone Bridge South Area', 'Stone Bridge Water'), # TODO: Doesn't work with OW Free Terrain
|
||||||
|
|
||||||
('Tree Line Water Clip', 'Tree Line Area', 'Tree Line Water'), #requires flippers
|
('Tree Line Water Clip', 'Tree Line Area', 'Tree Line Water'), #requires flippers
|
||||||
('Dark Tree Line Water Clip', 'Dark Tree Line Area', 'Dark Tree Line Water'), #requires flippers
|
('Dark Tree Line Water Clip', 'Dark Tree Line Area', 'Dark Tree Line Water'), #requires flippers
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -200,7 +200,7 @@ def link_overworld(world, player):
|
|||||||
|
|
||||||
categorize_world_regions(world, player)
|
categorize_world_regions(world, player)
|
||||||
|
|
||||||
if world.logic[player] in ('owglitches', 'nologic'):
|
if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'):
|
||||||
create_owg_connections(world, player)
|
create_owg_connections(world, player)
|
||||||
|
|
||||||
# crossed shuffle
|
# crossed shuffle
|
||||||
@@ -1486,7 +1486,7 @@ def build_accessible_region_list(world, start_region, player, build_copy_world=F
|
|||||||
elif exit.connected_region.name not in explored_regions \
|
elif exit.connected_region.name not in explored_regions \
|
||||||
and (exit.connected_region.type == region.type
|
and (exit.connected_region.type == region.type
|
||||||
or exit.name in OWExitTypes['OWEdge'] or (cross_world and exit.name in (OWExitTypes['Portal'] + OWExitTypes['Mirror']))) \
|
or exit.name in OWExitTypes['OWEdge'] or (cross_world and exit.name in (OWExitTypes['Portal'] + OWExitTypes['Mirror']))) \
|
||||||
and (not region_rules or exit.access_rule(blank_state)) and (not ignore_ledges or exit.name not in OWExitTypes['Ledge']):
|
and (not region_rules or exit.access_rule(blank_state)) and (not ignore_ledges or exit.name not in OWExitTypes['Ledge', 'OWG']):
|
||||||
explore_region(exit.connected_region.name, exit.connected_region)
|
explore_region(exit.connected_region.name, exit.connected_region)
|
||||||
|
|
||||||
if build_copy_world:
|
if build_copy_world:
|
||||||
|
|||||||
@@ -1365,9 +1365,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0x180211, gametype) # Game type
|
rom.write_byte(0x180211, gametype) # Game type
|
||||||
|
|
||||||
warningflags = 0x00 # none
|
warningflags = 0x00 # none
|
||||||
if world.logic[player] in ['owglitches', 'nologic']:
|
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
|
||||||
warningflags |= 0x20
|
warningflags |= 0x20
|
||||||
if world.logic[player] in ['minorglitches', 'owglitches', 'nologic']:
|
if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic']:
|
||||||
warningflags |= 0x40
|
warningflags |= 0x40
|
||||||
rom.write_byte(0x180212, warningflags) # Warning flags
|
rom.write_byte(0x180212, warningflags) # Warning flags
|
||||||
|
|
||||||
@@ -1599,7 +1599,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0x1800A3, 0x01) # enable correct world setting behaviour after agahnim kills
|
rom.write_byte(0x1800A3, 0x01) # enable correct world setting behaviour after agahnim kills
|
||||||
rom.write_byte(0x1800A4, 0x01 if world.logic[player] != 'nologic' else 0x00) # enable POD EG fix
|
rom.write_byte(0x1800A4, 0x01 if world.logic[player] != 'nologic' else 0x00) # enable POD EG fix
|
||||||
rom.write_byte(0x180042, 0x01 if world.save_and_quit_from_boss else 0x00) # Allow Save and Quit after boss kill
|
rom.write_byte(0x180042, 0x01 if world.save_and_quit_from_boss else 0x00) # Allow Save and Quit after boss kill
|
||||||
rom.write_byte(0x180358, 0x01 if (world.logic[player] in ['owglitches', 'nologic']) else 0x00)
|
rom.write_byte(0x180358, 0x01 if (world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']) else 0x00)
|
||||||
|
|
||||||
# remove shield from uncle
|
# remove shield from uncle
|
||||||
rom.write_bytes(0x6D253, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
rom.write_bytes(0x6D253, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from Dungeons import dungeon_table
|
|||||||
from RoomData import DoorKind
|
from RoomData import DoorKind
|
||||||
from OWEdges import OWExitTypes
|
from OWEdges import OWExitTypes
|
||||||
from OverworldGlitchRules import overworld_glitches_rules
|
from OverworldGlitchRules import overworld_glitches_rules
|
||||||
|
from UnderworldGlitchRules import underworld_glitches_rules
|
||||||
|
|
||||||
|
|
||||||
def set_rules(world, player):
|
def set_rules(world, player):
|
||||||
@@ -32,7 +33,7 @@ def set_rules(world, player):
|
|||||||
logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.')
|
logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.')
|
||||||
no_glitches_rules(world, player)
|
no_glitches_rules(world, player)
|
||||||
fake_flipper_rules(world, player)
|
fake_flipper_rules(world, player)
|
||||||
elif world.logic[player] == 'owglitches':
|
elif world.logic[player] in ['owglitches', 'hybridglitches']:
|
||||||
logging.getLogger('').info('There is a chance OWG has bugged edge case rulesets, especially in inverted. Definitely file a report on GitHub if you see anything strange.')
|
logging.getLogger('').info('There is a chance OWG has bugged edge case rulesets, especially in inverted. Definitely file a report on GitHub if you see anything strange.')
|
||||||
# Initially setting no_glitches_rules to set the baseline rules for some
|
# Initially setting no_glitches_rules to set the baseline rules for some
|
||||||
# entrances. The overworld_glitches_rules set is primarily additive.
|
# entrances. The overworld_glitches_rules set is primarily additive.
|
||||||
@@ -84,6 +85,9 @@ def set_rules(world, player):
|
|||||||
if not world.is_copied_world:
|
if not world.is_copied_world:
|
||||||
set_bunny_rules(world, player, world.mode[player] == 'inverted')
|
set_bunny_rules(world, player, world.mode[player] == 'inverted')
|
||||||
|
|
||||||
|
# These rules go here because they overwrite/add to some of the above rules
|
||||||
|
if world.logic[player] == 'hybridglitches':
|
||||||
|
underworld_glitches_rules(world, player)
|
||||||
|
|
||||||
def mirrorless_path_to_location(world, startName, targetName, player):
|
def mirrorless_path_to_location(world, startName, targetName, player):
|
||||||
# If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch.
|
# If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch.
|
||||||
@@ -845,6 +849,9 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_entrance('GT Crystal Circles to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_blunt_weapon(player) or state.has('Cane of Byrna', player)) # or state.has_beam_sword(player)
|
set_rule(world.get_entrance('GT Crystal Circles to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_blunt_weapon(player) or state.has('Cane of Byrna', player)) # or state.has_beam_sword(player)
|
||||||
|
|
||||||
add_key_logic_rules(world, player)
|
add_key_logic_rules(world, player)
|
||||||
|
|
||||||
|
if world.logic[player] == 'hybridglitches':
|
||||||
|
add_hmg_key_logic_rules(world, player)
|
||||||
# End of door rando rules.
|
# End of door rando rules.
|
||||||
|
|
||||||
if world.restrict_boss_items[player] != 'none':
|
if world.restrict_boss_items[player] != 'none':
|
||||||
@@ -1644,6 +1651,8 @@ def find_rules_for_zelda_delivery(world, player):
|
|||||||
def set_bunny_rules(world, player, inverted):
|
def set_bunny_rules(world, player, inverted):
|
||||||
# regions for the exits of multi-entrace caves/drops that bunny cannot pass
|
# regions for the exits of multi-entrace caves/drops that bunny cannot pass
|
||||||
# Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing.
|
# Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing.
|
||||||
|
all_single_exit_dungeons = ['Eastern Palace', 'Tower of Hera', 'Castle Tower', 'Palace of Darkness', 'Swamp Palace', 'Thieves Town', 'Ice Palace', 'Misery Mire', 'Ganons Tower']
|
||||||
|
hmg_single_exit_dungeons = [d for d in all_single_exit_dungeons if d not in ['Tower of Hera', 'Misery Mire', 'Thieves Town']]
|
||||||
bunny_impassable_caves = ['Bumper Cave (top)', 'Bumper Cave (bottom)', 'Two Brothers House',
|
bunny_impassable_caves = ['Bumper Cave (top)', 'Bumper Cave (bottom)', 'Two Brothers House',
|
||||||
'Hookshot Cave (Middle)', 'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)']
|
'Hookshot Cave (Middle)', 'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)']
|
||||||
bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree',
|
bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree',
|
||||||
@@ -1668,6 +1677,9 @@ def set_bunny_rules(world, player, inverted):
|
|||||||
'Take - Any # 3 Item 1', 'Take - Any # 3 Item 2',
|
'Take - Any # 3 Item 1', 'Take - Any # 3 Item 2',
|
||||||
'Take - Any # 4 Item 1', 'Take - Any # 4 Item 2',
|
'Take - Any # 4 Item 1', 'Take - Any # 4 Item 2',
|
||||||
]
|
]
|
||||||
|
bunny_pocket_entrances = ['Skull Woods Final Section', 'Bush Yard Pegs (Inner)', 'Bush Yard Pegs (Outer)',
|
||||||
|
'DM Hammer Bridge (West)', 'DM Hammer Bridge (East)', 'Blacksmith Ledge Peg (West)'
|
||||||
|
]
|
||||||
|
|
||||||
def path_to_access_rule(path, entrance):
|
def path_to_access_rule(path, entrance):
|
||||||
return lambda state: state.can_reach(entrance) and all(rule_func(state) for rule_func in path)
|
return lambda state: state.can_reach(entrance) and all(rule_func(state) for rule_func in path)
|
||||||
@@ -1688,12 +1700,31 @@ def set_bunny_rules(world, player, inverted):
|
|||||||
else:
|
else:
|
||||||
return region.is_light_world
|
return region.is_light_world
|
||||||
|
|
||||||
|
# Is it possible to do bunny pocket here
|
||||||
|
def can_bunny_pocket_to(world, entrance_name, player):
|
||||||
|
def can_activate_bunny_pocket(region):
|
||||||
|
explored_regions.append(region.name)
|
||||||
|
for ent in region.entrances:
|
||||||
|
if (is_link(ent.parent_region) or
|
||||||
|
(ent.parent_region.type == RegionType.Dungeon and ent.parent_region.name in bunny_revivable_entrances)):
|
||||||
|
return True
|
||||||
|
for ent in region.entrances:
|
||||||
|
if ent.spot_type in ['OWEdge', 'Ledge', 'OpenTerrain'] and ent.parent_region.name not in explored_regions:
|
||||||
|
if can_activate_bunny_pocket(ent.parent_region):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
entrance = world.get_entrance(entrance_name, player)
|
||||||
|
explored_regions = []
|
||||||
|
return can_activate_bunny_pocket(entrance.parent_region)
|
||||||
|
|
||||||
|
|
||||||
def get_rule_to_add(region, location=None, connecting_entrance=None):
|
def get_rule_to_add(region, location=None, connecting_entrance=None):
|
||||||
# In OWG, a location can potentially be superbunny-mirror accessible or
|
# In OWG, a location can potentially be superbunny-mirror accessible or
|
||||||
# bunny revival accessible.
|
# bunny revival accessible.
|
||||||
if world.logic[player] == 'owglitches':
|
if world.logic[player] in ['owglitches', 'hybridglitches']:
|
||||||
if region.type != RegionType.Dungeon \
|
if region.type != RegionType.Dungeon \
|
||||||
and (location is None or location.name not in OverworldGlitchRules.get_superbunny_accessible_locations()) \
|
and (location is None or location.name not in OverworldGlitchRules.superbunny_accessible_locations) \
|
||||||
and not is_link(region):
|
and not is_link(region):
|
||||||
return lambda state: state.has_Pearl(player)
|
return lambda state: state.has_Pearl(player)
|
||||||
else:
|
else:
|
||||||
@@ -1723,14 +1754,18 @@ def set_bunny_rules(world, player, inverted):
|
|||||||
new_path = path + [entrance.access_rule]
|
new_path = path + [entrance.access_rule]
|
||||||
seen_sets.add(frozenset(new_seen))
|
seen_sets.add(frozenset(new_seen))
|
||||||
if not is_link(new_region):
|
if not is_link(new_region):
|
||||||
if world.logic[player] == 'owglitches':
|
if world.logic[player] in ['owglitches', 'hybridglitches']:
|
||||||
|
# Is this a bunny pocketable entrance?
|
||||||
if region.type == RegionType.Dungeon and new_region.type != RegionType.Dungeon:
|
if region.type == RegionType.Dungeon and new_region.type != RegionType.Dungeon:
|
||||||
if entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances():
|
if entrance.name in OverworldGlitchRules.invalid_mirror_bunny_entrances:
|
||||||
|
continue
|
||||||
|
if entrance.name in bunny_pocket_entrances and not can_bunny_pocket_to(world, entrance.name, player):
|
||||||
continue
|
continue
|
||||||
if entrance.name in drop_dungeon_entrances:
|
if entrance.name in drop_dungeon_entrances:
|
||||||
lobby = entrance.connected_region
|
lobby = entrance.connected_region
|
||||||
else:
|
else:
|
||||||
lobby = next(exit.connected_region for exit in current.exits if exit.connected_region.type == RegionType.Dungeon)
|
portal_regions = [world.get_region(reg, player) for reg in region.dungeon.regions if reg.endswith('Portal')]
|
||||||
|
lobby = next(reg.connected_region for portal_reg in portal_regions for reg in portal_reg.exits if reg.name.startswith('Enter '))
|
||||||
if lobby.name in bunny_revivable_entrances:
|
if lobby.name in bunny_revivable_entrances:
|
||||||
possible_options.append(path_to_access_rule(new_path, entrance))
|
possible_options.append(path_to_access_rule(new_path, entrance))
|
||||||
elif lobby.name in superbunny_revivable_entrances:
|
elif lobby.name in superbunny_revivable_entrances:
|
||||||
@@ -1739,21 +1774,23 @@ def set_bunny_rules(world, player, inverted):
|
|||||||
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_sword(player)], entrance))
|
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_sword(player)], entrance))
|
||||||
continue
|
continue
|
||||||
elif region.type == RegionType.Cave and new_region.type != RegionType.Cave:
|
elif region.type == RegionType.Cave and new_region.type != RegionType.Cave:
|
||||||
if entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances():
|
if entrance.name in OverworldGlitchRules.invalid_mirror_bunny_entrances:
|
||||||
continue
|
continue
|
||||||
if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions():
|
if entrance.name in bunny_pocket_entrances and not can_bunny_pocket_to(world, entrance.name, player):
|
||||||
|
continue
|
||||||
|
if region.name in OverworldGlitchRules.sword_required_superbunny_mirror_regions:
|
||||||
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_sword(player)], entrance))
|
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_sword(player)], entrance))
|
||||||
elif region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions():
|
elif region.name in OverworldGlitchRules.boots_required_superbunny_mirror_regions:
|
||||||
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_Boots(player)], entrance))
|
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_Boots(player)], entrance))
|
||||||
elif location and location.name in OverworldGlitchRules.get_superbunny_accessible_locations():
|
elif location and location.name in OverworldGlitchRules.superbunny_accessible_locations:
|
||||||
if location.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_locations():
|
if location.name in OverworldGlitchRules.boots_required_superbunny_mirror_locations:
|
||||||
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_Boots(player)], entrance))
|
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_Boots(player)], entrance))
|
||||||
elif region.name == 'Kakariko Well (top)':
|
elif region.name == 'Kakariko Well (top)':
|
||||||
possible_options.append(path_to_access_rule(new_path, entrance))
|
possible_options.append(path_to_access_rule(new_path, entrance))
|
||||||
else:
|
else:
|
||||||
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player)], entrance))
|
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player)], entrance))
|
||||||
continue
|
continue
|
||||||
elif region.name == 'Superbunny Cave (Top)' and new_region.name == 'Superbunny Cave (Bottom)' and location and location.name in OverworldGlitchRules.get_superbunny_accessible_locations():
|
elif region.name == 'Superbunny Cave (Top)' and new_region.name == 'Superbunny Cave (Bottom)' and location and location.name in OverworldGlitchRules.superbunny_accessible_locations:
|
||||||
possible_options.append(path_to_access_rule(new_path, entrance))
|
possible_options.append(path_to_access_rule(new_path, entrance))
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
@@ -1767,7 +1804,6 @@ def set_bunny_rules(world, player, inverted):
|
|||||||
|
|
||||||
# Add requirements for bunny-impassible caves if they occur in the light world
|
# Add requirements for bunny-impassible caves if they occur in the light world
|
||||||
for region in [world.get_region(name, player) for name in bunny_impassable_caves]:
|
for region in [world.get_region(name, player) for name in bunny_impassable_caves]:
|
||||||
|
|
||||||
if not is_bunny(region):
|
if not is_bunny(region):
|
||||||
continue
|
continue
|
||||||
rule = get_rule_to_add(region)
|
rule = get_rule_to_add(region)
|
||||||
@@ -1802,6 +1838,11 @@ def set_bunny_rules(world, player, inverted):
|
|||||||
continue
|
continue
|
||||||
add_rule(location, get_rule_to_add(region, location))
|
add_rule(location, get_rule_to_add(region, location))
|
||||||
|
|
||||||
|
for ent_name in bunny_pocket_entrances:
|
||||||
|
bunny_exit = world.get_entrance(ent_name, player)
|
||||||
|
if bunny_exit.connected_region and is_bunny(bunny_exit.parent_region) and not can_bunny_pocket_to(world, ent_name, player):
|
||||||
|
add_rule(bunny_exit, lambda state: state.has_Pearl(player))
|
||||||
|
|
||||||
|
|
||||||
drop_dungeon_entrances = {
|
drop_dungeon_entrances = {
|
||||||
"Sewer Drop",
|
"Sewer Drop",
|
||||||
@@ -1929,6 +1970,11 @@ bunny_impassible_if_trapped = {
|
|||||||
'GT Speed Torch WN', 'Ice Lobby SE'
|
'GT Speed Torch WN', 'Ice Lobby SE'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def add_hmg_key_logic_rules(world, player):
|
||||||
|
for toh_loc in world.key_logic[player]['Tower of Hera'].bk_restricted:
|
||||||
|
set_always_allow(world.get_location(toh_loc.name, player), allow_big_key_in_big_chest('Big Key (Tower of Hera)', player))
|
||||||
|
set_always_allow(world.get_location('Swamp Palace - Entrance', player), allow_big_key_in_big_chest('Big Key (Swamp Palace)', player))
|
||||||
|
|
||||||
|
|
||||||
def add_key_logic_rules(world, player):
|
def add_key_logic_rules(world, player):
|
||||||
key_logic = world.key_logic[player]
|
key_logic = world.key_logic[player]
|
||||||
|
|||||||
@@ -0,0 +1,278 @@
|
|||||||
|
from BaseClasses import Entrance
|
||||||
|
import Rules
|
||||||
|
from OverworldGlitchRules import create_no_logic_connections
|
||||||
|
|
||||||
|
kikiskip_spots = [("Kiki Skip", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Portal")]
|
||||||
|
|
||||||
|
mireheraswamp_spots = [
|
||||||
|
("Mire to Hera Clip", "Mire Torches Top", "Hera Portal"),
|
||||||
|
("Hera to Swamp Clip", "Mire Torches Top", "Swamp Portal"),
|
||||||
|
]
|
||||||
|
|
||||||
|
icepalace_spots = [("Ice Lobby Clip", "Ice Portal", "Ice Bomb Drop")]
|
||||||
|
|
||||||
|
thievesdesert_spots = [
|
||||||
|
("Thieves to Desert Clip", "Thieves Attic", "Desert West Portal"),
|
||||||
|
("Thieves to Desert Clip", "Thieves Attic", "Desert South Portal"),
|
||||||
|
("Thieves to Desert Clip", "Thieves Attic", "Desert East Portal"),
|
||||||
|
]
|
||||||
|
|
||||||
|
specrock_spots = [("Spec Rock Clip", "Spectacle Rock Cave (Peak)", "Spectacle Rock Cave (Top)")]
|
||||||
|
|
||||||
|
paradox_spots = [("Paradox Front Teleport", "Paradox Cave Front", "Paradox Cave Chest Area")]
|
||||||
|
|
||||||
|
|
||||||
|
# We need to make connectors at a separate time from the connections, because of how dungeons are linked to regions
|
||||||
|
kikiskip_connectors = [("Kiki Skip", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Exit")]
|
||||||
|
|
||||||
|
|
||||||
|
mireheraswamp_connectors = [
|
||||||
|
("Mire to Hera Clip", "Mire Torches Top", "Tower of Hera Exit"),
|
||||||
|
("Mire to Hera Clip", "Mire Torches Top", "Swamp Palace Exit"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
thievesdesert_connectors = [
|
||||||
|
("Thieves to Desert Clip", "Thieves Attic", "Desert Palace Exit (West)"),
|
||||||
|
("Thieves to Desert Clip", "Thieves Attic", "Desert Palace Exit (South)"),
|
||||||
|
("Thieves to Desert Clip", "Thieves Attic", "Desert Palace Exit (East)"),
|
||||||
|
]
|
||||||
|
|
||||||
|
specrock_connectors = [
|
||||||
|
("Spec Rock Clip", "Spectacle Rock Cave (Peak)", "Spectacle Rock Cave Exit (Top)"),
|
||||||
|
("Spec Rock Clip", "Spectacle Rock Cave (Peak)", "Spectacle Rock Cave Exit"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Create connections between dungeons/locations
|
||||||
|
def create_hybridmajor_connections(world, player):
|
||||||
|
for spots in [
|
||||||
|
kikiskip_spots,
|
||||||
|
mireheraswamp_spots,
|
||||||
|
icepalace_spots,
|
||||||
|
thievesdesert_spots,
|
||||||
|
specrock_spots,
|
||||||
|
paradox_spots,
|
||||||
|
]:
|
||||||
|
create_no_logic_connections(player, world, spots)
|
||||||
|
|
||||||
|
|
||||||
|
# Turn dungeons into connectors
|
||||||
|
def create_hybridmajor_connectors(world, player):
|
||||||
|
for connectors in [
|
||||||
|
kikiskip_connectors,
|
||||||
|
mireheraswamp_connectors,
|
||||||
|
thievesdesert_connectors,
|
||||||
|
specrock_connectors,
|
||||||
|
]:
|
||||||
|
new_connectors = [(connector[0], connector[1], world.get_entrance(connector[2], player).connected_region) for connector in connectors]
|
||||||
|
create_no_logic_connections(player, world, new_connectors)
|
||||||
|
|
||||||
|
|
||||||
|
# For some entrances, we need to fake having pearl, because we're in fake DW/LW.
|
||||||
|
# This creates a copy of the input state that has Moon Pearl.
|
||||||
|
def fake_pearl_state(state, player):
|
||||||
|
if state.has("Moon Pearl", player):
|
||||||
|
return state
|
||||||
|
fake_state = state.copy()
|
||||||
|
fake_state.prog_items["Moon Pearl", player] += 1
|
||||||
|
return fake_state
|
||||||
|
|
||||||
|
|
||||||
|
# Sets the rules on where we can actually go using this clip.
|
||||||
|
# Behavior differs based on what type of ER shuffle we're playing.
|
||||||
|
def dungeon_reentry_rules(world, player, clip: Entrance, dungeon_region: str, dungeon_exit: str):
|
||||||
|
fix_dungeon_exits = world.fix_palaceofdarkness_exit[player]
|
||||||
|
fix_fake_worlds = world.fix_fake_world[player]
|
||||||
|
|
||||||
|
dungeon_entrance = [r for r in world.get_region(dungeon_region, player).entrances if r.name != clip.name][0]
|
||||||
|
if not fix_dungeon_exits: # vanilla, simple, restricted, dungeonssimple; should never have fake worlds fix
|
||||||
|
# Dungeons are only shuffled among themselves. We need to check SW, MM, and AT because they can't be reentered trivially.
|
||||||
|
|
||||||
|
# entrance doesn't exist until you fire rod it from the other side
|
||||||
|
if dungeon_entrance.name == "Skull Woods Final Section":
|
||||||
|
Rules.set_rule(clip, lambda state: False)
|
||||||
|
|
||||||
|
elif dungeon_entrance.name == "Misery Mire":
|
||||||
|
if world.swords[player] == "swordless":
|
||||||
|
Rules.add_rule(clip, lambda state: state.has_misery_mire_medallion(player))
|
||||||
|
else:
|
||||||
|
Rules.add_rule(clip, lambda state: state.has_sword(player) and state.has_misery_mire_medallion(player))
|
||||||
|
|
||||||
|
elif dungeon_entrance.name == "Agahnims Tower":
|
||||||
|
Rules.add_rule(
|
||||||
|
clip,
|
||||||
|
lambda state: state.has("Cape", player)
|
||||||
|
or state.has_beam_sword(player)
|
||||||
|
or state.has("Beat Agahnim 1", player),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Then we set a restriction on exiting the dungeon, so you can't leave unless you got in normally.
|
||||||
|
Rules.add_rule(world.get_entrance(dungeon_exit, player), lambda state: dungeon_entrance.can_reach(state))
|
||||||
|
elif not fix_fake_worlds: # full, dungeonsfull; fixed dungeon exits, but no fake worlds fix
|
||||||
|
# Entry requires the entrance's requirements plus a fake pearl, but you don't gain logical access to the surrounding region.
|
||||||
|
Rules.add_rule(clip, lambda state: dungeon_entrance.access_rule(fake_pearl_state(state, player)))
|
||||||
|
# exiting restriction
|
||||||
|
Rules.add_rule(world.get_entrance(dungeon_exit, player), lambda state: dungeon_entrance.can_reach(state))
|
||||||
|
|
||||||
|
# Otherwise, the shuffle type is lean, lite, crossed, or insanity; all of these do not need additional rules on where we can go,
|
||||||
|
# since the clip links directly to the exterior region.
|
||||||
|
|
||||||
|
|
||||||
|
def underworld_glitches_rules(world, player):
|
||||||
|
# Ice Palace Entrance Clip, needs bombs or cane of somaria to exit bomb drop room
|
||||||
|
Rules.add_rule(
|
||||||
|
world.get_entrance("Ice Bomb Drop SE", player),
|
||||||
|
lambda state: state.can_dash_clip(world.get_region("Ice Lobby", player), player)
|
||||||
|
and (state.can_use_bombs(player) or state.has("Cane of Somaria", player)),
|
||||||
|
combine="or",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Kiki Skip
|
||||||
|
kks = world.get_entrance("Kiki Skip", player)
|
||||||
|
Rules.set_rule(kks, lambda state: state.can_bomb_clip(kks.parent_region, player))
|
||||||
|
dungeon_reentry_rules(world, player, kks, "Palace of Darkness Portal", "Palace of Darkness Exit")
|
||||||
|
|
||||||
|
# Mire -> Hera -> Swamp
|
||||||
|
def mire_clip(state):
|
||||||
|
return state.can_reach("Mire Torches Top", "Region", player) and state.can_dash_clip(
|
||||||
|
world.get_region("Mire Torches Top", player), player
|
||||||
|
)
|
||||||
|
|
||||||
|
def hera_clip(state):
|
||||||
|
return state.can_reach("Hera 4F", "Region", player) and state.can_dash_clip(
|
||||||
|
world.get_region("Hera 4F", player), player
|
||||||
|
)
|
||||||
|
|
||||||
|
Rules.add_rule(
|
||||||
|
world.get_entrance("Hera Startile Corner NW", player),
|
||||||
|
lambda state: mire_clip(state) and state.has("Big Key (Misery Mire)", player),
|
||||||
|
combine="or",
|
||||||
|
)
|
||||||
|
Rules.add_rule(
|
||||||
|
world.get_location("Tower of Hera - Big Chest", player),
|
||||||
|
lambda state: mire_clip(state) and state.has("Big Key (Misery Mire)", player),
|
||||||
|
combine="or",
|
||||||
|
)
|
||||||
|
|
||||||
|
mire_to_hera = world.get_entrance("Mire to Hera Clip", player)
|
||||||
|
mire_to_swamp = world.get_entrance("Hera to Swamp Clip", player)
|
||||||
|
Rules.set_rule(mire_to_hera, mire_clip)
|
||||||
|
Rules.set_rule(mire_to_swamp, lambda state: mire_clip(state) and state.has("Flippers", player))
|
||||||
|
|
||||||
|
# Using the entrances for various ER types. Hera -> Swamp never matters because you can only logically traverse with the mire keys
|
||||||
|
dungeon_reentry_rules(world, player, mire_to_hera, "Hera Lobby", "Tower of Hera Exit")
|
||||||
|
dungeon_reentry_rules(world, player, mire_to_swamp, "Swamp Lobby", "Swamp Palace Exit")
|
||||||
|
# We need to set _all_ swamp doors to be openable with mire keys, otherwise the small key can't be behind them - 6 keys because of Pots
|
||||||
|
# Flippers required for all of these doors to prevent locks when flooding
|
||||||
|
for door in [
|
||||||
|
"Swamp Trench 1 Approach ES",
|
||||||
|
"Swamp Hammer Switch SW",
|
||||||
|
"Swamp Entrance Down Stairs",
|
||||||
|
"Swamp Pot Row WS",
|
||||||
|
"Swamp Trench 1 Key Ledge NW",
|
||||||
|
"Swamp Hub WN",
|
||||||
|
"Swamp Hub North Ledge N",
|
||||||
|
"Swamp Crystal Switch EN",
|
||||||
|
"Swamp Push Statue S",
|
||||||
|
"Swamp Waterway NW",
|
||||||
|
"Swamp T SW",
|
||||||
|
]:
|
||||||
|
Rules.add_rule(
|
||||||
|
world.get_entrance(door, player),
|
||||||
|
lambda state: mire_clip(state)
|
||||||
|
and state.has("Small Key (Misery Mire)", player, count=6)
|
||||||
|
and state.has("Flippers", player),
|
||||||
|
combine="or",
|
||||||
|
)
|
||||||
|
# Rules.add_rule(world.get_entrance(door, player), lambda state: mire_clip(state) and state.has('Flippers', player), combine="or")
|
||||||
|
|
||||||
|
Rules.add_rule(
|
||||||
|
world.get_location("Trench 1 Switch", player), lambda state: mire_clip(state) or hera_clip(state), combine="or"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build the rule for SP moat.
|
||||||
|
# We need to be able to s+q to old man, then go to either Mire or Hera at either Hera or GT.
|
||||||
|
# First we require a certain type of entrance shuffle, then build the rule from its pieces.
|
||||||
|
if not world.swamp_patch_required[player]:
|
||||||
|
if world.shuffle[player] in [
|
||||||
|
"vanilla",
|
||||||
|
"dungeonssimple",
|
||||||
|
"dungeonsfull",
|
||||||
|
"dungeonscrossed",
|
||||||
|
]:
|
||||||
|
rule_map = {
|
||||||
|
"Mire Portal": (lambda state: state.can_reach("Mire Torches Top", "Entrance", player)),
|
||||||
|
"Hera Portal": (lambda state: state.can_reach("Hera Startile Corner NW", "Entrance", player)),
|
||||||
|
}
|
||||||
|
inverted = world.mode[player] == "inverted"
|
||||||
|
|
||||||
|
def hera_rule(state):
|
||||||
|
return (state.has("Moon Pearl", player) or not inverted) and rule_map.get(
|
||||||
|
world.get_entrance("Tower of Hera", player).connected_region.name, lambda state: False
|
||||||
|
)(state)
|
||||||
|
|
||||||
|
def gt_rule(state):
|
||||||
|
return (state.has("Moon Pearl", player) or inverted) and rule_map.get(
|
||||||
|
world.get_entrance(("Ganons Tower"), player).connected_region.name, lambda state: False
|
||||||
|
)(state)
|
||||||
|
|
||||||
|
def mirrorless_moat_rule(state):
|
||||||
|
return (
|
||||||
|
state.can_reach("Old Man S&Q", "Entrance", player)
|
||||||
|
and state.has("Flippers", player)
|
||||||
|
and mire_clip(state)
|
||||||
|
and (hera_rule(state) or gt_rule(state))
|
||||||
|
)
|
||||||
|
|
||||||
|
Rules.add_rule(
|
||||||
|
world.get_entrance("Swamp Lobby Moat", player), lambda state: mirrorless_moat_rule(state), combine="or"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Thieves -> Desert
|
||||||
|
Rules.add_rule(
|
||||||
|
world.get_entrance("Thieves to Desert Clip", player),
|
||||||
|
lambda state: state.can_dash_clip(world.get_region("Thieves Attic", player), player),
|
||||||
|
)
|
||||||
|
dungeon_reentry_rules(
|
||||||
|
world,
|
||||||
|
player,
|
||||||
|
world.get_entrance("Thieves to Desert Clip", player),
|
||||||
|
"Desert West Portal",
|
||||||
|
"Desert Palace Exit (West)",
|
||||||
|
)
|
||||||
|
dungeon_reentry_rules(
|
||||||
|
world,
|
||||||
|
player,
|
||||||
|
world.get_entrance("Thieves to Desert Clip", player),
|
||||||
|
"Desert South Portal",
|
||||||
|
"Desert Palace Exit (South)",
|
||||||
|
)
|
||||||
|
dungeon_reentry_rules(
|
||||||
|
world,
|
||||||
|
player,
|
||||||
|
world.get_entrance("Thieves to Desert Clip", player),
|
||||||
|
"Desert East Portal",
|
||||||
|
"Desert Palace Exit (East)",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Collecting left chests in Paradox Cave using a dash clip -> dash citrus, 1f right, teleport up
|
||||||
|
paradox_left_chests = ["Paradox Cave Lower - Far Left", "Paradox Cave Lower - Left", "Paradox Cave Lower - Middle"]
|
||||||
|
for location in paradox_left_chests:
|
||||||
|
Rules.add_rule(
|
||||||
|
world.get_location(location, player),
|
||||||
|
lambda state: state.can_dash_clip(world.get_location(location, player).parent_region, player),
|
||||||
|
"or",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Collecting right chests in Paradox Cave using a dash clip on left side -> dash citrus, 1f right, teleport up, then hitting the switch
|
||||||
|
paradox_right_chests = ["Paradox Cave Lower - Right", "Paradox Cave Lower - Far Right"]
|
||||||
|
for location in paradox_right_chests:
|
||||||
|
Rules.add_rule(
|
||||||
|
world.get_location(location, player),
|
||||||
|
lambda state: (
|
||||||
|
state.can_dash_clip(world.get_location(location, player).parent_region, player)
|
||||||
|
and state.can_hit_crystal(player)
|
||||||
|
),
|
||||||
|
"or",
|
||||||
|
)
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
"noglitches",
|
"noglitches",
|
||||||
"minorglitches",
|
"minorglitches",
|
||||||
"owglitches",
|
"owglitches",
|
||||||
|
"hybridglitches",
|
||||||
"nologic"
|
"nologic"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -56,7 +56,8 @@
|
|||||||
"building.collection.spheres": "Building up collection spheres",
|
"building.collection.spheres": "Building up collection spheres",
|
||||||
"building.calculating.spheres": "Calculated sphere %i, containing %i of %i progress items.",
|
"building.calculating.spheres": "Calculated sphere %i, containing %i of %i progress items.",
|
||||||
"building.final.spheres": "Calculated final sphere %i, containing %i of %i progress items.",
|
"building.final.spheres": "Calculated final sphere %i, containing %i of %i progress items.",
|
||||||
"old.python.version": "Door Rando may have issues with python versions earlier than 3.7. Detected version: %s"
|
"old.python.version": "Door Rando may have issues with python versions earlier than 3.7. Detected version: %s",
|
||||||
|
"hybridglitches.door.shuffle": "Hybrid Major Glitches is not currently compatible with Door Shuffle."
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"lang": [ "App Language, if available, defaults to English" ],
|
"lang": [ "App Language, if available, defaults to English" ],
|
||||||
@@ -67,6 +68,8 @@
|
|||||||
"No Glitches: No Glitch knowledge required.",
|
"No Glitches: No Glitch knowledge required.",
|
||||||
"Minor Glitches: May require Fake Flippers, Bunny Revival",
|
"Minor Glitches: May require Fake Flippers, Bunny Revival",
|
||||||
" and Dark Room Navigation.",
|
" and Dark Room Navigation.",
|
||||||
|
"Overworld Glitches: May require overworld clips and teleports.",
|
||||||
|
"Hybrid Major Glitches: May require underworld clips.",
|
||||||
"No Logic: Distribute items without regard for",
|
"No Logic: Distribute items without regard for",
|
||||||
" item requirements."
|
" item requirements."
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -263,6 +263,7 @@
|
|||||||
"randomizer.item.logiclevel.noglitches": "No Glitches",
|
"randomizer.item.logiclevel.noglitches": "No Glitches",
|
||||||
"randomizer.item.logiclevel.minorglitches": "Minor Glitches",
|
"randomizer.item.logiclevel.minorglitches": "Minor Glitches",
|
||||||
"randomizer.item.logiclevel.owglitches": "Overworld Glitches",
|
"randomizer.item.logiclevel.owglitches": "Overworld Glitches",
|
||||||
|
"randomizer.item.logiclevel.hybridglitches": "Hybrid Major Glitches",
|
||||||
"randomizer.item.logiclevel.nologic": "No Logic",
|
"randomizer.item.logiclevel.nologic": "No Logic",
|
||||||
|
|
||||||
"randomizer.item.goal": "Goal",
|
"randomizer.item.goal": "Goal",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"noglitches",
|
"noglitches",
|
||||||
"minorglitches",
|
"minorglitches",
|
||||||
"owglitches",
|
"owglitches",
|
||||||
|
"hybridglitches",
|
||||||
"nologic"
|
"nologic"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1317,7 +1317,7 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
|
|||||||
invalid_connections = Must_Exit_Invalid_Connections.copy()
|
invalid_connections = Must_Exit_Invalid_Connections.copy()
|
||||||
invalid_cave_connections = defaultdict(set)
|
invalid_cave_connections = defaultdict(set)
|
||||||
|
|
||||||
if avail.world.logic[avail.player] in ['owglitches', 'nologic']:
|
if avail.world.logic[avail.player] in ['owglitches', 'hybridglitches', 'nologic']:
|
||||||
import OverworldGlitchRules
|
import OverworldGlitchRules
|
||||||
for entrance in OverworldGlitchRules.get_non_mandatory_exits(avail.world, avail.player):
|
for entrance in OverworldGlitchRules.get_non_mandatory_exits(avail.world, avail.player):
|
||||||
invalid_connections[entrance] = set()
|
invalid_connections[entrance] = set()
|
||||||
|
|||||||
@@ -46,8 +46,9 @@ def roll_settings(weights):
|
|||||||
|
|
||||||
ret.algorithm = get_choice('algorithm')
|
ret.algorithm = get_choice('algorithm')
|
||||||
|
|
||||||
glitch_map = {'none': 'noglitches', 'no_logic': 'nologic', 'owglitches': 'owglitches',
|
glitch_map = {'none': 'noglitches', 'minorglitches': 'minorglitches', 'no_logic': 'nologic',
|
||||||
'owg': 'owglitches', 'minorglitches': 'minorglitches'}
|
'hmg': 'hybridglitches', 'hybridglitches': 'hybridglitches',
|
||||||
|
'owg': 'owglitches', 'owglitches': 'owglitches'}
|
||||||
glitches_required = get_choice('glitches_required')
|
glitches_required = get_choice('glitches_required')
|
||||||
if glitches_required is not None:
|
if glitches_required is not None:
|
||||||
if glitches_required not in glitch_map.keys():
|
if glitches_required not in glitch_map.keys():
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
accessibility: items
|
||||||
|
door_shuffle: vanilla
|
||||||
|
logic: hybridglitches
|
||||||
|
mode: open
|
||||||
|
shuffle: vanilla
|
||||||
|
doors:
|
||||||
|
1:
|
||||||
|
doors:
|
||||||
|
Hera Beetles WS: Hera Startile Corner ES
|
||||||
|
Hera Startile Corner ES: Hera Beetles WS
|
||||||
|
Hera Startile Corner NW: Hera Startile Wide SW
|
||||||
|
Hera Startile Wide SW: Hera Startile Corner NW
|
||||||
|
Skull 1 Lobby ES: Skull Map Room WS
|
||||||
|
Skull 2 West Lobby ES: Skull Small Hall WS
|
||||||
|
Skull 2 West Lobby NW: Skull X Room SW
|
||||||
|
Skull Big Chest N: Skull Pull Switch S
|
||||||
|
Skull Compass Room WS: Skull Left Drop ES
|
||||||
|
Skull Final Drop WS: Skull Spike Corner ES
|
||||||
|
Skull Left Drop ES: Skull Compass Room WS
|
||||||
|
Skull Map Room WS: Skull 1 Lobby ES
|
||||||
|
Skull Pot Circle WN: Skull Pull Switch EN
|
||||||
|
Skull Pull Switch EN: Skull Pot Circle WN
|
||||||
|
Skull Pull Switch S: Skull Big Chest N
|
||||||
|
Skull Small Hall WS: Skull 2 West Lobby ES
|
||||||
|
Skull Spike Corner ES: Skull Final Drop WS
|
||||||
|
Skull X Room SW: Skull 2 West Lobby NW
|
||||||
|
lobbies: {}
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Ice Palace - Compass Chest: Fire Rod
|
||||||
|
Ice Palace - Freezor Chest: Bombos
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
accessibility: items
|
||||||
|
door_shuffle: vanilla
|
||||||
|
logic: hybridglitches
|
||||||
|
mode: open
|
||||||
|
shuffle: vanilla
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Flippers
|
||||||
|
- Lamp
|
||||||
|
- Tempered Sword
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
doors:
|
||||||
|
1:
|
||||||
|
doors:
|
||||||
|
Hera Beetles WS: Hera Startile Corner ES
|
||||||
|
Hera Startile Corner ES: Hera Beetles WS
|
||||||
|
Hera Startile Corner NW: Hera Startile Wide SW
|
||||||
|
Hera Startile Wide SW: Hera Startile Corner NW
|
||||||
|
Skull 1 Lobby ES: Skull Map Room WS
|
||||||
|
Skull 2 West Lobby ES: Skull Small Hall WS
|
||||||
|
Skull 2 West Lobby NW: Skull X Room SW
|
||||||
|
Skull Big Chest N: Skull Pull Switch S
|
||||||
|
Skull Compass Room WS: Skull Left Drop ES
|
||||||
|
Skull Final Drop WS: Skull Spike Corner ES
|
||||||
|
Skull Left Drop ES: Skull Compass Room WS
|
||||||
|
Skull Map Room WS: Skull 1 Lobby ES
|
||||||
|
Skull Pot Circle WN: Skull Pull Switch EN
|
||||||
|
Skull Pull Switch EN: Skull Pot Circle WN
|
||||||
|
Skull Pull Switch S: Skull Big Chest N
|
||||||
|
Skull Small Hall WS: Skull 2 West Lobby ES
|
||||||
|
Skull Spike Corner ES: Skull Final Drop WS
|
||||||
|
Skull X Room SW: Skull 2 West Lobby NW
|
||||||
|
lobbies: {}
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Swamp Palace - Big Chest: Hammer
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
accessibility: items
|
||||||
|
door_shuffle: vanilla
|
||||||
|
logic: hybridglitches
|
||||||
|
mode: open
|
||||||
|
shuffle: vanilla
|
||||||
|
doors:
|
||||||
|
1:
|
||||||
|
doors:
|
||||||
|
Hera Beetles WS: Hera Startile Corner ES
|
||||||
|
Hera Startile Corner ES: Hera Beetles WS
|
||||||
|
Hera Startile Corner NW: Hera Startile Wide SW
|
||||||
|
Hera Startile Wide SW: Hera Startile Corner NW
|
||||||
|
Skull 1 Lobby ES: Skull Map Room WS
|
||||||
|
Skull 2 West Lobby ES: Skull Small Hall WS
|
||||||
|
Skull 2 West Lobby NW: Skull X Room SW
|
||||||
|
Skull Big Chest N: Skull Pull Switch S
|
||||||
|
Skull Compass Room WS: Skull Left Drop ES
|
||||||
|
Skull Final Drop WS: Skull Spike Corner ES
|
||||||
|
Skull Left Drop ES: Skull Compass Room WS
|
||||||
|
Skull Map Room WS: Skull 1 Lobby ES
|
||||||
|
Skull Pot Circle WN: Skull Pull Switch EN
|
||||||
|
Skull Pull Switch EN: Skull Pot Circle WN
|
||||||
|
Skull Pull Switch S: Skull Big Chest N
|
||||||
|
Skull Small Hall WS: Skull 2 West Lobby ES
|
||||||
|
Skull Spike Corner ES: Skull Final Drop WS
|
||||||
|
Skull X Room SW: Skull 2 West Lobby NW
|
||||||
|
lobbies: {}
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Palace of Darkness - Shooter Room: Moon Pearl
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
accessibility: items
|
||||||
|
door_shuffle: vanilla
|
||||||
|
logic: hybridglitches
|
||||||
|
mode: open
|
||||||
|
shuffle: vanilla
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Flippers
|
||||||
|
- Lamp
|
||||||
|
- Tempered Sword
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
doors:
|
||||||
|
1:
|
||||||
|
doors:
|
||||||
|
Hera Beetles WS: Hera Startile Corner ES
|
||||||
|
Hera Startile Corner ES: Hera Beetles WS
|
||||||
|
Hera Startile Corner NW: Hera Startile Wide SW
|
||||||
|
Hera Startile Wide SW: Hera Startile Corner NW
|
||||||
|
Skull 1 Lobby ES: Skull Map Room WS
|
||||||
|
Skull 2 West Lobby ES: Skull Small Hall WS
|
||||||
|
Skull 2 West Lobby NW: Skull X Room SW
|
||||||
|
Skull Big Chest N: Skull Pull Switch S
|
||||||
|
Skull Compass Room WS: Skull Left Drop ES
|
||||||
|
Skull Final Drop WS: Skull Spike Corner ES
|
||||||
|
Skull Left Drop ES: Skull Compass Room WS
|
||||||
|
Skull Map Room WS: Skull 1 Lobby ES
|
||||||
|
Skull Pot Circle WN: Skull Pull Switch EN
|
||||||
|
Skull Pull Switch EN: Skull Pot Circle WN
|
||||||
|
Skull Pull Switch S: Skull Big Chest N
|
||||||
|
Skull Small Hall WS: Skull 2 West Lobby ES
|
||||||
|
Skull Spike Corner ES: Skull Final Drop WS
|
||||||
|
Skull X Room SW: Skull 2 West Lobby NW
|
||||||
|
lobbies: {}
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Swamp Palace - Big Chest: Magic Mirror
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
accessibility: items
|
||||||
|
door_shuffle: vanilla
|
||||||
|
logic: hybridglitches
|
||||||
|
mode: open
|
||||||
|
shuffle: crossed
|
||||||
|
doors:
|
||||||
|
1:
|
||||||
|
doors:
|
||||||
|
Hera Beetles WS: Hera Startile Corner ES
|
||||||
|
Hera Startile Corner ES: Hera Beetles WS
|
||||||
|
Hera Startile Corner NW: Hera Startile Wide SW
|
||||||
|
Hera Startile Wide SW: Hera Startile Corner NW
|
||||||
|
Skull 1 Lobby ES: Skull Map Room WS
|
||||||
|
Skull 2 West Lobby ES: Skull Small Hall WS
|
||||||
|
Skull 2 West Lobby NW: Skull X Room SW
|
||||||
|
Skull Big Chest N: Skull Pull Switch S
|
||||||
|
Skull Compass Room WS: Skull Left Drop ES
|
||||||
|
Skull Final Drop WS: Skull Spike Corner ES
|
||||||
|
Skull Left Drop ES: Skull Compass Room WS
|
||||||
|
Skull Map Room WS: Skull 1 Lobby ES
|
||||||
|
Skull Pot Circle WN: Skull Pull Switch EN
|
||||||
|
Skull Pull Switch EN: Skull Pot Circle WN
|
||||||
|
Skull Pull Switch S: Skull Big Chest N
|
||||||
|
Skull Small Hall WS: Skull 2 West Lobby ES
|
||||||
|
Skull Spike Corner ES: Skull Final Drop WS
|
||||||
|
Skull X Room SW: Skull 2 West Lobby NW
|
||||||
|
lobbies: {}
|
||||||
|
entrances:
|
||||||
|
1:
|
||||||
|
entrances:
|
||||||
|
Dark Lake Hylia Ledge Hint: Dark World Hammer Peg Cave
|
||||||
|
exits:
|
||||||
|
Links House: Chris Houlihan Room Exit
|
||||||
|
two-way:
|
||||||
|
Dark Lake Hylia Ledge Fairy: Palace of Darkness Exit
|
||||||
|
Lake Hylia Fortune Teller: Spectacle Rock Cave Exit
|
||||||
|
Links House: Links House Exit
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Peg Cave: Moon Pearl
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
accessibility: items
|
||||||
|
door_shuffle: vanilla
|
||||||
|
logic: hybridglitches
|
||||||
|
mode: open
|
||||||
|
shuffle: crossed
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Hookshot
|
||||||
|
- Lamp
|
||||||
|
- Hammer
|
||||||
|
- Magic Mirror
|
||||||
|
- Tempered Sword
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
doors:
|
||||||
|
1:
|
||||||
|
doors:
|
||||||
|
Hera Beetles WS: Hera Startile Corner ES
|
||||||
|
Hera Startile Corner ES: Hera Beetles WS
|
||||||
|
Hera Startile Corner NW: Hera Startile Wide SW
|
||||||
|
Hera Startile Wide SW: Hera Startile Corner NW
|
||||||
|
Skull 1 Lobby ES: Skull Map Room WS
|
||||||
|
Skull 2 West Lobby ES: Skull Small Hall WS
|
||||||
|
Skull 2 West Lobby NW: Skull X Room SW
|
||||||
|
Skull Big Chest N: Skull Pull Switch S
|
||||||
|
Skull Compass Room WS: Skull Left Drop ES
|
||||||
|
Skull Final Drop WS: Skull Spike Corner ES
|
||||||
|
Skull Left Drop ES: Skull Compass Room WS
|
||||||
|
Skull Map Room WS: Skull 1 Lobby ES
|
||||||
|
Skull Pot Circle WN: Skull Pull Switch EN
|
||||||
|
Skull Pull Switch EN: Skull Pot Circle WN
|
||||||
|
Skull Pull Switch S: Skull Big Chest N
|
||||||
|
Skull Small Hall WS: Skull 2 West Lobby ES
|
||||||
|
Skull Spike Corner ES: Skull Final Drop WS
|
||||||
|
Skull X Room SW: Skull 2 West Lobby NW
|
||||||
|
lobbies: {}
|
||||||
|
entrances:
|
||||||
|
1:
|
||||||
|
entrances:
|
||||||
|
Dark Lake Hylia Ledge Hint: Dark World Hammer Peg Cave
|
||||||
|
exits:
|
||||||
|
Links House: Chris Houlihan Room Exit
|
||||||
|
two-way:
|
||||||
|
Dark Lake Hylia Ledge Fairy: Swamp Palace Exit
|
||||||
|
Lake Hylia Fortune Teller: Misery Mire Exit
|
||||||
|
Links House: Links House Exit
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Peg Cave: Moon Pearl
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
accessibility: items
|
||||||
|
door_shuffle: vanilla
|
||||||
|
logic: hybridglitches
|
||||||
|
mode: open
|
||||||
|
shuffle: vanilla
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Hookshot
|
||||||
|
- Lamp
|
||||||
|
- Hammer
|
||||||
|
- Magic Mirror
|
||||||
|
- Tempered Sword
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
doors:
|
||||||
|
1:
|
||||||
|
doors:
|
||||||
|
Hera Beetles WS: Hera Startile Corner ES
|
||||||
|
Hera Startile Corner ES: Hera Beetles WS
|
||||||
|
Hera Startile Corner NW: Hera Startile Wide SW
|
||||||
|
Hera Startile Wide SW: Hera Startile Corner NW
|
||||||
|
Skull 1 Lobby ES: Skull Map Room WS
|
||||||
|
Skull 2 West Lobby ES: Skull Small Hall WS
|
||||||
|
Skull 2 West Lobby NW: Skull X Room SW
|
||||||
|
Skull Big Chest N: Skull Pull Switch S
|
||||||
|
Skull Compass Room WS: Skull Left Drop ES
|
||||||
|
Skull Final Drop WS: Skull Spike Corner ES
|
||||||
|
Skull Left Drop ES: Skull Compass Room WS
|
||||||
|
Skull Map Room WS: Skull 1 Lobby ES
|
||||||
|
Skull Pot Circle WN: Skull Pull Switch EN
|
||||||
|
Skull Pull Switch EN: Skull Pot Circle WN
|
||||||
|
Skull Pull Switch S: Skull Big Chest N
|
||||||
|
Skull Small Hall WS: Skull 2 West Lobby ES
|
||||||
|
Skull Spike Corner ES: Skull Final Drop WS
|
||||||
|
Skull X Room SW: Skull 2 West Lobby NW
|
||||||
|
lobbies: {}
|
||||||
|
# placements:
|
||||||
|
# 1:
|
||||||
|
# Swamp Palace - Entrance: Boss Heart Container
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
shuffle: crossed
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Flippers
|
||||||
|
- Pegasus Boots
|
||||||
|
- Progressive Sword
|
||||||
|
- Hammer
|
||||||
|
- Progressive Glove
|
||||||
|
- Progressive Glove
|
||||||
|
- Fire Rod
|
||||||
|
- Book of Mudora
|
||||||
|
- Bottle
|
||||||
|
- Magic Mirror
|
||||||
|
- Lamp
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- type: Verification
|
||||||
|
item: Moon Pearl
|
||||||
|
locations:
|
||||||
|
Pyramid Fairy - Left: True
|
||||||
|
entrances:
|
||||||
|
1:
|
||||||
|
entrances:
|
||||||
|
Skull Woods Final Section: Pyramid Fairy
|
||||||
|
two-way:
|
||||||
|
Chicken House: Two Brothers House Exit (West)
|
||||||
|
Skull Woods Second Section Door (West): Two Brothers House Exit (East)
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Flippers
|
||||||
|
- Moon Pearl
|
||||||
|
- Progressive Sword
|
||||||
|
- Hammer
|
||||||
|
- Progressive Glove
|
||||||
|
- Progressive Glove
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Ice Palace - Map Chest: Bombos
|
||||||
|
Ice Palace - Iced T Room: Fire Rod
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Pegasus Boots
|
||||||
|
- Moon Pearl
|
||||||
|
- Progressive Sword
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- type: Verification
|
||||||
|
item: Flippers
|
||||||
|
locations:
|
||||||
|
Zora's Ledge: True
|
||||||
|
Hobo: True
|
||||||
|
Ice Palace - Boss: True
|
||||||
|
Swamp Palace - Entrance: False
|
||||||
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: owglitches
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Pegasus Boots
|
||||||
|
- Moon Pearl
|
||||||
|
- Progressive Sword
|
||||||
|
- Flippers
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Peg Cave: Magic Mirror
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- type: Verification
|
||||||
|
item: Hammer
|
||||||
|
locations:
|
||||||
|
Link's House: True
|
||||||
|
Magic Bat: False
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- type: Verification
|
||||||
|
item: Progressive Glove
|
||||||
|
locations:
|
||||||
|
Link's House: True
|
||||||
|
Ice Palace - Freezor Chest: False
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Flippers
|
||||||
|
- Moon Pearl
|
||||||
|
- Progressive Sword
|
||||||
|
- Lamp
|
||||||
|
- Magic Mirror
|
||||||
|
- Ether
|
||||||
|
- Quake
|
||||||
|
- Bombos
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- type: Verification
|
||||||
|
item: Big Key (Tower of Hera)
|
||||||
|
locations:
|
||||||
|
Tower of Hera - Big Key Chest: True
|
||||||
|
Tower of Hera - Basement Cage: True
|
||||||
|
Tower of Hera - Map Chest: True
|
||||||
|
Tower of Hera - Compass Chest: True
|
||||||
|
Tower of Hera - Big Chest: True
|
||||||
|
Tower of Hera - Boss: True
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
mode: inverted
|
||||||
|
shuffle: crossed
|
||||||
|
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Pegasus Boots
|
||||||
|
- Progressive Sword
|
||||||
|
- Hammer
|
||||||
|
- Fire Rod
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Desert Palace - Boss: Moon Pearl
|
||||||
|
entrances:
|
||||||
|
1:
|
||||||
|
two-way:
|
||||||
|
Skull Woods Final Section: Desert Palace Exit (West)
|
||||||
|
Skull Woods Second Section Door (West): Desert Palace Exit (East)
|
||||||
|
Thieves Town: Thieves Town Exit
|
||||||
|
Hyrule Castle Entrance (East): Desert Palace Exit (South)
|
||||||
|
Hyrule Castle Entrance (West): Desert Palace Exit (North)
|
||||||
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
mode: inverted
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Flippers
|
||||||
|
- Progressive Sword
|
||||||
|
- Progressive Sword
|
||||||
|
- Book of Mudora
|
||||||
|
- Lamp
|
||||||
|
- Magic Mirror
|
||||||
|
- Ether
|
||||||
|
- Quake
|
||||||
|
- Bombos
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- type: Verification
|
||||||
|
item: Moon Pearl
|
||||||
|
locations:
|
||||||
|
Tower of Hera - Big Chest: True
|
||||||
|
Desert Palace - Big Chest: True
|
||||||
|
Eastern Palace - Big Chest: True
|
||||||
|
Bombos Tablet: True
|
||||||
|
Cave 45: True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Pegasus Boots
|
||||||
|
- Flippers
|
||||||
|
- Fire Rod
|
||||||
|
- Book of Mudora
|
||||||
|
- Progressive Sword
|
||||||
|
- Progressive Sword
|
||||||
|
- Lamp
|
||||||
|
- Magic Mirror
|
||||||
|
- Ether
|
||||||
|
- Quake
|
||||||
|
- Bombos
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- type: Verification
|
||||||
|
item: Moon Pearl
|
||||||
|
locations:
|
||||||
|
Skull Woods - Compass Chest: True
|
||||||
|
Skull Woods - Bridge Room: True
|
||||||
|
Palace of Darkness - Shooter Room: True
|
||||||
|
Palace of Darkness - The Arena - Bridge: True
|
||||||
|
Palace of Darkness - Stalfos Basement: True
|
||||||
|
Palace of Darkness - Big Key Chest: True
|
||||||
|
Palace of Darkness - The Arena - Ledge: True
|
||||||
|
Palace of Darkness - Map Chest: True
|
||||||
|
Palace of Darkness - Compass Chest: True
|
||||||
|
Palace of Darkness - Dark Basement - Left: True
|
||||||
|
Palace of Darkness - Dark Basement - Right: True
|
||||||
|
Palace of Darkness - Dark Maze - Top: True
|
||||||
|
Palace of Darkness - Dark Maze - Bottom: True
|
||||||
|
Palace of Darkness - Big Chest: True
|
||||||
|
Palace of Darkness - Harmless Hellway: True
|
||||||
|
Palace of Darkness - Boss: True
|
||||||
|
Bombos Tablet: True
|
||||||
|
C-Shaped House: True
|
||||||
|
Pyramid Fairy - Left: True
|
||||||
|
Swamp Palace - Entrance: False
|
||||||
|
Thieves' Town - Map Chest: False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Flippers
|
||||||
|
- Pegasus Boots
|
||||||
|
- Progressive Sword
|
||||||
|
- Hammer
|
||||||
|
- Progressive Glove
|
||||||
|
- Progressive Glove
|
||||||
|
- Fire Rod
|
||||||
|
- Book of Mudora
|
||||||
|
- Bottle
|
||||||
|
- Magic Mirror
|
||||||
|
- Lamp
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- type: Verification
|
||||||
|
item: Moon Pearl
|
||||||
|
locations:
|
||||||
|
Skull Woods - Bridge Room: True
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Flippers
|
||||||
|
- Moon Pearl
|
||||||
|
- Progressive Sword
|
||||||
|
- Lamp
|
||||||
|
- Magic Mirror
|
||||||
|
- Ether
|
||||||
|
- Quake
|
||||||
|
- Bombos
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- type: Verification
|
||||||
|
item: Small Key (Swamp Palace)
|
||||||
|
locations:
|
||||||
|
Swamp Palace - Entrance: True
|
||||||
|
Swamp Palace - Map Chest: True
|
||||||
|
Swamp Palace - Big Chest: True
|
||||||
|
Swamp Palace - Compass Chest: True
|
||||||
|
Swamp Palace - West Chest: True
|
||||||
|
Swamp Palace - Big Key Chest: True
|
||||||
|
Swamp Palace - Flooded Room - Left: True
|
||||||
|
Swamp Palace - Flooded Room - Right: True
|
||||||
|
Swamp Palace - Waterfall Room: True
|
||||||
|
Swamp Palace - Boss: True
|
||||||
|
- type: Verification
|
||||||
|
item: Big Key (Swamp Palace)
|
||||||
|
locations:
|
||||||
|
Swamp Palace - Entrance: True
|
||||||
|
Swamp Palace - Map Chest: True
|
||||||
|
Swamp Palace - Big Chest: True
|
||||||
|
Swamp Palace - Compass Chest: True
|
||||||
|
Swamp Palace - West Chest: True
|
||||||
|
Swamp Palace - Big Key Chest: True
|
||||||
|
Swamp Palace - Flooded Room - Left: True
|
||||||
|
Swamp Palace - Flooded Room - Right: True
|
||||||
|
Swamp Palace - Waterfall Room: True
|
||||||
|
Swamp Palace - Boss: True
|
||||||
Reference in New Issue
Block a user