Merge branch 'KrisDavie-hmg_logic' into DoorDevVolatile

This commit is contained in:
aerinon
2023-12-27 13:00:44 -07:00
33 changed files with 1325 additions and 251 deletions

View File

@@ -111,7 +111,7 @@ class World(object):
set_player_attr('can_access_trock_front', None)
set_player_attr('can_access_trock_big_chest', 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'])
set_player_attr('mapshuffle', False)
set_player_attr('compassshuffle', False)
@@ -550,6 +550,42 @@ class CollectionState(object):
self.placing_items = 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):
self.stale[player] = False
rrp = self.reachable_regions[player]
@@ -1099,6 +1135,12 @@ class CollectionState(object):
def can_lift_rocks(self, 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):
return self.bottle_count(player) > 0
@@ -1268,6 +1310,9 @@ class CollectionState(object):
def can_superbunny_mirror_with_sword(self, 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):
if location:
@@ -2973,7 +3018,7 @@ er_mode = {"vanilla": 0, "simple": 1, "restricted": 2, "full": 3, "crossed": 4,
'lean': 9, "dungeonsfull": 7, "dungeonssimple": 6, 'swapped': 10}
# 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}
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3}

View File

@@ -1106,15 +1106,16 @@ def connect_random(world, exitlist, targetlist, player, two_way=False):
def connect_mandatory_exits(world, entrances, caves, must_be_exits, player):
# Keeps track of entrances that cannot be used to access each exit / cave
if world.mode[player] == 'inverted':
inverted = world.mode[player] == 'inverted'
if inverted:
invalid_connections = Inverted_Must_Exit_Invalid_Connections.copy()
else:
invalid_connections = Must_Exit_Invalid_Connections.copy()
invalid_cave_connections = defaultdict(set)
if world.logic[player] in ['owglitches', 'nologic']:
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
import OverworldGlitchRules
for entrance in OverworldGlitchRules.get_non_mandatory_exits(world.mode[player] == 'inverted'):
for entrance in OverworldGlitchRules.inverted_non_mandatory_exits if inverted else OverworldGlitchRules.open_non_mandatory_exits:
invalid_connections[entrance] = set()
if entrance in must_be_exits:
must_be_exits.remove(entrance)
@@ -1125,7 +1126,7 @@ def connect_mandatory_exits(world, entrances, caves, must_be_exits, player):
random.shuffle(caves)
# Handle inverted Aga Tower - if it depends on connections, then so does Hyrule Castle Ledge
if world.mode[player] == 'inverted':
if inverted:
for entrance in invalid_connections:
if world.get_entrance(entrance, player).connected_region == world.get_region('Agahnims Tower Portal', player):
for exit in invalid_connections[entrance]:

View File

@@ -175,6 +175,9 @@ def valid_key_placement(item, location, key_pool, collection_state, world):
if dungeon:
if dungeon.name not in item.name and (dungeon.name != 'Hyrule Castle' or 'Escape' not in item.name):
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]
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
@@ -398,7 +401,7 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
# fill in gtower locations with trash first
for player in range(1, world.players + 1):
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
gt_count, total_count = calc_trash_locations(world, player)
scale_factor = .75 * (world.crystals_needed_for_gt[player] / 7)

View File

@@ -287,6 +287,11 @@ def generate_itempool(world, player):
for _ in range(0, amt):
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)
for item in precollected_items:
world.push_precollected(ItemFactory(item, player))
@@ -881,7 +886,7 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt
return random.choice([True, False]) if progressive == 'random' else progressive == 'on'
# provide boots to boots glitch dependent modes
if logic in ['owglitches', 'nologic']:
if logic in ['owglitches', 'hybridglitches', 'nologic']:
precollected_items.append('Pegasus Boots')
pool.remove('Pegasus Boots')
pool.extend(['Rupees (20)'])
@@ -1174,7 +1179,7 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer
pool.extend(['Nothing'] * nothings)
start_inventory = [x for x in world.precollected_items if x.player == player]
if world.logic[player] in ['owglitches', 'nologic'] and all(x.name !=' Pegasus Boots' for x in start_inventory):
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic'] and all(x.name !=' Pegasus Boots' for x in start_inventory):
precollected_items.append('Pegasus Boots')
if 'Pegasus Boots' in pool:
pool.remove('Pegasus Boots')
@@ -1316,7 +1321,7 @@ def make_customizer_pool(world, player):
sphere_0 = world.customizer.get_start_inventory()
no_start_inventory = not sphere_0 or not 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))):
precollected_items.append('Pegasus Boots')
if 'Pegasus Boots' in pool:

View File

