Merge pull request #110 from compiling/multiworld
OWG mandatory exit rules
This commit is contained in:
commit
35933b88c4
|
@ -1910,9 +1910,7 @@ def connect_random(world, exitlist, targetlist, player, two_way=False):
|
|||
|
||||
|
||||
def connect_mandatory_exits(world, entrances, caves, must_be_exits, player):
|
||||
"""This works inplace"""
|
||||
random.shuffle(entrances)
|
||||
random.shuffle(caves)
|
||||
|
||||
# Keeps track of entrances that cannot be used to access each exit / cave
|
||||
if world.mode[player] == 'inverted':
|
||||
invalid_connections = Inverted_Must_Exit_Invalid_Connections.copy()
|
||||
|
@ -1920,6 +1918,18 @@ 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']:
|
||||
import OverworldGlitchRules
|
||||
for entrance in OverworldGlitchRules.get_non_mandatory_exits(world.mode[player] == 'inverted'):
|
||||
invalid_connections[entrance] = set()
|
||||
if entrance in must_be_exits:
|
||||
must_be_exits.remove(entrance)
|
||||
entrances.append(entrance)
|
||||
|
||||
"""This works inplace"""
|
||||
random.shuffle(entrances)
|
||||
random.shuffle(caves)
|
||||
|
||||
# Handle inverted Aga Tower - if it depends on connections, then so does Hyrule Castle Ledge
|
||||
if world.mode[player] == 'inverted':
|
||||
for entrance in invalid_connections:
|
||||
|
|
|
@ -92,6 +92,37 @@ def get_superbunny_accessible_locations():
|
|||
yield location
|
||||
|
||||
|
||||
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:
|
||||
|
||||
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)
|
||||
"""
|
||||
|
||||
yield 'Bumper Cave (Top)'
|
||||
yield 'Death Mountain Return Cave (West)'
|
||||
yield 'Hookshot Cave Back Entrance'
|
||||
|
||||
if inverted:
|
||||
yield 'Desert Palace Entrance (North)'
|
||||
yield 'Desert Palace Entrance (West)'
|
||||
yield 'Inverted Ganons 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)'
|
||||
|
||||
|
||||
def get_boots_clip_exits_lw(inverted = False):
|
||||
"""
|
||||
Special Light World region exits that require boots clips.
|
||||
|
@ -120,7 +151,7 @@ def get_boots_clip_exits_lw(inverted = False):
|
|||
yield ('Cave 45 Clip Spot', 'Light World', 'Cave 45 Ledge')
|
||||
|
||||
|
||||
def get_boots_clip_exits_dw(inverted = False):
|
||||
def get_boots_clip_exits_dw(inverted, player):
|
||||
"""
|
||||
Special Dark World region exits that require boots clips.
|
||||
"""
|
||||
|
@ -139,6 +170,7 @@ def get_boots_clip_exits_dw(inverted = False):
|
|||
yield ('Ganons Tower Ascent', 'Dark Death Mountain (West Bottom)', 'Dark Death Mountain (Top)') # This only gets you to the GT entrance
|
||||
yield ('Dark Death Mountain Glitched Bridge', 'Dark Death Mountain (West Bottom)', 'Dark Death Mountain (Top)')
|
||||
yield ('Turtle Rock (Top) Clip Spot', 'Dark Death Mountain (Top)', 'Turtle Rock (Top)')
|
||||
yield ('Ice Palace Clip', 'South Dark World', 'Dark Lake Hylia Central Island', lambda state: state.can_boots_clip_dw(player) and state.has('Flippers', player))
|
||||
else:
|
||||
yield ('Dark Desert Teleporter Clip Spot', 'Dark Desert', 'Dark Desert Ledge')
|
||||
|
||||
|
@ -152,26 +184,33 @@ def get_glitched_speed_drops_dw(inverted = False):
|
|||
|
||||
def get_mirror_clip_spots_dw():
|
||||
"""
|
||||
Mirror shenanigans that are in logic even if the player is a bunny.
|
||||
Out of bounds transitions using the mirror
|
||||
"""
|
||||
yield ('Dark Death Mountain Offset Mirror', 'Dark Death Mountain (West Bottom)', 'East Dark World')
|
||||
yield ('Dark Death Mountain Bunny Descent Mirror Spot', 'Dark Death Mountain (West Bottom)', 'Dark Death Mountain Bunny Descent Area')
|
||||
yield ('West Dark World Bunny Descent', 'Dark Death Mountain Bunny Descent Area', 'West Dark World')
|
||||
yield ('Dark Death Mountain (East Bottom) Jump', 'Dark Death Mountain Bunny Descent Area', 'Dark Death Mountain (East Bottom)')
|
||||
yield ('Desert East Mirror Clip', 'Dark Desert', 'Desert Palace Lone Stairs')
|
||||
|
||||
|
||||
def get_mirror_clip_spots_lw():
|
||||
def get_mirror_offset_spots_dw():
|
||||
"""
|
||||
Inverted mirror shenanigans in logic even if the player is a bunny.
|
||||
Mirror shenanigans placing a mirror portal with a broken camera
|
||||
"""
|
||||
yield ('Death Mountain Bunny Descent Mirror Spot', 'Death Mountain', 'Death Mountain Bunny Descent Area')
|
||||
yield ('Light World Bunny Descent', 'Death Mountain Bunny Descent Area', 'Light World')
|
||||
yield ('East Death Mountain (Bottom) Jump', 'Death Mountain Bunny Descent Area', 'East Death Mountain (Bottom)')
|
||||
yield ('Dark Death Mountain Offset Mirror', 'Dark Death Mountain (West 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', 'Death Mountain', 'Light World')
|
||||
yield ('Death Mountain Offset Mirror (Houlihan Exit)', 'Death Mountain', 'Hyrule Castle Ledge', lambda state: state.has_Mirror(player) and state.can_boots_clip_dw(player) and state.has_Pearl(player))
|
||||
|
||||
|
||||
|
||||
def get_invalid_bunny_revival_dungeons():
|
||||
"""
|
||||
Dungeon regions that can't be bunny revived from.
|
||||
Dungeon regions that can't be bunny revived from without superbunny state.
|
||||
"""
|
||||
yield 'Tower of Hera (Bottom)'
|
||||
yield 'Swamp Palace (Entrance)'
|
||||
|
@ -183,10 +222,7 @@ def overworld_glitches_rules(world, player):
|
|||
|
||||
# Boots-accessible locations.
|
||||
create_owg_connections(player, world, get_boots_clip_exits_lw(world.mode[player] == 'inverted'), lambda state: state.can_boots_clip_lw(player))
|
||||
create_owg_connections(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted'), lambda state: state.can_boots_clip_dw(player))
|
||||
|
||||
if world.mode[player] != 'inverted':
|
||||
create_owg_connections(player, world, [('Ice Palace Clip', 'South Dark World', 'Dark Lake Hylia Central Island')], lambda state: state.can_boots_clip_dw(player) and state.has('Flippers', player))
|
||||
create_owg_connections(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted', player), lambda state: state.can_boots_clip_dw(player))
|
||||
|
||||
# Glitched speed drops.
|
||||
create_owg_connections(player, world, get_glitched_speed_drops_dw(world.mode[player] == 'inverted'), lambda state: state.can_get_glitched_speed_dw(player))
|
||||
|
@ -197,8 +233,9 @@ def overworld_glitches_rules(world, player):
|
|||
# Mirror clip spots.
|
||||
if world.mode[player] != 'inverted':
|
||||
create_owg_connections(player, world, get_mirror_clip_spots_dw(), lambda state: state.has_Mirror(player))
|
||||
create_owg_connections(player, world, get_mirror_offset_spots_dw(), lambda state: state.has_Mirror(player) and state.can_boots_clip_lw(player))
|
||||
else:
|
||||
create_owg_connections(player, world, get_mirror_clip_spots_lw(), lambda state: state.has_Mirror(player))
|
||||
create_owg_connections(player, world, get_mirror_offset_spots_lw(player), lambda state: state.has_Mirror(player) and state.can_boots_clip_dw(player))
|
||||
|
||||
# Regions that require the boots and some other stuff.
|
||||
if world.mode[player] != 'inverted':
|
||||
|
@ -220,11 +257,12 @@ def add_alternate_rule(entrance, rule):
|
|||
entrance.access_rule = lambda state: old_rule(state) or rule(state)
|
||||
|
||||
|
||||
def create_owg_connections(player, world, connections, rule):
|
||||
for entrance, parent_region, target_region in connections:
|
||||
def create_owg_connections(player, world, connections, default_rule):
|
||||
for entrance, parent_region, target_region, *rule_override in connections:
|
||||
parent = world.get_region(parent_region, player)
|
||||
target = world.get_region(target_region, player)
|
||||
connection = Entrance(player, entrance, parent)
|
||||
parent.exits.append(connection)
|
||||
connection.connect(target)
|
||||
rule = rule_override[0] if len(rule_override) > 0 else default_rule
|
||||
connection.access_rule = rule
|
||||
|
|
|
@ -81,42 +81,44 @@ class TestDarkWorld(TestVanillaOWG):
|
|||
|
||||
["Pyramid", False, []],
|
||||
["Pyramid", False, [], ['Beat Agahnim 1', 'Moon Pearl', 'Magic Mirror']],
|
||||
["Pyramid", False, [], ['Beat Agahnim 1', 'Moon Pearl', 'Pegasus Boots', 'Flute', 'Lamp']],
|
||||
["Pyramid", False, [], ['Beat Agahnim 1', 'Moon Pearl', 'Pegasus Boots']],
|
||||
["Pyramid", True, ['Moon Pearl', 'Pegasus Boots']],
|
||||
["Pyramid", True, ['Magic Mirror', 'Pegasus Boots']],
|
||||
["Pyramid", True, ['Magic Mirror', 'Flute']],
|
||||
["Pyramid", True, ['Magic Mirror', 'Progressive Glove', 'Lamp']],
|
||||
["Pyramid", True, ['Beat Agahnim 1']],
|
||||
["Pyramid", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']],
|
||||
["Pyramid", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Flippers']],
|
||||
|
||||
["Pyramid Fairy - Left", False, []],
|
||||
["Pyramid Fairy - Left", False, [], ['Pegasus Boots', 'Moon Pearl', 'Flute', 'Lamp']],
|
||||
["Pyramid Fairy - Left", False, [], ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']],
|
||||
["Pyramid Fairy - Left", False, [], ['Pegasus Boots', 'Moon Pearl', 'Crystal 5']],
|
||||
["Pyramid Fairy - Left", False, [], ['Pegasus Boots', 'Moon Pearl', 'Crystal 6']],
|
||||
["Pyramid Fairy - Left", False, [], ['Magic Mirror', 'Crystal 5']],
|
||||
["Pyramid Fairy - Left", False, [], ['Magic Mirror', 'Crystal 6']],
|
||||
["Pyramid Fairy - Left", False, [], ['Magic Mirror', 'Moon Pearl']],
|
||||
["Pyramid Fairy - Left", True, ['Magic Mirror', 'Pegasus Boots']],
|
||||
["Pyramid Fairy - Left", True, ['Flute', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Hammer']],
|
||||
["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Progressive Glove', 'Hammer']],
|
||||
["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Flippers', 'Hookshot', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Left", True, ['Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Flute', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Left", True, ['Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Lamp', 'Magic Mirror']],
|
||||
|
||||
["Pyramid Fairy - Right", False, []],
|
||||
["Pyramid Fairy - Right", False, [], ['Pegasus Boots', 'Moon Pearl', 'Flute', 'Lamp']],
|
||||
["Pyramid Fairy - Right", False, [], ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']],
|
||||
["Pyramid Fairy - Right", False, [], ['Pegasus Boots', 'Moon Pearl', 'Crystal 5']],
|
||||
["Pyramid Fairy - Right", False, [], ['Pegasus Boots', 'Moon Pearl', 'Crystal 6']],
|
||||
["Pyramid Fairy - Right", False, [], ['Magic Mirror', 'Crystal 5']],
|
||||
["Pyramid Fairy - Right", False, [], ['Magic Mirror', 'Crystal 6']],
|
||||
["Pyramid Fairy - Right", False, [], ['Magic Mirror', 'Moon Pearl']],
|
||||
["Pyramid Fairy - Right", True, ['Magic Mirror', 'Pegasus Boots']],
|
||||
["Pyramid Fairy - Right", True, ['Flute', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Hammer']],
|
||||
["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Progressive Glove', 'Hammer']],
|
||||
["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Flippers', 'Hookshot', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Right", True, ['Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Flute', 'Magic Mirror']],
|
||||
["Pyramid Fairy - Right", True, ['Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Lamp', 'Magic Mirror']],
|
||||
|
||||
["Ganon", False, []],
|
||||
["Ganon", False, [], ['Moon Pearl']],
|
||||
|
|
Loading…
Reference in New Issue