Implement basic HMG logic

* Ice Palace Lobby Clip
* Kikiskip to Pod
* Mire -> Hera -> Swamp
  - Mire small door to rupee room is removed
  - Hera and Swamp keys are placed without logic
  - Swamp locked by vanilla rules or having all mire smalls
* Above as connectors in ER
This commit is contained in:
KrisDavie
2023-02-12 09:44:52 +01:00
parent c4ebbe5421
commit dad1ee8336
22 changed files with 540 additions and 23 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)
@@ -1100,6 +1100,9 @@ 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 has_bottle(self, player):
return self.bottle_count(player) > 0
@@ -2973,7 +2976,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

@@ -938,8 +938,10 @@ def create_doors(world, player):
create_door(player, 'Mire Dark Shooters Up Stairs', Sprl).dir(Up, 0x93, 0, LTH).ss(A, 0x32, 0xec),
create_door(player, 'Mire Dark Shooters SW', Intr).dir(So, 0x93, Left, High).pos(0),
create_door(player, 'Mire Block X NW', Intr).dir(No, 0x93, Left, High).pos(0),
create_door(player, 'Mire Dark Shooters SE', Intr).dir(So, 0x93, Right, High).small_key().pos(1),
create_door(player, 'Mire Key Rupees NE', Intr).dir(No, 0x93, Right, High).small_key().pos(1),
create_door(player, 'Mire Dark Shooters SE', Intr).dir(So, 0x93, Right, High).pos(1) if world.logic[player] == 'hybridglitches' else create_door(player, 'Mire Dark Shooters SE', Intr).dir(So, 0x93, Right, High).small_key().pos(1),
create_door(player, 'Mire Key Rupees NE', Intr).dir(No, 0x93, Right, High).pos(1) if world.logic[player] == 'hybridglitches' else create_door(player, 'Mire Key Rupees NE', Intr).dir(No, 0x93, Right, High).small_key().pos(1),
# create_door(player, 'Mire Dark Shooters SE', Intr).dir(So, 0x93, Right, High).small_key().pos(1),
# create_door(player, 'Mire Key Rupees NE', Intr).dir(No, 0x93, Right, High).small_key().pos(1),
create_door(player, 'Mire Block X WS', Nrml).dir(We, 0x93, Bot, High).pos(2),
create_door(player, 'Mire Tall Dark and Roomy ES', Nrml).dir(Ea, 0x92, Bot, High).pos(4),
create_door(player, 'Mire Tall Dark and Roomy WN', Intr).dir(We, 0x92, Top, High).pos(0),

View File

@@ -1112,7 +1112,7 @@ def connect_mandatory_exits(world, entrances, caves, must_be_exits, player):
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'):
invalid_connections[entrance] = set()

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

@@ -881,7 +881,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 +1174,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 +1316,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

14
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
@@ -205,7 +206,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 +217,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 +248,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 +502,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 +587,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

@@ -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')
@@ -1898,7 +1903,7 @@ def set_bunny_rules(world, player, inverted):
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 not is_link(region):
@@ -1928,7 +1933,7 @@ 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():
continue
@@ -2154,6 +2159,9 @@ def add_key_logic_rules(world, player):
add_rule(dep.entrance, eval_func(door_name, d_name, player))
for location in d_logic.bk_restricted:
if not location.forced_item:
# Skip BK restricted locations in hybrid glitches. Bad, but necessary for now.
if world.logic[player] == 'hybridglitches' and d_name in ['Tower of Hera', 'Swamp Palace']:
continue
forbid_item(location, d_logic.bk_name, player)
for location in d_logic.sm_restricted:
forbid_item(location, d_logic.small_key_name, player)

173
UnderworldGlitchRules.py Normal file
View File

@@ -0,0 +1,173 @@
from BaseClasses import Entrance
import Rules
from OverworldGlitchRules import create_no_logic_connections
def get_kikiskip_spots():
"""
Spectacle Rock Cave (Bottom) -> Palace of Darkness Exit, a.k.a. Kiki Skip
"""
yield ("Kiki Skip", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Portal")
# We need to make connectors at a separate time from the connections, because of how dungeons are linked to regions
def get_kikiskip_connectors(world, player):
if world.fix_palaceofdarkness_exit[player] or world.fix_fake_world[player]:
yield ("Kiki Skip", "Spectacle Rock Cave (Bottom)", world.get_entrance("Palace of Darkness Exit", player).connected_region)
def get_mireheraswamp_connectors(world, player):
if world.fix_palaceofdarkness_exit[player] or world.fix_fake_world[player]:
yield ("Mire to Hera Clip", "Mire Torches Top", world.get_entrance("Tower of Hera Exit", player).connected_region)
yield ("Mire to Hera Clip", "Mire Torches Top", world.get_entrance("Swamp Palace Exit", player).connected_region)
def get_mireheraswamp_spots():
"""
"Mire Torches Top -> Tower of Hera Exit, a.k.a. Mire to Hera Clip
"Mire Torches Top -> Swamp Palace Exit, a.k.a. Hera to Swamp Clip
"""
yield ("Mire to Hera Clip", "Mire Torches Top", "Hera Portal")
yield ("Hera to Swamp Clip", "Mire Torches Top", "Swamp Portal")
def get_icepalace_spots():
"""
"Ice Palace Exit -> Ice Palace Exit, a.k.a. Ice Palace Clip
"""
yield ("Ice Lobby Clip", "Ice Portal", "Ice Bomb Drop")
# Create connections between dungeons
def create_hybridmajor_connections(world, player):
create_no_logic_connections(player, world, get_kikiskip_spots())
create_no_logic_connections(player, world, get_mireheraswamp_spots())
create_no_logic_connections(player, world, get_icepalace_spots())
# Turn dungeons into connectors 4
def create_hybridmajor_connectors(world, player):
create_no_logic_connections(player, world, get_kikiskip_connectors(world, player))
create_no_logic_connections(player, world, get_mireheraswamp_connectors(world, player))
# 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, 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
Rules.add_rule(world.get_entrance("Ice Lobby SE", player), lambda state: state.can_bomb_clip(world.get_region("Ice Lobby", player), 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_bomb_clip(world.get_region("Mire Torches Top", player), player) and state.has_fire_source(player)
def hera_clip(state):
return state.can_reach("Hera 4F", "Region", player) and state.can_bomb_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")
# 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 the doors going _into_ the dungeon
for door in [
"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")
# These doors let us go backwards so we don't require flippers
for door in [ "Swamp Trench 1 Approach ES", "Swamp Hammer Switch SW",]:
Rules.add_rule(world.get_entrance(door, player), lambda state: mire_clip(state) and state.has("Small Key (Misery Mire)", player, count=6), 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: True),
"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" if not inverted else "Inverted 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")
# Using the entrances for various ER types. Hera -> Swamp never matters because you can only logically traverse with the mire keys
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))
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")

View File

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

View File

@@ -63,11 +63,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,7 +957,7 @@ 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):
invalid_connections[entrance] = set()

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