@@ -2106,6 +2106,22 @@ def validate_key_placement(key_layout, world, player):
if i.player == player and i.name == smallkey_name:
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 it, the small key is available downstairs
big_key_outside = True
for code, counter in key_layout.key_counters.items():
if len(counter.child_doors) == 0:
continue

17
Main.py
View File

@@ -27,6 +27,7 @@ from Fill import distribute_items_restrictive, promote_dungeon_items, fill_dunge
from Fill import dungeon_tracking
from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops, fill_specific_items
from UnderworldGlitchRules import create_hybridmajor_connections, create_hybridmajor_connectors
from Utils import output_path, parse_player_names
from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config
@@ -78,6 +79,9 @@ def main(args, seed=None, fish=None):
seed = customized.determine_seed(seed)
seeded = True
customized.adjust_args(args)
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"))
world = World(args.multi, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords,
args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm,
args.accessibility, args.shuffleganon, args.custom, args.customitemarray, args.hints)
@@ -205,7 +209,7 @@ def main(args, seed=None, fish=None):
for player in range(1, world.players + 1):
create_regions(world, player)
if world.logic[player] in ('owglitches', 'nologic'):
if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'):
create_owg_connections(world, player)
create_dungeon_regions(world, player)
create_shops(world, player)
@@ -216,6 +220,8 @@ def main(args, seed=None, fish=None):
world.data_tables[player] = init_data_tables(world, player)
place_bosses(world, player)
randomize_enemies(world, player)
if world.logic[player] in ('nologic', 'hybridglitches'):
create_hybridmajor_connections(world, player)
adjust_locations(world, player)
if world.customizer and world.customizer.get_start_inventory():
@@ -245,6 +251,8 @@ def main(args, seed=None, fish=None):
link_entrances_new(world, player)
else:
link_entrances(world, player)
if world.logic[player] in ('nologic', 'hybridglitches'):
create_hybridmajor_connectors(world, player)
logger.info(world.fish.translate("cli", "cli", "shuffling.prep"))
for player in range(1, world.players + 1):
@@ -497,8 +505,11 @@ def copy_world(world):
create_shops(ret, player)
create_rooms(ret, player)
create_dungeons(ret, player)
if world.logic[player] in ('owglitches', 'nologic'):
if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'):
create_owg_connections(ret, player)
if world.logic[player] in ('nologic', 'hybridglitches'):
create_hybridmajor_connections(ret, player)
# there are region references here they must be migrated to preserve integrity
# ret.exp_cache = world.exp_cache.copy()
@@ -579,6 +590,8 @@ def copy_world(world):
ret.sanc_portal = world.sanc_portal
for player in range(1, world.players + 1):
if world.logic[player] in ('nologic', 'hybridglitches'):
create_hybridmajor_connectors(ret, player)
set_rules(ret, player)
return ret

View File

