diff --git a/EntranceShuffle.py b/EntranceShuffle.py index b1d3a97d..88179b92 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -2988,49 +2988,14 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Ganons Tower Moldorm Door', 'Ganons Tower (Moldorm)'), ('Ganons Tower Moldorm Gap', 'Agahnim 2'), ('Ganon Drop', 'Bottom of Pyramid'), - ('Pyramid Drop', 'East Dark World'), - ('Light World DMA Clip Spot', 'Death Mountain'), - ('Hera Ascent', 'Death Mountain (Top)'), - ('Spectacle Rock Clip Spot', 'Spectacle Rock'), - ('Death Mountain Return Ledge Clip Spot', 'Death Mountain Return Ledge'), - ('Death Mountain Glitched Bridge', 'East Death Mountain (Top)'), - ('Floating Island Clip Spot', 'Death Mountain Floating Island (Light World)'), - ('Dark Death Mountain Ledge Clip Spot', 'Dark Death Mountain Ledge'), - ('Zora Descent Clip Spot', 'Zoras River'), - #todo: Entrances shouldn't lead to multiple regions. This currently works, but it's fragile - ('Graveyard Ledge Clip Spot', 'Graveyard Ledge'), - ('Graveyard Ledge Clip Spot', 'Kings Grave Area'), - ('Desert Northern Cliffs', 'Desert Ledge'), - ('Desert Northern Cliffs', 'Desert Ledge (Northeast)'), - ('Desert Northern Cliffs', 'Desert Palace Entrance (North) Spot'), - ('Lake Hylia Island Clip Spot', 'Lake Hylia Island'), - ('Dark World DMA Clip Spot', 'Dark Death Mountain (West Bottom)'), - ('Ganons Tower Ascent', 'Dark Death Mountain (Top)'), - ('Bumper Cave Ledge Clip Spot', 'Bumper Cave Ledge'), - ('Dark Death Mountain Glitched Bridge', 'Dark Death Mountain (Top)'), - ('Dark Death Mountain Bunny Descent Mirror Spot', 'Dark Death Mountain Bunny Descent Area'), - ('Catfish Descent', 'Catfish'), - ('Dark Death Mountain Offset Mirror', 'East Dark World'), - ('Hammer Pegs River Clip Spot', 'Hammer Peg Area'), - ('Dark Lake Hylia Ledge Clip Spot', 'Dark Lake Hylia Ledge'), - ('Dark Desert Cliffs Clip Spot', 'Dark Desert'), - ('Bumper Cave Ledge Clip Spot', 'Bumper Cave Entrance'), - ('Death Mountain Return Ledge Clip Spot', 'Death Mountain Entrance'), - ('West Dark World Bunny Descent', 'West Dark World'), - ('Dark Death Mountain (East Bottom) Jump', 'Dark Death Mountain (East Bottom)'), - ('Bat Cave River Clip Spot', 'Bat Cave Drop Ledge'), - ('Turtle Rock (Top) Clip Spot', 'Turtle Rock (Top)'), - ('Dark Death Mountain Descent', 'West Dark World'), - ('Death Mountain Descent', 'Light World'), - ('Bombos Tablet Clip Spot', 'Bombos Tablet Ledge'), - ('Cave 45 Clip Spot', 'Cave 45 Ledge'), + ('Pyramid Drop', 'East Dark World') ] inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central Island'), ('Lake Hylia Island Pier', 'Lake Hylia Island'), ('Lake Hylia Warp', 'Northeast Light World'), ('Northeast Light World Warp', 'Light World'), - ('Zoras River', 'Zoras River'),('Graveyard Ledge Clip Spot', 'Kings Grave Area'), + ('Zoras River', 'Zoras River'), ('Kings Grave Outer Rocks', 'Kings Grave Area'), ('Kings Grave Inner Rocks', 'Light World'), ('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'), @@ -3243,32 +3208,7 @@ inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia ('Bush Covered Lawn Mirror Spot', 'Dark Grassy Lawn'), ('Bomb Hut Inner Bushes', 'Light World'), ('Bomb Hut Outer Bushes', 'Bomb Hut Area'), - ('Bomb Hut Mirror Spot', 'West Dark World'), - ('Light World DMA Clip Spot', 'Death Mountain'), - ('Hera Ascent', 'Death Mountain (Top)'), - ('Death Mountain Return Ledge Clip Spot', 'Death Mountain Return Ledge'), - ('Death Mountain Glitched Bridge', 'East Death Mountain (Top)'), - ('Dark Death Mountain Ledge Clip Spot', 'Dark Death Mountain Ledge'), - ('Zora Descent Clip Spot', 'Zoras River'), - ('Desert Northern Cliffs', 'Desert Ledge'), - ('Desert Northern Cliffs', 'Desert Palace Entrance (North) Spot'), - ('Lake Hylia Island Clip Spot', 'Lake Hylia Island'), - ('Dark World DMA Clip Spot', 'Dark Death Mountain'), - ('Bumper Cave Ledge Clip Spot', 'Bumper Cave Ledge'), - ('Catfish Descent', 'Catfish'), - ('Death Mountain Offset Mirror', 'Light World'), - ('Hammer Pegs River Clip Spot', 'Hammer Peg Area'), - ('Dark Lake Hylia Ledge Clip Spot', 'Dark Lake Hylia Ledge'), - ('Dark Desert Cliffs Clip Spot', 'Dark Desert'), - ('Bumper Cave Ledge Clip Spot', 'Bumper Cave Entrance'), - ('Death Mountain Return Ledge Clip Spot', 'Death Mountain Entrance'), - ('Light World Bunny Descent', 'Light World'), - ('East Death Mountain (Bottom) Jump', 'East Death Mountain (Bottom)'), - ('Bat Cave River Clip Spot', 'Bat Cave Drop Ledge'), - ('Turtle Rock (Top) Clip Spot', 'Turtle Rock (Top)'), - ('Dark Death Mountain Descent', 'West Dark World'), - ('Death Mountain Descent', 'Light World'), - ('Death Mountain Bunny Descent Mirror Spot', 'Death Mountain Bunny Descent Area')] + ('Bomb Hut Mirror Spot', 'West Dark World')] # non-shuffled entrance links default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'), ("Blinds Hideout", "Blinds Hideout"), diff --git a/InvertedRegions.py b/InvertedRegions.py index bd4b4051..75143410 100644 --- a/InvertedRegions.py +++ b/InvertedRegions.py @@ -18,8 +18,7 @@ def create_inverted_regions(world, player): 'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'East Dark World Mirror Spot', 'West Dark World Mirror Spot', 'South Dark World Mirror Spot', 'Cave 45', 'Checkerboard Cave', 'Mire Mirror Spot', 'Hammer Peg Area Mirror Spot', 'Shopping Mall Mirror Spot', 'Skull Woods Mirror Spot', 'Inverted Pyramid Entrance','Hyrule Castle Entrance (South)', 'Secret Passage Outer Bushes', 'Bush Covered Lawn Outer Bushes', - 'Potion Shop Outer Bushes', 'Graveyard Cave Outer Bushes', 'Bomb Hut Outer Bushes', 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Bat Cave River Clip Spot', - 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot']), + 'Potion Shop Outer Bushes', 'Graveyard Cave Outer Bushes', 'Bomb Hut Outer Bushes']), create_lw_region(player, 'Bush Covered Lawn', None, ['Bush Covered House', 'Bush Covered Lawn Inner Bushes', 'Bush Covered Lawn Mirror Spot']), create_lw_region(player, 'Bomb Hut Area', None, ['Light World Bomb Hut', 'Bomb Hut Inner Bushes', 'Bomb Hut Mirror Spot']), create_lw_region(player, 'Hyrule Castle Secret Entrance Area', None, ['Hyrule Castle Secret Entrance Stairs', 'Secret Passage Inner Bushes']), @@ -126,8 +125,7 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Old Man House', 'a connector', None, ['Old Man House Exit (Bottom)', 'Old Man House Front to Back']), create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']), create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', - 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Mirror Spot', 'Death Mountain Bunny Descent Mirror Spot', - 'Death Mountain Offset Mirror', 'Hera Ascent', 'Death Mountain Glitched Bridge', 'Death Mountain Descent', 'Graveyard Ledge Clip Spot']), + 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Mirror Spot']), create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']), create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Bumper Cave Ledge Mirror Spot']), create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']), @@ -148,7 +146,7 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Paradox Cave', 'a connector', None, ['Paradox Cave Exit (Middle)', 'Paradox Cave Exit (Top)', 'Paradox Cave Drop']), create_cave_region(player, 'Light World Death Mountain Shop', 'a common shop'), create_lw_region(player, 'East Death Mountain (Top)', ['Floating Island'], ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'East Death Mountain Mirror Spot (Top)', 'Fairy Ascension Ledge Access', 'Mimic Cave Ledge Access', - 'Floating Island Mirror Spot', 'Zora Descent Clip Spot']), + 'Floating Island Mirror Spot']), create_lw_region(player, 'Spiral Cave Ledge', None, ['Spiral Cave', 'Spiral Cave Ledge Drop', 'Dark Death Mountain Ledge Mirror Spot (West)']), create_lw_region(player, 'Mimic Cave Ledge', None, ['Mimic Cave', 'Mimic Cave Ledge Drop', 'Dark Death Mountain Ledge Mirror Spot (East)']), create_cave_region(player, 'Spiral Cave (Top)', 'a connector', ['Spiral Cave'], ['Spiral Cave (top to bottom)', 'Spiral Cave Exit (Top)']), @@ -165,14 +163,13 @@ def create_inverted_regions(world, player): create_dungeon_region(player, 'Tower of Hera (Top)', 'Tower of Hera', ['Tower of Hera - Compass Chest', 'Tower of Hera - Big Chest', 'Tower of Hera - Boss', 'Tower of Hera - Prize']), create_dw_region(player, 'East Dark World', ['Pyramid'], ['Pyramid Fairy', 'South Dark World Bridge', 'Palace of Darkness', 'Dark Lake Hylia Drop (East)', - 'Dark Lake Hylia Fairy', 'Palace of Darkness Hint', 'East Dark World Hint', 'Northeast Dark World Broken Bridge Pass', 'East Dark World Teleporter', 'EDW Flute', - 'Hammer Pegs River Clip Spot', 'Dark Lake Hylia Ledge Clip Spot']), + 'Dark Lake Hylia Fairy', 'Palace of Darkness Hint', 'East Dark World Hint', 'Northeast Dark World Broken Bridge Pass', 'East Dark World Teleporter', 'EDW Flute']), create_dw_region(player, 'Catfish', ['Catfish'], ['Catfish Exit Rock']), create_dw_region(player, 'Northeast Dark World', None, ['West Dark World Gap', 'Dark World Potion Shop', 'East Dark World Broken Bridge Pass', 'NEDW Flute', 'Dark Lake Hylia Teleporter', 'Catfish Entrance Rock']), create_cave_region(player, 'Palace of Darkness Hint', 'a storyteller'), create_cave_region(player, 'East Dark World Hint', 'a storyteller'), create_dw_region(player, 'South Dark World', ['Stumpy', 'Digging Game'], ['Dark Lake Hylia Drop (South)', 'Hype Cave', 'Swamp Palace', 'Village of Outcasts Heavy Rock', 'East Dark World Bridge', 'Inverted Links House', 'Archery Game', 'Bonk Fairy (Dark)', - 'Dark Lake Hylia Shop', 'South Dark World Teleporter', 'Post Aga Teleporter', 'SDW Flute', 'Dark Desert Cliffs Clip Spot']), + 'Dark Lake Hylia Shop', 'South Dark World Teleporter', 'Post Aga Teleporter', 'SDW Flute']), create_cave_region(player, 'Inverted Big Bomb Shop', 'the bomb shop'), create_cave_region(player, 'Archery Game', 'a game of skill'), create_dw_region(player, 'Dark Lake Hylia', None, ['East Dark World Pier', 'Dark Lake Hylia Ledge Pier', 'Ice Palace', 'Dark Lake Hylia Central Island Teleporter']), @@ -183,7 +180,7 @@ def create_inverted_regions(world, player): 'Hype Cave - Bottom', 'Hype Cave - Generous Guy']), create_dw_region(player, 'West Dark World', ['Frog'], ['Village of Outcasts Drop', 'East Dark World River Pier', 'Brewery', 'C-Shaped House', 'Chest Game', 'Thieves Town', 'Bumper Cave Entrance Rock', 'Skull Woods Forest', 'Village of Outcasts Pegs', 'Village of Outcasts Eastern Rocks', 'Red Shield Shop', 'Inverted Dark Sanctuary', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop', - 'West Dark World Teleporter', 'WDW Flute', 'Dark World DMA Clip Spot', 'Bumper Cave Ledge Clip Spot']), + 'West Dark World Teleporter', 'WDW Flute']), create_dw_region(player, 'Dark Grassy Lawn', None, ['Grassy Lawn Pegs', 'Dark World Shop', 'Dark Grassy Lawn Flute']), create_dw_region(player, 'Hammer Peg Area', ['Dark Blacksmith Ruins'], ['Dark World Hammer Peg Cave', 'Peg Area Rocks', 'Hammer Peg Area Flute']), create_dw_region(player, 'Bumper Cave Entrance', None, ['Bumper Cave (Bottom)', 'Bumper Cave Entrance Drop']), @@ -208,9 +205,7 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Mire Shed', 'a cave with two chests', ['Mire Shed - Left', 'Mire Shed - Right']), create_cave_region(player, 'Dark Desert Hint', 'a storyteller'), create_dw_region(player, 'Dark Death Mountain', None, ['Dark Death Mountain Drop (East)', 'Inverted Agahnims Tower', 'Superbunny Cave (Top)', 'Hookshot Cave', 'Turtle Rock', - 'Spike Cave', 'Dark Death Mountain Fairy', 'Dark Death Mountain Teleporter (West)', 'Turtle Rock Tail Drop', 'DDM Flute', - 'Dark Death Mountain Ledge Clip Spot', 'Catfish Descent', 'Turtle Rock (Top) Clip Spot', - 'Dark Death Mountain Descent']), + 'Spike Cave', 'Dark Death Mountain Fairy', 'Dark Death Mountain Teleporter (West)', 'Turtle Rock Tail Drop', 'DDM Flute']), create_dw_region(player, 'Dark Death Mountain Ledge', None, ['Dark Death Mountain Ledge (East)', 'Dark Death Mountain Ledge (West)']), create_dw_region(player, 'Turtle Rock (Top)', None, ['Dark Death Mountain Teleporter (East)', 'Turtle Rock Drop']), create_dw_region(player, 'Dark Death Mountain Isolated Ledge', None, ['Turtle Rock Isolated Ledge Entrance']), @@ -304,10 +299,12 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Pyramid', 'a drop\'s exit', ['Ganon'], ['Ganon Drop']), create_cave_region(player, 'Bottom of Pyramid', 'a drop\'s exit', None, ['Pyramid Exit']), create_dw_region(player, 'Pyramid Ledge', None, ['Pyramid Drop']), # houlihan room exits here in inverted - create_dw_region(player, 'Death Mountain Bunny Descent Area', None, ['Light World Bunny Descent', 'East Death Mountain (Bottom) Jump']), # to simplify flute connections - create_cave_region(player, 'The Sky', 'A Dark Sky', None, ['DDM Landing','NEDW Landing', 'WDW Landing', 'SDW Landing', 'EDW Landing', 'DD Landing', 'DLHL Landing']) + create_cave_region(player, 'The Sky', 'A Dark Sky', None, ['DDM Landing','NEDW Landing', 'WDW Landing', 'SDW Landing', 'EDW Landing', 'DD Landing', 'DLHL Landing']), + + create_lw_region(player, 'Desert Northern Cliffs'), + create_lw_region(player, 'Death Mountain Bunny Descent Area') ] world.initialize_regions() diff --git a/Main.py b/Main.py index 42135823..97d8c121 100644 --- a/Main.py +++ b/Main.py @@ -266,102 +266,6 @@ def main(args, seed=None): return world -def copy_world(world): - # ToDo: Not good yet - ret = World(world.players, world.shuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.retro, world.custom, world.customitemarray, world.hints) - ret.teams = world.teams - ret.player_names = copy.deepcopy(world.player_names) - ret.remote_items = world.remote_items.copy() - ret.required_medallions = world.required_medallions.copy() - ret.swamp_patch_required = world.swamp_patch_required.copy() - ret.ganon_at_pyramid = world.ganon_at_pyramid.copy() - ret.powder_patch_required = world.powder_patch_required.copy() - ret.ganonstower_vanilla = world.ganonstower_vanilla.copy() - ret.treasure_hunt_count = world.treasure_hunt_count.copy() - ret.treasure_hunt_icon = world.treasure_hunt_icon.copy() - ret.sewer_light_cone = world.sewer_light_cone.copy() - ret.light_world_light_cone = world.light_world_light_cone - ret.dark_world_light_cone = world.dark_world_light_cone - ret.seed = world.seed - ret.can_access_trock_eyebridge = world.can_access_trock_eyebridge.copy() - ret.can_access_trock_front = world.can_access_trock_front.copy() - ret.can_access_trock_big_chest = world.can_access_trock_big_chest.copy() - ret.can_access_trock_middle = world.can_access_trock_middle.copy() - ret.can_take_damage = world.can_take_damage - ret.difficulty_requirements = world.difficulty_requirements.copy() - ret.fix_fake_world = world.fix_fake_world.copy() - ret.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms - ret.mapshuffle = world.mapshuffle.copy() - ret.compassshuffle = world.compassshuffle.copy() - ret.keyshuffle = world.keyshuffle.copy() - ret.bigkeyshuffle = world.bigkeyshuffle.copy() - ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy() - ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy() - ret.open_pyramid = world.open_pyramid.copy() - ret.boss_shuffle = world.boss_shuffle.copy() - ret.enemy_shuffle = world.enemy_shuffle.copy() - ret.enemy_health = world.enemy_health.copy() - ret.enemy_damage = world.enemy_damage.copy() - ret.beemizer = world.beemizer.copy() - ret.timer = world.timer.copy() - ret.shufflepots = world.shufflepots.copy() - ret.extendedmsu = world.extendedmsu.copy() - - for player in range(1, world.players + 1): - if world.mode[player] != 'inverted': - create_regions(ret, player) - else: - create_inverted_regions(ret, player) - create_shops(ret, player) - create_dungeons(ret, player) - - copy_dynamic_regions_and_locations(world, ret) - - # copy bosses - for dungeon in world.dungeons: - for level, boss in dungeon.bosses.items(): - ret.get_dungeon(dungeon.name, dungeon.player).bosses[level] = boss - - for shop in world.shops: - copied_shop = ret.get_region(shop.region.name, shop.region.player).shop - copied_shop.inventory = copy.copy(shop.inventory) - - # connect copied world - for region in world.regions: - copied_region = ret.get_region(region.name, region.player) - copied_region.is_light_world = region.is_light_world - copied_region.is_dark_world = region.is_dark_world - for entrance in region.entrances: - ret.get_entrance(entrance.name, entrance.player).connect(copied_region) - - # fill locations - for location in world.get_locations(): - if location.item is not None: - item = Item(location.item.name, location.item.advancement, location.item.priority, location.item.type, player = location.item.player) - ret.get_location(location.name, location.player).item = item - item.location = ret.get_location(location.name, location.player) - item.world = ret - if location.event: - ret.get_location(location.name, location.player).event = True - if location.locked: - ret.get_location(location.name, location.player).locked = True - - # copy remaining itempool. No item in itempool should have an assigned location - for item in world.itempool: - ret.itempool.append(Item(item.name, item.advancement, item.priority, item.type, player = item.player)) - - for item in world.precollected_items: - ret.push_precollected(ItemFactory(item.name, item.player)) - - # copy progress items in state - ret.state.prog_items = world.state.prog_items.copy() - ret.state.stale = {player: True for player in range(1, world.players + 1)} - - for player in range(1, world.players + 1): - set_rules(ret, player) - - return ret - def copy_dynamic_regions_and_locations(world, ret): for region in world.dynamic_regions: new_reg = Region(region.name, region.type, region.hint_text, region.player) @@ -391,7 +295,7 @@ def copy_dynamic_regions_and_locations(world, ret): def create_playthrough(world): # create a copy as we will modify it old_world = world - world = copy_world(world) + world = copy.deepcopy(world) # if we only check for beatable, we can do this sanity check first before writing down spheres if not world.can_beat_game(): diff --git a/OWGSets.py b/OWGSets.py deleted file mode 100644 index d330c210..00000000 --- a/OWGSets.py +++ /dev/null @@ -1,181 +0,0 @@ -""" -Helper functions to deliver entrance/exit/region sets to OWG rules. -""" - - -# TODO: reevaluate these points: -# why is this its own module? -# why are these functions? -# why is it named sets, when it was originally functions that return lists and had nothing to do with sets? - -def get_immediately_accessible_entrances(): - """ - Entrances that are available with no items at all. - - At this point, these are fake flipper spots. - """ - yield 'Hobo Bridge' - yield 'Zoras River' - yield 'Lake Hylia Central Island Pier' - - -def get_sword_required_superbunny_mirror_regions(): - """ - Cave regions that superbunny can get through - but only with a sword. - """ - yield 'Mini Moldorm Cave' - yield 'Spiral Cave (Top)' - - -def get_invalid_mirror_bunny_entrances_dw(): - """ - Dark World entrances that can't be superbunny-mirrored into. - """ - - yield 'Skull Woods Final Section (Entrance)' - yield 'Hype Cave' - yield 'Bonk Fairy (Dark)' - yield 'Thieves Town' - yield 'Dark World Hammer Peg Cave' - yield 'Brewery' - yield 'Hookshot Cave' - yield 'Hookshot Cave Exit (South)' - yield 'Dark Lake Hylia Ledge Fairy' - yield 'Dark Lake Hylia Ledge Spike Cave' - - -def get_invalid_mirror_bunny_entrances_lw(): - """ - Light World entrances that can't be superbunny-mirrored into. - """ - - 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' - #todo: you can for insanity shuffle - yield 'Hyrule Castle Secret Entrance Stairs' - yield 'Tower of Hera' - - -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' - - -def get_boots_clip_exits_lw(inverted = False): - """ - Special Light World region exits that require boots clips. - """ - - yield 'Bat Cave River Clip Spot' - yield 'Light World DMA Clip Spot' - yield 'Hera Ascent' - yield 'Death Mountain Return Ledge Clip Spot' - yield 'Death Mountain Glitched Bridge' - yield 'Zora Descent Clip Spot' - yield 'Desert Northern Cliffs' - yield 'Lake Hylia Island Clip Spot' - yield 'Death Mountain Descent' - yield 'Graveyard Ledge Clip Spot' - # TODO: This is not an OWG only entrance - # Also requires a waterwalk setup, but the point still remains. - # yield 'Waterfall of Wishing' - - if not inverted: - yield 'Spectacle Rock Clip Spot' - yield 'Bombos Tablet Clip Spot' - yield 'Floating Island Clip Spot' - yield 'Cave 45 Clip Spot' - - -def get_boots_clip_exits_dw(inverted = False): - """ - Special Dark World region exits that require boots clips. - """ - - yield 'Dark World DMA Clip Spot' - yield 'Bumper Cave Ledge Clip Spot' - yield 'Catfish Descent' - yield 'Hammer Pegs River Clip Spot' - yield 'Dark Lake Hylia Ledge Clip Spot' - yield 'Dark Desert Cliffs Clip Spot' - yield 'Dark Death Mountain Descent' - - if not inverted: - yield 'Ganons Tower Ascent' - yield 'Dark Death Mountain Glitched Bridge' - yield 'Turtle Rock (Top) Clip Spot' - - -def get_glitched_speed_drops_dw(): - """ - Dark World drop-down ledges that require glitched speed. - """ - yield 'Dark Death Mountain Ledge Clip Spot' - - -def get_mirror_clip_spots_dw(): - """ - Mirror shenanigans that are in logic even if the player is a bunny. - """ - yield 'Dark Death Mountain Offset Mirror' - yield 'Dark Death Mountain Bunny Descent Mirror Spot' - - -def get_mirror_clip_spots_lw(): - """ - Inverted mirror shenanigans in logic even if the player is a bunny. - """ - yield 'Death Mountain Bunny Descent Mirror Spot' - yield 'Death Mountain Offset Mirror' - - -def get_invalid_bunny_revival_dungeons(): - """ - Dungeon regions that can't be bunny revived from. - """ - - yield 'Tower of Hera (Bottom)' - yield 'Swamp Palace (Entrance)' - yield 'Turtle Rock (Entrance)' - yield 'Sanctuary' diff --git a/OverworldGlitchRules.py b/OverworldGlitchRules.py new file mode 100644 index 00000000..0badb022 --- /dev/null +++ b/OverworldGlitchRules.py @@ -0,0 +1,243 @@ +""" +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 'Mini Moldorm Cave' + 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' + + +def get_invalid_mirror_bunny_entrances_dw(): + """ + Dark World entrances that can't be superbunny-mirrored into. + """ + yield 'Skull Woods Final Section (Entrance)' + yield 'Hype Cave' + yield 'Bonk Fairy (Dark)' + yield 'Thieves Town' + yield 'Dark World Hammer Peg Cave' + yield 'Brewery' + yield 'Hookshot Cave' + yield 'Hookshot Cave Exit (South)' + yield 'Dark Lake Hylia Ledge Fairy' + yield 'Dark Lake Hylia Ledge Spike Cave' + + +def get_invalid_mirror_bunny_entrances_lw(): + """ + Light World entrances that can't be superbunny-mirrored into. + """ + 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' + #todo: you can for insanity shuffle + yield 'Hyrule Castle Secret Entrance Stairs' + yield 'Tower of Hera' + + +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 + + +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') + + +def get_boots_clip_exits_dw(inverted = False): + """ + 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') + + 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)') + 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(): + """ + Mirror shenanigans that are in logic even if the player is a bunny. + """ + 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)') + + +def get_mirror_clip_spots_lw(): + """ + Inverted mirror shenanigans in logic even if the player is a bunny. + """ + 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)') + + +def get_invalid_bunny_revival_dungeons(): + """ + Dungeon regions that can't be bunny revived from. + """ + yield 'Tower of Hera (Bottom)' + yield 'Swamp Palace (Entrance)' + yield 'Turtle Rock (Entrance)' + yield 'Sanctuary' + + +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)) + + # 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': + 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': + create_owg_connections(player, world, get_mirror_clip_spots_dw(), lambda state: state.has_Mirror(player)) + else: + create_owg_connections(player, world, get_mirror_clip_spots_lw(), lambda state: state.has_Mirror(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 of Wishing', player), lambda state: state.has('Moon Pearl', player) or state.has_Boots(player)) + else: + add_alternate_rule(world.get_entrance('Waterfall of Wishing', player), lambda state: state.has('Moon Pearl', player)) + + world.get_entrance('Dark Desert Teleporter', player).access_rule = lambda state: (state.has('Flute', player) or state.has_Boots(player)) and state.can_lift_heavy_rocks(player) + 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. + add_alternate_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player)) + + +def add_alternate_rule(entrance, rule): + old_rule = entrance.access_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: + #@todo: remove - making sure I didn't leave an entrance + for region in world.regions: + for exit in region.exits: + if exit.name == entrance and exit.player == player: + raise RuntimeError('Redefining an entrance %s:%d' % (entrance, player)) + 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) + connection.access_rule = rule diff --git a/Regions.py b/Regions.py index 3b538820..eeeae43d 100644 --- a/Regions.py +++ b/Regions.py @@ -14,8 +14,7 @@ def create_regions(world, player): 'Sanctuary', 'Sanctuary Grave', 'Death Mountain Entrance Rock', 'Flute Spot 1', 'Dark Desert Teleporter', 'East Hyrule Teleporter', 'South Hyrule Teleporter', 'Kakariko Teleporter', 'Elder House (East)', 'Elder House (West)', 'North Fairy Cave', 'North Fairy Cave Drop', 'Lost Woods Gamble', 'Snitch Lady (East)', 'Snitch Lady (West)', 'Tavern (Front)', 'Bush Covered House', 'Light World Bomb Hut', 'Kakariko Shop', 'Long Fairy Cave', 'Good Bee Cave', '20 Rupee Cave', 'Cave Shop (Lake Hylia)', 'Waterfall of Wishing', 'Hyrule Castle Main Gate', - 'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid', - 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Bat Cave River Clip Spot', 'Bombos Tablet Clip Spot', 'Cave 45 Clip Spot']), + 'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid']), create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop']), create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Teleporter']), create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', ["Blind\'s Hideout - Top", @@ -118,7 +117,7 @@ def create_regions(world, player): create_cave_region(player, 'Old Man Cave', 'a connector', ['Old Man'], ['Old Man Cave Exit (East)', 'Old Man Cave Exit (West)']), create_cave_region(player, 'Old Man House', 'a connector', None, ['Old Man House Exit (Bottom)', 'Old Man House Front to Back']), create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']), - create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Teleporter', 'Death Mountain Glitched Bridge', 'Graveyard Ledge Clip Spot', 'Hera Ascent', 'Death Mountain Descent']), + create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Teleporter']), create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']), create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)']), create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']), @@ -137,7 +136,7 @@ def create_regions(world, player): ['Paradox Cave Push Block', 'Paradox Cave Bomb Jump']), create_cave_region(player, 'Paradox Cave', 'a connector', None, ['Paradox Cave Exit (Middle)', 'Paradox Cave Exit (Top)', 'Paradox Cave Drop']), create_cave_region(player, 'Light World Death Mountain Shop', 'a common shop'), - create_lw_region(player, 'East Death Mountain (Top)', None, ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'Turtle Rock Teleporter', 'Fairy Ascension Ledge', 'Floating Island Clip Spot', 'Zora Descent Clip Spot']), + create_lw_region(player, 'East Death Mountain (Top)', None, ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'Turtle Rock Teleporter', 'Fairy Ascension Ledge']), create_lw_region(player, 'Spiral Cave Ledge', None, ['Spiral Cave', 'Spiral Cave Ledge Drop']), create_cave_region(player, 'Spiral Cave (Top)', 'a connector', ['Spiral Cave'], ['Spiral Cave (top to bottom)', 'Spiral Cave Exit (Top)']), create_cave_region(player, 'Spiral Cave (Bottom)', 'a connector', None, ['Spiral Cave Exit']), @@ -146,22 +145,21 @@ def create_regions(world, player): create_cave_region(player, 'Fairy Ascension Cave (Drop)', 'a connector', None, ['Fairy Ascension Cave Pots']), create_cave_region(player, 'Fairy Ascension Cave (Top)', 'a connector', None, ['Fairy Ascension Cave Exit (Top)', 'Fairy Ascension Cave Drop']), create_lw_region(player, 'Fairy Ascension Ledge', None, ['Fairy Ascension Ledge Drop', 'Fairy Ascension Cave (Top)']), - create_lw_region(player, 'Death Mountain (Top)', ['Ether Tablet'], ['East Death Mountain (Top)', 'Tower of Hera', 'Death Mountain Drop', 'Spectacle Rock Clip Spot']), + create_lw_region(player, 'Death Mountain (Top)', ['Ether Tablet'], ['East Death Mountain (Top)', 'Tower of Hera', 'Death Mountain Drop']), create_lw_region(player, 'Spectacle Rock', ['Spectacle Rock'], ['Spectacle Rock Drop']), create_dungeon_region(player, 'Tower of Hera (Bottom)', 'Tower of Hera', ['Tower of Hera - Basement Cage', 'Tower of Hera - Map Chest'], ['Tower of Hera Small Key Door', 'Tower of Hera Big Key Door', 'Tower of Hera Exit']), create_dungeon_region(player, 'Tower of Hera (Basement)', 'Tower of Hera', ['Tower of Hera - Big Key Chest']), create_dungeon_region(player, 'Tower of Hera (Top)', 'Tower of Hera', ['Tower of Hera - Compass Chest', 'Tower of Hera - Big Chest', 'Tower of Hera - Boss', 'Tower of Hera - Prize']), create_dw_region(player, 'East Dark World', ['Pyramid'], ['Pyramid Fairy', 'South Dark World Bridge', 'Palace of Darkness', 'Dark Lake Hylia Drop (East)', 'Dark Lake Hylia Teleporter', - 'Hyrule Castle Ledge Mirror Spot', 'Dark Lake Hylia Fairy', 'Palace of Darkness Hint', 'East Dark World Hint', 'Pyramid Hole', 'Northeast Dark World Broken Bridge Pass', - 'Hammer Pegs River Clip Spot', 'Dark Lake Hylia Ledge Clip Spot']), + 'Hyrule Castle Ledge Mirror Spot', 'Dark Lake Hylia Fairy', 'Palace of Darkness Hint', 'East Dark World Hint', 'Pyramid Hole', 'Northeast Dark World Broken Bridge Pass',]), create_dw_region(player, 'Catfish', ['Catfish'], ['Catfish Exit Rock']), create_dw_region(player, 'Northeast Dark World', None, ['West Dark World Gap', 'Dark World Potion Shop', 'East Dark World Broken Bridge Pass', 'Catfish Entrance Rock']), create_cave_region(player, 'Palace of Darkness Hint', 'a storyteller'), create_cave_region(player, 'East Dark World Hint', 'a storyteller'), create_dw_region(player, 'South Dark World', ['Stumpy', 'Digging Game'], ['Dark Lake Hylia Drop (South)', 'Hype Cave', 'Swamp Palace', 'Village of Outcasts Heavy Rock', 'Maze Race Mirror Spot', 'Cave 45 Mirror Spot', 'East Dark World Bridge', 'Big Bomb Shop', 'Archery Game', 'Bonk Fairy (Dark)', 'Dark Lake Hylia Shop', - 'Bombos Tablet Mirror Spot', 'Dark Desert Cliffs Clip Spot']), + 'Bombos Tablet Mirror Spot']), create_lw_region(player, 'Bombos Tablet Ledge', ['Bombos Tablet']), create_cave_region(player, 'Big Bomb Shop', 'the bomb shop'), create_cave_region(player, 'Archery Game', 'a game of skill'), @@ -173,8 +171,7 @@ def create_regions(world, player): create_cave_region(player, 'Hype Cave', 'a bounty of five items', ['Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left', 'Hype Cave - Bottom', 'Hype Cave - Generous Guy']), create_dw_region(player, 'West Dark World', ['Frog'], ['Village of Outcasts Drop', 'East Dark World River Pier', 'Brewery', 'C-Shaped House', 'Chest Game', 'Thieves Town', 'Graveyard Ledge Mirror Spot', 'Kings Grave Mirror Spot', 'Bumper Cave Entrance Rock', - 'Skull Woods Forest', 'Village of Outcasts Pegs', 'Village of Outcasts Eastern Rocks', 'Red Shield Shop', 'Dark Sanctuary Hint', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop', - 'Dark World DMA Clip Spot', 'Bumper Cave Ledge Clip Spot']), + 'Skull Woods Forest', 'Village of Outcasts Pegs', 'Village of Outcasts Eastern Rocks', 'Red Shield Shop', 'Dark Sanctuary Hint', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop']), create_dw_region(player, 'Dark Grassy Lawn', None, ['Grassy Lawn Pegs', 'Dark World Shop']), create_dw_region(player, 'Hammer Peg Area', ['Dark Blacksmith Ruins'], ['Bat Cave Drop Ledge Mirror Spot', 'Dark World Hammer Peg Cave', 'Peg Area Rocks']), create_dw_region(player, 'Bumper Cave Entrance', None, ['Bumper Cave (Bottom)', 'Bumper Cave Entrance Mirror Spot', 'Bumper Cave Entrance Drop']), @@ -199,9 +196,9 @@ def create_regions(world, player): 'Desert Palace Entrance (North) Mirror Spot', 'Dark Desert Hint', 'Dark Desert Fairy']), create_cave_region(player, 'Mire Shed', 'a cave with two chests', ['Mire Shed - Left', 'Mire Shed - Right']), create_cave_region(player, 'Dark Desert Hint', 'a storyteller'), - create_dw_region(player, 'Dark Death Mountain (West Bottom)', None, ['Spike Cave', 'Spectacle Rock Mirror Spot', 'Dark Death Mountain Fairy', 'Ganons Tower Ascent', 'Dark Death Mountain Glitched Bridge', 'Dark Death Mountain Bunny Descent Mirror Spot', 'Dark Death Mountain Offset Mirror', 'Dark Death Mountain Descent']), + create_dw_region(player, 'Dark Death Mountain (West Bottom)', None, ['Spike Cave', 'Spectacle Rock Mirror Spot', 'Dark Death Mountain Fairy']), create_dw_region(player, 'Dark Death Mountain (Top)', None, ['Dark Death Mountain Drop (East)', 'Dark Death Mountain Drop (West)', 'Ganons Tower', 'Superbunny Cave (Top)', - 'Hookshot Cave', 'East Death Mountain (Top) Mirror Spot', 'Turtle Rock', 'Catfish Descent', 'Dark Death Mountain Ledge Clip Spot', 'Turtle Rock (Top) Clip Spot']), + 'Hookshot Cave', 'East Death Mountain (Top) Mirror Spot', 'Turtle Rock']), create_dw_region(player, 'Dark Death Mountain Ledge', None, ['Dark Death Mountain Ledge (East)', 'Dark Death Mountain Ledge (West)', 'Mimic Cave Mirror Spot', 'Spiral Cave Mirror Spot']), create_dw_region(player, 'Dark Death Mountain Isolated Ledge', None, ['Isolated Ledge Mirror Spot', 'Turtle Rock Isolated Ledge Entrance']), create_dw_region(player, 'Dark Death Mountain (East Bottom)', None, ['Superbunny Cave (Bottom)', 'Cave Shop (Dark Death Mountain)', 'Fairy Ascension Mirror Spot']), @@ -297,7 +294,8 @@ def create_regions(world, player): create_cave_region(player, 'Pyramid', 'a drop\'s exit', ['Ganon'], ['Ganon Drop']), create_cave_region(player, 'Bottom of Pyramid', 'a drop\'s exit', None, ['Pyramid Exit']), create_dw_region(player, 'Pyramid Ledge', None, ['Pyramid Entrance', 'Pyramid Drop']), - create_dw_region(player, 'Dark Death Mountain Bunny Descent Area', None, ['West Dark World Bunny Descent', 'Dark Death Mountain (East Bottom) Jump']), + create_lw_region(player, 'Desert Northern Cliffs'), + create_dw_region(player, 'Dark Death Mountain Bunny Descent Area') ] world.initialize_regions() diff --git a/Rules.py b/Rules.py index 1a8c5372..2786f0f7 100644 --- a/Rules.py +++ b/Rules.py @@ -1,8 +1,9 @@ import collections import logging -import OWGSets -from BaseClasses import CollectionState, RegionType +import OverworldGlitchRules +from BaseClasses import RegionType from Items import ItemFactory +from OverworldGlitchRules import overworld_glitches_rules def set_rules(world, player): @@ -44,6 +45,7 @@ def set_rules(world, player): # Initially setting no_glitches_rules to set the baseline rules for some # entrances. The overworld_glitches_rules set is primarily additive. no_glitches_rules(world, player) + fake_flipper_rules(world, player) overworld_glitches_rules(world, player) elif world.logic[player] == 'minorglitches': logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.') @@ -431,7 +433,7 @@ def default_rules(world, player): set_rule(world.get_entrance('Dark Lake Hylia Drop (South)', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # ToDo any fake flipper set up? set_rule(world.get_entrance('Dark Lake Hylia Ledge Fairy', player), lambda state: state.has_Pearl(player)) # bomb required set_rule(world.get_entrance('Dark Lake Hylia Ledge Spike Cave', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player)) - set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) # Fake Flippers + set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) # Move this to NE Dark World set_rule(world.get_entrance('Village of Outcasts Heavy Rock', player), lambda state: state.has_Pearl(player) and state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Hype Cave', player), lambda state: state.has_Pearl(player)) # bomb required set_rule(world.get_entrance('Brewery', player), lambda state: state.has_Pearl(player)) # bomb required @@ -482,21 +484,6 @@ def default_rules(world, player): swordless_rules(world, player) -def forbid_overworld_glitches(world, player): - for exit in OWGSets.get_boots_clip_exits_lw(world.mode[player] == 'inverted'): - set_rule(world.get_entrance(exit, player), lambda state: False) - for exit in OWGSets.get_boots_clip_exits_dw(world.mode[player] == 'inverted'): - set_rule(world.get_entrance(exit, player), lambda state: False) - for exit in OWGSets.get_glitched_speed_drops_dw(): - set_rule(world.get_entrance(exit, player), lambda state: False) - if world.mode[player] != 'inverted': - for exit in OWGSets.get_mirror_clip_spots_dw(): - set_rule(world.get_entrance(exit, player), lambda state: False) - else: - for exit in OWGSets.get_mirror_clip_spots_lw(): - set_rule(world.get_entrance(exit, player), lambda state: False) - - def inverted_rules(world, player): # s&q regions. link's house entrance is set to true so the filler knows the chest inside can always be reached world.get_region('Inverted Links House', player).can_reach_private = lambda state: True @@ -669,16 +656,35 @@ def no_glitches_rules(world, player): set_rule(world.get_entrance('Northeast Light World Warp', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # can be fake flippered to set_rule(world.get_entrance('Hobo Bridge', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has('Flippers', player)) - set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) + set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('East Dark World Pier', player), lambda state: state.has('Flippers', player)) add_rule(world.get_entrance('Ganons Tower (Double Switch Room)', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: False) # no glitches does not require block override forbid_bomb_jump_requirements(world, player) - forbid_overworld_glitches(world, player) add_conditional_lamps(world, player) +def fake_flipper_rules(world, player): + if world.mode[player] != 'inverted': + set_rule(world.get_entrance('Zoras River', player), lambda state: True) + set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: True) + set_rule(world.get_entrance('Hobo Bridge', player), lambda state: True) + set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) + set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) + set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has_Pearl(player)) + else: + set_rule(world.get_entrance('Zoras River', player), lambda state: state.has_Pearl(player)) + set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has_Pearl(player)) + set_rule(world.get_entrance('Lake Hylia Island Pier', player), lambda state: state.has_Pearl(player)) + set_rule(world.get_entrance('Lake Hylia Warp', player), lambda state: state.has_Pearl(player)) + set_rule(world.get_entrance('Northeast Light World Warp', player), lambda state: state.has_Pearl(player)) + set_rule(world.get_entrance('Hobo Bridge', player), lambda state: state.has_Pearl(player)) + set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has('Flippers', player)) + set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: True) + set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: True) + set_rule(world.get_entrance('East Dark World Pier', player), lambda state: True) #todo: Ice Palace exit + def forbid_bomb_jump_requirements(world, player): DMs_room_chests = ['Ganons Tower - DMs Room - Top Left', 'Ganons Tower - DMs Room - Top Right', 'Ganons Tower - DMs Room - Bottom Left', 'Ganons Tower - DMs Room - Bottom Right'] @@ -753,52 +759,6 @@ def add_conditional_lamps(world, player): add_lamp_requirement(world.get_entrance('Throne Room', player), player) -def overworld_glitches_rules(world, player): - # Spots that are immediately accessible. - for entrance in OWGSets.get_immediately_accessible_entrances(): - set_rule(world.get_entrance(entrance, player), lambda state: True) - - # Boots-accessible locations. - for entrance in OWGSets.get_boots_clip_exits_lw(world.mode[player] == 'inverted'): - set_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_lw(player)) - for entrance in OWGSets.get_boots_clip_exits_dw(world.mode[player] == 'inverted'): - set_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_dw(player)) - - # Glitched speed drops. - for drop in OWGSets.get_glitched_speed_drops_dw(): - set_rule(world.get_entrance(drop, player), 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_rule(world.get_entrance('Dark Death Mountain Ledge Clip Spot', player), lambda state: state.has_Mirror(player), 'or') - - # Mirror clip spots. - if world.mode[player] != 'inverted': - for clip_spot in OWGSets.get_mirror_clip_spots_dw(): - set_rule(world.get_entrance(clip_spot, player), lambda state: state.has_Mirror(player)) - else: - for clip_spot in OWGSets.get_mirror_clip_spots_lw(): - set_rule(world.get_entrance(clip_spot, player), lambda state: state.has_Mirror(player)) - - # Locations that you can superbunny mirror into, but need a sword to clear. - for superbunny_mirror_weapon_region in OWGSets.get_sword_required_superbunny_mirror_regions(): - region = world.get_region(superbunny_mirror_weapon_region, player) - if check_is_dark_world(region): - for spot in region.locations: - add_rule(spot, lambda state: state.can_superbunny_mirror_with_sword(player), 'or') - - # Regions that require the boots and some other stuff. - if world.mode[player] != 'inverted': - set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: (state.has('Flute', player) or state.can_boots_clip_lw(player)) and state.can_lift_heavy_rocks(player)) - set_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: (state.can_boots_clip_lw(player) or state.can_lift_heavy_rocks(player)) and state.has('Hammer', player)) - add_rule(world.get_entrance('Catfish Exit Rock', player), lambda state: state.can_boots_clip_dw(player), 'or') - add_rule(world.get_entrance('East Dark World Broken Bridge Pass', player), lambda state: state.can_boots_clip_dw(player), 'or') - else: - add_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') - - # Zora's Ledge via waterwalk setup. - add_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player), 'or') - - def open_rules(world, player): # softlock protection as you can reach the sewers small key door with a guard drop key set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), lambda state: state.has_key('Small Key (Escape)', player)) @@ -1367,12 +1327,17 @@ def set_bunny_rules(world, player): if world.logic[player] == 'owglitches': if region.name == 'Swamp Palace (Entrance)': return lambda state: state.has_Pearl(player) - if region.name in OWGSets.get_invalid_bunny_revival_dungeons(): + if region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): return lambda state: state.has_Mirror(player) or state.has_Pearl(player) if region.type == RegionType.Dungeon: return lambda state: True - if (((location is None or location.name not in OWGSets.get_superbunny_accessible_locations()) - or (connecting_entrance is not None and connecting_entrance.name in OWGSets.get_invalid_bunny_revival_dungeons())) + if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions(): + return lambda state: state.has_Mirror(player) and state.has_sword(player) or state.has_Pearl(player) + if (region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions() + or location is not None and location.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_locations()): + return lambda state: state.has_Mirror(player) and state.has_Boots(player) or state.has_Pearl(player) + if (((location is None or location.name not in OverworldGlitchRules.get_superbunny_accessible_locations()) + or (connecting_entrance is not None and connecting_entrance.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons())) and not region.is_light_world): return lambda state: state.has_Pearl(player) else: @@ -1402,8 +1367,13 @@ def set_bunny_rules(world, player): seen.add(new_region) if not new_region.is_light_world: # For OWG, establish superbunny and revival rules. - if world.logic[player] == 'owglitches' and entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): - if location is not None and location.name in OWGSets.get_superbunny_accessible_locations(): + if world.logic[player] == 'owglitches' and entrance.name not in OverworldGlitchRules.get_invalid_mirror_bunny_entrances_dw(): + if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions(): + possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has_Mirror(player) and state.has_sword(player)) + elif (region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions() + or location is not None and location.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_locations()): + possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has_Mirror(player) and state.has_Boots(player)) + elif location is not None and location.name in OverworldGlitchRules.get_superbunny_accessible_locations(): if new_region.name == 'Superbunny Cave (Bottom)' or region.name == 'Kakariko Well (top)': possible_options.append(lambda state: path_to_access_rule(new_path, entrance)) else: @@ -1437,19 +1407,20 @@ def set_bunny_rules(world, player): if entrance.player == player and entrance.connected_region.is_dark_world: if world.logic[player] == 'owglitches': if entrance.connected_region.type == RegionType.Dungeon: - if entrance.parent_region.type != RegionType.Dungeon and entrance.connected_region.name in OWGSets.get_invalid_bunny_revival_dungeons(): + if entrance.parent_region.type != RegionType.Dungeon and entrance.connected_region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): add_rule(entrance, get_rule_to_add(entrance.connected_region, None, entrance)) continue if entrance.connected_region.name == 'Turtle Rock (Entrance)': add_rule(world.get_entrance('Turtle Rock Entrance Gap', player), get_rule_to_add(entrance.connected_region, None, entrance)) for location in entrance.connected_region.locations: - if world.logic[player] == 'owglitches' and entrance.name in OWGSets.get_invalid_mirror_bunny_entrances_dw(): + if world.logic[player] == 'owglitches' and entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances_dw(): add_rule(location, get_rule_to_add(entrance.connected_region, location, entrance)) continue if location.name in bunny_accessible_locations: continue add_rule(location, get_rule_to_add(entrance.connected_region, location)) +#todo: combine this with set_bunny_rules def set_inverted_bunny_rules(world, player): # 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. @@ -1469,12 +1440,12 @@ def set_inverted_bunny_rules(world, player): if world.logic[player] == 'owglitches': if region.name == 'Swamp Palace (Entrance)': return lambda state: state.has_Pearl(player) - if region.name in OWGSets.get_invalid_bunny_revival_dungeons(): + if region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): return lambda state: state.has_Mirror(player) or state.has_Pearl(player) if region.type == RegionType.Dungeon: return lambda state: True - if (((location is None or location.name not in OWGSets.get_superbunny_accessible_locations()) - or (connecting_entrance is not None and connecting_entrance.name in OWGSets.get_invalid_bunny_revival_dungeons())) + if (((location is None or location.name not in OverworldGlitchRules.get_superbunny_accessible_locations()) + or (connecting_entrance is not None and connecting_entrance.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons())) and not region.is_dark_world): return lambda state: state.has_Pearl(player) else: @@ -1503,8 +1474,13 @@ def set_inverted_bunny_rules(world, player): seen.add(new_region) if not new_region.is_dark_world: # For OWG, establish superbunny and revival rules. - if world.logic[player] == 'owglitches' and entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): - if location is not None and location.name in OWGSets.get_superbunny_accessible_locations(): + if world.logic[player] == 'owglitches' and entrance.name not in OverworldGlitchRules.get_invalid_mirror_bunny_entrances_lw(): + if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions(): + possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has_Mirror(player) and state.has_sword(player)) + elif (region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions() + or location is not None and location.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_locations()): + possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has_Mirror(player) and state.has_Boots(player)) + elif location is not None and location.name in OverworldGlitchRules.get_superbunny_accessible_locations(): if new_region.name == 'Superbunny Cave (Bottom)' or region.name == 'Kakariko Well (top)': possible_options.append(lambda state: path_to_access_rule(new_path, entrance)) else: @@ -1538,13 +1514,13 @@ def set_inverted_bunny_rules(world, player): if entrance.player == player and entrance.connected_region.is_light_world: if world.logic[player] == 'owglitches': if entrance.connected_region.type == RegionType.Dungeon: - if entrance.parent_region.type != RegionType.Dungeon and entrance.connected_region.name in OWGSets.get_invalid_bunny_revival_dungeons(): + if entrance.parent_region.type != RegionType.Dungeon and entrance.connected_region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): add_rule(entrance, get_rule_to_add(entrance.connected_region, None, entrance)) continue if entrance.connected_region.name == 'Turtle Rock (Entrance)': add_rule(world.get_entrance('Turtle Rock Entrance Gap', player), get_rule_to_add(entrance.connected_region, None, entrance)) for location in entrance.connected_region.locations: - if world.logic[player] == 'owglitches' and entrance.name in OWGSets.get_invalid_mirror_bunny_entrances_lw(): + if world.logic[player] == 'owglitches' and entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances_lw(): add_rule(location, get_rule_to_add(entrance.connected_region, location, entrance)) continue if location.name in bunny_accessible_locations: diff --git a/test/inverted_owg/TestDarkWorld.py b/test/inverted_owg/TestDarkWorld.py index ffa40300..89dff120 100644 --- a/test/inverted_owg/TestDarkWorld.py +++ b/test/inverted_owg/TestDarkWorld.py @@ -52,8 +52,7 @@ class TestDarkWorld(TestInvertedOWG): #todo: Qirn Jump #["Pyramid", True, []], ["Pyramid", False, []], - #todo: Waterwalk - #["Pyramid", True, ['Pegasus Boots']], + ["Pyramid", True, ['Pegasus Boots']], ["Pyramid", True, ['Flippers']], ["Pyramid Fairy - Left", False, []], diff --git a/test/inverted_owg/TestDeathMountain.py b/test/inverted_owg/TestDeathMountain.py index 90de0d0e..7688a20e 100644 --- a/test/inverted_owg/TestDeathMountain.py +++ b/test/inverted_owg/TestDeathMountain.py @@ -16,6 +16,8 @@ class TestDeathMountain(TestInvertedOWG): def testEastDeathMountain(self): self.run_location_tests([ ["Spiral Cave", False, []], + ["Spiral Cave", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Spiral Cave", False, [], ['Moon Pearl', 'Progressive Sword']], ["Spiral Cave", True, ['Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Progressive Sword']], ["Spiral Cave", True, ['Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Pegasus Boots', 'Progressive Sword']], ["Spiral Cave", True, ['Moon Pearl', 'Pegasus Boots']], diff --git a/test/inverted_owg/TestDungeons.py b/test/inverted_owg/TestDungeons.py index 610f7f5b..841a3382 100644 --- a/test/inverted_owg/TestDungeons.py +++ b/test/inverted_owg/TestDungeons.py @@ -47,9 +47,9 @@ class TestDungeons(TestInvertedOWG): ["Castle Tower - Room 03", True, ['Pegasus Boots', 'Progressive Sword']], ["Castle Tower - Room 03", True, ['Pegasus Boots', 'Progressive Bow']], - #todo: Qirn Jump, Waterwalk + #todo: Qirn Jump #["Palace of Darkness - Shooter Room", True, []], - #["Palace of Darkness - Shooter Room", True, ['Pegasus Boots']], + ["Palace of Darkness - Shooter Room", True, ['Pegasus Boots']], ["Palace of Darkness - Shooter Room", True, ['Hammer']], ["Palace of Darkness - Shooter Room", True, ['Flippers']], ["Palace of Darkness - Shooter Room", True, ['Pegasus Boots', 'Progressive Glove']], @@ -80,8 +80,8 @@ class TestDungeons(TestInvertedOWG): #todo: Qirn Jump #["Ice Palace - Compass Chest", True, ['Fire Rod']], #["Ice Palace - Compass Chest", True, ['Bombos', 'Progressive Sword']], - ["Ice Palace - Compass Chest", True, ['Pegasus Boots', 'Magic Mirror', 'Fire Rod']], - ["Ice Palace - Compass Chest", True, ['Pegasus Boots', 'Magic Mirror', 'Bombos', 'Progressive Sword']], + ["Ice Palace - Compass Chest", True, ['Pegasus Boots', 'Fire Rod']], + ["Ice Palace - Compass Chest", True, ['Pegasus Boots', 'Bombos', 'Progressive Sword']], ["Misery Mire - Bridge Chest", False, []], ["Misery Mire - Bridge Chest", False, [], ['Ether']], diff --git a/test/inverted_owg/TestLightWorld.py b/test/inverted_owg/TestLightWorld.py index f7f003dc..ad833017 100644 --- a/test/inverted_owg/TestLightWorld.py +++ b/test/inverted_owg/TestLightWorld.py @@ -13,11 +13,11 @@ class TestLightWorld(TestInvertedOWG): ["Master Sword Pedestal", True, ['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Magic Mirror', 'Pegasus Boots']], ["Link's Uncle", False, []], - ["Link's Uncle", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Link's Uncle", False, [], ['Moon Pearl']], ["Link's Uncle", True, ['Moon Pearl', 'Pegasus Boots']], ["Secret Passage", False, []], - ["Secret Passage", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Secret Passage", False, [], ['Moon Pearl']], ["Secret Passage", True, ['Moon Pearl', 'Pegasus Boots']], ["King's Tomb", False, []], @@ -26,6 +26,7 @@ class TestLightWorld(TestInvertedOWG): ["King's Tomb", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl']], ["Floodgate Chest", False, []], + ["Floodgate Chest", False, [], ['Moon Pearl', 'Magic Mirror']], ["Floodgate Chest", True, ['Moon Pearl', 'Pegasus Boots']], ["Floodgate Chest", True, ['Magic Mirror', 'Pegasus Boots']], @@ -45,24 +46,27 @@ class TestLightWorld(TestInvertedOWG): ["Aginah's Cave", True, ['Moon Pearl', 'Pegasus Boots']], ["Sahasrahla's Hut - Left", False, []], - ["Sahasrahla's Hut - Left", False, ['Moon Pearl', 'Magic Mirror']], + ["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Pegasus Boots']], ["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Pegasus Boots']], - #todo: superbunny into sahasrahla in logic? - #["Sahasrahla's Hut - Left", True, ['Magic Mirror', 'Pegasus Boots']], + ["Sahasrahla's Hut - Left", True, ['Magic Mirror', 'Pegasus Boots']], + ##todo: Damage boost superbunny not in logic #["Sahasrahla's Hut - Left", True, ['Beat Agahnim 1', 'Pegasus Boots']], ["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Sahasrahla's Hut - Middle", False, []], - ["Sahasrahla's Hut - Middle", False, ['Moon Pearl', 'Magic Mirror']], + ["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Pegasus Boots']], ["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Pegasus Boots']], - #["Sahasrahla's Hut - Middle", True, ['Magic Mirror', 'Pegasus Boots']], + ["Sahasrahla's Hut - Middle", True, ['Magic Mirror', 'Pegasus Boots']], #["Sahasrahla's Hut - Middle", True, ['Beat Agahnim 1', 'Pegasus Boots']], ["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Sahasrahla's Hut - Right", False, []], - ["Sahasrahla's Hut - Right", False, ['Moon Pearl', 'Magic Mirror']], + ["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Pegasus Boots']], ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Pegasus Boots']], - #["Sahasrahla's Hut - Right", True, ['Magic Mirror', 'Pegasus Boots']], + ["Sahasrahla's Hut - Right", True, ['Magic Mirror', 'Pegasus Boots']], #["Sahasrahla's Hut - Right", True, ['Beat Agahnim 1', 'Pegasus Boots']], ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], @@ -73,21 +77,25 @@ class TestLightWorld(TestInvertedOWG): ["Kakariko Well - Left", False, []], ["Kakariko Well - Left", True, ['Moon Pearl', 'Pegasus Boots']], ["Kakariko Well - Left", True, ['Magic Mirror', 'Pegasus Boots']], + ["Kakariko Well - Left", True, ['Progressive Glove', 'Progressive Glove', 'Pegasus Boots']], ["Kakariko Well - Left", True, ['Beat Agahnim 1']], ["Kakariko Well - Middle", False, []], ["Kakariko Well - Middle", True, ['Moon Pearl', 'Pegasus Boots']], ["Kakariko Well - Middle", True, ['Magic Mirror', 'Pegasus Boots']], + ["Kakariko Well - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Pegasus Boots']], ["Kakariko Well - Middle", True, ['Beat Agahnim 1']], ["Kakariko Well - Right", False, []], ["Kakariko Well - Right", True, ['Moon Pearl', 'Pegasus Boots']], ["Kakariko Well - Right", True, ['Magic Mirror', 'Pegasus Boots']], + ["Kakariko Well - Right", True, ['Progressive Glove', 'Progressive Glove', 'Pegasus Boots']], ["Kakariko Well - Right", True, ['Beat Agahnim 1']], ["Kakariko Well - Bottom", False, []], ["Kakariko Well - Bottom", True, ['Moon Pearl', 'Pegasus Boots']], ["Kakariko Well - Bottom", True, ['Magic Mirror', 'Pegasus Boots']], + ["Kakariko Well - Bottom", True, ['Progressive Glove', 'Progressive Glove', 'Pegasus Boots']], ["Kakariko Well - Bottom", True, ['Beat Agahnim 1']], ["Blind's Hideout - Top", False, []], @@ -95,21 +103,25 @@ class TestLightWorld(TestInvertedOWG): ["Blind's Hideout - Top", True, ['Moon Pearl', 'Pegasus Boots']], ["Blind's Hideout - Left", False, []], + ["Blind's Hideout - Left", False, [], ['Moon Pearl', 'Magic Mirror']], ["Blind's Hideout - Left", True, ['Moon Pearl', 'Pegasus Boots']], ["Blind's Hideout - Left", True, ['Magic Mirror', 'Pegasus Boots']], ["Blind's Hideout - Left", True, ['Magic Mirror', 'Beat Agahnim 1']], ["Blind's Hideout - Right", False, []], + ["Blind's Hideout - Right", False, [], ['Moon Pearl', 'Magic Mirror']], ["Blind's Hideout - Right", True, ['Moon Pearl', 'Pegasus Boots']], ["Blind's Hideout - Right", True, ['Magic Mirror', 'Pegasus Boots']], ["Blind's Hideout - Right", True, ['Magic Mirror', 'Beat Agahnim 1']], ["Blind's Hideout - Far Left", False, []], + ["Blind's Hideout - Far Left", False, [], ['Moon Pearl', 'Magic Mirror']], ["Blind's Hideout - Far Left", True, ['Moon Pearl', 'Pegasus Boots']], ["Blind's Hideout - Far Left", True, ['Magic Mirror', 'Pegasus Boots']], ["Blind's Hideout - Far Left", True, ['Magic Mirror', 'Beat Agahnim 1']], ["Blind's Hideout - Far Right", False, []], + ["Blind's Hideout - Far Right", False, [], ['Moon Pearl', 'Magic Mirror']], ["Blind's Hideout - Far Right", True, ['Moon Pearl', 'Pegasus Boots']], ["Blind's Hideout - Far Right", True, ['Magic Mirror', 'Pegasus Boots']], ["Blind's Hideout - Far Right", True, ['Magic Mirror', 'Beat Agahnim 1']], @@ -125,6 +137,7 @@ class TestLightWorld(TestInvertedOWG): ["Mini Moldorm Cave - Left", False, []], ["Mini Moldorm Cave - Left", False, [], ['Moon Pearl']], + ["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Pegasus Boots']], ["Mini Moldorm Cave - Right", False, []], ["Mini Moldorm Cave - Right", False, [], ['Moon Pearl']], @@ -132,9 +145,13 @@ class TestLightWorld(TestInvertedOWG): ["Mini Moldorm Cave - Far Right", False, []], ["Mini Moldorm Cave - Far Right", False, [], ['Moon Pearl']], + ["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Mini Moldorm Cave - Generous Guy", False, []], + ["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']], + ["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Pegasus Boots']], ["Ice Rod Cave", False, []], - #["Ice Rod Cave", False, [], ['Moon Pearl', 'BigRedBomb']], ["Ice Rod Cave", False, [], ['Moon Pearl']], ["Ice Rod Cave", True, ['Moon Pearl', 'Pegasus Boots']], #I don't think so @@ -144,11 +161,15 @@ class TestLightWorld(TestInvertedOWG): ["Bottle Merchant", False, []], ["Bottle Merchant", True, ['Pegasus Boots', 'Magic Mirror']], ["Bottle Merchant", True, ['Moon Pearl', 'Pegasus Boots']], + ["Bottle Merchant", True, ['Progressive Glove', 'Progressive Glove', 'Pegasus Boots']], + ["Bottle Merchant", True, ['Magic Mirror', 'Pegasus Boots']], ["Sahasrahla", False, []], ["Sahasrahla", False, [], ['Green Pendant']], ["Sahasrahla", True, ['Green Pendant', 'Magic Mirror', 'Pegasus Boots']], ["Sahasrahla", True, ['Green Pendant', 'Moon Pearl', 'Pegasus Boots']], + ["Sahasrahla", True, ['Green Pendant', 'Magic Mirror', 'Pegasus Boots']], + ["Sahasrahla", True, ['Green Pendant', 'Progressive Glove', 'Progressive Glove', 'Pegasus Boots']], ["Magic Bat", False, []], ["Magic Bat", False, [], ['Magic Powder']], @@ -174,10 +195,11 @@ class TestLightWorld(TestInvertedOWG): ["Sick Kid", True, ['Bottle (Green Potion)', 'Moon Pearl', 'Pegasus Boots']], ["Sick Kid", True, ['Bottle (Blue Potion)', 'Magic Mirror', 'Pegasus Boots']], ["Sick Kid", True, ['Bottle (Blue Potion)', 'Moon Pearl', 'Pegasus Boots']], - ["Sick Kid", True, ['Bottle', 'Magic Mirror', 'Pegasus Boots']], - ["Sick Kid", True, ['Bottle', 'Moon Pearl', 'Pegasus Boots']], ["Sick Kid", True, ['Bottle (Good Bee)', 'Magic Mirror', 'Pegasus Boots']], ["Sick Kid", True, ['Bottle (Good Bee)', 'Moon Pearl', 'Pegasus Boots']], + ["Sick Kid", True, ['Bottle', 'Magic Mirror', 'Pegasus Boots']], + ["Sick Kid", True, ['Bottle', 'Moon Pearl', 'Pegasus Boots']], + ["Sick Kid", True, ['Bottle', 'Progressive Glove', 'Progressive Glove', 'Pegasus Boots']], ["Hobo", False, []], ["Hobo", False, [], ['Moon Pearl']], @@ -189,6 +211,7 @@ class TestLightWorld(TestInvertedOWG): ["Bombos Tablet", False, [], ['Book of Mudora']], ["Bombos Tablet", True, ['Moon Pearl', 'Book of Mudora', 'Pegasus Boots', 'Progressive Sword', 'Progressive Sword']], ["Bombos Tablet", True, ['Magic Mirror', 'Book of Mudora', 'Pegasus Boots', 'Progressive Sword', 'Progressive Sword']], + ["Bombos Tablet", True, ['Progressive Glove', 'Progressive Glove', 'Book of Mudora', 'Pegasus Boots', 'Progressive Sword', 'Progressive Sword']], ["King Zora", False, []], ["King Zora", False, [], ['Moon Pearl']], @@ -205,6 +228,7 @@ class TestLightWorld(TestInvertedOWG): ["Lumberjack Tree", True, ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']], ["Cave 45", False, []], + ["Cave 45", False, [], ['Moon Pearl', 'Magic Mirror']], ["Cave 45", True, ['Moon Pearl', 'Pegasus Boots']], ["Cave 45", True, ['Magic Mirror', 'Pegasus Boots']], ["Cave 45", True, ['Magic Mirror', 'Beat Agahnim 1']], @@ -218,12 +242,9 @@ class TestLightWorld(TestInvertedOWG): ["Checkerboard Cave", False, [], ['Moon Pearl']], ["Checkerboard Cave", True, ['Progressive Glove', 'Pegasus Boots', 'Moon Pearl']], - ["Mini Moldorm Cave - Generous Guy", False, []], - ["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Pegasus Boots']], - ["Library", False, []], ["Library", False, [], ['Pegasus Boots']], + ["Library", False, [], ['Moon Pearl', 'Magic Mirror']], ["Library", True, ['Pegasus Boots', 'Moon Pearl']], ["Library", True, ['Pegasus Boots', 'Magic Mirror']], @@ -242,6 +263,7 @@ class TestLightWorld(TestInvertedOWG): ["Desert Ledge", False, []], ["Desert Ledge", True, ['Book of Mudora', 'Magic Mirror', 'Pegasus Boots']], + ["Desert Ledge", True, ['Book of Mudora', 'Progressive Glove', 'Progressive Glove', 'Pegasus Boots']], ["Desert Ledge", True, ['Book of Mudora', 'Beat Agahnim 1']], ["Desert Ledge", True, ['Moon Pearl', 'Pegasus Boots']], @@ -250,6 +272,7 @@ class TestLightWorld(TestInvertedOWG): ["Lake Hylia Island", True, ['Moon Pearl', 'Pegasus Boots']], ["Sunken Treasure", False, []], + ["Sunken Treasure", False, [], ['Moon Pearl', 'Magic Mirror']], ["Sunken Treasure", True, ['Moon Pearl', 'Pegasus Boots']], ["Sunken Treasure", True, ['Magic Mirror', 'Pegasus Boots']], ["Sunken Treasure", True, ['Magic Mirror', 'Beat Agahnim 1']], @@ -265,20 +288,17 @@ class TestLightWorld(TestInvertedOWG): ["Waterfall Fairy - Left", False, []], ["Waterfall Fairy - Left", False, [], ['Moon Pearl']], - ["Waterfall Fairy - Left", True, ['Moon Pearl', 'Pegasus Boots', 'Flippers']], - #todo: Waterwalking into caves not in logic - # ["Waterfall Fairy - Left", True, ['Moon Pearl', 'Pegasus Boots']], - # ["Waterfall Fairy - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], - # ["Waterfall Fairy - Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - # ["Waterfall Fairy - Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Waterfall Fairy - Left", True, ['Moon Pearl', 'Pegasus Boots']], + ["Waterfall Fairy - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], + ["Waterfall Fairy - Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Waterfall Fairy - Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Waterfall Fairy - Right", False, []], ["Waterfall Fairy - Right", False, [], ['Moon Pearl']], - ["Waterfall Fairy - Right", True, ['Moon Pearl', 'Pegasus Boots', 'Flippers']], - # ["Waterfall Fairy - Right", True, ['Moon Pearl', 'Pegasus Boots']], - # ["Waterfall Fairy - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], - # ["Waterfall Fairy - Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - # ["Waterfall Fairy - Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Waterfall Fairy - Right", True, ['Moon Pearl', 'Pegasus Boots']], + ["Waterfall Fairy - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], + ["Waterfall Fairy - Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Waterfall Fairy - Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], # Bomb Merchant is not a separate check, and is only used as part of the Pyramid Fairy rules # ["Bomb Merchant", False, []], diff --git a/test/owg/TestDungeons.py b/test/owg/TestDungeons.py index 69a65167..4231c088 100644 --- a/test/owg/TestDungeons.py +++ b/test/owg/TestDungeons.py @@ -89,9 +89,8 @@ class TestDungeons(TestVanillaOWG): ["Ice Palace - Compass Chest", False, []], ["Ice Palace - Compass Chest", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Compass Chest", False, [], ['Fire Rod', 'Progressive Sword']], - #todo: Missing clip? - #["Ice Palace - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Flippers', 'Fire Rod']], - #["Ice Palace - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Flippers', 'Bombos', 'Progressive Sword']], + ["Ice Palace - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Flippers', 'Fire Rod']], + ["Ice Palace - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Flippers', 'Bombos', 'Progressive Sword']], ["Ice Palace - Compass Chest", True, ['Progressive Glove', 'Progressive Glove', 'Fire Rod']], ["Ice Palace - Compass Chest", True, ['Progressive Glove', 'Progressive Glove', 'Bombos', 'Progressive Sword']], @@ -121,6 +120,7 @@ class TestDungeons(TestVanillaOWG): #todo: does clip require sword? #["Turtle Rock - Crystaroller Room", True, ['Moon Pearl', 'Pegasus Boots', 'Big Key (Turtle Rock)']], ["Turtle Rock - Crystaroller Room", True, ['Moon Pearl', 'Pegasus Boots', 'Big Key (Turtle Rock)', 'Progressive Sword']], + ["Turtle Rock - Crystaroller Room", True, ['Moon Pearl', 'Pegasus Boots', 'Big Key (Turtle Rock)', 'Hookshot']], ["Turtle Rock - Crystaroller Room", True, ['Pegasus Boots', 'Magic Mirror', 'Hammer', 'Big Key (Turtle Rock)']], ["Ganons Tower - Hope Room - Left", False, []],