2020-05-07 08:07:53 +00:00
"""
Helper functions to deliver entrance / exit / region sets to OWG rules .
"""
from BaseClasses import Entrance
def get_sword_required_superbunny_mirror_regions ( ) :
"""
Cave regions that superbunny can get through - but only with a sword .
"""
yield ' Spiral Cave (Top) '
def get_boots_required_superbunny_mirror_regions ( ) :
"""
Cave regions that superbunny can get through - but only with boots .
"""
yield ' Two Brothers House '
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 '
2020-05-07 10:00:29 +00:00
def get_invalid_mirror_bunny_entrances ( ) :
2020-05-07 08:07:53 +00:00
"""
2020-05-07 10:00:29 +00:00
Entrances that can ' t be superbunny-mirrored into.
2020-05-07 08:07:53 +00:00
"""
2020-05-07 10:00:29 +00:00
yield ' Skull Woods Final Section '
2020-05-07 08:07:53 +00:00
yield ' Hype Cave '
yield ' Bonk Fairy (Dark) '
yield ' Thieves Town '
yield ' Dark World Hammer Peg Cave '
yield ' Brewery '
yield ' Hookshot Cave '
yield ' Dark Lake Hylia Ledge Fairy '
yield ' Dark Lake Hylia Ledge Spike Cave '
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 '
def get_superbunny_accessible_locations ( ) :
"""
Interior locations that can be accessed with superbunny state .
"""
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
2020-06-13 09:12:01 +00:00
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) '
2020-05-07 08:07:53 +00:00
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 Drop Ledge ' )
yield ( ' Light World DMA Clip Spot ' , ' Light World ' , ' Death Mountain ' )
yield ( ' Hera Ascent ' , ' Death Mountain ' , ' 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 ' , ' Death Mountain ' , ' East Death Mountain (Top) ' )
yield ( ' Zora Descent Clip Spot ' , ' East Death Mountain (Top) ' , ' Zoras River ' )
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 ' , ' Death Mountain ' , ' Light World ' )
yield ( ' Kings Grave Clip Spot ' , ' Death Mountain ' , ' Kings Grave Area ' )
if not inverted :
yield ( ' Graveyard Ledge Clip Spot ' , ' Death Mountain ' , ' Graveyard Ledge ' )
yield ( ' Desert Ledge (Northeast) Dropdown ' , ' Desert Northern Cliffs ' , ' Desert Ledge (Northeast) ' )
yield ( ' Spectacle Rock Clip Spot ' , ' 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 (Light World) ' )
yield ( ' Cave 45 Clip Spot ' , ' Light World ' , ' Cave 45 Ledge ' )
2020-06-13 05:39:58 +00:00
def get_boots_clip_exits_dw ( inverted , player ) :
2020-05-07 08:07:53 +00:00
"""
Special Dark World region exits that require boots clips .
"""
yield ( ' Dark World DMA Clip Spot ' , ' West Dark World ' , inverted and ' Dark Death Mountain ' or ' Dark Death Mountain (West 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 ' , inverted and ' Dark Death Mountain ' or ' Dark Death Mountain (Top) ' , ' Catfish ' )
yield ( ' Hammer Pegs River Clip Spot ' , ' East Dark World ' , ' Hammer Peg Area ' )
yield ( ' Dark Lake Hylia Ledge Clip Spot ' , ' East Dark World ' , ' Dark Lake Hylia Ledge ' )
yield ( ' Dark Desert Cliffs Clip Spot ' , ' South Dark World ' , ' Dark Desert ' )
2020-05-08 08:23:55 +00:00
yield ( ' DW Floating Island Clip Spot ' , ' Dark Death Mountain (East Bottom) ' , ' Death Mountain Floating Island (Dark World) ' )
2020-05-07 08:07:53 +00:00
if not inverted :
yield ( ' Dark Death Mountain Descent ' , ' Dark Death Mountain (West Bottom) ' , ' West Dark World ' )
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) ' )
2020-06-13 05:39:58 +00:00
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 ) )
2020-05-07 08:07:53 +00:00
else :
yield ( ' Dark Desert Teleporter Clip Spot ' , ' Dark Desert ' , ' Dark Desert Ledge ' )
def get_glitched_speed_drops_dw ( inverted = False ) :
"""
Dark World drop - down ledges that require glitched speed .
"""
yield ( ' Dark Death Mountain Ledge Clip Spot ' , inverted and ' Dark Death Mountain ' or ' Dark Death Mountain (Top) ' , ' Dark Death Mountain Ledge ' )
def get_mirror_clip_spots_dw ( ) :
"""
2020-06-13 05:39:58 +00:00
Out of bounds transitions using the mirror
2020-05-07 08:07:53 +00:00
"""
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) ' )
2020-06-13 05:39:58 +00:00
yield ( ' Desert East Mirror Clip ' , ' Dark Desert ' , ' Desert Palace Lone Stairs ' )
2020-05-07 08:07:53 +00:00
2020-06-13 05:39:58 +00:00
def get_mirror_offset_spots_dw ( ) :
2020-05-07 08:07:53 +00:00
"""
2020-06-13 05:39:58 +00:00
Mirror shenanigans placing a mirror portal with a broken camera
2020-05-07 08:07:53 +00:00
"""
2020-06-13 05:39:58 +00:00
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 ' )
2021-02-27 16:11:54 +00:00
yield ( ' Death Mountain Offset Mirror (Houlihan Exit) ' , ' Death Mountain ' , ' Hyrule Castle Ledge ' , lambda state : state . has ( ' Magic Mirror ' , player ) and state . can_boots_clip_dw ( player ) and state . has ( ' Moon Pearl ' , player ) )
2020-06-13 05:39:58 +00:00
2020-05-07 08:07:53 +00:00
def get_invalid_bunny_revival_dungeons ( ) :
"""
2020-06-13 05:39:58 +00:00
Dungeon regions that can ' t be bunny revived from without superbunny state.
2020-05-07 08:07:53 +00:00
"""
yield ' Tower of Hera (Bottom) '
yield ' Swamp Palace (Entrance) '
yield ' Turtle Rock (Entrance) '
yield ' Sanctuary '
2020-07-10 07:37:35 +00:00
def no_logic_rules ( world , player ) :
"""
Add OWG transitions to no logic player ' s world
"""
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 ' , player ) )
# 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 ( ) )
else :
create_no_logic_connections ( player , world , get_mirror_offset_spots_lw ( player ) )
2020-05-07 08:07:53 +00:00
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 ) )
2020-06-13 05:39:58 +00:00
create_owg_connections ( player , world , get_boots_clip_exits_dw ( world . mode [ player ] == ' inverted ' , player ) , lambda state : state . can_boots_clip_dw ( player ) )
2020-05-07 08:07:53 +00:00
# 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 ) )
# Dark Death Mountain Ledge Clip Spot also accessible with mirror.
if world . mode [ player ] != ' inverted ' :
2021-02-27 16:11:54 +00:00
add_alternate_rule ( world . get_entrance ( ' Dark Death Mountain Ledge Clip Spot ' , player ) , lambda state : state . has ( ' Magic Mirror ' , player ) )
2020-05-07 08:07:53 +00:00
# Mirror clip spots.
if world . mode [ player ] != ' inverted ' :
2021-02-27 16:11:54 +00:00
create_owg_connections ( player , world , get_mirror_clip_spots_dw ( ) , lambda state : state . has ( ' Magic Mirror ' , player ) )
create_owg_connections ( player , world , get_mirror_offset_spots_dw ( ) , lambda state : state . has ( ' Magic Mirror ' , player ) and state . can_boots_clip_lw ( player ) )
2020-05-07 08:07:53 +00:00
else :
2021-02-27 16:11:54 +00:00
create_owg_connections ( player , world , get_mirror_offset_spots_lw ( player ) , lambda state : state . has ( ' Magic Mirror ' , player ) and state . can_boots_clip_dw ( player ) )
2020-05-07 08:07:53 +00:00
# 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 )
2021-02-27 16:11:54 +00:00
add_alternate_rule ( world . get_entrance ( ' Waterfall of Wishing ' , player ) , lambda state : state . has ( ' Moon Pearl ' , player ) or state . has ( ' Pegasus Boots ' , player ) )
2020-05-07 08:07:53 +00:00
else :
2020-05-07 08:58:57 +00:00
add_alternate_rule ( world . get_entrance ( ' Waterfall of Wishing Cave ' , player ) , lambda state : state . has ( ' Moon Pearl ' , player ) )
2020-05-07 08:07:53 +00:00
2021-02-27 16:11:54 +00:00
world . get_entrance ( ' Dark Desert Teleporter ' , player ) . access_rule = lambda state : ( state . has ( ' Flute ' , player ) or state . has ( ' Pegasus Boots ' , player ) ) and state . can_lift_heavy_rocks ( player )
2020-05-07 08:07:53 +00:00
add_alternate_rule ( world . get_entrance ( ' Catfish Exit Rock ' , player ) , lambda state : state . can_boots_clip_dw ( player ) )
add_alternate_rule ( world . get_entrance ( ' East Dark World Broken Bridge Pass ' , player ) , lambda state : state . can_boots_clip_dw ( player ) )
# Zora's Ledge via waterwalk setup.
2021-02-27 16:11:54 +00:00
add_alternate_rule ( world . get_location ( ' Zora \' s Ledge ' , player ) , lambda state : state . has ( ' Pegasus Boots ' , player ) )
2020-05-07 08:07:53 +00:00
def add_alternate_rule ( entrance , rule ) :
old_rule = entrance . access_rule
entrance . access_rule = lambda state : old_rule ( state ) or rule ( state )
2020-05-08 09:32:04 +00:00
2020-07-10 07:37:35 +00:00
def create_no_logic_connections ( player , world , connections ) :
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 )
2020-06-13 05:39:58 +00:00
def create_owg_connections ( player , world , connections , default_rule ) :
for entrance , parent_region , target_region , * rule_override in connections :
2020-05-07 08:07:53 +00:00
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 )
2020-06-13 05:39:58 +00:00
rule = rule_override [ 0 ] if len ( rule_override ) > 0 else default_rule
2020-05-07 08:07:53 +00:00
connection . access_rule = rule