@@ -4,261 +4,303 @@ Helper functions to deliver entrance/exit/region sets to OWG rules.
from BaseClasses import Entrance
# 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 a sword.
"""
yield 'Spiral Cave (Top)'
# Cave regions that superbunny can get through - but only with boots.
boots_required_superbunny_mirror_regions = ["Two Brothers House"]
def get_boots_required_superbunny_mirror_regions():
"""
Cave regions that superbunny can get through - but only with boots.
"""
yield 'Two Brothers House'
# Cave locations that superbunny can access - but only with boots.
boots_required_superbunny_mirror_locations = [
"Sahasrahla's Hut - Left",
"Sahasrahla's Hut - Middle",
"Sahasrahla's Hut - Right",
]
def get_boots_required_superbunny_mirror_locations():
"""
Cave locations that superbunny can access - but only with boots.
"""
yield 'Sahasrahla\'s Hut - Left'
yield 'Sahasrahla\'s Hut - Middle'
yield 'Sahasrahla\'s Hut - Right'
# Entrances that can't be superbunny-mirrored into.
invalid_mirror_bunny_entrances = [
"Hype Cave",
"Bonk Fairy (Dark)",
"Thieves Town",
"Hammer Peg Cave",
"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
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)'
# Entrances that can be reached with full equipment using overworld glitches and don't need to be an exit.
# The following are still be mandatory exits:
# Open:
# Turtle Rock Isolated Ledge Entrance
# Skull Woods Second Section Door (West) (or Skull Woods Final Section)
# Inverted:
# Two Brothers House (West)
# Desert Palace Entrance (East)
def get_superbunny_accessible_locations():
"""
Interior locations that can be accessed with superbunny state.
"""
non_mandatory_exits = [
"Bumper Cave (Top)",
"Death Mountain Return Cave (West)",
"Hookshot Cave Back Entrance",
]
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
inverted_non_mandatory_exits = [
"Desert Palace Entrance (North)",
"Desert Palace Entrance (West)",
"Agahnims Tower",
"Hyrule Castle Entrance (West)",
"Hyrule Castle Entrance (East)",
] + non_mandatory_exits
open_non_mandatory_exits = [
"Dark Death Mountain Ledge (West)",
"Dark Death Mountain Ledge (East)",
"Mimic Cave",
"Desert Palace Entrance (East)",
] + non_mandatory_exits
def get_non_mandatory_exits(inverted):
"""
Entrances that can be reached with full equipment using overworld glitches and don't need to be an exit.
The following are still be mandatory exits:
# Special Light World region exits that require boots clips.
Open:
Turtle Rock Isolated Ledge Entrance
Skull Woods Second Section Door (West) (or Skull Woods Final Section)
inverted_boots_clip_exits_lw = [
("Light World DMA Clip Spot", "Light World", "West Death Mountain (Bottom)"),
("Hera Ascent", "West Death Mountain (Bottom)", "West Death Mountain (Top)"),
("Death Mountain Return Ledge Clip Spot", "Light World", "Death Mountain Return Ledge"),
("Death Mountain Entrance Clip Spot", "Light World", "Death Mountain Entrance"),
("Death Mountain Glitched Bridge", "West Death Mountain (Bottom)", "East Death Mountain (Top)"),
("Zora Descent Clip Spot", "East Death Mountain (Top)", "Zoras Domain"),
("Desert Northern Cliffs", "Light World", "Desert Northern Cliffs"),
("Desert Ledge Dropdown", "Desert Northern Cliffs", "Desert Ledge"),
("Desert Palace Entrance Dropdown", "Desert Northern Cliffs", "Desert Palace Entrance (North) Spot"),
("Lake Hylia Island Clip Spot", "Light World", "Lake Hylia Island"),
("Death Mountain Descent", "West Death Mountain (Bottom)", "Light World"),
("Kings Grave Clip Spot", "West Death Mountain (Bottom)", "Kings Grave Area"),
]
Inverted:
Two Brothers House (West)
Desert Palace Entrance (East)
"""
open_boots_clip_exits_lw = [
("Graveyard Ledge Clip Spot", "West Death Mountain (Bottom)", "Graveyard Ledge"),
("Desert Ledge (Northeast) Dropdown", "Desert Northern Cliffs", "Desert Checkerboard Ledge"),
("Spectacle Rock Clip Spot", "West Death Mountain (Top)", "Spectacle Rock"),
("Bombos Tablet Clip Spot", "Light World", "Bombos Tablet Ledge"),
("Floating Island Clip Spot", "East Death Mountain (Top)", "Death Mountain Floating Island"),
("Cave 45 Clip Spot", "Light World", "Cave 45 Ledge"),
] + inverted_boots_clip_exits_lw
yield 'Bumper Cave (Top)'
yield 'Death Mountain Return Cave (West)'
yield 'Hookshot Cave Back Entrance'
# Special Dark World region exits that require boots clips.
boots_clip_exits_dw = [
("Dark World DMA Clip Spot", "West Dark World", "West Dark Death Mountain (Bottom)"),
("Bumper Cave Ledge Clip Spot", "West Dark World", "Bumper Cave Ledge"),
("Bumper Cave Entrance Clip Spot", "West Dark World", "Bumper Cave Entrance"),
("Catfish Descent", "Dark Death Mountain (Top)", "Catfish Area"),
("Hammer Pegs River Clip Spot", "East Dark World", "Hammer Peg Area"),
("Dark Lake Hylia Ledge Clip Spot", "East Dark World", "Southeast Dark World"),
("Dark Desert Cliffs Clip Spot", "South Dark World", "Dark Desert"),
("DW Floating Island Clip Spot", "East Dark Death Mountain (Bottom)", "Dark Death Mountain Floating Island"),
]
if inverted:
yield 'Desert Palace Entrance (North)'
yield 'Desert Palace Entrance (West)'
yield 'Agahnims Tower'
yield 'Hyrule Castle Entrance (West)'
yield 'Hyrule Castle Entrance (East)'
else:
yield 'Dark Death Mountain Ledge (West)'
yield 'Dark Death Mountain Ledge (East)'
yield 'Mimic Cave'
yield 'Desert Palace Entrance (East)'
open_boots_clip_exits_dw = [
("Dark Death Mountain Descent", "West Dark Death Mountain (Bottom)", "West Dark World"),
("Ganons Tower Ascent", "West Dark Death Mountain (Bottom)", "Dark Death Mountain (Top)"),
("Dark Death Mountain Glitched Bridge", "West Dark Death Mountain (Bottom)", "Dark Death Mountain (Top)"),
("Turtle Rock (Top) Clip Spot", "Dark Death Mountain (Top)", "Turtle Rock (Top)"),
] + boots_clip_exits_dw
inverted_boots_clip_exits_dw = [
("Dark Desert Teleporter Clip Spot", "Dark Desert", "Dark Desert Ledge")
] + boots_clip_exits_dw
def get_boots_clip_exits_lw(inverted = False):
"""
Special Light World region exits that require boots clips.
"""
yield ('Bat Cave River Clip Spot', 'Light World', 'Bat Cave Ledge')
yield ('Light World DMA Clip Spot', 'Light World', 'West Death Mountain (Bottom)')
yield ('Hera Ascent', 'West Death Mountain (Bottom)', 'West Death Mountain (Top)')
yield ('Death Mountain Return Ledge Clip Spot', 'Light World', 'Death Mountain Return Ledge')
yield ('Death Mountain Entrance Clip Spot', 'Light World', 'Death Mountain Entrance')
yield ('Death Mountain Glitched Bridge', 'West Death Mountain (Bottom)', 'East Death Mountain (Top)')
yield ('Zora Descent Clip Spot', 'East Death Mountain (Top)', 'Zoras Domain')
yield ('Desert Northern Cliffs', 'Light World', 'Desert Northern Cliffs')
yield ('Desert Ledge Dropdown', 'Desert Northern Cliffs', 'Desert Ledge')
yield ('Desert Palace Entrance Dropdown', 'Desert Northern Cliffs', 'Desert Palace Entrance (North) Spot')
yield ('Lake Hylia Island Clip Spot', 'Light World', 'Lake Hylia Island')
yield ('Death Mountain Descent', 'West Death Mountain (Bottom)', 'Light World')
yield ('Kings Grave Clip Spot', 'West Death Mountain (Bottom)', 'Kings Grave Area')
if not inverted:
yield ('Graveyard Ledge Clip Spot', 'West Death Mountain (Bottom)', 'Graveyard Ledge')
yield ('Desert Ledge (Northeast) Dropdown', 'Desert Northern Cliffs', 'Desert Checkerboard Ledge')
yield ('Spectacle Rock Clip Spot', 'West Death Mountain (Top)', 'Spectacle Rock')
yield ('Bombos Tablet Clip Spot', 'Light World', 'Bombos Tablet Ledge')
yield ('Floating Island Clip Spot', 'East Death Mountain (Top)', 'Death Mountain Floating Island')
yield ('Cave 45 Clip Spot', 'Light World', 'Cave 45 Ledge')
# Dark World drop-down ledges that require glitched speed.
glitched_speed_drops_dw = [
("Dark Death Mountain Ledge Clip Spot", "Dark Death Mountain (Top)", "Dark Death Mountain Ledge")
]
def get_boots_clip_exits_dw(inverted):
"""
Special Dark World region exits that require boots clips.
"""
# Out of bounds transitions using the mirror
mirror_clip_spots_dw = [
("Dark Death Mountain Bunny Descent Mirror Spot", "West Dark Death Mountain (Bottom)", "West Dark World"),
(
"Dark Death Mountain Bunny Mirror To East Jump",
"West Dark Death Mountain (Bottom)",
"East Dark Death Mountain (Bottom)",
),
("Desert East Mirror Clip", "Dark Desert", "Desert Palace Mouth"),
]
yield ('Dark World DMA Clip Spot', 'West Dark World', 'West Dark Death Mountain (Bottom)')
yield ('Bumper Cave Ledge Clip Spot', 'West Dark World', 'Bumper Cave Ledge')
yield ('Bumper Cave Entrance Clip Spot', 'West Dark World', 'Bumper Cave Entrance')
yield ('Catfish Descent', 'Dark Death Mountain (Top)', 'Catfish Area')
yield ('Hammer Pegs River Clip Spot', 'East Dark World', 'Hammer Peg Area')
yield ('Dark Lake Hylia Ledge Clip Spot', 'East Dark World', 'Southeast Dark World')
yield ('Dark Desert Cliffs Clip Spot', 'South Dark World', 'Dark Desert')
yield ('DW Floating Island Clip Spot', 'East Dark Death Mountain (Bottom)', 'Dark Death Mountain Floating Island')
# Mirror shenanigans placing a mirror portal with a broken camera
mirror_offset_spots_dw = [("Dark Death Mountain Offset Mirror", "West Dark Death Mountain (Bottom)", "East Dark World")]
if not inverted:
yield ('Dark Death Mountain Descent', 'West Dark Death Mountain (Bottom)', 'West Dark World')
yield ('Ganons Tower Ascent', 'West Dark Death Mountain (Bottom)', 'Dark Death Mountain (Top)') # This only gets you to the GT entrance
yield ('Dark Death Mountain Glitched Bridge', 'West Dark Death Mountain (Bottom)', 'Dark Death Mountain (Top)')
yield ('Turtle Rock (Top) Clip Spot', 'Dark Death Mountain (Top)', 'Turtle Rock (Top)')
else:
yield ('Dark Desert Teleporter Clip Spot', 'Dark Desert', 'Dark Desert Ledge')
# Mirror shenanigans placing a mirror portal with a broken camera
def get_glitched_speed_drops_dw(inverted = False):
"""
Dark World drop-down ledges that require glitched speed.
"""
yield ('Dark Death Mountain Ledge Clip Spot', 'Dark Death Mountain (Top)', 'Dark Death Mountain Ledge')
def get_mirror_clip_spots_dw():
"""
Out of bounds transitions using the mirror
"""
yield ('Dark Death Mountain Bunny Descent Mirror Spot', 'West Dark Death Mountain (Bottom)', 'West Dark World')
yield ('Dark Death Mountain Bunny Mirror To East Jump', 'West Dark Death Mountain (Bottom)', 'East Dark Death Mountain (Bottom)')
yield ('Desert East Mirror Clip', 'Dark Desert', 'Desert Palace Mouth')
def get_mirror_offset_spots_dw():
"""
Mirror shenanigans placing a mirror portal with a broken camera
"""
yield ('Dark Death Mountain Offset Mirror', 'West Dark Death Mountain (Bottom)', 'East Dark World')
def get_mirror_offset_spots_lw(player):
"""
Mirror shenanigans placing a mirror portal with a broken camera
"""
yield ('Death Mountain Offset Mirror', 'West Death Mountain (Bottom)', 'Light World')
yield ('Death Mountain Uncle Offset Mirror', 'West Death Mountain (Bottom)', 'Hyrule Castle Secret Entrance Area')
yield ('Death Mountain Castle Ledge Offset Mirror', 'West Death Mountain (Bottom)', 'Hyrule Castle Ledge')
mirror_offset_spots_lw = [
("Death Mountain Offset Mirror", "West Death Mountain (Bottom)", "Light World"),
("Death Mountain Uncle Offset Mirror", "West Death Mountain (Bottom)", "Hyrule Castle Secret Entrance Area"),
("Death Mountain Castle Ledge Offset Mirror", "West Death Mountain (Bottom)", "Hyrule Castle Ledge"),
]
def create_owg_connections(world, player):
"""
Add OWG transitions to player's world without logic
"""
create_no_logic_connections(player, world, get_boots_clip_exits_lw(world.mode[player] == 'inverted'))
create_no_logic_connections(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted'))
# Glitched speed drops.
create_no_logic_connections(player, world, get_glitched_speed_drops_dw(world.mode[player] == 'inverted'))
# Mirror clip spots.
if world.mode[player] != 'inverted':
create_no_logic_connections(player, world, get_mirror_clip_spots_dw())
create_no_logic_connections(player, world, get_mirror_offset_spots_dw())
if world.mode[player] == "inverted":
connections = (
inverted_boots_clip_exits_dw
+ inverted_boots_clip_exits_lw
+ glitched_speed_drops_dw
+ mirror_offset_spots_lw
)
else:
create_no_logic_connections(player, world, get_mirror_offset_spots_lw(player))
connections = (
open_boots_clip_exits_dw
+ open_boots_clip_exits_lw
+ glitched_speed_drops_dw
+ mirror_clip_spots_dw
+ mirror_offset_spots_dw
)
create_no_logic_connections(player, world, connections)
def overworld_glitches_rules(world, player):
# Boots-accessible locations.
set_owg_rules(player, world, get_boots_clip_exits_lw(world.mode[player] == 'inverted'), lambda state: state.can_boots_clip_lw(player))
set_owg_rules(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted'), lambda state: state.can_boots_clip_dw(player))
inverted = world.mode[player] == "inverted"
# Boots-accessible locations.
set_owg_rules(
player,
world,
inverted_boots_clip_exits_lw if inverted else open_boots_clip_exits_lw,
lambda state: state.can_boots_clip_lw(player),
)
set_owg_rules(
player,
world,
inverted_boots_clip_exits_dw if inverted else open_boots_clip_exits_dw,
lambda state: state.can_boots_clip_dw(player),
)
# Glitched speed drops.
set_owg_rules(player, world, get_glitched_speed_drops_dw(world.mode[player] == 'inverted'), lambda state: state.can_get_glitched_speed_dw(player))
set_owg_rules(
player,
world,
glitched_speed_drops_dw,
lambda state: state.can_get_glitched_speed_dw(player),
)
# Dark Death Mountain Ledge Clip Spot also accessible with mirror.
if world.mode[player] != 'inverted':
add_alternate_rule(world.get_entrance('Dark Death Mountain Ledge Clip Spot', player), lambda state: state.has_Mirror(player))
if not inverted:
add_alternate_rule(
world.get_entrance("Dark Death Mountain Ledge Clip Spot", player), lambda state: state.has_Mirror(player)
)
# Mirror clip spots.
if world.mode[player] != 'inverted':
set_owg_rules(player, world, get_mirror_clip_spots_dw(), lambda state: state.has_Mirror(player))
set_owg_rules(player, world, get_mirror_offset_spots_dw(), lambda state: state.has_Mirror(player) and state.can_boots_clip_lw(player))
if inverted:
set_owg_rules(
player,
world,
mirror_offset_spots_lw,
lambda state: state.has_Mirror(player) and state.can_boots_clip_dw(player),
)
else:
set_owg_rules(player, world, get_mirror_offset_spots_lw(player), lambda state: state.has_Mirror(player) and state.can_boots_clip_dw(player))
set_owg_rules(player, world, mirror_clip_spots_dw, lambda state: state.has_Mirror(player))
set_owg_rules(
player,
world,
mirror_offset_spots_dw,
lambda state: state.has_Mirror(player) and state.can_boots_clip_lw(player),
)
# Regions that require the boots and some other stuff.
if world.mode[player] != 'inverted':
world.get_entrance('Turtle Rock Teleporter', player).access_rule = lambda state: (state.can_boots_clip_lw(player) or state.can_lift_heavy_rocks(player)) and state.has('Hammer', player)
add_alternate_rule(world.get_entrance('Waterfall Fairy Access', player), lambda state: state.has_Pearl(player) or state.has_Boots(player)) # assumes access to Waterwalk ability (boots case)
else:
add_alternate_rule(world.get_entrance('Waterfall Fairy Access', player), lambda state: state.has_Pearl(player))
if not inverted:
world.get_entrance("Turtle Rock Teleporter", player).access_rule = lambda state: (
state.can_boots_clip_lw(player) or state.can_lift_heavy_rocks(player)
) and state.has("Hammer", player)
world.get_entrance('Dark Desert Teleporter', player).access_rule = lambda state: (state.can_flute(player) or state.can_boots_clip_dw(player)) and state.can_lift_heavy_rocks(player)
add_alternate_rule(world.get_entrance('Dark Witch Rock (North)', player), lambda state: state.can_boots_clip_dw(player))
add_alternate_rule(world.get_entrance('Broken Bridge Pass (Top)', player), lambda state: state.can_boots_clip_dw(player))
add_alternate_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.can_boots_clip_lw(player)) # assumes access to Waterwalk ability
add_alternate_rule(
world.get_entrance("Waterfall Fairy Access", player),
lambda state: state.has_Pearl(player) or state.has_Boots(player),
) # assumes access to Waterwalk ability (boots case)
else:
add_alternate_rule(world.get_entrance("Waterfall Fairy Access", player), lambda state: state.has_Pearl(player))
world.get_entrance("Dark Desert Teleporter", player).access_rule = lambda state: (
state.can_flute(player) or state.can_boots_clip_dw(player)
) and state.can_lift_heavy_rocks(player)
add_alternate_rule(
world.get_entrance("Dark Witch Rock (North)", player), lambda state: state.can_boots_clip_dw(player)
)
add_alternate_rule(
world.get_entrance("Broken Bridge Pass (Top)", player), lambda state: state.can_boots_clip_dw(player)
)
add_alternate_rule(
world.get_location("Zora's Ledge", player), lambda state: state.can_boots_clip_lw(player)
) # assumes access to Waterwalk ability
add_alternate_rule(
world.get_location('Maze Race', player), lambda state: state.can_boots_clip_lw(player)
)
# This is doable even with bad enemies
add_alternate_rule(world.get_location("Hobo", player), lambda state: state.can_boots_clip_lw(player))
# Bunny pocket
if not inverted:
add_alternate_rule(world.get_entrance("Skull Woods Final Section", player), lambda state: state.can_bunny_pocket(player) and state.has("Fire Rod", player))
add_alternate_rule(world.get_entrance("Dark World Shop", player), lambda state: state.can_bunny_pocket(player) and state.has("Hammer", player))
def add_alternate_rule(entrance, rule):

View File

@@ -37,6 +37,7 @@ See https://alttpr.com/ for more details on the normal randomizer.
7. [Standard Changes](#standard-changes)
8. [Game Options](#game-options)
9. [Generation Setup & Miscellaneous](#generation-setup--miscellaneous)
10. [Glitched Logic](#glitched-logic)
## Setup and Installation
@@ -597,4 +598,34 @@ Can be used to set a seed number to generate. Using the same seed with same sett
Use to batch generate multiple seeds with same settings. If a seed number is provided, it will be used for the first seed, then used to derive the next seed (i.e. generating 10 seeds with the same seed number given will produce the same 10 (different) roms each time).
## Glitched Logic
Overworld glitches, Hybrid Major Glitches (HMG) and No Logic are currently supported.
### Overworld Glitches
_Support added by qadan and compiling_
Overworld Glitches logic includes (but is not limited to) the following:
* Overworld teleports and clips to reach various items/entrances
* Use of superbunny to obtain items and/or bonk open entrances
* Use of mirror to access Desert Palace East Entrance
* Use of bunny pocket to access the Back of Skull Woods and VOO Hammer house entrances
### Hybrid Major Glitches
_Support added by Muffins (ported from work by Espeon)_.
**Not currently compatible with Door Shuffle**
Hybrid Major Glitches logic includes the following:
* All Overworld Glitches logic
* Kikiskip to access PoD wihtout MP or DW access
* IP Lobby clip to skip fire requirement
* Traversal between TT -> Desert
* Traversal between Spec rock upper -> Spec rock mid
* Traversal between Paradox lower -> Paradox mid + upper
* Traversal between Mire -> Hera -> Swamp
* Stealing SK from Mire to open SP
* Using the Mire big key to open Hera doors and big chest
All traversals mentioned are considered connectors in entrance shuffle

View File

@@ -8,6 +8,7 @@ from BaseClasses import PotFlags
from Dungeons import dungeon_table
from RoomData import DoorKind
from OverworldGlitchRules import overworld_glitches_rules
from UnderworldGlitchRules import underworld_glitches_rules
from source.logic.Rule import RuleFactory
from source.dungeon.EnemyList import EnemySprite, Sprite
@@ -48,7 +49,7 @@ def set_rules(world, player):
logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.')
no_glitches_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.')
# Initially setting no_glitches_rules to set the baseline rules for some
# entrances. The overworld_glitches_rules set is primarily additive.
@@ -73,7 +74,7 @@ def set_rules(world, player):
if world.mode[player] != 'inverted':
set_big_bomb_rules(world, player)
if world.logic[player] == 'owglitches' and world.shuffle[player] != 'insanity':
if world.logic[player] in ['owglitches', 'hybridglitches'] and world.shuffle[player] != 'insanity':
path_to_courtyard = mirrorless_path_to_castle_courtyard(world, player)
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.world.get_entrance('Dark Death Mountain Offset Mirror', player).can_reach(state) and all(rule(state) for rule in path_to_courtyard), 'or')
else:
@@ -85,7 +86,11 @@ def set_rules(world, player):
set_bunny_rules(world, player, world.mode[player] == 'inverted')
if world.mode[player] != 'inverted' and world.logic[player] == 'owglitches':
# These rules go here because the overwrite/add to some of the above rules
if world.logic[player] == 'hybridglitches':
underworld_glitches_rules(world, player)
if world.mode[player] != 'inverted' and world.logic[player] in ['owglitches', 'hybridglitches']:
add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.world.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or')
@@ -732,6 +737,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)
add_key_logic_rules(world, player)
if world.logic[player] == 'hybridglitches':
add_hmg_key_logic_rules(world, player)
# End of door rando rules.
if world.restrict_boss_items[player] != 'none':
@@ -1852,6 +1860,8 @@ def set_inverted_big_bomb_rules(world, player):
def set_bunny_rules(world, player, inverted):
# 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.
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',
'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',
@@ -1894,13 +1904,29 @@ def set_bunny_rules(world, player, inverted):
return region.is_dark_world
else:
return region.is_light_world
# Is it possible to do bunny pocket here
def can_bunny_pocket_skull_woods(world, player):
return world.get_entrance(
"Skull Woods Second Section Door (West)", player
).connected_region.type == RegionType.Dungeon or (
world.state.can_reach_from("Skull Woods Forest (West)", "Light World", 1)
and world.state.can_reach_from("Light World", "Skull Woods Forest (West)", 1)
)
def can_bunny_pocket_voo_shop(world, player):
return (
world.state.can_reach_from("West Dark World", "Light World", 1)
and world.state.can_reach_from("Light World", "West Dark World", 1)
)
def get_rule_to_add(region, location=None, connecting_entrance=None):
# In OWG, a location can potentially be superbunny-mirror accessible or
# bunny revival accessible.
if world.logic[player] == 'owglitches':
if world.logic[player] in ['owglitches', 'hybridglitches']:
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):
return lambda state: state.has_Pearl(player)
else:
@@ -1928,14 +1954,19 @@ def set_bunny_rules(world, player, inverted):
new_path = path + [entrance.access_rule]
new_seen = seen.union({new_region})
if not is_link(new_region):
if world.logic[player] == 'owglitches':
if world.logic[player] in ['owglitches', 'hybridglitches']:
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
# Is this a bunny pocketable entrance?
if entrance.name == 'Skull Woods Final Section' and not can_bunny_pocket_skull_woods(world, player) or \
entrance.name == 'Dark World Shop' and not can_bunny_pocket_voo_shop(world, player):
continue
if entrance.name in drop_dungeon_entrances:
lobby = entrance.connected_region
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:
possible_options.append(path_to_access_rule(new_path, entrance))
elif lobby.name in superbunny_revivable_entrances:
@@ -1944,21 +1975,24 @@ 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))
continue
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
if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions():
if entrance.name == 'Skull Woods Final Section' and not can_bunny_pocket_skull_woods(world, player) or \
entrance.name == 'Dark World Shop' and not can_bunny_pocket_voo_shop(world, 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))
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))
elif location and location.name in OverworldGlitchRules.get_superbunny_accessible_locations():
if location.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_locations():
elif location and location.name in OverworldGlitchRules.superbunny_accessible_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))
elif region.name == 'Kakariko Well (top)':
possible_options.append(path_to_access_rule(new_path, entrance))
else:
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player)], entrance))
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))
else:
continue
@@ -2137,6 +2171,11 @@ bunny_impassible_if_trapped = {
'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):
key_logic = world.key_logic[player]

277
UnderworldGlitchRules.py Normal file
View File

@@ -0,0 +1,277 @@
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 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",
)

View File

@@ -23,6 +23,7 @@
"noglitches",
"minorglitches",
"owglitches",
"hybridglitches",
"nologic"
]
},

View File

@@ -55,7 +55,8 @@
"building.collection.spheres": "Building up collection spheres",
"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.",
"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": {
"lang": [ "App Language, if available, defaults to English" ],
@@ -63,11 +64,13 @@
"bps": [ "Output BPS patches instead of ROMs"],
"logic": [
"Select Enforcement of Item Requirements. (default: %(default)s)",
"No Glitches: No Glitch knowledge required.",
"Minor Glitches: May require Fake Flippers, Bunny Revival",
" and Dark Room Navigation.",
"No Logic: Distribute items without regard for",
" item requirements."
"No Glitches: No Glitch knowledge required.",
"Minor Glitches: May require Fake Flippers, Bunny Revival",
" 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",
" item requirements."
],
"mode": [
"Select game mode. (default: %(default)s)",

View File

@@ -237,6 +237,7 @@
"randomizer.item.logiclevel.noglitches": "No Glitches",
"randomizer.item.logiclevel.minorglitches": "Minor Glitches",
"randomizer.item.logiclevel.owglitches": "Overworld Glitches",
"randomizer.item.logiclevel.hybridglitches": "Hybrid Major Glitches",
"randomizer.item.logiclevel.nologic": "No Logic",
"randomizer.item.goal": "Goal",

View File

@@ -20,6 +20,7 @@
"noglitches",
"minorglitches",
"owglitches",
"hybridglitches",
"nologic"
]
},

View File

@@ -957,9 +957,9 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
invalid_connections = Must_Exit_Invalid_Connections.copy()
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
for entrance in OverworldGlitchRules.get_non_mandatory_exits(avail.inverted):
for entrance in OverworldGlitchRules.inverted_non_mandatory_exits if avail.inverted else OverworldGlitchRules.open_non_mandatory_exits:
invalid_connections[entrance] = set()
if entrance in must_exit:
must_exit.remove(entrance)

View File

@@ -80,7 +80,8 @@ def roll_settings(weights):
ret.algorithm = get_choice('algorithm')
glitch_map = {'none': 'noglitches', 'no_logic': 'nologic', 'owglitches': 'owglitches',
glitch_map = {'none': 'noglitches', 'no_logic': 'nologic', 'hybridglitches': 'hybridglitches',
'hmg': 'hybridglitches', 'owglitches': 'owglitches',
'owg': 'owglitches', 'minorglitches': 'minorglitches'}
glitches_required = get_choice('glitches_required')
if glitches_required is not None:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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