Merge branch 'KrisDavie-hmg_logic' into DoorDevVolatile
This commit is contained in:
72
Rules.py
72
Rules.py
@@ -9,6 +9,7 @@ from Dungeons import dungeon_table
|
||||
from RoomData import DoorKind
|
||||
from OWEdges import OWExitTypes
|
||||
from OverworldGlitchRules import overworld_glitches_rules
|
||||
from UnderworldGlitchRules import underworld_glitches_rules
|
||||
|
||||
|
||||
def set_rules(world, player):
|
||||
@@ -32,7 +33,7 @@ def set_rules(world, player):
|
||||
logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.')
|
||||
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.
|
||||
@@ -84,6 +85,9 @@ def set_rules(world, player):
|
||||
if not world.is_copied_world:
|
||||
set_bunny_rules(world, player, world.mode[player] == 'inverted')
|
||||
|
||||
# These rules go here because they overwrite/add to some of the above rules
|
||||
if world.logic[player] == 'hybridglitches':
|
||||
underworld_glitches_rules(world, player)
|
||||
|
||||
def mirrorless_path_to_location(world, startName, targetName, player):
|
||||
# If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch.
|
||||
@@ -845,6 +849,9 @@ def global_rules(world, player):
|
||||
set_rule(world.get_entrance('GT Crystal Circles to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_blunt_weapon(player) or state.has('Cane of Byrna', player)) # or state.has_beam_sword(player)
|
||||
|
||||
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':
|
||||
@@ -1644,6 +1651,8 @@ def find_rules_for_zelda_delivery(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',
|
||||
@@ -1668,6 +1677,9 @@ def set_bunny_rules(world, player, inverted):
|
||||
'Take - Any # 3 Item 1', 'Take - Any # 3 Item 2',
|
||||
'Take - Any # 4 Item 1', 'Take - Any # 4 Item 2',
|
||||
]
|
||||
bunny_pocket_entrances = ['Skull Woods Final Section', 'Bush Yard Pegs (Inner)', 'Bush Yard Pegs (Outer)',
|
||||
'DM Hammer Bridge (West)', 'DM Hammer Bridge (East)', 'Blacksmith Ledge Peg (West)'
|
||||
]
|
||||
|
||||
def path_to_access_rule(path, entrance):
|
||||
return lambda state: state.can_reach(entrance) and all(rule_func(state) for rule_func in path)
|
||||
@@ -1687,13 +1699,32 @@ 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_to(world, entrance_name, player):
|
||||
def can_activate_bunny_pocket(region):
|
||||
explored_regions.append(region.name)
|
||||
for ent in region.entrances:
|
||||
if (is_link(ent.parent_region) or
|
||||
(ent.parent_region.type == RegionType.Dungeon and ent.parent_region.name in bunny_revivable_entrances)):
|
||||
return True
|
||||
for ent in region.entrances:
|
||||
if ent.spot_type in ['OWEdge', 'Ledge', 'OpenTerrain'] and ent.parent_region.name not in explored_regions:
|
||||
if can_activate_bunny_pocket(ent.parent_region):
|
||||
return True
|
||||
return False
|
||||
|
||||
entrance = world.get_entrance(entrance_name, player)
|
||||
explored_regions = []
|
||||
return can_activate_bunny_pocket(entrance.parent_region)
|
||||
|
||||
|
||||
def get_rule_to_add(region, location=None, connecting_entrance=None):
|
||||
# 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:
|
||||
@@ -1723,14 +1754,18 @@ def set_bunny_rules(world, player, inverted):
|
||||
new_path = path + [entrance.access_rule]
|
||||
seen_sets.add(frozenset(new_seen))
|
||||
if not is_link(new_region):
|
||||
if world.logic[player] == 'owglitches':
|
||||
if world.logic[player] in ['owglitches', 'hybridglitches']:
|
||||
# Is this a bunny pocketable entrance?
|
||||
if region.type == RegionType.Dungeon and new_region.type != RegionType.Dungeon:
|
||||
if entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances():
|
||||
if entrance.name in OverworldGlitchRules.invalid_mirror_bunny_entrances:
|
||||
continue
|
||||
if entrance.name in bunny_pocket_entrances and not can_bunny_pocket_to(world, entrance.name, player):
|
||||
continue
|
||||
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:
|
||||
@@ -1739,21 +1774,23 @@ def set_bunny_rules(world, player, inverted):
|
||||
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_sword(player)], entrance))
|
||||
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 in bunny_pocket_entrances and not can_bunny_pocket_to(world, entrance.name, player):
|
||||
continue
|
||||
if region.name in OverworldGlitchRules.sword_required_superbunny_mirror_regions:
|
||||
possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_sword(player)], entrance))
|
||||
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
|
||||
@@ -1767,7 +1804,6 @@ def set_bunny_rules(world, player, inverted):
|
||||
|
||||
# Add requirements for bunny-impassible caves if they occur in the light world
|
||||
for region in [world.get_region(name, player) for name in bunny_impassable_caves]:
|
||||
|
||||
if not is_bunny(region):
|
||||
continue
|
||||
rule = get_rule_to_add(region)
|
||||
@@ -1802,6 +1838,11 @@ def set_bunny_rules(world, player, inverted):
|
||||
continue
|
||||
add_rule(location, get_rule_to_add(region, location))
|
||||
|
||||
for ent_name in bunny_pocket_entrances:
|
||||
bunny_exit = world.get_entrance(ent_name, player)
|
||||
if bunny_exit.connected_region and is_bunny(bunny_exit.parent_region) and not can_bunny_pocket_to(world, ent_name, player):
|
||||
add_rule(bunny_exit, lambda state: state.has_Pearl(player))
|
||||
|
||||
|
||||
drop_dungeon_entrances = {
|
||||
"Sewer Drop",
|
||||
@@ -1929,6 +1970,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]
|
||||
|
||||
Reference in New Issue
Block a user