From b5ea688847e9be2db14d75cb4dae00d8a5e95992 Mon Sep 17 00:00:00 2001 From: compiling <8335770+compiling@users.noreply.github.com> Date: Thu, 23 Jan 2020 19:41:03 +1100 Subject: [PATCH 1/4] Add inverted door shuffle --- DoorShuffle.py | 31 ++-------- Dungeons.py | 9 +-- EntranceShuffle.py | 148 +++++++++++++++++---------------------------- InvertedRegions.py | 115 +++-------------------------------- Main.py | 4 +- Regions.py | 10 ++- Rules.py | 146 +++++++------------------------------------- 7 files changed, 106 insertions(+), 357 deletions(-) diff --git a/DoorShuffle.py b/DoorShuffle.py index ba7c82eb..4ac15750 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -1155,7 +1155,7 @@ def overworld_prep(world, player): def find_inaccessible_regions(world, player): world.inaccessible_regions[player] = [] - if world.mode != 'inverted': + if world.mode[player] != 'inverted': start_regions = ['Links House', 'Sanctuary'] else: start_regions = ['Inverted Links House', 'Inverted Dark Sanctuary'] @@ -1185,30 +1185,11 @@ def valid_inaccessible_region(r): def add_inaccessible_doors(world, player): - if 'Skull Woods Forest (West)' in world.inaccessible_regions[player]: - create_door(world, player, 'Skull Woods Second Section Door (West)', 'Skull Woods Forest (West)') - create_door(world, player, 'Skull Woods Second Section Hole', 'Skull Woods Forest (West)') - create_door(world, player, 'Skull Woods Final Section', 'Skull Woods Forest (West)') - if 'Dark Death Mountain Ledge' in world.inaccessible_regions[player]: - create_door(world, player, 'Dark Death Mountain Ledge (East)', 'Dark Death Mountain Ledge') - create_door(world, player, 'Dark Death Mountain Ledge (West)', 'Dark Death Mountain Ledge') - create_door(world, player, 'Mimic Cave Mirror Spot', 'Dark Death Mountain Ledge') - if 'Mimic Cave Ledge' in world.inaccessible_regions[player]: - create_door(world, player, 'Mimic Cave', 'Mimic Cave Ledge') - if 'Dark Death Mountain Isolated Ledge' in world.inaccessible_regions[player]: - create_door(world, player, 'Turtle Rock Isolated Ledge Entrance', 'Dark Death Mountain Isolated Ledge') - if 'Death Mountain Floating Island (Dark World)' in world.inaccessible_regions[player]: - create_door(world, player, 'Hookshot Cave Back Entrance', 'Death Mountain Floating Island (Dark World)') - if 'Bumper Cave Ledge' in world.inaccessible_regions[player]: - create_door(world, player, 'Bumper Cave (Top)', 'Bumper Cave Ledge') - create_door(world, player, 'Bumper Cave Ledge Mirror Spot', 'Bumper Cave Ledge') - if 'Death Mountain Return Ledge' in world.inaccessible_regions[player]: - create_door(world, player, 'Death Mountain Return Cave (West)', 'Death Mountain Return Ledge') - if 'Desert Palace Lone Stairs' in world.inaccessible_regions[player]: - create_door(world, player, 'Desert Palace Entrance (East)', 'Desert Palace Lone Stairs') - # if world.mode[player] == 'standard' and 'Hyrule Castle Ledge' in world.inaccessible_regions[player]: - # create_door(world, player, 'Hyrule Castle Entrance (East)', 'Hyrule Castle Ledge') - # create_door(world, player, 'Hyrule Castle Entrance (West)', 'Hyrule Castle Ledge') + # todo: ignore standard mode hyrule castle ledge? + for inaccessible_region in world.inaccessible_regions[player]: + region = world.get_region(inaccessible_region, player) + for exit in region.exits: + create_door(world, player, exit.name, region.name) def create_door(world, player, entName, region_name): diff --git a/Dungeons.py b/Dungeons.py index dc8f5629..54928d7f 100644 --- a/Dungeons.py +++ b/Dungeons.py @@ -26,13 +26,8 @@ def create_dungeons(world, player): IP = make_dungeon('Ice Palace', 'Kholdstare', ice_regions, ItemFactory('Big Key (Ice Palace)', player), ItemFactory(['Small Key (Ice Palace)'] * 2, player), ItemFactory(['Map (Ice Palace)', 'Compass (Ice Palace)'], player)) MM = make_dungeon('Misery Mire', 'Vitreous', mire_regions, ItemFactory('Big Key (Misery Mire)', player), ItemFactory(['Small Key (Misery Mire)'] * 3, player), ItemFactory(['Map (Misery Mire)', 'Compass (Misery Mire)'], player)) TR = make_dungeon('Turtle Rock', 'Trinexx', tr_regions, ItemFactory('Big Key (Turtle Rock)', player), ItemFactory(['Small Key (Turtle Rock)'] * 4, player), ItemFactory(['Map (Turtle Rock)', 'Compass (Turtle Rock)'], player)) - - if world.mode[player] != 'inverted': - AT = make_dungeon('Agahnims Tower', 'Agahnim', tower_regions, None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), []) - GT = make_dungeon('Ganons Tower', 'Agahnim2', gt_regions, ItemFactory('Big Key (Ganons Tower)', player), ItemFactory(['Small Key (Ganons Tower)'] * 4, player), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'], player)) - else: - AT = make_dungeon('Inverted Agahnims Tower', 'Agahnim', ['Inverted Agahnims Tower', 'Agahnim 1'], None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), []) - GT = make_dungeon('Inverted Ganons Tower', 'Agahnim2', ['Inverted Ganons Tower (Entrance)', 'Ganons Tower (Tile Room)', 'Ganons Tower (Compass Room)', 'Ganons Tower (Hookshot Room)', 'Ganons Tower (Map Room)', 'Ganons Tower (Firesnake Room)', 'Ganons Tower (Teleport Room)', 'Ganons Tower (Bottom)', 'Ganons Tower (Top)', 'Ganons Tower (Before Moldorm)', 'Ganons Tower (Moldorm)', 'Agahnim 2'], ItemFactory('Big Key (Ganons Tower)', player), ItemFactory(['Small Key (Ganons Tower)'] * 4, player), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'], player)) + AT = make_dungeon('Agahnims Tower', 'Agahnim', tower_regions, None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), []) + GT = make_dungeon('Ganons Tower', 'Agahnim2', gt_regions, ItemFactory('Big Key (Ganons Tower)', player), ItemFactory(['Small Key (Ganons Tower)'] * 4, player), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'], player)) GT.bosses['bottom'] = BossFactory('Armos Knights', player) GT.bosses['middle'] = BossFactory('Lanmolas', player) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 96770372..3cdc9054 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -1746,8 +1746,8 @@ def link_inverted_entrances(world, player): else: raise NotImplementedError('Shuffling not supported yet') - # patch swamp drain - if world.get_entrance('Dam', player).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', player).connected_region.name != 'Swamp Palace (Entrance)': + # check for swamp palace fix + if world.get_entrance('Dam', player).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', player).connected_region.name != 'Swamp Lobby': world.swamp_patch_required[player] = True # check for potion shop location @@ -1759,7 +1759,7 @@ def link_inverted_entrances(world, player): world.ganon_at_pyramid[player] = False # check for Ganon's Tower location - if world.get_entrance('Inverted Ganons Tower', player).connected_region.name != 'Ganons Tower (Entrance)': + if world.get_entrance('Inverted Ganons Tower', player).connected_region.name != 'GT Lobby': world.ganonstower_vanilla[player] = False def connect_simple(world, exitname, regionname, player): @@ -2935,11 +2935,7 @@ inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia ('Desert Palace Stairs Drop', 'Light World'), ('Desert Palace Entrance (North) Rocks', 'Desert Palace Entrance (North) Spot'), ('Desert Ledge Return Rocks', 'Desert Ledge'), - ('Throne Room', 'Sewers (Dark)'), ('Sewers Door', 'Sewers'), - ('Sanctuary Push Door', 'Sanctuary'), - ('Sewer Drop', 'Sewers'), - ('Sewers Back Door', 'Sewers (Dark)'), - ('Agahnim 1', 'Agahnim 1'), + ('Sewer Drop', 'Sewers Rat Path'), ('Death Mountain Entrance Rock', 'Death Mountain Entrance'), ('Death Mountain Entrance Drop', 'Light World'), ('Spectacle Rock Cave Drop', 'Spectacle Rock Cave (Bottom)'), @@ -2991,37 +2987,6 @@ inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia ('Fairy Ascension Cave Pots', 'Fairy Ascension Cave (Bottom)'), ('Fairy Ascension Cave Drop', 'Fairy Ascension Cave (Drop)'), ('Dark Death Mountain Drop (East)', 'Dark Death Mountain (East Bottom)'), - ('Swamp Palace Moat', 'Swamp Palace (First Room)'), - ('Swamp Palace Small Key Door', 'Swamp Palace (Starting Area)'), - ('Swamp Palace (Center)', 'Swamp Palace (Center)'), - ('Swamp Palace (North)', 'Swamp Palace (North)'), - ('Skull Woods Torch Room', 'Skull Woods Final Section (Mothula)'), - ('Skull Woods First Section South Door', 'Skull Woods First Section (Right)'), - ('Skull Woods First Section West Door', 'Skull Woods First Section (Left)'), - ('Skull Woods First Section (Right) North Door', 'Skull Woods First Section'), - ('Skull Woods First Section (Left) Door to Right', 'Skull Woods First Section (Right)'), - ('Skull Woods First Section (Left) Door to Exit', 'Skull Woods First Section'), - ('Skull Woods First Section (Top) One-Way Path', 'Skull Woods First Section'), - ('Skull Woods Second Section (Drop)', 'Skull Woods Second Section'), - ('Blind Fight', 'Blind Fight'), - ('Misery Mire Entrance Gap', 'Misery Mire (Main)'), - ('Misery Mire (West)', 'Misery Mire (West)'), - ('Misery Mire Big Key Door', 'Misery Mire (Final Area)'), - ('Misery Mire (Vitreous)', 'Misery Mire (Vitreous)'), - ('Turtle Rock Entrance Gap', 'Turtle Rock (First Section)'), - ('Turtle Rock Entrance Gap Reverse', 'Turtle Rock (Entrance)'), - ('Turtle Rock Pokey Room', 'Turtle Rock (Chain Chomp Room)'), - ('Turtle Rock (Chain Chomp Room) (North)', 'Turtle Rock (Second Section)'), - ('Turtle Rock (Chain Chomp Room) (South)', 'Turtle Rock (First Section)'), - ('Turtle Rock Chain Chomp Staircase', 'Turtle Rock (Chain Chomp Room)'), - ('Turtle Rock (Big Chest) (North)', 'Turtle Rock (Second Section)'), - ('Turtle Rock Big Key Door', 'Turtle Rock (Crystaroller Room)'), - ('Turtle Rock Big Key Door Reverse', 'Turtle Rock (Second Section)'), - ('Turtle Rock Dark Room Staircase', 'Turtle Rock (Dark Room)'), - ('Turtle Rock (Dark Room) (North)', 'Turtle Rock (Crystaroller Room)'), - ('Turtle Rock (Dark Room) (South)', 'Turtle Rock (Eye Bridge)'), - ('Turtle Rock Dark Room (South)', 'Turtle Rock (Dark Room)'), - ('Turtle Rock (Trinexx)', 'Turtle Rock (Trinexx)'), ('Ganon Drop', 'Bottom of Pyramid'), ('Pyramid Drop', 'East Dark World'), ('Post Aga Teleporter', 'Light World'), @@ -3461,58 +3426,59 @@ default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert Main L ('Ganons Tower Exit', 'Dark Death Mountain (Top)') ] -inverted_default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert Palace Main (Inner)'), - ('Desert Palace Entrance (West)', 'Desert Palace Main (Outer)'), - ('Desert Palace Entrance (North)', 'Desert Palace North'), - ('Desert Palace Entrance (East)', 'Desert Palace Main (Outer)'), - ('Desert Palace Exit (South)', 'Desert Palace Stairs'), - ('Desert Palace Exit (West)', 'Desert Ledge'), - ('Desert Palace Exit (East)', 'Desert Palace Lone Stairs'), - ('Desert Palace Exit (North)', 'Desert Palace Entrance (North) Spot'), - ('Eastern Palace', 'Eastern Palace'), - ('Eastern Palace Exit', 'Light World'), - ('Tower of Hera', 'Tower of Hera (Bottom)'), - ('Tower of Hera Exit', 'Death Mountain (Top)'), - ('Hyrule Castle Entrance (South)', 'Hyrule Castle'), - ('Hyrule Castle Entrance (West)', 'Hyrule Castle'), - ('Hyrule Castle Entrance (East)', 'Hyrule Castle'), - ('Hyrule Castle Exit (South)', 'Light World'), - ('Hyrule Castle Exit (West)', 'Hyrule Castle Ledge'), - ('Hyrule Castle Exit (East)', 'Hyrule Castle Ledge'), - ('Thieves Town', 'Thieves Lobby'), - ('Thieves Town Exit', 'West Dark World'), - ('Skull Woods First Section Hole (East)', 'Skull Woods First Section (Right)'), - ('Skull Woods First Section Hole (West)', 'Skull Woods First Section (Left)'), - ('Skull Woods First Section Hole (North)', 'Skull Woods First Section (Top)'), - ('Skull Woods First Section Door', 'Skull Woods First Section'), - ('Skull Woods First Section Exit', 'Skull Woods Forest'), - ('Skull Woods Second Section Hole', 'Skull Woods Second Section (Drop)'), - ('Skull Woods Second Section Door (East)', 'Skull Woods Second Section'), - ('Skull Woods Second Section Door (West)', 'Skull Woods Second Section'), - ('Skull Woods Second Section Exit (East)', 'Skull Woods Forest'), - ('Skull Woods Second Section Exit (West)', 'Skull Woods Forest (West)'), - ('Skull Woods Final Section', 'Skull Woods Final Section (Entrance)'), - ('Skull Woods Final Section Exit', 'Skull Woods Forest (West)'), - ('Ice Palace', 'Ice Lobby'), - ('Misery Mire', 'Misery Mire (Entrance)'), - ('Misery Mire Exit', 'Dark Desert'), - ('Palace of Darkness', 'PoD Lobby'), - ('Palace of Darkness Exit', 'East Dark World'), - ('Swamp Palace', 'Swamp Palace (Entrance)'), - ('Swamp Palace Exit', 'South Dark World'), - ('Turtle Rock', 'Turtle Rock (Entrance)'), - ('Turtle Rock Ledge Exit (West)', 'Dark Death Mountain Ledge'), - ('Turtle Rock Ledge Exit (East)', 'Dark Death Mountain Ledge'), - ('Dark Death Mountain Ledge (West)', 'Turtle Rock (Second Section)'), - ('Dark Death Mountain Ledge (East)', 'Turtle Rock (Big Chest)'), - ('Turtle Rock Isolated Ledge Exit', 'Dark Death Mountain Isolated Ledge'), - ('Turtle Rock Isolated Ledge Entrance', 'Turtle Rock (Eye Bridge)'), - ('Inverted Ganons Tower', 'Inverted Ganons Tower (Entrance)'), - ('Inverted Ganons Tower Exit', 'Hyrule Castle Ledge'), - ('Inverted Agahnims Tower', 'Inverted Agahnims Tower'), - ('Inverted Agahnims Tower Exit', 'Dark Death Mountain'), - ('Turtle Rock Exit (Front)', 'Dark Death Mountain'), - ('Ice Palace Exit', 'Dark Lake Hylia')] +inverted_default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert Main Lobby'), + ('Desert Palace Entrance (West)', 'Desert West Lobby'), + ('Desert Palace Entrance (North)', 'Desert Back Lobby'), + ('Desert Palace Entrance (East)', 'Desert East Lobby'), + ('Desert Palace Exit (South)', 'Desert Palace Stairs'), + ('Desert Palace Exit (West)', 'Desert Ledge'), + ('Desert Palace Exit (East)', 'Desert Palace Lone Stairs'), + ('Desert Palace Exit (North)', 'Desert Palace Entrance (North) Spot'), + ('Eastern Palace', 'Eastern Lobby'), + ('Eastern Palace Exit', 'Light World'), + ('Tower of Hera', 'Hera Lobby'), + ('Tower of Hera Exit', 'Death Mountain (Top)'), + ('Hyrule Castle Entrance (South)', 'Hyrule Castle Lobby'), + ('Hyrule Castle Entrance (West)', 'Hyrule Castle West Lobby'), + ('Hyrule Castle Entrance (East)', 'Hyrule Castle East Lobby'), + ('Hyrule Castle Exit (South)', 'Light World'), + ('Hyrule Castle Exit (West)', 'Hyrule Castle Ledge'), + ('Hyrule Castle Exit (East)', 'Hyrule Castle Ledge'), + ('Thieves Town', 'Thieves Lobby'), + ('Thieves Town Exit', 'West Dark World'), + ('Skull Woods First Section Hole (East)', 'Skull Pinball'), + ('Skull Woods First Section Hole (West)', 'Skull Left Drop'), + ('Skull Woods First Section Hole (North)', 'Skull Pot Circle'), + ('Skull Woods First Section Door', 'Skull 1 Lobby'), + ('Skull Woods First Section Exit', 'Skull Woods Forest'), + ('Skull Woods Second Section Hole', 'Skull Back Drop'), + ('Skull Woods Second Section Door (East)', 'Skull 2 East Lobby'), + ('Skull Woods Second Section Door (West)', 'Skull 2 West Lobby'), + ('Skull Woods Second Section Exit (East)', 'Skull Woods Forest'), + ('Skull Woods Second Section Exit (West)', 'Skull Woods Forest (West)'), + ('Skull Woods Final Section', 'Skull 3 Lobby'), + ('Skull Woods Final Section Exit', 'Skull Woods Forest (West)'), + ('Ice Palace', 'Ice Lobby'), + ('Misery Mire', 'Mire Lobby'), + ('Misery Mire Exit', 'Dark Desert'), + ('Palace of Darkness', 'PoD Lobby'), + ('Palace of Darkness Exit', 'East Dark World'), + ('Swamp Palace', 'Swamp Lobby'), # requires additional patch for flooding moat if moved + ('Swamp Palace Exit', 'South Dark World'), + ('Turtle Rock', 'TR Main Lobby'), + ('Turtle Rock Ledge Exit (West)', 'Dark Death Mountain Ledge'), + ('Turtle Rock Ledge Exit (East)', 'Dark Death Mountain Ledge'), + ('Dark Death Mountain Ledge (West)', 'TR Lazy Eyes'), + ('Dark Death Mountain Ledge (East)', 'TR Big Chest Entrance'), + ('Turtle Rock Isolated Ledge Exit', 'Dark Death Mountain Isolated Ledge'), + ('Turtle Rock Isolated Ledge Entrance', 'TR Eye Bridge'), + ('Inverted Ganons Tower', 'GT Lobby'), + ('Inverted Ganons Tower Exit', 'Hyrule Castle Ledge'), + ('Inverted Agahnims Tower', 'Tower Lobby'), + ('Inverted Agahnims Tower Exit', 'Dark Death Mountain'), + ('Turtle Rock Exit (Front)', 'Dark Death Mountain'), + ('Ice Palace Exit', 'Dark Lake Hylia') + ] # format: # Key=Name diff --git a/InvertedRegions.py b/InvertedRegions.py index 609d4fd4..cea882dd 100644 --- a/InvertedRegions.py +++ b/InvertedRegions.py @@ -34,6 +34,7 @@ def create_inverted_regions(world, player): create_lw_region(player, 'Graveyard Cave Area', None, ['Graveyard Cave', 'Graveyard Cave Inner Bushes', 'Graveyard Cave Mirror Spot']), create_lw_region(player, 'River', None, ['Light World Pier', 'Potion Shop Pier']), create_cave_region(player, 'Hyrule Castle Secret Entrance', 'a drop\'s exit', ['Link\'s Uncle', 'Secret Passage'], ['Hyrule Castle Secret Entrance Exit']), + create_dungeon_region(player, 'Sewer Drop', 'a drop\'s exit', None, ['Sewer Drop']), # This exists only to be referenced for access checks create_lw_region(player, 'Zoras River', ['King Zora', 'Zora\'s Ledge']), create_cave_region(player, 'Waterfall of Wishing', 'a cave with two chests', ['Waterfall Fairy - Left', 'Waterfall Fairy - Right']), create_lw_region(player, 'Kings Grave Area', None, ['Kings Grave', 'Kings Grave Inner Rocks']), @@ -102,25 +103,9 @@ def create_inverted_regions(world, player): create_lw_region(player, 'Desert Palace Stairs', None, ['Desert Palace Entrance (South)', 'Desert Palace Stairs Mirror Spot']), create_lw_region(player, 'Desert Palace Lone Stairs', None, ['Desert Palace Stairs Drop', 'Desert Palace Entrance (East)']), create_lw_region(player, 'Desert Palace Entrance (North) Spot', None, ['Desert Palace Entrance (North)', 'Desert Ledge Return Rocks', 'Desert Palace North Mirror Spot']), - create_dungeon_region(player, 'Desert Palace Main (Outer)', 'Desert Palace', ['Desert Palace - Big Chest', 'Desert Palace - Torch', 'Desert Palace - Map Chest'], - ['Desert Palace Pots (Outer)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace East Wing']), - create_dungeon_region(player, 'Desert Palace Main (Inner)', 'Desert Palace', None, ['Desert Palace Exit (South)', 'Desert Palace Pots (Inner)']), - create_dungeon_region(player, 'Desert Palace East', 'Desert Palace', ['Desert Palace - Compass Chest', 'Desert Palace - Big Key Chest']), - create_dungeon_region(player, 'Desert Palace North', 'Desert Palace', ['Desert Palace - Boss', 'Desert Palace - Prize'], ['Desert Palace Exit (North)']), - create_dungeon_region(player, 'Eastern Palace', 'Eastern Palace', ['Eastern Palace - Compass Chest', 'Eastern Palace - Big Chest', 'Eastern Palace - Cannonball Chest', - 'Eastern Palace - Big Key Chest', 'Eastern Palace - Map Chest', 'Eastern Palace - Boss', 'Eastern Palace - Prize'], ['Eastern Palace Exit']), create_lw_region(player, 'Master Sword Meadow', ['Master Sword Pedestal']), create_cave_region(player, 'Lost Woods Gamble', 'a game of chance'), create_lw_region(player, 'Hyrule Castle Ledge', None, ['Hyrule Castle Entrance (East)', 'Hyrule Castle Entrance (West)', 'Inverted Ganons Tower', 'Hyrule Castle Ledge Courtyard Drop', 'Inverted Pyramid Hole']), - create_dungeon_region(player, 'Hyrule Castle', 'Hyrule Castle', ['Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest', 'Hyrule Castle - Zelda\'s Chest'], - ['Hyrule Castle Exit (East)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (South)', 'Throne Room']), - create_dungeon_region(player, 'Sewer Drop', 'a drop\'s exit', None, ['Sewer Drop']), # This exists only to be referenced for access checks - create_dungeon_region(player, 'Sewers (Dark)', 'a drop\'s exit', ['Sewers - Dark Cross'], ['Sewers Door']), - create_dungeon_region(player, 'Sewers', 'a drop\'s exit', ['Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle', - 'Sewers - Secret Room - Right'], ['Sanctuary Push Door', 'Sewers Back Door']), - create_dungeon_region(player, 'Sanctuary', 'a drop\'s exit', ['Sanctuary'], ['Sanctuary Exit']), - create_dungeon_region(player, 'Inverted Agahnims Tower', 'Castle Tower', ['Castle Tower - Room 03', 'Castle Tower - Dark Maze'], ['Agahnim 1', 'Inverted Agahnims Tower Exit']), - create_dungeon_region(player, 'Agahnim 1', 'Castle Tower', ['Agahnim 1'], None), 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']), @@ -158,9 +143,6 @@ def create_inverted_regions(world, player): create_lw_region(player, 'Fairy Ascension Ledge', None, ['Fairy Ascension Ledge Drop', 'Fairy Ascension Cave (Top)', 'Laser Bridge Mirror Spot']), create_lw_region(player, 'Death Mountain (Top)', ['Ether Tablet', 'Spectacle Rock'], ['East Death Mountain (Top)', 'Tower of Hera', 'Death Mountain Drop', 'Death Mountain (Top) Mirror Spot']), create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Ledge Drop', 'Bumper Cave (Top)']), - 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 Fairy', 'Palace of Darkness Hint', 'East Dark World Hint', 'Northeast Dark World Broken Bridge Pass', 'East Dark World Teleporter', 'EDW Flute']), @@ -217,84 +199,6 @@ def create_inverted_regions(world, player): create_dw_region(player, 'Death Mountain Floating Island (Dark World)', None, ['Floating Island Drop', 'Hookshot Cave Back Entrance']), create_cave_region(player, 'Mimic Cave', 'Mimic Cave', ['Mimic Cave']), - create_dungeon_region(player, 'Swamp Palace (Entrance)', 'Swamp Palace', None, ['Swamp Palace Moat', 'Swamp Palace Exit']), - create_dungeon_region(player, 'Swamp Palace (First Room)', 'Swamp Palace', ['Swamp Palace - Entrance'], ['Swamp Palace Small Key Door']), - create_dungeon_region(player, 'Swamp Palace (Starting Area)', 'Swamp Palace', ['Swamp Palace - Map Chest'], ['Swamp Palace (Center)']), - create_dungeon_region(player, 'Swamp Palace (Center)', 'Swamp Palace', ['Swamp Palace - Big Chest', 'Swamp Palace - Compass Chest', - 'Swamp Palace - Big Key Chest', 'Swamp Palace - West Chest'], ['Swamp Palace (North)']), - create_dungeon_region(player, 'Swamp Palace (North)', 'Swamp Palace', ['Swamp Palace - Flooded Room - Left', 'Swamp Palace - Flooded Room - Right', - 'Swamp Palace - Waterfall Room', 'Swamp Palace - Boss', 'Swamp Palace - Prize']), - create_dungeon_region(player, 'Thieves Town (Entrance)', 'Thieves\' Town', ['Thieves\' Town - Big Key Chest', - 'Thieves\' Town - Map Chest', - 'Thieves\' Town - Compass Chest', - 'Thieves\' Town - Ambush Chest'], ['Thieves Town Big Key Door', 'Thieves Town Exit']), - create_dungeon_region(player, 'Thieves Town (Deep)', 'Thieves\' Town', ['Thieves\' Town - Attic', - 'Thieves\' Town - Big Chest', - 'Thieves\' Town - Blind\'s Cell'], ['Blind Fight']), - create_dungeon_region(player, 'Blind Fight', 'Thieves\' Town', ['Thieves\' Town - Boss', 'Thieves\' Town - Prize']), - create_dungeon_region(player, 'Skull Woods First Section', 'Skull Woods', ['Skull Woods - Map Chest'], ['Skull Woods First Section Exit', 'Skull Woods First Section Bomb Jump', 'Skull Woods First Section South Door', 'Skull Woods First Section West Door']), - create_dungeon_region(player, 'Skull Woods First Section (Right)', 'Skull Woods', ['Skull Woods - Pinball Room'], ['Skull Woods First Section (Right) North Door']), - create_dungeon_region(player, 'Skull Woods First Section (Left)', 'Skull Woods', ['Skull Woods - Compass Chest', 'Skull Woods - Pot Prison'], ['Skull Woods First Section (Left) Door to Exit', 'Skull Woods First Section (Left) Door to Right']), - create_dungeon_region(player, 'Skull Woods First Section (Top)', 'Skull Woods', ['Skull Woods - Big Chest'], ['Skull Woods First Section (Top) One-Way Path']), - create_dungeon_region(player, 'Skull Woods Second Section (Drop)', 'Skull Woods', None, ['Skull Woods Second Section (Drop)']), - create_dungeon_region(player, 'Skull Woods Second Section', 'Skull Woods', ['Skull Woods - Big Key Chest'], ['Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)']), - create_dungeon_region(player, 'Skull Woods Final Section (Entrance)', 'Skull Woods', ['Skull Woods - Bridge Room'], ['Skull Woods Torch Room', 'Skull Woods Final Section Exit']), - create_dungeon_region(player, 'Skull Woods Final Section (Mothula)', 'Skull Woods', ['Skull Woods - Boss', 'Skull Woods - Prize']), - create_dungeon_region(player, 'Ice Palace (Entrance)', 'Ice Palace', None, ['Ice Palace Entrance Room', 'Ice Palace Exit']), - create_dungeon_region(player, 'Ice Palace (Main)', 'Ice Palace', ['Ice Palace - Compass Chest', 'Ice Palace - Freezor Chest', - 'Ice Palace - Big Chest', 'Ice Palace - Iced T Room'], ['Ice Palace (East)', 'Ice Palace (Kholdstare)']), - create_dungeon_region(player, 'Ice Palace (East)', 'Ice Palace', ['Ice Palace - Spike Room'], ['Ice Palace (East Top)']), - create_dungeon_region(player, 'Ice Palace (East Top)', 'Ice Palace', ['Ice Palace - Big Key Chest', 'Ice Palace - Map Chest']), - create_dungeon_region(player, 'Ice Palace (Kholdstare)', 'Ice Palace', ['Ice Palace - Boss', 'Ice Palace - Prize']), - create_dungeon_region(player, 'Misery Mire (Entrance)', 'Misery Mire', None, ['Misery Mire Entrance Gap', 'Misery Mire Exit']), - create_dungeon_region(player, 'Misery Mire (Main)', 'Misery Mire', ['Misery Mire - Big Chest', 'Misery Mire - Map Chest', 'Misery Mire - Main Lobby', - 'Misery Mire - Bridge Chest', 'Misery Mire - Spike Chest'], ['Misery Mire (West)', 'Misery Mire Big Key Door']), - create_dungeon_region(player, 'Misery Mire (West)', 'Misery Mire', ['Misery Mire - Compass Chest', 'Misery Mire - Big Key Chest']), - create_dungeon_region(player, 'Misery Mire (Final Area)', 'Misery Mire', None, ['Misery Mire (Vitreous)']), - create_dungeon_region(player, 'Misery Mire (Vitreous)', 'Misery Mire', ['Misery Mire - Boss', 'Misery Mire - Prize']), - create_dungeon_region(player, 'Turtle Rock (Entrance)', 'Turtle Rock', None, ['Turtle Rock Entrance Gap', 'Turtle Rock Exit (Front)']), - create_dungeon_region(player, 'Turtle Rock (First Section)', 'Turtle Rock', ['Turtle Rock - Compass Chest', 'Turtle Rock - Roller Room - Left', - 'Turtle Rock - Roller Room - Right'], ['Turtle Rock Pokey Room', 'Turtle Rock Entrance Gap Reverse']), - create_dungeon_region(player, 'Turtle Rock (Chain Chomp Room)', 'Turtle Rock', ['Turtle Rock - Chain Chomps'], ['Turtle Rock (Chain Chomp Room) (North)', 'Turtle Rock (Chain Chomp Room) (South)']), - create_dungeon_region(player, 'Turtle Rock (Second Section)', 'Turtle Rock', ['Turtle Rock - Big Key Chest'], ['Turtle Rock Ledge Exit (West)', 'Turtle Rock Chain Chomp Staircase', 'Turtle Rock Big Key Door']), - create_dungeon_region(player, 'Turtle Rock (Big Chest)', 'Turtle Rock', ['Turtle Rock - Big Chest'], ['Turtle Rock (Big Chest) (North)', 'Turtle Rock Ledge Exit (East)']), - create_dungeon_region(player, 'Turtle Rock (Crystaroller Room)', 'Turtle Rock', ['Turtle Rock - Crystaroller Room'], ['Turtle Rock Dark Room Staircase', 'Turtle Rock Big Key Door Reverse']), - create_dungeon_region(player, 'Turtle Rock (Dark Room)', 'Turtle Rock', None, ['Turtle Rock (Dark Room) (North)', 'Turtle Rock (Dark Room) (South)']), - create_dungeon_region(player, 'Turtle Rock (Eye Bridge)', 'Turtle Rock', ['Turtle Rock - Eye Bridge - Bottom Left', 'Turtle Rock - Eye Bridge - Bottom Right', - 'Turtle Rock - Eye Bridge - Top Left', 'Turtle Rock - Eye Bridge - Top Right'], - ['Turtle Rock Dark Room (South)', 'Turtle Rock (Trinexx)', 'Turtle Rock Isolated Ledge Exit']), - create_dungeon_region(player, 'Turtle Rock (Trinexx)', 'Turtle Rock', ['Turtle Rock - Boss', 'Turtle Rock - Prize']), - create_dungeon_region(player, 'Palace of Darkness (Entrance)', 'Palace of Darkness', ['Palace of Darkness - Shooter Room'], ['Palace of Darkness Bridge Room', 'Palace of Darkness Bonk Wall', 'Palace of Darkness Exit']), - create_dungeon_region(player, 'Palace of Darkness (Center)', 'Palace of Darkness', ['Palace of Darkness - The Arena - Bridge', 'Palace of Darkness - Stalfos Basement'], - ['Palace of Darkness Big Key Chest Staircase', 'Palace of Darkness (North)', 'Palace of Darkness Big Key Door']), - create_dungeon_region(player, 'Palace of Darkness (Big Key Chest)', 'Palace of Darkness', ['Palace of Darkness - Big Key Chest']), - create_dungeon_region(player, 'Palace of Darkness (Bonk Section)', 'Palace of Darkness', ['Palace of Darkness - The Arena - Ledge', 'Palace of Darkness - Map Chest'], ['Palace of Darkness Hammer Peg Drop']), - create_dungeon_region(player, 'Palace of Darkness (North)', 'Palace of Darkness', ['Palace of Darkness - Compass Chest', 'Palace of Darkness - Dark Basement - Left', 'Palace of Darkness - Dark Basement - Right'], - ['Palace of Darkness Spike Statue Room Door', 'Palace of Darkness Maze Door']), - create_dungeon_region(player, 'Palace of Darkness (Maze)', 'Palace of Darkness', ['Palace of Darkness - Dark Maze - Top', 'Palace of Darkness - Dark Maze - Bottom', 'Palace of Darkness - Big Chest']), - create_dungeon_region(player, 'Palace of Darkness (Harmless Hellway)', 'Palace of Darkness', ['Palace of Darkness - Harmless Hellway']), - create_dungeon_region(player, 'Palace of Darkness (Final Section)', 'Palace of Darkness', ['Palace of Darkness - Boss', 'Palace of Darkness - Prize']), - create_dungeon_region(player, 'Inverted Ganons Tower (Entrance)', 'Ganon\'s Tower', ['Ganons Tower - Bob\'s Torch', 'Ganons Tower - Hope Room - Left', 'Ganons Tower - Hope Room - Right'], - ['Ganons Tower (Tile Room)', 'Ganons Tower (Hookshot Room)', 'Ganons Tower Big Key Door', 'Inverted Ganons Tower Exit']), - create_dungeon_region(player, 'Ganons Tower (Tile Room)', 'Ganon\'s Tower', ['Ganons Tower - Tile Room'], ['Ganons Tower (Tile Room) Key Door']), - create_dungeon_region(player, 'Ganons Tower (Compass Room)', 'Ganon\'s Tower', ['Ganons Tower - Compass Room - Top Left', 'Ganons Tower - Compass Room - Top Right', - 'Ganons Tower - Compass Room - Bottom Left', 'Ganons Tower - Compass Room - Bottom Right'], - ['Ganons Tower (Bottom) (East)']), - create_dungeon_region(player, 'Ganons Tower (Hookshot Room)', 'Ganon\'s Tower', ['Ganons Tower - DMs Room - Top Left', 'Ganons Tower - DMs Room - Top Right', - 'Ganons Tower - DMs Room - Bottom Left', 'Ganons Tower - DMs Room - Bottom Right'], - ['Ganons Tower (Map Room)', 'Ganons Tower (Double Switch Room)']), - create_dungeon_region(player, 'Ganons Tower (Map Room)', 'Ganon\'s Tower', ['Ganons Tower - Map Chest']), - create_dungeon_region(player, 'Ganons Tower (Firesnake Room)', 'Ganon\'s Tower', ['Ganons Tower - Firesnake Room'], ['Ganons Tower (Firesnake Room)']), - create_dungeon_region(player, 'Ganons Tower (Teleport Room)', 'Ganon\'s Tower', ['Ganons Tower - Randomizer Room - Top Left', 'Ganons Tower - Randomizer Room - Top Right', - 'Ganons Tower - Randomizer Room - Bottom Left', 'Ganons Tower - Randomizer Room - Bottom Right'], - ['Ganons Tower (Bottom) (West)']), - create_dungeon_region(player, 'Ganons Tower (Bottom)', 'Ganon\'s Tower', ['Ganons Tower - Bob\'s Chest', 'Ganons Tower - Big Chest', 'Ganons Tower - Big Key Room - Left', - 'Ganons Tower - Big Key Room - Right', 'Ganons Tower - Big Key Chest']), - create_dungeon_region(player, 'Ganons Tower (Top)', 'Ganon\'s Tower', None, ['Ganons Tower Torch Rooms']), - create_dungeon_region(player, 'Ganons Tower (Before Moldorm)', 'Ganon\'s Tower', ['Ganons Tower - Mini Helmasaur Room - Left', 'Ganons Tower - Mini Helmasaur Room - Right', - 'Ganons Tower - Pre-Moldorm Chest'], ['Ganons Tower Moldorm Door']), - create_dungeon_region(player, 'Ganons Tower (Moldorm)', 'Ganon\'s Tower', None, ['Ganons Tower Moldorm Gap']), - create_dungeon_region(player, 'Agahnim 2', 'Ganon\'s Tower', ['Ganons Tower - Validation Chest', 'Agahnim 2'], None), 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 @@ -313,8 +217,8 @@ def mark_dark_world_regions(world, player): current = queue.popleft() current.is_dark_world = True for exit in current.exits: - if exit.connected_region.type == RegionType.LightWorld: - # Don't venture into the dark world + if exit.connected_region is None or exit.connected_region.type == RegionType.LightWorld: # todo: remove none check + # Don't venture into the light world continue if exit.connected_region not in seen: seen.add(exit.connected_region) @@ -326,12 +230,13 @@ def mark_dark_world_regions(world, player): current = queue.popleft() current.is_light_world = True for exit in current.exits: - if exit.connected_region.type == RegionType.DarkWorld: - # Don't venture into the light world - continue - if exit.connected_region not in seen: - seen.add(exit.connected_region) - queue.append(exit.connected_region) + if exit.connected_region is not None: + if exit.connected_region.type == RegionType.DarkWorld: + # Don't venture into the dark world + continue + if exit.connected_region not in seen: + seen.add(exit.connected_region) + queue.append(exit.connected_region) location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), diff --git a/Main.py b/Main.py index f9d61c2a..c0dec0f6 100644 --- a/Main.py +++ b/Main.py @@ -10,7 +10,7 @@ import zlib from BaseClasses import World, CollectionState, Item, Region, Location, Shop from Items import ItemFactory -from Regions import create_regions, create_shops, mark_light_world_regions +from Regions import create_regions, create_shops, mark_light_world_regions, create_dungeon_regions from InvertedRegions import create_inverted_regions, mark_dark_world_regions from EntranceShuffle import link_entrances, link_inverted_entrances from Rom import patch_rom, patch_race_rom, patch_enemizer, apply_rom_settings, LocalRom, JsonRom, get_hash_string @@ -84,6 +84,7 @@ def main(args, seed=None): create_regions(world, player) else: create_inverted_regions(world, player) + create_dungeon_regions(world, player) create_shops(world, player) create_doors(world, player) create_rooms(world, player) @@ -286,6 +287,7 @@ def copy_world(world): create_regions(ret, player) else: create_inverted_regions(ret, player) + create_dungeon_regions(ret, player) create_shops(ret, player) create_doors(ret, player) create_rooms(ret, player) diff --git a/Regions.py b/Regions.py index 6a27612e..e92347c1 100644 --- a/Regions.py +++ b/Regions.py @@ -3,7 +3,6 @@ from BaseClasses import Region, Location, Entrance, RegionType, Shop, ShopType def create_regions(world, player): - std_flag = world.mode[player] == 'standard' world.regions += [ create_lw_region(player, 'Light World', ['Mushroom', 'Bottle Merchant', 'Flute Spot', 'Sunken Treasure', 'Purple Chest'], ["Blinds Hideout", "Hyrule Castle Secret Entrance Drop", 'Zoras River', 'Kings Grave Outer Rocks', 'Dam', @@ -196,7 +195,12 @@ 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']), + ] +def create_dungeon_regions(world, player): + std_flag = world.mode[player] == 'standard' + inv_flag = world.mode[player] == 'inverted' + world.regions += [ create_dungeon_region(player, 'Hyrule Castle Lobby', 'Hyrule Castle', None, ['Hyrule Castle Lobby W', 'Hyrule Castle Lobby E', 'Hyrule Castle Lobby WN', 'Hyrule Castle Lobby North Stairs', 'Hyrule Castle Exit (South)']), create_dungeon_region(player, 'Hyrule Castle West Lobby', 'Hyrule Castle', None, ['Hyrule Castle West Lobby E', 'Hyrule Castle West Lobby N', @@ -316,7 +320,7 @@ def create_regions(world, player): create_dungeon_region(player, 'Hera Boss', 'Tower of Hera', ['Tower of Hera - Boss', 'Tower of Hera - Prize'], ['Hera Boss Down Stairs', 'Hera Boss Outer Hole', 'Hera Boss Inner Hole']), # AgaTower - create_dungeon_region(player, 'Tower Lobby', 'Castle Tower', None, ['Tower Lobby NW', 'Agahnims Tower Exit']), + create_dungeon_region(player, 'Tower Lobby', 'Castle Tower', None, ['Tower Lobby NW', inv_flag and 'Inverted Agahnims Tower Exit' or 'Agahnims Tower Exit']), create_dungeon_region(player, 'Tower Gold Knights', 'Castle Tower', None, ['Tower Gold Knights SW', 'Tower Gold Knights EN']), create_dungeon_region(player, 'Tower Room 03', 'Castle Tower', ['Castle Tower - Room 03'], ['Tower Room 03 WN', 'Tower Room 03 Up Stairs']), create_dungeon_region(player, 'Tower Lone Statue', 'Castle Tower', None, ['Tower Lone Statue Down Stairs', 'Tower Lone Statue WN']), @@ -622,7 +626,7 @@ def create_regions(world, player): create_dungeon_region(player, 'TR Boss', 'Turtle Rock', ['Turtle Rock - Boss', 'Turtle Rock - Prize'], ['TR Boss SW']), # gt - create_dungeon_region(player, 'GT Lobby', 'Ganon\'s Tower', None, ['GT Lobby Left Down Stairs', 'GT Lobby Up Stairs', 'GT Lobby Right Down Stairs', 'Ganons Tower Exit']), + create_dungeon_region(player, 'GT Lobby', 'Ganon\'s Tower', None, ['GT Lobby Left Down Stairs', 'GT Lobby Up Stairs', 'GT Lobby Right Down Stairs', inv_flag and 'Inverted Ganons Tower Exit' or 'Ganons Tower Exit']), create_dungeon_region(player, 'GT Bob\'s Torch', 'Ganon\'s Tower', ['Ganons Tower - Bob\'s Torch'], ['GT Torch Up Stairs', 'GT Torch WN', 'GT Torch EN', 'GT Torch SW']), create_dungeon_region(player, 'GT Hope Room', 'Ganon\'s Tower', ['Ganons Tower - Hope Room - Left', 'Ganons Tower - Hope Room - Right'], ['GT Hope Room Up Stairs', 'GT Hope Room WN', 'GT Hope Room EN']), create_dungeon_region(player, 'GT Big Chest', 'Ganon\'s Tower', ['Ganons Tower - Big Chest'], ['GT Big Chest NW', 'GT Big Chest SW']), diff --git a/Rules.py b/Rules.py index 780e795c..a29ec51d 100644 --- a/Rules.py +++ b/Rules.py @@ -639,8 +639,6 @@ def inverted_rules(world, player): if world.swords[player] == 'swordless': swordless_rules(world, player) - set_trock_key_rules(world, player) - set_rule(world.get_entrance('Inverted Ganons Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player)) def no_glitches_rules(world, player): @@ -732,24 +730,20 @@ def no_glitches_rules(world, player): add_conditional_lamp('Eastern Rupees SE', 'Eastern Rupees', 'Entrance') add_conditional_lamp('Eastern Palace - Dark Square Pot Key', 'Eastern Dark Square', 'Location') add_conditional_lamp('Eastern Palace - Dark Eyegore Key Drop', 'Eastern Darkness', 'Location') - if world.mode[player] != 'inverted': - add_conditional_lamp('Tower Lone Statue Down Stairs', 'Tower Lone Statue', 'Entrance') - add_conditional_lamp('Tower Lone Statue WN', 'Tower Lone Statue', 'Entrance') - add_conditional_lamp('Tower Dark Maze EN', 'Tower Dark Maze', 'Entrance') - add_conditional_lamp('Tower Dark Maze ES', 'Tower Dark Maze', 'Entrance') - add_conditional_lamp('Tower Dark Chargers WS', 'Tower Dark Chargers', 'Entrance') - add_conditional_lamp('Tower Dark Chargers Up Stairs', 'Tower Dark Chargers', 'Entrance') - add_conditional_lamp('Tower Dual Statues Down Stairs', 'Tower Dual Statues', 'Entrance') - add_conditional_lamp('Tower Dual Statues WS', 'Tower Dual Statues', 'Entrance') - add_conditional_lamp('Tower Dark Pits ES', 'Tower Dark Pits', 'Entrance') - add_conditional_lamp('Tower Dark Pits EN', 'Tower Dark Pits', 'Entrance') - add_conditional_lamp('Tower Dark Archers WN', 'Tower Dark Archers', 'Entrance') - add_conditional_lamp('Tower Dark Archers Up Stairs', 'Tower Dark Archers', 'Entrance') - add_conditional_lamp('Castle Tower - Dark Maze', 'Tower Dark Maze', 'Location') - add_conditional_lamp('Castle Tower - Dark Archer Key Drop', 'Tower Dark Archers', 'Location') - else: - add_conditional_lamp('Agahnim 1', 'Inverted Agahnims Tower', 'Entrance') - add_conditional_lamp('Castle Tower - Dark Maze', 'Inverted Agahnims Tower', 'Location') + add_conditional_lamp('Tower Lone Statue Down Stairs', 'Tower Lone Statue', 'Entrance') + add_conditional_lamp('Tower Lone Statue WN', 'Tower Lone Statue', 'Entrance') + add_conditional_lamp('Tower Dark Maze EN', 'Tower Dark Maze', 'Entrance') + add_conditional_lamp('Tower Dark Maze ES', 'Tower Dark Maze', 'Entrance') + add_conditional_lamp('Tower Dark Chargers WS', 'Tower Dark Chargers', 'Entrance') + add_conditional_lamp('Tower Dark Chargers Up Stairs', 'Tower Dark Chargers', 'Entrance') + add_conditional_lamp('Tower Dual Statues Down Stairs', 'Tower Dual Statues', 'Entrance') + add_conditional_lamp('Tower Dual Statues WS', 'Tower Dual Statues', 'Entrance') + add_conditional_lamp('Tower Dark Pits ES', 'Tower Dark Pits', 'Entrance') + add_conditional_lamp('Tower Dark Pits EN', 'Tower Dark Pits', 'Entrance') + add_conditional_lamp('Tower Dark Archers WN', 'Tower Dark Archers', 'Entrance') + add_conditional_lamp('Tower Dark Archers Up Stairs', 'Tower Dark Archers', 'Entrance') + add_conditional_lamp('Castle Tower - Dark Maze', 'Tower Dark Maze', 'Location') + add_conditional_lamp('Castle Tower - Dark Archer Key Drop', 'Tower Dark Archers', 'Location') add_conditional_lamp('Old Man', 'Old Man Cave', 'Location') add_conditional_lamp('Old Man Cave Exit (East)', 'Old Man Cave', 'Entrance') add_conditional_lamp('Death Mountain Return Cave Exit (East)', 'Death Mountain Return Cave', 'Entrance') @@ -857,109 +851,6 @@ def standard_rules(world, player): 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid']: add_rule(world.get_entrance(entrance, player), lambda state: state.has('Zelda Delivered', player)) -def set_trock_key_rules(world, player): - - - # First set all relevant locked doors to impassible. - for entrance in ['Turtle Rock Dark Room Staircase', 'Turtle Rock (Chain Chomp Room) (North)', 'Turtle Rock (Chain Chomp Room) (South)', 'Turtle Rock Pokey Room']: - set_rule(world.get_entrance(entrance, player), lambda state: False) - - all_state = world.get_all_state(True) - - # Check if each of the four main regions of the dungoen can be reached. The previous code section prevents key-costing moves within the dungeon. - can_reach_back = all_state.can_reach(world.get_region('Turtle Rock (Eye Bridge)', player)) if world.can_access_trock_eyebridge[player] is None else world.can_access_trock_eyebridge[player] - world.can_access_trock_eyebridge[player] = can_reach_back - can_reach_front = all_state.can_reach(world.get_region('Turtle Rock (Entrance)', player)) if world.can_access_trock_front[player] is None else world.can_access_trock_front[player] - world.can_access_trock_front[player] = can_reach_front - can_reach_big_chest = all_state.can_reach(world.get_region('Turtle Rock (Big Chest)', player)) if world.can_access_trock_big_chest[player] is None else world.can_access_trock_big_chest[player] - world.can_access_trock_big_chest[player] = can_reach_big_chest - can_reach_middle = all_state.can_reach(world.get_region('Turtle Rock (Second Section)', player)) if world.can_access_trock_middle[player] is None else world.can_access_trock_middle[player] - world.can_access_trock_middle[player] = can_reach_middle - - # No matter what, the key requirement for going from the middle to the bottom should be three keys. - set_rule(world.get_entrance('Turtle Rock Dark Room Staircase', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 3)) - - # The following represent the most common and most restrictive key rules. These are overwritten later as needed. - set_rule(world.get_entrance('Turtle Rock (Chain Chomp Room) (South)', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 4)) - set_rule(world.get_entrance('Turtle Rock (Chain Chomp Room) (North)', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 4)) - set_rule(world.get_entrance('Turtle Rock Pokey Room', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 4)) - - # No matter what, the Big Key cannot be in the Big Chest or held by Trinexx. - non_big_key_locations = ['Turtle Rock - Big Chest', 'Turtle Rock - Boss'] - - def tr_big_key_chest_keys_needed(state): - # This function handles the key requirements for the TR Big Chest in the situations it having the Big Key should logically require 2 keys, small key - # should logically require no keys, and anything else should logically require 4 keys. - item = item_name(state, 'Turtle Rock - Big Key Chest', player) - if item in [('Small Key (Turtle Rock)', player)]: - return 0 - if item in [('Big Key (Turtle Rock)', player)]: - return 2 - return 4 - - # Now we need to set rules based on which entrances we have access to. The most important point is whether we have back access. If we have back access, we - # might open all the locked doors in any order so we need maximally restrictive rules. - if can_reach_back: - set_rule(world.get_location('Turtle Rock - Big Key Chest', player), lambda state: (state.has_key('Small Key (Turtle Rock)', player, 4) or item_name(state, 'Turtle Rock - Big Key Chest', player) == ('Small Key (Turtle Rock)', player))) - if world.accessibility[player] != 'locations': - set_always_allow(world.get_location('Turtle Rock - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Turtle Rock)' and item.player == player - and state.can_reach(world.get_region('Turtle Rock (Eye Bridge)', player))) - else: - forbid_item(world.get_location('Turtle Rock - Big Key Chest', player), 'Small Key (Turtle Rock)', player) - elif can_reach_front and can_reach_middle: - set_rule(world.get_location('Turtle Rock - Big Key Chest', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, tr_big_key_chest_keys_needed(state))) - if world.accessibility[player] != 'locations': - set_always_allow(world.get_location('Turtle Rock - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Turtle Rock)' and item.player == player - and state.can_reach(world.get_region('Turtle Rock (Entrance)', player)) and state.can_reach(world.get_region('Turtle Rock (Second Section)', player))) - else: - forbid_item(world.get_location('Turtle Rock - Big Key Chest', player), 'Small Key (Turtle Rock)', player) - non_big_key_locations += ['Turtle Rock - Crystaroller Room', 'Turtle Rock - Eye Bridge - Bottom Left', - 'Turtle Rock - Eye Bridge - Bottom Right', 'Turtle Rock - Eye Bridge - Top Left', - 'Turtle Rock - Eye Bridge - Top Right'] - elif can_reach_front: - set_rule(world.get_entrance('Turtle Rock (Chain Chomp Room) (North)', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 2)) - set_rule(world.get_entrance('Turtle Rock Pokey Room', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 1)) - set_rule(world.get_location('Turtle Rock - Big Key Chest', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, tr_big_key_chest_keys_needed(state))) - if world.accessibility[player] != 'locations': - set_always_allow(world.get_location('Turtle Rock - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Turtle Rock)' and item.player == player and state.has_key('Small Key (Turtle Rock)', player, 2) - and state.can_reach(world.get_region('Turtle Rock (Entrance)', player))) - else: - forbid_item(world.get_location('Turtle Rock - Big Key Chest', player), 'Small Key (Turtle Rock)', player) - non_big_key_locations += ['Turtle Rock - Crystaroller Room', 'Turtle Rock - Eye Bridge - Bottom Left', - 'Turtle Rock - Eye Bridge - Bottom Right', 'Turtle Rock - Eye Bridge - Top Left', - 'Turtle Rock - Eye Bridge - Top Right'] - elif can_reach_big_chest: - set_rule(world.get_entrance('Turtle Rock (Chain Chomp Room) (South)', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 2) if item_in_locations(state, 'Big Key (Turtle Rock)', player, [('Turtle Rock - Compass Chest', player), ('Turtle Rock - Roller Room - Left', player), ('Turtle Rock - Roller Room - Right', player)]) else state.has_key('Small Key (Turtle Rock)', player, 4)) - set_rule(world.get_location('Turtle Rock - Big Key Chest', player), lambda state: (state.has_key('Small Key (Turtle Rock)', player, 4) or item_name(state, 'Turtle Rock - Big Key Chest', player) == ('Small Key (Turtle Rock)', player))) - if world.accessibility[player] != 'locations': - set_always_allow(world.get_location('Turtle Rock - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Turtle Rock)' and item.player == player - and state.can_reach(world.get_region('Turtle Rock (Big Chest)', player))) - else: - forbid_item(world.get_location('Turtle Rock - Big Key Chest', player), 'Small Key (Turtle Rock)', player) - non_big_key_locations += ['Turtle Rock - Crystaroller Room', 'Turtle Rock - Eye Bridge - Bottom Left', - 'Turtle Rock - Eye Bridge - Bottom Right', 'Turtle Rock - Eye Bridge - Top Left', - 'Turtle Rock - Eye Bridge - Top Right'] - if not world.keyshuffle[player]: - non_big_key_locations += ['Turtle Rock - Big Key Chest'] - else: - set_rule(world.get_entrance('Turtle Rock (Chain Chomp Room) (South)', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 2) if item_in_locations(state, 'Big Key (Turtle Rock)', player, [('Turtle Rock - Compass Chest', player), ('Turtle Rock - Roller Room - Left', player), ('Turtle Rock - Roller Room - Right', player)]) else state.has_key('Small Key (Turtle Rock)', player, 4)) - set_rule(world.get_location('Turtle Rock - Big Key Chest', player), lambda state: (state.has_key('Small Key (Turtle Rock)', player, 4) or item_name(state, 'Turtle Rock - Big Key Chest', player) == ('Small Key (Turtle Rock)', player))) - if world.accessibility[player] != 'locations': - set_always_allow(world.get_location('Turtle Rock - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Turtle Rock)' and item.player == player) - non_big_key_locations += ['Turtle Rock - Crystaroller Room', 'Turtle Rock - Eye Bridge - Bottom Left', - 'Turtle Rock - Eye Bridge - Bottom Right', 'Turtle Rock - Eye Bridge - Top Left', - 'Turtle Rock - Eye Bridge - Top Right'] - if not world.keyshuffle[player]: - non_big_key_locations += ['Turtle Rock - Big Key Chest', 'Turtle Rock - Chain Chomps'] - - # set big key restrictions - for location in non_big_key_locations: - forbid_item(world.get_location(location, player), 'Big Key (Turtle Rock)', player) - - # small key restriction - for location in ['Turtle Rock - Boss']: - forbid_item(world.get_location(location, player), 'Small Key (Turtle Rock)', player) - def set_big_bomb_rules(world, player): # this is a mess @@ -1443,8 +1334,13 @@ 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. - bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', - 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)', 'The Sky'] + bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', + 'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)', 'The Sky'] + # todo: bunny impassable caves + # sewers drop may or may not be - maybe just new terminology + # desert pots are impassible by bunny - need rules for those transitions + # skull woods drops tend to soft lock bunny + # tr too - dark ride, chest gap, entrance gap, pots in lazy eyes, etc bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest'] From 33b849a176cbaf4e0f3e45ddfe6bfe3d073c323f Mon Sep 17 00:00:00 2001 From: compiling <8335770+compiling@users.noreply.github.com> Date: Thu, 23 Jan 2020 20:08:37 +1100 Subject: [PATCH 2/4] Speed hacks - reduce the regions being checked every iteration when updating - only sweep for crystal access when new locations are found, and when starting a new sphere --- BaseClasses.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index db6659fe..bb721407 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -418,9 +418,8 @@ class CollectionState(object): new_regions = True reachable_regions_count = len(rrp) while new_regions: - region_queue = deque([region for region in player_regions if region not in rrp]) - while len(region_queue) > 0: - candidate = region_queue.popleft() + player_regions = [region for region in player_regions if region not in rrp] + for candidate in player_regions: if candidate.can_reach_private(self): rrp.add(candidate) if candidate.type == RegionType.Dungeon: @@ -778,7 +777,6 @@ class CollectionState(object): if changed: if not event: self.sweep_for_events() - self.sweep_for_crystal_access() def remove(self, item): if item.advancement: From 3937f4d9e98dec549fb6c670cd90af308d8ac7e0 Mon Sep 17 00:00:00 2001 From: aerinon Date: Thu, 23 Jan 2020 09:10:11 -0700 Subject: [PATCH 3/4] Door shuffle setting added to spoiler --- BaseClasses.py | 1 + 1 file changed, 1 insertion(+) diff --git a/BaseClasses.py b/BaseClasses.py index db6659fe..f95a86b1 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1620,6 +1620,7 @@ class Spoiler(object): outfile.write('Difficulty: %s\n' % self.metadata['item_pool'][player]) outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player]) outfile.write('Entrance Shuffle: %s\n' % self.metadata['shuffle'][player]) + outfile.write('Door Shuffle: %s\n' % self.metadata['door_shuffle'][player]) outfile.write('Crystals required for GT: %s\n' % self.metadata['gt_crystals'][player]) outfile.write('Crystals required for Ganon: %s\n' % self.metadata['ganon_crystals'][player]) outfile.write('Pyramid hole pre-opened: %s\n' % ('Yes' if self.metadata['open_pyramid'][player] else 'No')) From a57a52e2865ff57fb17bf8577ed36b08e36c86cc Mon Sep 17 00:00:00 2001 From: aerinon Date: Thu, 23 Jan 2020 09:39:58 -0700 Subject: [PATCH 4/4] Bump version --- Main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Main.py b/Main.py index c0dec0f6..7585f8a6 100644 --- a/Main.py +++ b/Main.py @@ -23,7 +23,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute from ItemList import generate_itempool, difficulties, fill_prizes from Utils import output_path, parse_player_names -__version__ = '0.0.4-pre' +__version__ = '0.0.5-pre' def main(args, seed=None): if args.outputpath: