Merge branch 'KrisDavie-hmg_logic' into DoorDevVolatile
This commit is contained in:
@@ -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}
|
||||
|
||||
|
||||
@@ -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]:
|
||||
|
||||
5
Fill.py
5
Fill.py
@@ -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)
|
||||
|
||||
11
ItemList.py
11
ItemList.py
@@ -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:
|
||||
|
||||
@@ -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
17
Main.py
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
31
README.md
31
README.md
@@ -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
|
||||
|
||||
67
Rules.py
67
Rules.py
@@ -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
277
UnderworldGlitchRules.py
Normal 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",
|
||||
)
|
||||
@@ -23,6 +23,7 @@
|
||||
"noglitches",
|
||||
"minorglitches",
|
||||
"owglitches",
|
||||
"hybridglitches",
|
||||
"nologic"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -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)",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"noglitches",
|
||||
"minorglitches",
|
||||
"owglitches",
|
||||
"hybridglitches",
|
||||
"nologic"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
35
test/customizer/hmg/fireless_ice.yaml
Normal file
35
test/customizer/hmg/fireless_ice.yaml
Normal 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
|
||||
42
test/customizer/hmg/hammer_in_swamp.yaml
Normal file
42
test/customizer/hmg/hammer_in_swamp.yaml
Normal 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
|
||||
34
test/customizer/hmg/mearl_in_pod.yaml
Normal file
34
test/customizer/hmg/mearl_in_pod.yaml
Normal 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
|
||||
42
test/customizer/hmg/mirrorless_swamp.yaml
Normal file
42
test/customizer/hmg/mirrorless_swamp.yaml
Normal 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
|
||||
44
test/customizer/hmg/pod_as_connector.yaml
Normal file
44
test/customizer/hmg/pod_as_connector.yaml
Normal 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
|
||||
55
test/customizer/hmg/swamp_as_connector.yaml
Normal file
55
test/customizer/hmg/swamp_as_connector.yaml
Normal 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
|
||||
|
||||
44
test/customizer/hmg/swamp_small_in_swamp_back.yaml
Normal file
44
test/customizer/hmg/swamp_small_in_swamp_back.yaml
Normal 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
|
||||
34
test/suite/hmg/entrance_bunny_pocket_sw.yaml
Normal file
34
test/suite/hmg/entrance_bunny_pocket_sw.yaml
Normal 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)
|
||||
|
||||
17
test/suite/hmg/fireless_ice.yaml
Normal file
17
test/suite/hmg/fireless_ice.yaml
Normal 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
|
||||
20
test/suite/hmg/flippers_locked_flippers.yaml
Normal file
20
test/suite/hmg/flippers_locked_flippers.yaml
Normal 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
|
||||
|
||||
29
test/suite/hmg/flippers_wraps.yaml
Normal file
29
test/suite/hmg/flippers_wraps.yaml
Normal 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
|
||||
|
||||
26
test/suite/hmg/hera_from_mire.yaml
Normal file
26
test/suite/hmg/hera_from_mire.yaml
Normal 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
|
||||
26
test/suite/hmg/inverted_inaccessible_desert.yaml
Normal file
26
test/suite/hmg/inverted_inaccessible_desert.yaml
Normal 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)
|
||||
|
||||
31
test/suite/hmg/inverted_moon_pearl_locs.yaml
Normal file
31
test/suite/hmg/inverted_moon_pearl_locs.yaml
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
48
test/suite/hmg/moon_pearl_locs.yaml
Normal file
48
test/suite/hmg/moon_pearl_locs.yaml
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
25
test/suite/hmg/pearlless_sw.yaml
Normal file
25
test/suite/hmg/pearlless_sw.yaml
Normal 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
|
||||
43
test/suite/hmg/swamp_from_mire.yaml
Normal file
43
test/suite/hmg/swamp_from_mire.yaml
Normal 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
|
||||
Reference in New Issue
Block a user