diff --git a/BaseClasses.py b/BaseClasses.py index 4a530189..9270a579 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -113,7 +113,7 @@ class World(object): set_player_attr('can_access_trock_front', None) set_player_attr('can_access_trock_big_chest', None) set_player_attr('can_access_trock_middle', None) - set_player_attr('fix_fake_world', True) + set_player_attr('fix_fake_world', logic[player] not in ['owglitches', 'nologic'] or shuffle[player] in ['crossed', 'insanity', 'madness_legacy']) set_player_attr('mapshuffle', False) set_player_attr('compassshuffle', False) set_player_attr('keyshuffle', False) @@ -719,7 +719,33 @@ class CollectionState(object): or (self.has('Cane of Byrna', player) and (enemies < 6 or self.can_extend_magic(player))) or self.can_shoot_arrows(player) or self.has('Fire Rod', player) - ) + ) + + # In the future, this can be used to check if the player starts without bombs + def can_use_bombs(self, player): + StartingBombs = True + return StartingBombs or self.has('Bomb Upgrade (+10)', player) + + def can_hit_crystal(self, player): + return (self.can_use_bombs(player) + or self.can_shoot_arrows(player) + or self.has_blunt_weapon(player) + or self.has('Blue Boomerang', player) + or self.has('Red Boomerang', player) + or self.has('Hookshot', player) + or self.has('Fire Rod', player) + or self.has('Ice Rod', player) + or self.has('Cane of Somaria', player) + or self.has('Cane of Byrna', player)) + + def can_hit_crystal_through_barrier(self, player): + return (self.can_use_bombs(player) + or self.can_shoot_arrows(player) + or self.has('Blue Boomerang', player) + or self.has('Red Boomerang', player) + or self.has('Fire Rod', player) + or self.has('Ice Rod', player) + or self.has('Cane of Somaria', player)) def can_shoot_arrows(self, player): if self.world.retro[player]: @@ -790,6 +816,31 @@ class CollectionState(object): def has_turtle_rock_medallion(self, player): return self.has(self.world.required_medallions[player][1], player) + def can_boots_clip_lw(self, player): + if self.world.mode[player] == 'inverted': + return self.has_Boots(player) and self.has_Pearl(player) + return self.has_Boots(player) + + def can_boots_clip_dw(self, player): + if self.world.mode[player] != 'inverted': + return self.has_Boots(player) and self.has_Pearl(player) + return self.has_Boots(player) + + def can_get_glitched_speed_lw(self, player): + rules = [self.has_Boots(player), any([self.has('Hookshot', player), self.has_sword(player)])] + if self.world.mode[player] == 'inverted': + rules.append(self.has_Pearl(player)) + return all(rules) + + def can_get_glitched_speed_dw(self, player): + rules = [self.has_Boots(player), any([self.has('Hookshot', player), self.has_sword(player)])] + if self.world.mode[player] != 'inverted': + rules.append(self.has_Pearl(player)) + return all(rules) + + def can_superbunny_mirror_with_sword(self, player): + return self.has_Mirror(player) and self.has_sword(player) + def collect(self, item, event=False, location=None): if location: self.locations_checked.add(location) @@ -1367,6 +1418,11 @@ class Door(object): self.edge_width = width return self + def kind(self, world): + if self.roomIndex != -1 and self.doorListPos != -1: + return world.get_room(self.roomIndex, self.player).kind(self) + return None + def small_key(self): self.smallKey = True return self @@ -2338,7 +2394,7 @@ er_mode = {"vanilla": 0, "simple": 1, "restricted": 2, "full": 3, "crossed": 4, "full_legacy": 9, "madness_legacy": 10, "insanity_legacy": 11, "dungeonsfull": 7, "dungeonssimple": 6} # byte 1: LLLW WSSR (logic, mode, sword, retro) -logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owg": 3, "majorglitches": 4} +logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4} world_mode = {"open": 0, "standard": 1, "inverted": 2} sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3} diff --git a/Bosses.py b/Bosses.py index de04cbef..c1f311ef 100644 --- a/Bosses.py +++ b/Bosses.py @@ -39,8 +39,7 @@ def MoldormDefeatRule(state, player): return state.has_blunt_weapon(player) def HelmasaurKingDefeatRule(state, player): - # TODO: technically possible with the hammer - return state.has_sword(player) or state.can_shoot_arrows(player) + return (state.has('Hammer', player) or state.can_use_bombs(player)) and (state.has_sword(player) or state.can_shoot_arrows(player)) def ArrghusDefeatRule(state, player): if not state.has('Hookshot', player): diff --git a/DoorShuffle.py b/DoorShuffle.py index acae5712..734dc50d 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -1959,6 +1959,7 @@ def determine_init_crystal(initial, state, start_regions): return CrystalBarrier.Orange else: raise Exception(f'Can\'t get to {start_region.name} from initial state') +# raise Exception(f'Can\'t get to {start_region.name} from initial state\n{state.dungeon}\n{state.found_locations}') def explore_state(state, world, player): @@ -2036,27 +2037,83 @@ logical_connections = [ ('Desert Main Lobby Right Path', 'Desert Right Alcove'), ('Desert Left Alcove Path', 'Desert Main Lobby'), ('Desert Right Alcove Path', 'Desert Main Lobby'), + + ('Hera Lobby to Front Barrier - Blue', 'Hera Front'), + ('Hera Front to Lobby Barrier - Blue', 'Hera Lobby'), + ('Hera Lobby to Crystal', 'Hera Lobby - Crystal'), + ('Hera Lobby Crystal Exit', 'Hera Lobby'), + ('Hera Front to Crystal', 'Hera Front - Crystal'), + ('Hera Front to Back Bypass', 'Hera Back'), + ('Hera Front Crystal Exit', 'Hera Front'), + ('Hera Front to Down Stairs Barrier - Blue', 'Hera Down Stairs Landing'), + ('Hera Front to Up Stairs Barrier - Orange', 'Hera Up Stairs Landing'), + ('Hera Front to Back Barrier - Orange', 'Hera Back'), + ('Hera Down Stairs to Front Barrier - Blue', 'Hera Front'), + ('Hera Down Stairs Landing to Ranged Crystal', 'Hera Down Stairs Landing - Ranged Crystal'), + ('Hera Down Stairs Landing Ranged Crystal Exit', 'Hera Down Stairs Landing'), + ('Hera Up Stairs to Front Barrier - Orange', 'Hera Front'), + ('Hera Up Stairs Landing to Ranged Crystal', 'Hera Up Stairs Landing - Ranged Crystal'), + ('Hera Up Stairs Landing Ranged Crystal Exit', 'Hera Up Stairs Landing'), + ('Hera Back to Front Barrier - Orange', 'Hera Front'), + ('Hera Back to Ranged Crystal', 'Hera Back - Ranged Crystal'), + ('Hera Back Ranged Crystal Exit', 'Hera Back'), + ('Hera Basement Cage to Crystal', 'Hera Basement Cage - Crystal'), + ('Hera Basement Cage Crystal Exit', 'Hera Basement Cage'), + ('Hera Tridorm to Crystal', 'Hera Tridorm - Crystal'), + ('Hera Tridorm Crystal Exit', 'Hera Tridorm'), + ('Hera Startile Wide to Crystal', 'Hera Startile Wide - Crystal'), + ('Hera Startile Wide Crystal Exit', 'Hera Startile Wide'), ('Hera Big Chest Hook Path', 'Hera Big Chest Landing'), ('Hera Big Chest Landing Exit', 'Hera 4F'), + ('PoD Pit Room Block Path N', 'PoD Pit Room Blocked'), ('PoD Pit Room Block Path S', 'PoD Pit Room'), - ('PoD Arena Bonk Path', 'PoD Arena Bridge'), - ('PoD Arena Main Crystal Path', 'PoD Arena Crystal'), - ('PoD Arena Crystal Path', 'PoD Arena Main'), - ('PoD Arena Main Orange Barrier', 'PoD Arena North'), + ('PoD Arena Landing Bonk Path', 'PoD Arena Bridge'), ('PoD Arena North Drop Down', 'PoD Arena Main'), ('PoD Arena Bridge Drop Down', 'PoD Arena Main'), + ('PoD Arena North to Landing Barrier - Orange', 'PoD Arena Landing'), + ('PoD Arena Main to Ranged Crystal', 'PoD Arena Main - Ranged Crystal'), + ('PoD Arena Main to Landing Barrier - Blue', 'PoD Arena Landing'), + ('PoD Arena Main to Landing Bypass', 'PoD Arena Landing'), + ('PoD Arena Main to Right Bypass', 'PoD Arena Right'), + ('PoD Arena Main Ranged Crystal Exit', 'PoD Arena Main'), + ('PoD Arena Bridge to Ranged Crystal', 'PoD Arena Bridge - Ranged Crystal'), + ('PoD Arena Bridge Ranged Crystal Exit', 'PoD Arena Bridge'), + ('PoD Arena Landing to Main Barrier - Blue', 'PoD Arena Main'), + ('PoD Arena Landing to Right Barrier - Blue', 'PoD Arena Right'), + ('PoD Arena Landing to North Barrier - Orange', 'PoD Arena North'), + ('PoD Arena Right to Landing Barrier - Blue', 'PoD Arena Landing'), + ('PoD Arena Right to Ranged Crystal', 'PoD Arena Right - Ranged Crystal'), + ('PoD Arena Right Ranged Crystal Exit', 'PoD Arena Right'), + ('PoD Arena Ledge to Ranged Crystal', 'PoD Arena Ledge - Ranged Crystal'), + ('PoD Arena Ledge Ranged Crystal Exit', 'PoD Arena Ledge'), ('PoD Map Balcony Drop Down', 'PoD Sexy Statue'), + ('PoD Map Balcony to Ranged Crystal', 'PoD Map Balcony - Ranged Crystal'), + ('PoD Map Balcony Ranged Crystal Exit', 'PoD Map Balcony'), ('PoD Basement Ledge Drop Down', 'PoD Stalfos Basement'), ('PoD Falling Bridge Path N', 'PoD Falling Bridge Ledge'), ('PoD Falling Bridge Path S', 'PoD Falling Bridge'), - ('PoD Bow Statue Crystal Path', 'PoD Bow Statue Moving Wall'), - ('PoD Bow Statue Moving Wall Path', 'PoD Bow Statue'), - ('PoD Bow Statue Moving Wall Cane Path', 'PoD Bow Statue'), - ('PoD Dark Pegs Hammer Path', 'PoD Dark Pegs Ladder'), - ('PoD Dark Pegs Ladder Hammer Path', 'PoD Dark Pegs'), - ('PoD Dark Pegs Ladder Cane Path', 'PoD Dark Pegs Switch'), - ('PoD Dark Pegs Switch Path', 'PoD Dark Pegs Ladder'), + ('PoD Bow Statue Left to Right Barrier - Orange', 'PoD Bow Statue Right'), + ('PoD Bow Statue Left to Right Bypass', 'PoD Bow Statue Right'), + ('PoD Bow Statue Left to Crystal', 'PoD Bow Statue Left - Crystal'), + ('PoD Bow Statue Left Crystal Exit', 'PoD Bow Statue Left'), + ('PoD Bow Statue Right to Left Barrier - Orange', 'PoD Bow Statue Left'), + ('PoD Bow Statue Right to Ranged Crystal', 'PoD Bow Statue Right - Ranged Crystal'), + ('PoD Bow Statue Ranged Crystal Exit', 'PoD Bow Statue Right'), + ('PoD Dark Pegs Landing to Right', 'PoD Dark Pegs Right'), + ('PoD Dark Pegs Landing to Ranged Crystal', 'PoD Dark Pegs Landing - Ranged Crystal'), + ('PoD Dark Pegs Right to Landing', 'PoD Dark Pegs Landing'), + ('PoD Dark Pegs Right to Middle Barrier - Orange', 'PoD Dark Pegs Middle'), + ('PoD Dark Pegs Right to Middle Bypass', 'PoD Dark Pegs Middle'), + ('PoD Dark Pegs Middle to Right Barrier - Orange', 'PoD Dark Pegs Right'), + ('PoD Dark Pegs Middle to Left Barrier - Blue', 'PoD Dark Pegs Left'), + ('PoD Dark Pegs Middle to Ranged Crystal', 'PoD Dark Pegs Middle - Ranged Crystal'), + ('PoD Dark Pegs Left to Middle Barrier - Blue', 'PoD Dark Pegs Middle'), + ('PoD Dark Pegs Left to Ranged Crystal', 'PoD Dark Pegs Left - Ranged Crystal'), + ('PoD Dark Pegs Landing Ranged Crystal Exit', 'PoD Dark Pegs Landing'), + ('PoD Dark Pegs Middle Ranged Crystal Exit', 'PoD Dark Pegs Middle'), + ('PoD Dark Pegs Middle to Left Bypass', 'PoD Dark Pegs Left'), + ('PoD Dark Pegs Left Ranged Crystal Exit', 'PoD Dark Pegs Left'), ('Swamp Lobby Moat', 'Swamp Entrance'), ('Swamp Entrance Moat', 'Swamp Lobby'), ('Swamp Trench 1 Approach Dry', 'Swamp Trench 1 Nexus'), @@ -2072,6 +2129,14 @@ logical_connections = [ ('Swamp Trench 1 Departure Key', 'Swamp Trench 1 Key Ledge'), ('Swamp Hub Hook Path', 'Swamp Hub North Ledge'), ('Swamp Hub North Ledge Drop Down', 'Swamp Hub'), + ('Swamp Crystal Switch Outer to Inner Barrier - Blue', 'Swamp Crystal Switch Inner'), + ('Swamp Crystal Switch Outer to Ranged Crystal', 'Swamp Crystal Switch Outer - Ranged Crystal'), + ('Swamp Crystal Switch Outer to Inner Bypass', 'Swamp Crystal Switch Inner'), + ('Swamp Crystal Switch Outer Ranged Crystal Exit', 'Swamp Crystal Switch Outer'), + ('Swamp Crystal Switch Inner to Outer Barrier - Blue', 'Swamp Crystal Switch Outer'), + ('Swamp Crystal Switch Inner to Outer Bypass', 'Swamp Crystal Switch Outer'), + ('Swamp Crystal Switch Inner to Crystal', 'Swamp Crystal Switch Inner - Crystal'), + ('Swamp Crystal Switch Inner Crystal Exit', 'Swamp Crystal Switch Inner'), ('Swamp Compass Donut Push Block', 'Swamp Donut Top'), ('Swamp Shortcut Blue Barrier', 'Swamp Trench 2 Pots'), ('Swamp Trench 2 Pots Blue Barrier', 'Swamp Shortcut'), @@ -2090,6 +2155,7 @@ logical_connections = [ ('Swamp Drain Right Switch', 'Swamp Drain Left'), ('Swamp Flooded Spot Ladder', 'Swamp Flooded Room'), ('Swamp Flooded Room Ladder', 'Swamp Flooded Spot'), + ('Skull Pot Circle Star Path', 'Skull Map Room'), ('Skull Big Chest Hookpath', 'Skull 1 Lobby'), ('Skull Back Drop Star Path', 'Skull Small Hall'), @@ -2106,8 +2172,12 @@ logical_connections = [ ('Thieves Conveyor Block Path', 'Thieves Conveyor Bridge'), ("Thieves Blind's Cell Door", "Thieves Blind's Cell Interior"), ("Thieves Blind's Cell Exit", "Thieves Blind's Cell"), + ('Ice Cross Bottom Push Block Left', 'Ice Floor Switch'), ('Ice Cross Right Push Block Top', 'Ice Bomb Drop'), + ('Ice Cross Top Push Block Bottom', 'Ice Compass Room'), + ('Ice Conveyor to Crystal', 'Ice Conveyor - Crystal'), + ('Ice Conveyor Crystal Exit', 'Ice Conveyor'), ('Ice Big Key Push Block', 'Ice Dead End'), ('Ice Bomb Jump Ledge Orange Barrier', 'Ice Bomb Jump Catwalk'), ('Ice Bomb Jump Catwalk Orange Barrier', 'Ice Bomb Jump Ledge'), @@ -2118,6 +2188,9 @@ logical_connections = [ ('Ice Crystal Left Blue Barrier', 'Ice Crystal Block'), ('Ice Crystal Block Exit', 'Ice Crystal Left'), ('Ice Big Chest Landing Push Blocks', 'Ice Big Chest View'), + ('Ice Refill to Crystal', 'Ice Refill - Crystal'), + ('Ice Refill Crystal Exit', 'Ice Refill'), + ('Mire Lobby Gap', 'Mire Post-Gap'), ('Mire Post-Gap Gap', 'Mire Lobby'), ('Mire Hub Upper Blue Barrier', 'Mire Hub Switch'), @@ -2133,7 +2206,11 @@ logical_connections = [ ('Mire Crystal Dead End Right Barrier', 'Mire Map Spike Side'), ('Mire Hidden Shooters Block Path S', 'Mire Hidden Shooters'), ('Mire Hidden Shooters Block Path N', 'Mire Hidden Shooters Blocked'), + ('Mire Conveyor to Crystal', 'Mire Conveyor - Crystal'), + ('Mire Conveyor Crystal Exit', 'Mire Conveyor Crystal'), ('Mire Left Bridge Hook Path', 'Mire Right Bridge'), + ('Mire Tall Dark and Roomy to Ranged Crystal', 'Mire Tall Dark and Roomy - Ranged Crystal'), + ('Mire Tall Dark and Roomy Ranged Crystal Exit', 'Mire Tall Dark and Roomy'), ('Mire Crystal Right Orange Barrier', 'Mire Crystal Mid'), ('Mire Crystal Mid Orange Barrier', 'Mire Crystal Right'), ('Mire Crystal Mid Blue Barrier', 'Mire Crystal Left'), @@ -2144,14 +2221,49 @@ logical_connections = [ ('Mire Compass Chest Exit', 'Mire Compass Room'), ('Mire South Fish Blue Barrier', 'Mire Fishbone'), ('Mire Fishbone Blue Barrier', 'Mire South Fish'), + ('Mire Fishbone Blue Barrier Bypass', 'Mire South Fish'), + ('TR Main Lobby Gap', 'TR Lobby Ledge'), ('TR Lobby Ledge Gap', 'TR Main Lobby'), ('TR Pipe Ledge Drop Down', 'TR Pipe Pit'), ('TR Big Chest Gap', 'TR Big Chest Entrance'), ('TR Big Chest Entrance Gap', 'TR Big Chest'), - ('TR Crystal Maze Forwards Path', 'TR Crystal Maze End'), - ('TR Crystal Maze Blue Path', 'TR Crystal Maze'), - ('TR Crystal Maze Cane Path', 'TR Crystal Maze'), + ('TR Chain Chomps Top to Bottom Barrier - Orange', 'TR Chain Chomps Bottom'), + ('TR Chain Chomps Top to Crystal', 'TR Chain Chomps Top - Crystal'), + ('TR Chain Chomps Top Crystal Exit', 'TR Chain Chomps Top'), + ('TR Chain Chomps Bottom to Top Barrier - Orange', 'TR Chain Chomps Top'), + ('TR Chain Chomps Bottom to Ranged Crystal', 'TR Chain Chomps Bottom - Ranged Crystal'), + ('TR Chain Chomps Bottom Ranged Crystal Exit', 'TR Chain Chomps Bottom'), + ('TR Pokey 2 Top to Bottom Barrier - Blue', 'TR Pokey 2 Bottom'), + ('TR Pokey 2 Top to Crystal', 'TR Pokey 2 Top - Crystal'), + ('TR Pokey 2 Top Crystal Exit', 'TR Pokey 2 Top'), + ('TR Pokey 2 Bottom to Top Barrier - Blue', 'TR Pokey 2 Top'), + ('TR Pokey 2 Bottom to Ranged Crystal', 'TR Pokey 2 Bottom - Ranged Crystal'), + ('TR Pokey 2 Bottom Ranged Crystal Exit', 'TR Pokey 2 Bottom'), + ('TR Crystaroller Bottom to Middle Barrier - Orange', 'TR Crystaroller Middle'), + ('TR Crystaroller Bottom to Ranged Crystal', 'TR Crystaroller Bottom - Ranged Crystal'), + ('TR Crystaroller Middle to Bottom Barrier - Orange', 'TR Crystaroller Bottom'), + ('TR Crystaroller Middle to Bottom Bypass', 'TR Crystaroller Bottom'), + ('TR Crystaroller Middle to Chest Barrier - Blue', 'TR Crystaroller Chest'), + ('TR Crystaroller Middle to Top Barrier - Orange', 'TR Crystaroller Top'), + ('TR Crystaroller Middle to Ranged Crystal', 'TR Crystaroller Middle - Ranged Crystal'), + ('TR Crystaroller Top to Middle Barrier - Orange', 'TR Crystaroller Middle'), + ('TR Crystaroller Top to Crystal', 'TR Crystaroller Top - Crystal'), + ('TR Crystaroller Top Crystal Exit', 'TR Crystaroller Top'), + ('TR Crystaroller Chest to Middle Barrier - Blue', 'TR Crystaroller Middle'), + ('TR Crystaroller Middle Ranged Crystal Exit', 'TR Crystaroller Middle'), + ('TR Crystaroller Bottom Ranged Crystal Exit', 'TR Crystaroller Bottom'), + ('TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze Interior'), + ('TR Crystal Maze Start to Crystal', 'TR Crystal Maze Start - Crystal'), + ('TR Crystal Maze Start Crystal Exit', 'TR Crystal Maze Start'), + ('TR Crystal Maze Interior to End Barrier - Blue', 'TR Crystal Maze End'), + ('TR Crystal Maze Interior to Start Barrier - Blue', 'TR Crystal Maze Start'), + ('TR Crystal Maze Interior to End Bypass', 'TR Crystal Maze End'), + ('TR Crystal Maze Interior to Start Bypass', 'TR Crystal Maze Start'), + ('TR Crystal Maze End to Interior Barrier - Blue', 'TR Crystal Maze Interior'), + ('TR Crystal Maze End to Ranged Crystal', 'TR Crystal Maze End - Ranged Crystal'), + ('TR Crystal Maze End Ranged Crystal Exit', 'TR Crystal Maze End'), + ('GT Blocked Stairs Block Path', 'GT Big Chest'), ('GT Speed Torch South Path', 'GT Speed Torch'), ('GT Speed Torch North Path', 'GT Speed Torch Upper'), @@ -2162,21 +2274,46 @@ logical_connections = [ ('GT Hookshot South-East Path', 'GT Hookshot East Platform'), ('GT Hookshot South-North Path', 'GT Hookshot North Platform'), ('GT Hookshot Platform Blue Barrier', 'GT Hookshot South Entry'), + ('GT Hookshot Platform Barrier Bypass', 'GT Hookshot South Entry'), ('GT Hookshot Entry Blue Barrier', 'GT Hookshot South Platform'), - ('GT Hookshot Entry Boomerang Path', 'GT Hookshot South Platform'), - ('GT Double Switch Orange Barrier', 'GT Double Switch Switches'), - ('GT Double Switch Orange Barrier 2', 'GT Double Switch Key Spot'), - ('GT Double Switch Transition Blue', 'GT Double Switch Exit'), - ('GT Double Switch Blue Path', 'GT Double Switch Transition'), - ('GT Double Switch Orange Path', 'GT Double Switch Entry'), - ('GT Double Switch Key Blue Path', 'GT Double Switch Exit'), - ('GT Double Switch Key Orange Path', 'GT Double Switch Entry'), - ('GT Double Switch Blue Barrier', 'GT Double Switch Key Spot'), + ('GT Hookshot South Entry to Ranged Crystal', 'GT Hookshot South Entry - Ranged Crystal'), + ('GT HookShot South Entry Ranged Crystal Exit', 'GT Hookshot South Entry'), + ('GT Double Switch Entry to Pot Corners Barrier - Orange', 'GT Double Switch Pot Corners'), + ('GT Double Switch Entry to Left Barrier - Orange', 'GT Double Switch Left'), + ('GT Double Switch Entry to Ranged Switches', 'GT Double Switch Entry - Ranged Switches'), + ('GT Double Switch Entry Ranged Switches Exit', 'GT Double Switch Entry'), + ('GT Double Switch Left to Entry Barrier - Orange', 'GT Double Switch Entry'), + ('GT Double Switch Left to Entry Bypass', 'GT Double Switch Entry'), + ('GT Double Switch Left to Pot Corners Bypass', 'GT Double Switch Pot Corners'), + ('GT Double Switch Left to Exit Bypass', 'GT Double Switch Exit'), + ('GT Double Switch Pot Corners to Entry Barrier - Orange', 'GT Double Switch Entry'), + ('GT Double Switch Pot Corners to Exit Barrier - Blue', 'GT Double Switch Exit'), + ('GT Double Switch Pot Corners to Ranged Switches', 'GT Double Switch Pot Corners - Ranged Switches'), + ('GT Double Switch Pot Corners Ranged Switches Exit', 'GT Double Switch Pot Corners'), + ('GT Double Switch Exit to Blue Barrier', 'GT Double Switch Pot Corners'), + ('GT Spike Crystal Left to Right Barrier - Orange', 'GT Spike Crystal Right'), + ('GT Spike Crystal Right to Left Barrier - Orange', 'GT Spike Crystal Left'), + ('GT Spike Crystal Left to Right Bypass', 'GT Spike Crystal Right'), ('GT Warp Maze - Pit Section Warp Spot', 'GT Warp Maze - Pit Exit Warp Spot'), ('GT Warp Maze Exit Section Warp Spot', 'GT Warp Maze - Pit Exit Warp Spot'), ('GT Firesnake Room Hook Path', 'GT Firesnake Room Ledge'), + + ('GT Crystal Conveyor to Corner Barrier - Blue', 'GT Crystal Conveyor Corner'), + ('GT Crystal Conveyor to Ranged Crystal', 'GT Crystal Conveyor - Ranged Crystal'), + ('GT Crystal Conveyor Corner to Left Bypass', 'GT Crystal Conveyor Left'), + ('GT Crystal Conveyor Corner to Barrier - Blue', 'GT Crystal Conveyor Left'), + ('GT Crystal Conveyor Corner to Barrier - Orange', 'GT Crystal Conveyor'), + ('GT Crystal Conveyor Corner to Ranged Crystal', 'GT Crystal Conveyor Corner - Ranged Crystal'), + ('GT Crystal Conveyor Left to Corner Barrier - Orange', 'GT Crystal Conveyor Corner'), + ('GT Crystal Conveyor Ranged Crystal Exit', 'GT Crystal Conveyor'), + ('GT Crystal Conveyor Corner Ranged Crystal Exit', 'GT Crystal Conveyor Corner'), + ('GT Left Moldorm Ledge Drop Down', 'GT Moldorm'), ('GT Right Moldorm Ledge Drop Down', 'GT Moldorm'), + ('GT Crystal Circles Barrier - Orange', 'GT Crystal Inner Circle'), + ('GT Crystal Circles to Ranged Crystal', 'GT Crystal Circles - Ranged Crystal'), + ('GT Crystal Inner Circle Barrier - Orange', 'GT Crystal Circles'), + ('GT Crystal Circles Ranged Crystal Exit', 'GT Crystal Circles'), ('GT Moldorm Gap', 'GT Validation'), ('GT Validation Block Path', 'GT Validation Door') ] @@ -2274,10 +2411,12 @@ open_edges = [ falldown_pits = [ ('Eastern Courtyard Potholes', 'Eastern Fairies'), - ('Hera Beetles Holes', 'Hera Lobby'), - ('Hera Startile Corner Holes', 'Hera Lobby'), - ('Hera Startile Wide Holes', 'Hera Lobby'), - ('Hera 4F Holes', 'Hera Lobby'), # failed bomb jump + ('Hera Beetles Holes Front', 'Hera Front'), + ('Hera Beetles Holes Landing', 'Hera Up Stairs Landing'), + ('Hera Startile Corner Holes Front', 'Hera Front'), + ('Hera Startile Corner Holes Landing', 'Hera Down Stairs Landing'), + ('Hera Startile Wide Holes', 'Hera Back'), + ('Hera 4F Holes', 'Hera Back'), # failed bomb jump ('Hera Big Chest Landing Holes', 'Hera Startile Wide'), # the other holes near big chest ('Hera 5F Star Hole', 'Hera Big Chest Landing'), ('Hera 5F Pothole Chain', 'Hera Fairies'), @@ -2371,11 +2510,11 @@ interior_doors = [ ('Desert Sandworm Corner NE', 'Desert Bonk Torch SE'), ('Desert Sandworm Corner WS', 'Desert Circle of Pots ES'), ('Desert Circle of Pots NW', 'Desert Big Chest SW'), - ('Desert West Wing WS', 'Desert West Lobby ES',), + ('Desert West Wing WS', 'Desert West Lobby ES'), ('Desert Fairy Fountain SW', 'Desert West Lobby NW'), ('Desert Back Lobby NW', 'Desert Tiles 1 SW'), ('Desert Bridge SW', 'Desert Four Statues NW'), - ('Desert Four Statues ES', 'Desert Beamos Hall WS',), + ('Desert Four Statues ES', 'Desert Beamos Hall WS'), ('Desert Tiles 2 NE', 'Desert Wall Slide SE'), ('Hera Tile Room EN', 'Hera Tridorm WN'), ('Hera Tridorm SE', 'Hera Torches NE'), @@ -2734,8 +2873,8 @@ default_door_connections = [ ('TR Torches NW', 'TR Roller Room SW'), ('TR Pipe Pit WN', 'TR Lava Dual Pipes EN'), ('TR Lava Island ES', 'TR Pipe Ledge WS'), - ('TR Lava Dual Pipes WN', 'TR Pokey 2 EN'), ('TR Lava Dual Pipes SW', 'TR Twin Pokeys NW'), + ('TR Lava Dual Pipes WN', 'TR Pokey 2 EN'), ('TR Pokey 2 ES', 'TR Lava Island WS'), ('TR Dodgers NE', 'TR Lava Escape SE'), ('TR Lava Escape NW', 'TR Dash Room SW'), diff --git a/Doors.py b/Doors.py index 73806dd3..5f20d285 100644 --- a/Doors.py +++ b/Doors.py @@ -252,25 +252,52 @@ def create_doors(world, player): # Hera create_door(player, 'Hera Lobby S', Nrml).dir(So, 0x77, Mid, Low).pos(0).portal(Z, 0x22, 1), + create_door(player, 'Hera Lobby to Front Barrier - Blue', Lgcl), + create_door(player, 'Hera Lobby to Crystal', Lgcl), + create_door(player, 'Hera Lobby Crystal Exit', Lgcl), + create_door(player, 'Hera Front to Lobby Barrier - Blue', Lgcl), + create_door(player, 'Hera Front to Crystal', Lgcl), + create_door(player, 'Hera Front Crystal Exit', Lgcl), + create_door(player, 'Hera Front to Down Stairs Barrier - Blue', Lgcl), + create_door(player, 'Hera Down Stairs to Front Barrier - Blue', Lgcl), + create_door(player, 'Hera Down Stairs Landing to Ranged Crystal', Lgcl), + create_door(player, 'Hera Down Stairs Landing Ranged Crystal Exit', Lgcl), + create_door(player, 'Hera Front to Up Stairs Barrier - Orange', Lgcl), + create_door(player, 'Hera Up Stairs to Front Barrier - Orange', Lgcl), + create_door(player, 'Hera Up Stairs Landing to Ranged Crystal', Lgcl), + create_door(player, 'Hera Up Stairs Landing Ranged Crystal Exit', Lgcl), + create_door(player, 'Hera Front to Back Barrier - Orange', Lgcl), + create_door(player, 'Hera Front to Back Bypass', Lgcl), + create_door(player, 'Hera Back to Front Barrier - Orange', Lgcl), + create_door(player, 'Hera Back to Ranged Crystal', Lgcl), + create_door(player, 'Hera Back Ranged Crystal Exit', Lgcl), create_door(player, 'Hera Lobby Down Stairs', Sprl).dir(Dn, 0x77, 3, HTL).ss(Z, 0x21, 0x90, False, True), create_door(player, 'Hera Lobby Key Stairs', Sprl).dir(Dn, 0x77, 1, HTL).ss(A, 0x12, 0x80).small_key().pos(1), create_door(player, 'Hera Lobby Up Stairs', Sprl).dir(Up, 0x77, 2, HTL).ss(X, 0x2b, 0x5c, False, True), create_door(player, 'Hera Basement Cage Up Stairs', Sprl).dir(Up, 0x87, 3, LTH).ss(Z, 0x42, 0x7c, True, True), + create_door(player, 'Hera Basement Cage to Crystal', Lgcl), + create_door(player, 'Hera Basement Cage Crystal Exit', Lgcl), create_door(player, 'Hera Tile Room Up Stairs', Sprl).dir(Up, 0x87, 1, LTH).ss(A, 0x32, 0x6c, True, True), create_door(player, 'Hera Tile Room EN', Intr).dir(Ea, 0x87, Top, High).pos(0), create_door(player, 'Hera Tridorm WN', Intr).dir(We, 0x87, Top, High).pos(0), + create_door(player, 'Hera Tridorm to Crystal', Lgcl), + create_door(player, 'Hera Tridorm Crystal Exit', Lgcl), create_door(player, 'Hera Tridorm SE', Intr).dir(So, 0x87, Right, High).pos(1), create_door(player, 'Hera Torches NE', Intr).dir(No, 0x87, Right, High).pos(1), create_door(player, 'Hera Beetles Down Stairs', Sprl).dir(Dn, 0x31, 2, LTH).ss(X, 0x3a, 0x70, True, True), create_door(player, 'Hera Beetles WS', Intr).dir(We, 0x31, Bot, High).pos(1), - create_door(player, 'Hera Beetles Holes', Hole), + create_door(player, 'Hera Beetles Holes Front', Hole), + create_door(player, 'Hera Beetles Holes Landing', Hole), create_door(player, 'Hera Startile Corner ES', Intr).dir(Ea, 0x31, Bot, High).pos(1), create_door(player, 'Hera Startile Corner NW', Intr).dir(No, 0x31, Left, High).big_key().pos(0), - create_door(player, 'Hera Startile Corner Holes', Hole), + create_door(player, 'Hera Startile Corner Holes Front', Hole), + create_door(player, 'Hera Startile Corner Holes Landing', Hole), # technically ugly but causes lots of failures in basic create_door(player, 'Hera Startile Wide SW', Intr).dir(So, 0x31, Left, High).pos(0), create_door(player, 'Hera Startile Wide Up Stairs', Sprl).dir(Up, 0x31, 0, HTH).ss(S, 0x6b, 0xac, False, True), create_door(player, 'Hera Startile Wide Holes', Hole), + create_door(player, 'Hera Startile Wide to Crystal', Lgcl), + create_door(player, 'Hera Startile Wide Crystal Exit', Lgcl), create_door(player, 'Hera 4F Down Stairs', Sprl).dir(Dn, 0x27, 0, HTH).ss(S, 0x62, 0xc0), create_door(player, 'Hera 4F Up Stairs', Sprl).dir(Up, 0x27, 1, HTH).ss(A, 0x6b, 0x2c), create_door(player, 'Hera 4F Holes', Hole), @@ -354,17 +381,32 @@ def create_doors(world, player): create_door(player, 'PoD Arena Bridge SE', Nrml).dir(So, 0x2a, Right, High).pos(5).portal(X, 0x22), create_door(player, 'PoD Arena Main NW', Nrml).dir(No, 0x2a, Left, High).small_key().pos(1), create_door(player, 'PoD Arena Main NE', Nrml).dir(No, 0x2a, Right, High).no_exit().trap(0x4).pos(0), - create_door(player, 'PoD Arena Main Crystal Path', Lgcl), - create_door(player, 'PoD Arena Main Orange Barrier', Lgcl), - create_door(player, 'PoD Arena North Drop Down', Lgcl), - create_door(player, 'PoD Arena Bonk Path', Lgcl), create_door(player, 'PoD Arena Crystals E', Nrml).dir(Ea, 0x2a, Mid, High).pos(3), - create_door(player, 'PoD Arena Crystal Path', Lgcl), + create_door(player, 'PoD Arena Landing Bonk Path', Lgcl), + create_door(player, 'PoD Arena North Drop Down', Lgcl), create_door(player, 'PoD Arena Bridge Drop Down', Lgcl), + create_door(player, 'PoD Arena North to Landing Barrier - Orange', Lgcl), + create_door(player, 'PoD Arena Main to Ranged Crystal', Lgcl), + create_door(player, 'PoD Arena Main to Landing Barrier - Blue', Lgcl), + create_door(player, 'PoD Arena Main to Landing Bypass', Lgcl), + create_door(player, 'PoD Arena Main to Right Bypass', Lgcl), + create_door(player, 'PoD Arena Main Ranged Crystal Exit', Lgcl), + create_door(player, 'PoD Arena Bridge to Ranged Crystal', Lgcl), + create_door(player, 'PoD Arena Bridge Ranged Crystal Exit', Lgcl), + create_door(player, 'PoD Arena Landing to Main Barrier - Blue', Lgcl), + create_door(player, 'PoD Arena Landing to Right Barrier - Blue', Lgcl), + create_door(player, 'PoD Arena Landing to North Barrier - Orange', Lgcl), + create_door(player, 'PoD Arena Right to Landing Barrier - Blue', Lgcl), + create_door(player, 'PoD Arena Right to Ranged Crystal', Lgcl), + create_door(player, 'PoD Arena Right Ranged Crystal Exit', Lgcl), + create_door(player, 'PoD Arena Ledge to Ranged Crystal', Lgcl), + create_door(player, 'PoD Arena Ledge Ranged Crystal Exit', Lgcl), create_door(player, 'PoD Arena Ledge ES', Nrml).dir(Ea, 0x2a, Bot, High).pos(2), create_door(player, 'PoD Sexy Statue W', Nrml).dir(We, 0x2b, Mid, High).pos(3), create_door(player, 'PoD Sexy Statue NW', Nrml).dir(No, 0x2b, Left, High).trap(0x1).pos(2), create_door(player, 'PoD Map Balcony Drop Down', Lgcl), + create_door(player, 'PoD Map Balcony to Ranged Crystal', Lgcl), + create_door(player, 'PoD Map Balcony Ranged Crystal Exit', Lgcl), create_door(player, 'PoD Map Balcony WS', Nrml).dir(We, 0x2b, Bot, High).pos(1), create_door(player, 'PoD Map Balcony South Stairs', StrS).dir(So, 0x2b, Left, High), create_door(player, 'PoD Conveyor North Stairs', StrS).dir(No, 0x3b, Left, High), @@ -395,15 +437,29 @@ def create_doors(world, player): create_door(player, 'PoD Mimics 2 SW', Nrml).dir(So, 0x1b, Left, High).pos(1).kill().portal(Z, 0x00), create_door(player, 'PoD Mimics 2 NW', Intr).dir(No, 0x1b, Left, High).pos(0), create_door(player, 'PoD Bow Statue SW', Intr).dir(So, 0x1b, Left, High).pos(0), - create_door(player, 'PoD Bow Statue Crystal Path', Lgcl), - create_door(player, 'PoD Bow Statue Moving Wall Path', Lgcl), - create_door(player, 'PoD Bow Statue Moving Wall Cane Path', Lgcl), + create_door(player, 'PoD Bow Statue Left to Right Barrier - Orange', Lgcl), + create_door(player, 'PoD Bow Statue Left to Right Bypass', Lgcl), + create_door(player, 'PoD Bow Statue Left to Crystal', Lgcl), + create_door(player, 'PoD Bow Statue Left Crystal Exit', Lgcl), + create_door(player, 'PoD Bow Statue Right to Left Barrier - Orange', Lgcl), + create_door(player, 'PoD Bow Statue Right to Ranged Crystal', Lgcl), + create_door(player, 'PoD Bow Statue Ranged Crystal Exit', Lgcl), create_door(player, 'PoD Bow Statue Down Ladder', Lddr).dir(So, 0x1b, 1, High).no_entrance(), create_door(player, 'PoD Dark Pegs Up Ladder', Lddr).dir(No, 0x0b, 0, High), - create_door(player, 'PoD Dark Pegs Hammer Path', Lgcl), - create_door(player, 'PoD Dark Pegs Ladder Hammer Path', Lgcl), - create_door(player, 'PoD Dark Pegs Ladder Cane Path', Lgcl), - create_door(player, 'PoD Dark Pegs Switch Path', Lgcl), + create_door(player, 'PoD Dark Pegs Landing to Right', Lgcl), + create_door(player, 'PoD Dark Pegs Landing to Ranged Crystal', Lgcl), + create_door(player, 'PoD Dark Pegs Right to Landing', Lgcl), + create_door(player, 'PoD Dark Pegs Right to Middle Barrier - Orange', Lgcl), + create_door(player, 'PoD Dark Pegs Right to Middle Bypass', Lgcl), + create_door(player, 'PoD Dark Pegs Middle to Right Barrier - Orange', Lgcl), + create_door(player, 'PoD Dark Pegs Middle to Left Barrier - Blue', Lgcl), + create_door(player, 'PoD Dark Pegs Middle to Ranged Crystal', Lgcl), + create_door(player, 'PoD Dark Pegs Middle to Left Bypass', Lgcl), + create_door(player, 'PoD Dark Pegs Left to Middle Barrier - Blue', Lgcl), + create_door(player, 'PoD Dark Pegs Left to Ranged Crystal', Lgcl), + create_door(player, 'PoD Dark Pegs Landing Ranged Crystal Exit', Lgcl), + create_door(player, 'PoD Dark Pegs Middle Ranged Crystal Exit', Lgcl), + create_door(player, 'PoD Dark Pegs Left Ranged Crystal Exit', Lgcl), create_door(player, 'PoD Dark Pegs WN', Intr).dir(We, 0x0b, Mid, High).small_key().pos(2), create_door(player, 'PoD Lonely Turtle SW', Intr).dir(So, 0x0b, Mid, High).pos(0), create_door(player, 'PoD Lonely Turtle EN', Intr).dir(Ea, 0x0b, Mid, High).small_key().pos(2), @@ -455,6 +511,14 @@ def create_doors(world, player): create_door(player, 'Swamp Compass Donut Push Block', Lgcl), create_door(player, 'Swamp Crystal Switch EN', Nrml).dir(Ea, 0x35, Top, High).small_key().pos(0), create_door(player, 'Swamp Crystal Switch SE', Intr).dir(So, 0x35, Right, High).pos(3), + create_door(player, 'Swamp Crystal Switch Outer to Inner Barrier - Blue', Lgcl), + create_door(player, 'Swamp Crystal Switch Outer to Ranged Crystal', Lgcl), + create_door(player, 'Swamp Crystal Switch Outer to Inner Bypass', Lgcl), + create_door(player, 'Swamp Crystal Switch Outer Ranged Crystal Exit', Lgcl), + create_door(player, 'Swamp Crystal Switch Inner to Outer Barrier - Blue', Lgcl), + create_door(player, 'Swamp Crystal Switch Inner to Outer Bypass', Lgcl), + create_door(player, 'Swamp Crystal Switch Inner to Crystal', Lgcl), + create_door(player, 'Swamp Crystal Switch Inner Crystal Exit', Lgcl), create_door(player, 'Swamp Shortcut NE', Intr).dir(No, 0x35, Right, High).pos(3), create_door(player, 'Swamp Shortcut Blue Barrier', Lgcl), create_door(player, 'Swamp Trench 2 Pots ES', Nrml).dir(Ea, 0x35, Bot, High).pos(4), @@ -673,6 +737,8 @@ def create_doors(world, player): create_door(player, 'Ice Big Key Down Ladder', Lddr).dir(So, 0x1f, 3, High), create_door(player, 'Ice Stalfos Hint SE', Intr).dir(So, 0x3e, Right, High).pos(0), create_door(player, 'Ice Conveyor NE', Intr).dir(No, 0x3e, Right, High).no_exit().pos(0), + create_door(player, 'Ice Conveyor to Crystal', Lgcl), + create_door(player, 'Ice Conveyor Crystal Exit', Lgcl), create_door(player, 'Ice Conveyor SW', Nrml).dir(So, 0x3e, Left, High).small_key().pos(1).portal(Z, 0x20), create_door(player, 'Ice Bomb Jump NW', Nrml).dir(No, 0x4e, Left, High).small_key().pos(1), create_door(player, 'Ice Bomb Jump Ledge Orange Barrier', Lgcl), @@ -739,6 +805,9 @@ def create_doors(world, player): create_door(player, 'Ice Switch Room ES', Nrml).dir(Ea, 0xbe, Bot, High).small_key().pos(1), create_door(player, 'Ice Switch Room SE', Nrml).dir(So, 0xbe, Right, High).trap(0x4).pos(0).portal(X, 0x00), create_door(player, 'Ice Refill WS', Nrml).dir(We, 0xbf, Bot, High).small_key().pos(0), + create_door(player, 'Ice Refill to Crystal', Lgcl), + create_door(player, 'Ice Refill Crystal Exit', Lgcl), + create_door(player, 'Ice Fairy Warp', Warp), create_door(player, 'Ice Antechamber NE', Nrml).dir(No, 0xce, Right, High).trap(0x4).pos(0), create_door(player, 'Ice Antechamber Hole', Hole), @@ -806,6 +875,7 @@ def create_doors(world, player): create_door(player, 'Mire Left Bridge Down Stairs', Sprl).dir(Dn, 0xa2, 0, HTL).ss(A, 0x12, 0x00), create_door(player, 'Mire Fishbone E', Nrml).dir(Ea, 0xa1, Mid, High).pos(1), create_door(player, 'Mire Fishbone Blue Barrier', Lgcl), + create_door(player, 'Mire Fishbone Blue Barrier Bypass', Lgcl), create_door(player, 'Mire South Fish Blue Barrier', Lgcl), create_door(player, 'Mire Fishbone SE', Nrml).dir(So, 0xa1, Right, High).small_key().pos(0), create_door(player, 'Mire Spike Barrier NE', Nrml).dir(No, 0xb1, Right, High).small_key().pos(1), @@ -820,6 +890,8 @@ def create_doors(world, player): create_door(player, 'Mire Conveyor Crystal ES', Nrml).dir(Ea, 0xc1, Bot, High).small_key().pos(1), create_door(player, 'Mire Conveyor Crystal SE', Nrml).dir(So, 0xc1, Right, High).pos(7).portal(X, 0x00), create_door(player, 'Mire Conveyor Crystal WS', Intr).dir(We, 0xc1, Bot, High).small_key().pos(0), + create_door(player, 'Mire Conveyor to Crystal', Lgcl), + create_door(player, 'Mire Conveyor Crystal Exit', Lgcl), create_door(player, 'Mire Tile Room ES', Intr).dir(Ea, 0xc1, Bot, High).small_key().pos(0), create_door(player, 'Mire Tile Room SW', Nrml).dir(So, 0xc1, Left, High).pos(4).portal(Z, 0x00), create_door(player, 'Mire Tile Room NW', Intr).dir(No, 0xc1, Left, High).pos(3), @@ -854,6 +926,8 @@ def create_doors(world, player): create_door(player, 'Mire Tall Dark and Roomy WN', Intr).dir(We, 0x92, Top, High).pos(0), create_door(player, 'Mire Shooter Rupees EN', Intr).dir(Ea, 0x92, Top, High).pos(0), create_door(player, 'Mire Tall Dark and Roomy WS', Intr).dir(We, 0x92, Bot, High).pos(3), + create_door(player, 'Mire Tall Dark and Roomy to Ranged Crystal', Lgcl), + create_door(player, 'Mire Tall Dark and Roomy Ranged Crystal Exit', Lgcl), create_door(player, 'Mire Crystal Right ES', Intr).dir(Ea, 0x92, Bot, High).pos(3), create_door(player, 'Mire Crystal Mid NW', Intr).dir(No, 0x92, Left, High).pos(1), create_door(player, 'Mire Crystal Top SW', Intr).dir(So, 0x92, Left, High).pos(1), @@ -891,6 +965,12 @@ def create_doors(world, player): create_door(player, 'TR Refill SE', Intr).dir(So, 0xb6, Right, High).pos(1), create_door(player, 'TR Pokey 1 NW', Intr).dir(No, 0xb6, Left, High).small_key().pos(3), create_door(player, 'TR Chain Chomps SW', Intr).dir(So, 0xb6, Left, High).small_key().pos(3), + create_door(player, 'TR Chain Chomps Top to Bottom Barrier - Orange', Lgcl), + create_door(player, 'TR Chain Chomps Top to Crystal', Lgcl), + create_door(player, 'TR Chain Chomps Top Crystal Exit', Lgcl), + create_door(player, 'TR Chain Chomps Bottom to Top Barrier - Orange', Lgcl), + create_door(player, 'TR Chain Chomps Bottom to Ranged Crystal', Lgcl), + create_door(player, 'TR Chain Chomps Bottom Ranged Crystal Exit', Lgcl), create_door(player, 'TR Chain Chomps Down Stairs', Sprl).dir(Dn, 0xb6, 0, HTH).ss(A, 0x12, 0x80, True, True).small_key().pos(0), create_door(player, 'TR Pipe Pit Up Stairs', Sprl).dir(Up, 0x15, 0, HTH).ss(A, 0x1b, 0x6c), create_door(player, 'TR Pipe Pit WN', Nrml).dir(We, 0x15, Top, High).pos(1), @@ -904,6 +984,12 @@ def create_doors(world, player): create_door(player, 'TR Lava Escape SE', Nrml).dir(So, 0x14, Right, High).small_key().pos(0), create_door(player, 'TR Lava Escape NW', Nrml).dir(No, 0x14, Left, High).pos(2), create_door(player, 'TR Pokey 2 EN', Nrml).dir(Ea, 0x13, Top, High).pos(1), + create_door(player, 'TR Pokey 2 Top to Bottom Barrier - Blue', Lgcl), + create_door(player, 'TR Pokey 2 Top to Crystal', Lgcl), + create_door(player, 'TR Pokey 2 Top Crystal Exit', Lgcl), + create_door(player, 'TR Pokey 2 Bottom to Top Barrier - Blue', Lgcl), + create_door(player, 'TR Pokey 2 Bottom to Ranged Crystal', Lgcl), + create_door(player, 'TR Pokey 2 Bottom Ranged Crystal Exit', Lgcl), create_door(player, 'TR Pokey 2 ES', Nrml).dir(Ea, 0x13, Bot, High).small_key().pos(0), create_door(player, 'TR Twin Pokeys NW', Nrml).dir(No, 0x24, Left, High).pos(5), create_door(player, 'TR Twin Pokeys SW', Intr).dir(So, 0x24, Left, High).pos(2), @@ -928,6 +1014,19 @@ def create_doors(world, player): create_door(player, 'TR Rupees SE', Intr).dir(So, 0x04, Right, High).pos(3), create_door(player, 'TR Dash Room NW', Intr).dir(No, 0x04, Left, High).pos(1), create_door(player, 'TR Crystaroller SW', Intr).dir(So, 0x04, Left, High).pos(1), + create_door(player, 'TR Crystaroller Bottom to Middle Barrier - Orange', Lgcl), + create_door(player, 'TR Crystaroller Bottom to Ranged Crystal', Lgcl), + create_door(player, 'TR Crystaroller Middle to Bottom Barrier - Orange', Lgcl), + create_door(player, 'TR Crystaroller Middle to Bottom Bypass', Lgcl), + create_door(player, 'TR Crystaroller Middle to Chest Barrier - Blue', Lgcl), + create_door(player, 'TR Crystaroller Middle to Top Barrier - Orange', Lgcl), + create_door(player, 'TR Crystaroller Middle to Ranged Crystal', Lgcl), + create_door(player, 'TR Crystaroller Top to Middle Barrier - Orange', Lgcl), + create_door(player, 'TR Crystaroller Top to Crystal', Lgcl), + create_door(player, 'TR Crystaroller Top Crystal Exit', Lgcl), + create_door(player, 'TR Crystaroller Chest to Middle Barrier - Blue', Lgcl), + create_door(player, 'TR Crystaroller Middle Ranged Crystal Exit', Lgcl), + create_door(player, 'TR Crystaroller Bottom Ranged Crystal Exit', Lgcl), create_door(player, 'TR Crystaroller Down Stairs', Sprl).dir(Dn, 0x04, 0, HTH).ss(A, 0x12, 0x80, True, True).small_key().pos(0), create_door(player, 'TR Dark Ride Up Stairs', Sprl).dir(Up, 0xb5, 0, HTH).ss(A, 0x1b, 0x6c), create_door(player, 'TR Dark Ride SW', Nrml).dir(So, 0xb5, Left, High).trap(0x4).pos(0).portal(Z, 0x22), @@ -937,9 +1036,16 @@ def create_doors(world, player): create_door(player, 'TR Eye Bridge NW', Nrml).dir(No, 0xd5, Left, High).pos(1), create_door(player, 'TR Eye Bridge SW', Nrml).dir(So, 0xd5, Left, High).pos(0).portal(Z, 0x02), create_door(player, 'TR Crystal Maze ES', Nrml).dir(Ea, 0xc4, Bot, High).small_key().pos(0), - create_door(player, 'TR Crystal Maze Forwards Path', Lgcl), - create_door(player, 'TR Crystal Maze Blue Path', Lgcl), - create_door(player, 'TR Crystal Maze Cane Path', Lgcl), + create_door(player, 'TR Crystal Maze Start to Interior Barrier - Blue', Lgcl), + create_door(player, 'TR Crystal Maze Start to Crystal', Lgcl), + create_door(player, 'TR Crystal Maze Start Crystal Exit', Lgcl), + create_door(player, 'TR Crystal Maze Interior to Start Barrier - Blue', Lgcl), + create_door(player, 'TR Crystal Maze Interior to End Barrier - Blue', Lgcl), + create_door(player, 'TR Crystal Maze Interior to End Bypass', Lgcl), + create_door(player, 'TR Crystal Maze Interior to Start Bypass', Lgcl), + create_door(player, 'TR Crystal Maze End to Interior Barrier - Blue', Lgcl), + create_door(player, 'TR Crystal Maze End to Ranged Crystal', Lgcl), + create_door(player, 'TR Crystal Maze End Ranged Crystal Exit', Lgcl), create_door(player, 'TR Crystal Maze North Stairs', StrS).dir(No, 0xc4, Mid, High), create_door(player, 'TR Final Abyss South Stairs', StrS).dir(So, 0xb4, Mid, High), create_door(player, 'TR Final Abyss NW', Nrml).dir(No, 0xb4, Left, High).big_key().pos(0), @@ -972,6 +1078,15 @@ def create_doors(world, player): create_door(player, 'GT Pots n Blocks ES', Intr).dir(Ea, 0x8d, Bot, High).pos(4), create_door(player, 'GT Speed Torch SE', Nrml).dir(So, 0x8d, Right, High).trap(0x4).pos(0).portal(X, 0x02), create_door(player, 'GT Crystal Conveyor NE', Nrml).dir(No, 0x9d, Right, High).pos(0).kill(), + create_door(player, 'GT Crystal Conveyor to Corner Barrier - Blue', Lgcl), + create_door(player, 'GT Crystal Conveyor to Ranged Crystal', Lgcl), + create_door(player, 'GT Crystal Conveyor Corner to Left Bypass', Lgcl), + create_door(player, 'GT Crystal Conveyor Corner to Barrier - Blue', Lgcl), + create_door(player, 'GT Crystal Conveyor Corner to Barrier - Orange', Lgcl), + create_door(player, 'GT Crystal Conveyor Corner to Ranged Crystal', Lgcl), + create_door(player, 'GT Crystal Conveyor Left to Corner Barrier - Orange', Lgcl), + create_door(player, 'GT Crystal Conveyor Ranged Crystal Exit', Lgcl), + create_door(player, 'GT Crystal Conveyor Corner Ranged Crystal Exit', Lgcl), create_door(player, 'GT Crystal Conveyor WN', Intr).dir(We, 0x9d, Top, High).pos(2), create_door(player, 'GT Compass Room EN', Intr).dir(Ea, 0x9d, Top, High).pos(2), create_door(player, 'GT Compass Room Warp', Warp), @@ -991,22 +1106,32 @@ def create_doors(world, player): create_door(player, 'GT Hookshot South-North Path', Lgcl), create_door(player, 'GT Hookshot Platform Blue Barrier', Lgcl), create_door(player, 'GT Hookshot Entry Blue Barrier', Lgcl), - create_door(player, 'GT Hookshot Entry Boomerang Path', Lgcl), + create_door(player, 'GT Hookshot Platform Barrier Bypass', Lgcl), + create_door(player, 'GT Hookshot South Entry to Ranged Crystal', Lgcl), + create_door(player, 'GT HookShot South Entry Ranged Crystal Exit', Lgcl), create_door(player, 'GT Hookshot NW', Nrml).dir(No, 0x8b, Left, High).pos(4), create_door(player, 'GT Hookshot ES', Intr).dir(Ea, 0x8b, Bot, High).small_key().pos(1), create_door(player, 'GT Map Room WS', Intr).dir(We, 0x8b, Bot, High).small_key().pos(1), create_door(player, 'GT Hookshot SW', Nrml).dir(So, 0x8b, Left, High).pos(3).portal(Z, 0x02), create_door(player, 'GT Double Switch NW', Nrml).dir(No, 0x9b, Left, High).pos(1).kill(), - create_door(player, 'GT Double Switch Orange Barrier', Lgcl), - create_door(player, 'GT Double Switch Orange Barrier 2', Lgcl), - create_door(player, 'GT Double Switch Blue Path', Lgcl), - create_door(player, 'GT Double Switch Orange Path', Lgcl), - create_door(player, 'GT Double Switch Key Blue Path', Lgcl), - create_door(player, 'GT Double Switch Key Orange Path', Lgcl), - create_door(player, 'GT Double Switch Blue Barrier', Lgcl), - create_door(player, 'GT Double Switch Transition Blue', Lgcl), + create_door(player, 'GT Double Switch Entry to Pot Corners Barrier - Orange', Lgcl), + create_door(player, 'GT Double Switch Entry to Left Barrier - Orange', Lgcl), + create_door(player, 'GT Double Switch Entry to Ranged Switches', Lgcl), + create_door(player, 'GT Double Switch Entry Ranged Switches Exit', Lgcl), + create_door(player, 'GT Double Switch Left to Entry Barrier - Orange', Lgcl), + create_door(player, 'GT Double Switch Left to Pot Corners Bypass', Lgcl), + create_door(player, 'GT Double Switch Left to Entry Bypass', Lgcl), + create_door(player, 'GT Double Switch Left to Exit Bypass', Lgcl), + create_door(player, 'GT Double Switch Pot Corners to Entry Barrier - Orange', Lgcl), + create_door(player, 'GT Double Switch Pot Corners to Exit Barrier - Blue', Lgcl), + create_door(player, 'GT Double Switch Pot Corners to Ranged Switches', Lgcl), + create_door(player, 'GT Double Switch Pot Corners Ranged Switches Exit', Lgcl), + create_door(player, 'GT Double Switch Exit to Blue Barrier', Lgcl), create_door(player, 'GT Double Switch EN', Intr).dir(Ea, 0x9b, Top, High).small_key().pos(0), create_door(player, 'GT Spike Crystals WN', Intr).dir(We, 0x9b, Top, High).small_key().pos(0), + create_door(player, 'GT Spike Crystal Left to Right Barrier - Orange', Lgcl), + create_door(player, 'GT Spike Crystal Right to Left Barrier - Orange', Lgcl), + create_door(player, 'GT Spike Crystal Left to Right Bypass', Lgcl), create_door(player, 'GT Spike Crystals Warp', Warp), create_door(player, 'GT Warp Maze - Left Section Warp', Warp), create_door(player, 'GT Warp Maze - Mid Section Left Warp', Warp), @@ -1094,6 +1219,10 @@ def create_doors(world, player): create_door(player, 'GT Bomb Conveyor EN', Intr).dir(Ea, 0x3d, Top, High).small_key().pos(1), create_door(player, 'GT Bomb Conveyor SW', Intr).dir(So, 0x3d, Left, High).pos(3), create_door(player, 'GT Crystal Circles NW', Intr).dir(No, 0x3d, Left, High).pos(3), + create_door(player, 'GT Crystal Circles Barrier - Orange', Lgcl), + create_door(player, 'GT Crystal Inner Circle Barrier - Orange', Lgcl), + create_door(player, 'GT Crystal Circles to Ranged Crystal', Lgcl), + create_door(player, 'GT Crystal Circles Ranged Crystal Exit', Lgcl), create_door(player, 'GT Crystal Circles SW', Nrml).dir(So, 0x3d, Left, High).small_key().pos(2).portal(Z, 0x00), create_door(player, 'GT Left Moldorm Ledge NW', Nrml).dir(No, 0x4d, Left, High).small_key().pos(0).kill(), create_door(player, 'GT Left Moldorm Ledge Drop Down', Lgcl), @@ -1135,42 +1264,69 @@ def create_doors(world, player): world.get_door('Hyrule Castle Tapestry Backwards', player).event('Zelda Pickup') # crystal switches and barriers - world.get_door('Hera Lobby Down Stairs', player).c_switch() - world.get_door('Hera Lobby Key Stairs', player).c_switch() - world.get_door('Hera Lobby Up Stairs', player).c_switch() - world.get_door('Hera Basement Cage Up Stairs', player).c_switch() + world.get_door('Hera Lobby Crystal Exit', player).c_switch() + world.get_door('Hera Lobby to Front Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('Hera Front to Lobby Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('Hera Front Crystal Exit', player).c_switch() + world.get_door('Hera Front to Down Stairs Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('Hera Down Stairs to Front Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('Hera Down Stairs Landing Ranged Crystal Exit', player).c_switch() + world.get_door('Hera Front to Up Stairs Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('Hera Up Stairs to Front Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('Hera Up Stairs Landing Ranged Crystal Exit', player).c_switch() + world.get_door('Hera Front to Back Bypass', player).barrier(CrystalBarrier.Blue) + world.get_door('Hera Front to Back Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('Hera Back to Front Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('Hera Back Ranged Crystal Exit', player).c_switch() + world.get_door('Hera Basement Cage Crystal Exit', player).c_switch() world.get_door('Hera Tile Room Up Stairs', player).c_switch() - world.get_door('Hera Tile Room EN', player).c_switch() - world.get_door('Hera Tridorm WN', player).c_switch() - world.get_door('Hera Tridorm SE', player).c_switch() + world.get_door('Hera Tile Room EN', player).barrier(CrystalBarrier.Blue) + world.get_door('Hera Tridorm WN', player).barrier(CrystalBarrier.Blue) + world.get_door('Hera Tridorm Crystal Exit', player).c_switch() + world.get_door('Hera Tridorm SE', player).barrier(CrystalBarrier.Orange) world.get_door('Hera Beetles Down Stairs', player).c_switch() world.get_door('Hera Beetles WS', player).c_switch() - world.get_door('Hera Beetles Holes', player).c_switch() - world.get_door('Hera Startile Wide SW', player).c_switch() - world.get_door('Hera Startile Wide Up Stairs', player).c_switch() - world.get_door('Hera Startile Wide Holes', player).c_switch() + world.get_door('Hera Beetles Holes Front', player).c_switch() + world.get_door('Hera Beetles Holes Landing', player).c_switch() + world.get_door('Hera Startile Wide Crystal Exit', player).c_switch() + + world.get_door('PoD Arena North to Landing Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('PoD Arena Main to Landing Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('PoD Arena Main to Landing Bypass', player).barrier(CrystalBarrier.Orange) + world.get_door('PoD Arena Main to Right Bypass', player).barrier(CrystalBarrier.Orange) + world.get_door('PoD Arena Main Ranged Crystal Exit', player).c_switch() + world.get_door('PoD Arena Bridge Ranged Crystal Exit', player).c_switch() + world.get_door('PoD Arena Landing to Main Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('PoD Arena Landing to Right Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('PoD Arena Landing to North Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('PoD Arena Right to Landing Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('PoD Arena Right Ranged Crystal Exit', player).c_switch() + world.get_door('PoD Arena Ledge Ranged Crystal Exit', player).c_switch() - world.get_door('PoD Arena Main SW', player).c_switch() - world.get_door('PoD Arena Bonk Path', player).c_switch() - world.get_door('PoD Arena Bridge SE', player).c_switch() - world.get_door('PoD Arena Bridge Drop Down', player).c_switch() - world.get_door('PoD Arena Main Orange Barrier', player).barrier(CrystalBarrier.Orange) - # maybe you can cross this way with blue up?? - world.get_door('PoD Arena Main Crystal Path', player).barrier(CrystalBarrier.Blue) - world.get_door('PoD Arena Crystal Path', player).barrier(CrystalBarrier.Blue) world.get_door('PoD Sexy Statue W', player).c_switch() world.get_door('PoD Sexy Statue NW', player).c_switch() - world.get_door('PoD Map Balcony WS', player).c_switch() - world.get_door('PoD Map Balcony South Stairs', player).c_switch() - world.get_door('PoD Bow Statue SW', player).c_switch() - world.get_door('PoD Bow Statue Moving Wall Path', player).barrier(CrystalBarrier.Orange) - world.get_door('PoD Bow Statue Crystal Path', player).c_switch() - world.get_door('PoD Dark Pegs WN', player).c_switch() - world.get_door('PoD Dark Pegs Switch Path', player).c_switch() - world.get_door('PoD Dark Pegs Hammer Path', player).c_switch() + world.get_door('PoD Map Balcony Ranged Crystal Exit', player).c_switch() + world.get_door('PoD Bow Statue Left Crystal Exit', player).c_switch() + world.get_door('PoD Bow Statue Left to Right Bypass', player).barrier(CrystalBarrier.Blue) + world.get_door('PoD Bow Statue Left to Right Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('PoD Bow Statue Right to Left Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('PoD Bow Statue Ranged Crystal Exit', player).c_switch() + world.get_door('PoD Dark Pegs Right to Middle Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('PoD Dark Pegs Right to Middle Bypass', player).barrier(CrystalBarrier.Blue) + world.get_door('PoD Dark Pegs Middle to Right Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('PoD Dark Pegs Middle to Left Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('PoD Dark Pegs Middle to Left Bypass', player).barrier(CrystalBarrier.Orange) + world.get_door('PoD Dark Pegs Left to Middle Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('PoD Dark Pegs Landing Ranged Crystal Exit', player).c_switch() + world.get_door('PoD Dark Pegs Middle Ranged Crystal Exit', player).c_switch() + world.get_door('PoD Dark Pegs Left Ranged Crystal Exit', player).c_switch() - world.get_door('Swamp Crystal Switch EN', player).c_switch() - world.get_door('Swamp Crystal Switch SE', player).c_switch() + world.get_door('Swamp Crystal Switch Outer to Inner Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('Swamp Crystal Switch Outer to Inner Bypass', player).barrier(CrystalBarrier.Orange) + world.get_door('Swamp Crystal Switch Inner to Outer Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('Swamp Crystal Switch Inner to Outer Bypass', player).barrier(CrystalBarrier.Orange) + world.get_door('Swamp Crystal Switch Inner Crystal Exit', player).c_switch() + world.get_door('Swamp Crystal Switch Outer Ranged Crystal Exit', player).c_switch() world.get_door('Swamp Shortcut Blue Barrier', player).barrier(CrystalBarrier.Blue) world.get_door('Swamp Trench 2 Pots Blue Barrier', player).barrier(CrystalBarrier.Blue) world.get_door('Swamp Barrier Ledge - Orange', player).barrier(CrystalBarrier.Orange) @@ -1186,13 +1342,12 @@ def create_doors(world, player): world.get_door('Thieves Triple Bypass EN', player).barrier(CrystalBarrier.Blue) world.get_door('Thieves Hellway Orange Barrier', player).barrier(CrystalBarrier.Orange) world.get_door('Thieves Hellway Crystal Orange Barrier', player).barrier(CrystalBarrier.Orange) - world.get_door('Thieves Hellway Crystal Orange Barrier', player).barrier(CrystalBarrier.Orange) world.get_door('Thieves Attic Orange Barrier', player).barrier(CrystalBarrier.Orange) world.get_door('Thieves Attic Hint Orange Barrier', player).barrier(CrystalBarrier.Orange) world.get_door('Ice Bomb Drop SE', player).c_switch() - world.get_door('Ice Conveyor SW', player).c_switch() - world.get_door('Ice Refill WS', player).c_switch() + world.get_door('Ice Conveyor Crystal Exit', player).c_switch() + world.get_door('Ice Refill Crystal Exit', player).c_switch() world.get_door('Ice Bomb Drop Hole', player).barrier(CrystalBarrier.Orange) # not required to hit switch w/ bomb world.get_door('Ice Bomb Jump Ledge Orange Barrier', player).barrier(CrystalBarrier.Orange) world.get_door('Ice Bomb Jump Catwalk Orange Barrier', player).barrier(CrystalBarrier.Orange) @@ -1203,12 +1358,8 @@ def create_doors(world, player): world.get_door('Ice Backwards Room Hole', player).barrier(CrystalBarrier.Blue) world.get_door('Mire Fishbone E', player).c_switch() - world.get_door('Mire Conveyor Crystal ES', player).c_switch() - world.get_door('Mire Conveyor Crystal SE', player).c_switch() - world.get_door('Mire Conveyor Crystal WS', player).c_switch() - world.get_door('Mire Tall Dark and Roomy ES', player).c_switch() - world.get_door('Mire Tall Dark and Roomy WN', player).c_switch() - world.get_door('Mire Tall Dark and Roomy WS', player).c_switch() + world.get_door('Mire Conveyor Crystal Exit', player).c_switch() + world.get_door('Mire Tall Dark and Roomy Ranged Crystal Exit', player).c_switch() world.get_door('Mire Crystal Top SW', player).c_switch() world.get_door('Mire Falling Foes ES', player).c_switch() world.get_door('Mire Falling Foes Up Stairs', player).c_switch() @@ -1223,6 +1374,8 @@ def create_doors(world, player): world.get_door('Mire Crystal Dead End Left Barrier', player).barrier(CrystalBarrier.Blue) world.get_door('Mire Crystal Dead End Right Barrier', player).barrier(CrystalBarrier.Blue) world.get_door('Mire Fishbone Blue Barrier', player).barrier(CrystalBarrier.Blue) + world.get_door('Mire Fishbone Blue Barrier Bypass', player).barrier(CrystalBarrier.Orange) + world.get_door('Mire South Fish Blue Barrier', player).barrier(CrystalBarrier.Blue) world.get_door('Mire Compass Blue Barrier', player).barrier(CrystalBarrier.Blue) world.get_door('Mire Crystal Mid Blue Barrier', player).barrier(CrystalBarrier.Blue) @@ -1232,42 +1385,70 @@ def create_doors(world, player): world.get_door('Mire Firesnake Skip Orange Barrier', player).barrier(CrystalBarrier.Orange) world.get_door('Mire Antechamber Orange Barrier', player).barrier(CrystalBarrier.Orange) - world.get_door('TR Chain Chomps SW', player).c_switch() - world.get_door('TR Chain Chomps Down Stairs', player).c_switch() - world.get_door('TR Pokey 2 EN', player).c_switch() - world.get_door('TR Pokey 2 ES', player).c_switch() - world.get_door('TR Crystaroller SW', player).c_switch() - world.get_door('TR Crystaroller Down Stairs', player).c_switch() - world.get_door('TR Crystal Maze ES', player).c_switch() - world.get_door('TR Crystal Maze Forwards Path', player).c_switch() - world.get_door('TR Crystal Maze Cane Path', player).c_switch() - world.get_door('TR Crystal Maze Blue Path', player).barrier(CrystalBarrier.Blue) + world.get_door('TR Chain Chomps Top Crystal Exit', player).c_switch() + world.get_door('TR Chain Chomps Top to Bottom Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('TR Chain Chomps Bottom to Top Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('TR Chain Chomps Bottom Ranged Crystal Exit', player).c_switch() + world.get_door('TR Pokey 2 Top Crystal Exit', player).c_switch() + world.get_door('TR Pokey 2 Top to Bottom Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('TR Pokey 2 Bottom to Top Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('TR Pokey 2 Bottom Ranged Crystal Exit', player).c_switch() + world.get_door('TR Crystaroller Bottom to Middle Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('TR Crystaroller Middle to Bottom Bypass', player).barrier(CrystalBarrier.Blue) + world.get_door('TR Crystaroller Middle to Bottom Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('TR Crystaroller Middle to Chest Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('TR Crystaroller Chest to Middle Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('TR Crystaroller Middle to Top Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('TR Crystaroller Top to Middle Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('TR Crystaroller Middle Ranged Crystal Exit', player).c_switch() + world.get_door('TR Crystaroller Bottom Ranged Crystal Exit', player).c_switch() + world.get_door('TR Crystaroller Top Crystal Exit', player).c_switch() + world.get_door('TR Crystal Maze Start Crystal Exit', player).c_switch() + world.get_door('TR Crystal Maze Start to Interior Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('TR Crystal Maze Interior to Start Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('TR Crystal Maze Interior to End Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('TR Crystal Maze Interior to End Bypass', player).barrier(CrystalBarrier.Orange) + world.get_door('TR Crystal Maze Interior to Start Bypass', player).barrier(CrystalBarrier.Orange) + world.get_door('TR Crystal Maze End to Interior Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('TR Crystal Maze End Ranged Crystal Exit', player).c_switch() - world.get_door('GT Crystal Conveyor NE', player).c_switch() - world.get_door('GT Crystal Conveyor WN', player).c_switch() + world.get_door('GT Crystal Conveyor to Corner Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('GT Crystal Conveyor Corner to Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('GT Crystal Conveyor Corner to Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Crystal Conveyor Left to Corner Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Crystal Conveyor Ranged Crystal Exit', player).c_switch() + world.get_door('GT Crystal Conveyor Corner Ranged Crystal Exit', player).c_switch() + world.get_door('GT Crystal Conveyor Corner to Left Bypass', player).barrier(CrystalBarrier.Blue) world.get_door('GT Hookshot South-North Path', player).c_switch() world.get_door('GT Hookshot South-East Path', player).c_switch() world.get_door('GT Hookshot ES', player).c_switch() - world.get_door('GT Hookshot Platform Blue Barrier', player).c_switch() - world.get_door('GT Hookshot Entry Boomerang Path', player).c_switch() - world.get_door('GT Double Switch Orange Path', player).c_switch() - world.get_door('GT Double Switch Blue Path', player).c_switch() + world.get_door('GT Hookshot Platform Barrier Bypass', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Hookshot Platform Blue Barrier', player).barrier(CrystalBarrier.Blue) + world.get_door('GT HookShot South Entry Ranged Crystal Exit', player).c_switch() world.get_door('GT Spike Crystals WN', player).c_switch() world.get_door('GT Spike Crystals Warp', player).c_switch() world.get_door('GT Crystal Paths Down Stairs', player).c_switch() world.get_door('GT Crystal Paths SW', player).c_switch() world.get_door('GT Hidden Spikes SE', player).c_switch() world.get_door('GT Hidden Spikes EN', player).c_switch() - world.get_door('GT Crystal Circles NW', player).c_switch() - world.get_door('GT Crystal Circles SW', player).c_switch() + world.get_door('GT Crystal Circles Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Crystal Inner Circle Barrier - Orange', player).c_switch() + world.get_door('GT Crystal Circles Ranged Crystal Exit', player).c_switch() world.get_door('GT Hookshot Entry Blue Barrier', player).barrier(CrystalBarrier.Blue) - world.get_door('GT Double Switch Orange Barrier', player).barrier(CrystalBarrier.Orange) - world.get_door('GT Double Switch Orange Barrier 2', player).barrier(CrystalBarrier.Orange) - world.get_door('GT Double Switch Orange Path', player).barrier(CrystalBarrier.Orange) - world.get_door('GT Double Switch Key Orange Path', player).barrier(CrystalBarrier.Orange) - world.get_door('GT Double Switch Key Blue Path', player).barrier(CrystalBarrier.Blue) - world.get_door('GT Double Switch Blue Barrier', player).barrier(CrystalBarrier.Blue) - world.get_door('GT Double Switch Transition Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('GT Double Switch Entry to Pot Corners Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Double Switch Entry to Left Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Double Switch Entry Ranged Switches Exit', player).c_switch() + world.get_door('GT Double Switch Left to Entry Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Double Switch Left to Entry Bypass', player).barrier(CrystalBarrier.Blue) + world.get_door('GT Double Switch Left to Pot Corners Bypass', player).barrier(CrystalBarrier.Blue) + world.get_door('GT Double Switch Left to Exit Bypass', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Double Switch Pot Corners to Entry Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Double Switch Pot Corners to Exit Barrier - Blue', player).barrier(CrystalBarrier.Blue) + world.get_door('GT Double Switch Pot Corners Ranged Switches Exit', player).c_switch() + world.get_door('GT Double Switch Exit to Blue Barrier', player).barrier(CrystalBarrier.Blue) + world.get_door('GT Spike Crystal Left to Right Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Spike Crystal Right to Left Barrier - Orange', player).barrier(CrystalBarrier.Orange) + world.get_door('GT Spike Crystal Left to Right Bypass', player).barrier(CrystalBarrier.Blue) # nifty dynamic logical doors: south_controller = world.get_door('Ice Cross Bottom SE', player) diff --git a/DungeonGenerator.py b/DungeonGenerator.py index 9bb73802..c8599748 100644 --- a/DungeonGenerator.py +++ b/DungeonGenerator.py @@ -1432,7 +1432,8 @@ def calc_allowance_and_dead_ends(builder, connections_tuple, world, player): check_list = list(potentials[enabling_region]) if enabling_region.name in ['Desert Ledge', 'Desert Palace Entrance (North) Spot']: alternate = 'Desert Palace Entrance (North) Spot' if enabling_region.name == 'Desert Ledge' else 'Desert Ledge' - check_list.extend(potentials[world.get_region(alternate, player)]) + if world.get_region(alternate, player) in potentials: + check_list.extend(potentials[world.get_region(alternate, player)]) connecting_entrances = [x for x in check_list if x != entrance and x not in dead_entrances and x not in drop_entrances_allowance] connect_able = len(connecting_entrances) > 0 if is_destination and sector.branches() == 0: # diff --git a/Dungeons.py b/Dungeons.py index 9229140c..0acf7852 100644 --- a/Dungeons.py +++ b/Dungeons.py @@ -195,8 +195,11 @@ desert_regions = [ ] hera_regions = [ - 'Hera Lobby', 'Hera Basement Cage', 'Hera Tile Room', 'Hera Tridorm', 'Hera Torches', 'Hera Beetles', - 'Hera Startile Corner', 'Hera Startile Wide', 'Hera 4F', 'Hera Big Chest Landing', 'Hera 5F', + 'Hera Lobby', 'Hera Lobby - Crystal', 'Hera Front', 'Hera Back', 'Hera Front - Crystal', 'Hera Down Stairs Landing', + 'Hera Down Stairs Landing - Ranged Crystal', 'Hera Up Stairs Landing', 'Hera Up Stairs Landing - Ranged Crystal', + 'Hera Back - Ranged Crystal', 'Hera Basement Cage', 'Hera Basement Cage - Crystal', 'Hera Tile Room', + 'Hera Tridorm', 'Hera Tridorm - Crystal', 'Hera Torches', 'Hera Beetles', 'Hera Startile Corner', + 'Hera Startile Wide', 'Hera Startile Wide - Crystal', 'Hera 4F', 'Hera Big Chest Landing', 'Hera 5F', 'Hera Fairies', 'Hera Boss', 'Hera Portal' ] @@ -209,19 +212,23 @@ tower_regions = [ pod_regions = [ 'PoD Lobby', 'PoD Left Cage', 'PoD Middle Cage', 'PoD Shooter Room', 'PoD Pit Room', 'PoD Pit Room Blocked', - 'PoD Arena Main', 'PoD Arena North', 'PoD Arena Crystal', 'PoD Arena Bridge', 'PoD Arena Ledge', 'PoD Sexy Statue', - 'PoD Map Balcony', 'PoD Conveyor', 'PoD Mimics 1', 'PoD Jelly Hall', 'PoD Warp Hint', 'PoD Warp Room', + 'PoD Arena Main', 'PoD Arena Main - Ranged Crystal', 'PoD Arena North', 'PoD Arena Bridge', 'PoD Arena Bridge - Ranged Crystal', + 'PoD Arena Landing', 'PoD Arena Right', 'PoD Arena Right - Ranged Crystal', 'PoD Arena Ledge', 'PoD Arena Ledge - Ranged Crystal', 'PoD Sexy Statue', + 'PoD Map Balcony', 'PoD Map Balcony - Ranged Crystal', 'PoD Conveyor', 'PoD Mimics 1', 'PoD Jelly Hall', 'PoD Warp Hint', 'PoD Warp Room', 'PoD Stalfos Basement', 'PoD Basement Ledge', 'PoD Big Key Landing', 'PoD Falling Bridge', 'PoD Falling Bridge Ledge', 'PoD Dark Maze', 'PoD Big Chest Balcony', 'PoD Compass Room', 'PoD Dark Basement', - 'PoD Harmless Hellway', 'PoD Mimics 2', 'PoD Bow Statue', 'PoD Bow Statue Moving Wall', 'PoD Dark Pegs', 'PoD Dark Pegs Ladder', 'PoD Dark Pegs Switch', - 'PoD Lonely Turtle', 'PoD Turtle Party', 'PoD Dark Alley', 'PoD Callback', 'PoD Boss', 'Palace of Darkness Portal' + 'PoD Harmless Hellway', 'PoD Mimics 2', 'PoD Bow Statue Left', 'PoD Bow Statue Left - Crystal', 'PoD Bow Statue Right', 'PoD Bow Statue Right - Ranged Crystal', + 'PoD Dark Pegs Landing', 'PoD Dark Pegs Right', 'PoD Dark Pegs Middle', 'PoD Dark Pegs Left', 'PoD Dark Pegs Landing - Ranged Crystal', + 'PoD Dark Pegs Middle - Ranged Crystal', 'PoD Dark Pegs Left - Ranged Crystal', 'PoD Lonely Turtle', 'PoD Turtle Party', + 'PoD Dark Alley', 'PoD Callback', 'PoD Boss', 'Palace of Darkness Portal' ] swamp_regions = [ 'Swamp Lobby', 'Swamp Entrance', 'Swamp Pot Row', 'Swamp Map Ledge', 'Swamp Trench 1 Approach', 'Swamp Trench 1 Nexus', 'Swamp Trench 1 Alcove', 'Swamp Trench 1 Key Ledge', 'Swamp Trench 1 Departure', 'Swamp Hammer Switch', 'Swamp Hub', 'Swamp Hub Dead Ledge', 'Swamp Hub North Ledge', 'Swamp Donut Top', - 'Swamp Donut Bottom', 'Swamp Compass Donut', 'Swamp Crystal Switch', 'Swamp Shortcut', 'Swamp Trench 2 Pots', + 'Swamp Donut Bottom', 'Swamp Compass Donut', 'Swamp Crystal Switch Outer', 'Swamp Crystal Switch Outer - Ranged Crystal', + 'Swamp Crystal Switch Inner', 'Swamp Crystal Switch Inner - Crystal', 'Swamp Shortcut', 'Swamp Trench 2 Pots', 'Swamp Trench 2 Blocks', 'Swamp Trench 2 Alcove', 'Swamp Trench 2 Departure', 'Swamp Big Key Ledge', 'Swamp West Shallows', 'Swamp West Block Path', 'Swamp West Ledge', 'Swamp Barrier Ledge', 'Swamp Barrier', 'Swamp Attic', 'Swamp Push Statue', 'Swamp Shooters', 'Swamp Left Elbow', 'Swamp Right Elbow', 'Swamp Drain Left', @@ -253,13 +260,13 @@ thieves_regions = [ ice_regions = [ 'Ice Lobby', 'Ice Jelly Key', 'Ice Floor Switch', 'Ice Cross Left', 'Ice Cross Bottom', 'Ice Cross Right', 'Ice Cross Top', 'Ice Compass Room', 'Ice Pengator Switch', 'Ice Dead End', 'Ice Big Key', 'Ice Bomb Drop', - 'Ice Stalfos Hint', 'Ice Conveyor', 'Ice Bomb Jump Ledge', 'Ice Bomb Jump Catwalk', 'Ice Narrow Corridor', + 'Ice Stalfos Hint', 'Ice Conveyor', 'Ice Conveyor - Crystal', 'Ice Bomb Jump Ledge', 'Ice Bomb Jump Catwalk', 'Ice Narrow Corridor', 'Ice Pengator Trap', 'Ice Spike Cross', 'Ice Firebar', 'Ice Falling Square', 'Ice Spike Room', 'Ice Hammer Block', 'Ice Tongue Pull', 'Ice Freezors', 'Ice Freezors Ledge', 'Ice Tall Hint', 'Ice Hookshot Ledge', 'Ice Hookshot Balcony', 'Ice Spikeball', 'Ice Lonely Freezor', 'Iced T', 'Ice Catwalk', 'Ice Many Pots', 'Ice Crystal Right', 'Ice Crystal Left', 'Ice Crystal Block', 'Ice Big Chest View', 'Ice Big Chest Landing', - 'Ice Backwards Room', 'Ice Anti-Fairy', 'Ice Switch Room', 'Ice Refill', 'Ice Fairy', 'Ice Antechamber', 'Ice Boss', - 'Ice Portal' + 'Ice Backwards Room', 'Ice Anti-Fairy', 'Ice Switch Room', 'Ice Refill', 'Ice Refill - Crystal', + 'Ice Fairy', 'Ice Antechamber', 'Ice Boss', 'Ice Portal' ] mire_regions = [ @@ -268,31 +275,38 @@ mire_regions = [ 'Mire Crystal Dead End', 'Mire Hidden Shooters', 'Mire Hidden Shooters Blocked', 'Mire Cross', 'Mire Minibridge', 'Mire BK Door Room', 'Mire Spikes', 'Mire Ledgehop', 'Mire Bent Bridge', 'Mire Over Bridge', 'Mire Right Bridge', 'Mire Left Bridge', 'Mire Fishbone', 'Mire South Fish', 'Mire Spike Barrier', 'Mire Square Rail', 'Mire Lone Warp', - 'Mire Wizzrobe Bypass', 'Mire Conveyor Crystal', 'Mire Tile Room', 'Mire Compass Room', 'Mire Compass Chest', + 'Mire Wizzrobe Bypass', 'Mire Conveyor Crystal', 'Mire Conveyor - Crystal', 'Mire Tile Room', 'Mire Compass Room', 'Mire Compass Chest', 'Mire Neglected Room', 'Mire Chest View', 'Mire Conveyor Barrier', 'Mire BK Chest Ledge', 'Mire Warping Pool', 'Mire Torches Top', 'Mire Torches Bottom', 'Mire Attic Hint', 'Mire Dark Shooters', 'Mire Key Rupees', - 'Mire Block X', 'Mire Tall Dark and Roomy', 'Mire Crystal Right', 'Mire Crystal Mid', 'Mire Crystal Left', + 'Mire Block X', 'Mire Tall Dark and Roomy', 'Mire Tall Dark and Roomy - Ranged Crystal', 'Mire Crystal Right', 'Mire Crystal Mid', 'Mire Crystal Left', 'Mire Crystal Top', 'Mire Shooter Rupees', 'Mire Falling Foes', 'Mire Firesnake Skip', 'Mire Antechamber', 'Mire Boss', 'Mire Portal' ] tr_regions = [ 'TR Main Lobby', 'TR Lobby Ledge', 'TR Compass Room', 'TR Hub', 'TR Torches Ledge', 'TR Torches', 'TR Roller Room', - 'TR Tile Room', 'TR Refill', 'TR Pokey 1', 'TR Chain Chomps', 'TR Pipe Pit', 'TR Pipe Ledge', 'TR Lava Dual Pipes', - 'TR Lava Island', 'TR Lava Escape', 'TR Pokey 2', 'TR Twin Pokeys', 'TR Hallway', 'TR Dodgers', 'TR Big View', - 'TR Big Chest', 'TR Big Chest Entrance', 'TR Lazy Eyes', 'TR Dash Room', 'TR Tongue Pull', 'TR Rupees', - 'TR Crystaroller', 'TR Dark Ride', 'TR Dash Bridge', 'TR Eye Bridge', 'TR Crystal Maze', 'TR Crystal Maze End', - 'TR Final Abyss', 'TR Boss', 'Turtle Rock Main Portal', 'Turtle Rock Lazy Eyes Portal', 'Turtle Rock Chest Portal', - 'Turtle Rock Eye Bridge Portal' + 'TR Tile Room', 'TR Refill', 'TR Pokey 1', 'TR Chain Chomps Top', 'TR Chain Chomps Top - Crystal', + 'TR Chain Chomps Bottom', 'TR Chain Chomps Bottom - Ranged Crystal', 'TR Pipe Pit', 'TR Pipe Ledge', 'TR Lava Dual Pipes', + 'TR Lava Island', 'TR Lava Escape', 'TR Pokey 2 Top', 'TR Pokey 2 Top - Crystal', 'TR Pokey 2 Bottom', 'TR Pokey 2 Bottom - Ranged Crystal', + 'TR Twin Pokeys', 'TR Hallway', 'TR Dodgers', 'TR Big View','TR Big Chest', 'TR Big Chest Entrance', + 'TR Lazy Eyes', 'TR Dash Room', 'TR Tongue Pull', 'TR Rupees', 'TR Crystaroller Bottom', + 'TR Crystaroller Middle', 'TR Crystaroller Top', 'TR Crystaroller Top - Crystal', 'TR Crystaroller Chest', + 'TR Crystaroller Middle - Ranged Crystal', 'TR Crystaroller Bottom - Ranged Crystal', 'TR Dark Ride', 'TR Dash Bridge', 'TR Eye Bridge', + 'TR Crystal Maze Start', 'TR Crystal Maze Start - Crystal', 'TR Crystal Maze Interior', 'TR Crystal Maze End', + 'TR Crystal Maze End - Ranged Crystal', 'TR Final Abyss', 'TR Boss', 'Turtle Rock Main Portal', + 'Turtle Rock Lazy Eyes Portal', 'Turtle Rock Chest Portal', 'Turtle Rock Eye Bridge Portal' ] gt_regions = [ 'GT Lobby', 'GT Bob\'s Torch', 'GT Hope Room', 'GT Big Chest', 'GT Blocked Stairs', 'GT Bob\'s Room', 'GT Tile Room', 'GT Speed Torch', 'GT Speed Torch Upper', 'GT Pots n Blocks', 'GT Crystal Conveyor', + 'GT Crystal Conveyor Corner', 'GT Crystal Conveyor Left', 'GT Crystal Conveyor - Ranged Crystal', + 'GT Crystal Conveyor Corner - Ranged Crystal', 'GT Compass Room', 'GT Invisible Bridges', 'GT Invisible Catwalk', 'GT Conveyor Cross', 'GT Hookshot East Platform', - 'GT Hookshot North Platform', 'GT Hookshot South Platform', 'GT Hookshot South Entry', 'GT Map Room', - 'GT Double Switch Entry', 'GT Double Switch Switches', 'GT Double Switch Transition', 'GT Double Switch Key Spot', - 'GT Double Switch Exit', 'GT Spike Crystals', 'GT Warp Maze - Left Section', 'GT Warp Maze - Mid Section', + 'GT Hookshot North Platform', 'GT Hookshot South Platform', 'GT Hookshot South Entry', 'GT Hookshot South Entry - Ranged Crystal', 'GT Map Room', + 'GT Double Switch Entry', 'GT Double Switch Pot Corners - Ranged Switches', 'GT Double Switch Pot Corners', 'GT Double Switch Left', + 'GT Double Switch Entry - Ranged Switches', 'GT Double Switch Exit', 'GT Spike Crystal Left', + 'GT Spike Crystal Right', 'GT Warp Maze - Left Section', 'GT Warp Maze - Mid Section', 'GT Warp Maze - Right Section', 'GT Warp Maze - Pit Section', 'GT Warp Maze - Pit Exit Warp Spot', 'GT Warp Maze Exit Section', 'GT Firesnake Room', 'GT Firesnake Room Ledge', 'GT Warp Maze - Rail Choice', 'GT Warp Maze - Rando Rail', 'GT Warp Maze - Main Rails', 'GT Warp Maze - Pot Rail', 'GT Petting Zoo', @@ -301,9 +315,9 @@ gt_regions = [ 'GT Dash Hall', 'GT Hidden Spikes', 'GT Cannonball Bridge', 'GT Refill', 'GT Gauntlet 1', 'GT Gauntlet 2', 'GT Gauntlet 3', 'GT Gauntlet 4', 'GT Gauntlet 5', 'GT Beam Dash', 'GT Lanmolas 2', 'GT Quad Pot', 'GT Wizzrobes 1', 'GT Dashing Bridge', 'GT Wizzrobes 2', 'GT Conveyor Bridge', 'GT Torch Cross', 'GT Staredown', 'GT Falling Torches', - 'GT Mini Helmasaur Room', 'GT Bomb Conveyor', 'GT Crystal Circles', 'GT Left Moldorm Ledge', - 'GT Right Moldorm Ledge', 'GT Moldorm', 'GT Moldorm Pit', 'GT Validation', 'GT Validation Door', 'GT Frozen Over', - 'GT Brightly Lit Hall', 'GT Agahnim 2', 'Ganons Tower Portal' + 'GT Mini Helmasaur Room', 'GT Bomb Conveyor', 'GT Crystal Circles', 'GT Crystal Inner Circle', 'GT Crystal Circles - Ranged Crystal', + 'GT Left Moldorm Ledge', 'GT Right Moldorm Ledge', 'GT Moldorm', 'GT Moldorm Pit', 'GT Validation', 'GT Validation Door', + 'GT Frozen Over', 'GT Brightly Lit Hall', 'GT Agahnim 2', 'Ganons Tower Portal' ] diff --git a/EntranceShuffle.py b/EntranceShuffle.py index f0702734..aecfd8ae 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -59,7 +59,9 @@ def link_entrances(world, player): if world.mode[player] == 'standard': # rest of hyrule castle must be in light world, so it has to be the one connected to east exit of desert - connect_mandatory_exits(world, lw_entrances, [('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')], list(LW_Dungeon_Entrances_Must_Exit), player) + hyrule_castle_exits = [('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')] + connect_mandatory_exits(world, lw_entrances, hyrule_castle_exits, list(LW_Dungeon_Entrances_Must_Exit), player) + connect_caves(world, lw_entrances, [], hyrule_castle_exits, player) elif world.doorShuffle[player] != 'vanilla': # sanc is in light world, so must all of HC if door shuffle is on connect_mandatory_exits(world, lw_entrances, @@ -1759,7 +1761,7 @@ def link_inverted_entrances(world, player): raise NotImplementedError('Shuffling not supported yet') # 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': + if world.get_entrance('Dam', player).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', player).connected_region.name != 'Swamp Portal': world.swamp_patch_required[player] = True # check for potion shop location @@ -1933,20 +1935,30 @@ def connect_random(world, exitlist, targetlist, player, two_way=False): def connect_mandatory_exits(world, entrances, caves, must_be_exits, player): - """This works inplace""" - random.shuffle(entrances) - random.shuffle(caves) + # Keeps track of entrances that cannot be used to access each exit / cave - if world.mode == 'inverted': + if world.mode[player] == 'inverted': invalid_connections = Inverted_Must_Exit_Invalid_Connections.copy() else: invalid_connections = Must_Exit_Invalid_Connections.copy() invalid_cave_connections = defaultdict(set) + if world.logic[player] in ['owglitches', 'nologic']: + import OverworldGlitchRules + for entrance in OverworldGlitchRules.get_non_mandatory_exits(world.mode[player] == 'inverted'): + invalid_connections[entrance] = set() + if entrance in must_be_exits: + must_be_exits.remove(entrance) + entrances.append(entrance) + + """This works inplace""" + random.shuffle(entrances) + random.shuffle(caves) + # Handle inverted Aga Tower - if it depends on connections, then so does Hyrule Castle Ledge - if world.mode == 'inverted': + if world.mode[player] == 'inverted': for entrance in invalid_connections: - if world.get_entrance(entrance, player).connected_region == world.get_region('Inverted Agahnims Tower', player): + if world.get_entrance(entrance, player).connected_region == world.get_region('Agahnims Tower Portal', player): for exit in invalid_connections[entrance]: invalid_connections[exit] = invalid_connections[exit].union({'Inverted Ganons Tower', 'Hyrule Castle Entrance (West)', 'Hyrule Castle Entrance (East)'}) break @@ -2950,6 +2962,7 @@ mandatory_connections = [('Links House S&Q', 'Links House'), ('Fairy Ascension Cave Climb', 'Fairy Ascension Cave (Top)'), ('Fairy Ascension Cave Pots', 'Fairy Ascension Cave (Bottom)'), ('Fairy Ascension Cave Drop', 'Fairy Ascension Cave (Drop)'), + ('Superbunny Cave Climb', 'Superbunny Cave (Top)'), ('Ganon Drop', 'Bottom of Pyramid') ] @@ -2962,6 +2975,8 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'), ('Lake Hylia Warp', 'Northeast Light World'), ('Northeast Light World Warp', 'Light World'), ('Zoras River', 'Zoras River'), + ('Waterfall of Wishing Cave', 'Waterfall of Wishing Cave'), + ('Northeast Light World Return', 'Northeast Light World'), ('Kings Grave Outer Rocks', 'Kings Grave Area'), ('Kings Grave Inner Rocks', 'Light World'), ('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'), @@ -2998,6 +3013,8 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'), ('Dark Lake Hylia Teleporter', 'Dark Lake Hylia'), ('Dark Lake Hylia Ledge Pier', 'Dark Lake Hylia Ledge'), ('Dark Lake Hylia Ledge Drop', 'Dark Lake Hylia'), + ('Ice Palace Missing Wall', 'Dark Lake Hylia Central Island'), + ('Dark Lake Hylia Shallows', 'Dark Lake Hylia'), ('East Dark World Pier', 'East Dark World'), ('South Dark World Bridge', 'South Dark World'), ('East Dark World Bridge', 'East Dark World'), @@ -3011,6 +3028,8 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'), ('West Dark World Gap', 'West Dark World'), ('East Dark World Broken Bridge Pass', 'East Dark World'), ('Northeast Dark World Broken Bridge Pass', 'Northeast Dark World'), + ('Catfish Exit Rock', 'Northeast Dark World'), + ('Catfish Entrance Rock', 'Catfish'), ('Bumper Cave Entrance Rock', 'Bumper Cave Entrance'), ('Bumper Cave Entrance Drop', 'West Dark World'), ('Bumper Cave Ledge Drop', 'West Dark World'), @@ -3049,6 +3068,7 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'), ('Mimic Cave Ledge Drop', 'East Death Mountain (Bottom)'), ('Turtle Rock Tail Drop', 'Turtle Rock (Top)'), ('Turtle Rock Drop', 'Dark Death Mountain'), + ('Superbunny Cave Climb', 'Superbunny Cave (Top)'), ('Desert Ledge Drop', 'Light World'), ('Floating Island Drop', 'Dark Death Mountain'), ('Dark Lake Hylia Central Island Teleporter', 'Lake Hylia Central Island'), @@ -3064,7 +3084,7 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'), ('Desert Palace Stairs Mirror Spot', 'Dark Desert'), ('Desert Palace North Mirror Spot', 'Dark Desert'), ('Maze Race Mirror Spot', 'West Dark World'), - ('Lake Hylia Central Island Mirror Spot', 'Dark Lake Hylia'), + ('Lake Hylia Central Island Mirror Spot', 'Dark Lake Hylia Central Island'), ('Hammer Peg Area Mirror Spot', 'Hammer Peg Area'), ('Bumper Cave Ledge Mirror Spot', 'Bumper Cave Ledge'), ('Bumper Cave Entrance Mirror Spot', 'Bumper Cave Entrance'), @@ -3080,7 +3100,7 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'), ('West Dark World Mirror Spot', 'West Dark World'), ('South Dark World Mirror Spot', 'South Dark World'), ('Potion Shop Mirror Spot', 'Northeast Dark World'), - ('Northeast Dark World Mirror Spot', 'Northeast Dark World'), + ('Catfish Mirror Spot', 'Catfish'), ('Shopping Mall Mirror Spot', 'Dark Lake Hylia Ledge'), ('Skull Woods Mirror Spot', 'Skull Woods Forest (West)'), ('DDM Flute', 'The Sky'), @@ -3243,10 +3263,10 @@ default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'), ('Dark Desert Fairy', 'Dark Desert Healer Fairy'), ('Spike Cave', 'Spike Cave'), ('Hookshot Cave', 'Hookshot Cave'), - ('Superbunny Cave (Top)', 'Superbunny Cave'), + ('Superbunny Cave (Top)', 'Superbunny Cave (Top)'), ('Cave Shop (Dark Death Mountain)', 'Cave Shop (Dark Death Mountain)'), ('Dark Death Mountain Fairy', 'Dark Death Mountain Healer Fairy'), - ('Superbunny Cave (Bottom)', 'Superbunny Cave'), + ('Superbunny Cave (Bottom)', 'Superbunny Cave (Bottom)'), ('Superbunny Cave Exit (Top)', 'Dark Death Mountain (Top East)'), ('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'), ('Hookshot Cave Exit (South)', 'Dark Death Mountain (Top East)'), @@ -3377,9 +3397,9 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing' ('Dark Desert Fairy', 'Dark Desert Healer Fairy'), ('Spike Cave', 'Spike Cave'), ('Hookshot Cave', 'Hookshot Cave'), - ('Superbunny Cave (Top)', 'Superbunny Cave'), + ('Superbunny Cave (Top)', 'Superbunny Cave (Top)'), ('Cave Shop (Dark Death Mountain)', 'Cave Shop (Dark Death Mountain)'), - ('Superbunny Cave (Bottom)', 'Superbunny Cave'), + ('Superbunny Cave (Bottom)', 'Superbunny Cave (Bottom)'), ('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'), ('Hookshot Cave Exit (North)', 'Death Mountain Floating Island (Dark World)'), ('Hookshot Cave Back Entrance', 'Hookshot Cave'), diff --git a/Fill.py b/Fill.py index 894024b2..9a9ebd0f 100644 --- a/Fill.py +++ b/Fill.py @@ -274,7 +274,7 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None # fill in gtower locations with trash first for player in range(1, world.players + 1): - if not gftower_trash or not world.ganonstower_vanilla[player] or world.doorShuffle[player] == 'crossed': + if not gftower_trash or not world.ganonstower_vanilla[player] or world.doorShuffle[player] == 'crossed' or world.logic[player] in ['owglitches', 'nologic']: continue gftower_trash_count = (random.randint(15, 50) if world.goal[player] == 'triforcehunt' else random.randint(0, 15)) diff --git a/InvertedRegions.py b/InvertedRegions.py index 53a33f43..f0a69eaa 100644 --- a/InvertedRegions.py +++ b/InvertedRegions.py @@ -30,7 +30,8 @@ def create_inverted_regions(world, player): "Blind\'s Hideout - Right", "Blind\'s Hideout - Far Left", "Blind\'s Hideout - Far Right"]), - create_lw_region(player, 'Northeast Light World', None, ['Zoras River', 'Waterfall of Wishing', 'Potion Shop Outer Rock', 'Northeast Dark World Mirror Spot', 'Northeast Light World Warp']), + create_lw_region(player, 'Northeast Light World', None, ['Zoras River', 'Waterfall of Wishing Cave', 'Potion Shop Outer Rock', 'Catfish Mirror Spot', 'Northeast Light World Warp']), + create_lw_region(player, 'Waterfall of Wishing Cave', None, ['Waterfall of Wishing', 'Northeast Light World Return']), create_lw_region(player, 'Potion Shop Area', None, ['Potion Shop', 'Potion Shop Inner Bushes', 'Potion Shop Inner Rock', 'Potion Shop Mirror Spot', 'Potion Shop River Drop']), 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']), @@ -148,14 +149,16 @@ def create_inverted_regions(world, player): 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']), - create_dw_region(player, 'Northeast Dark World', ['Catfish'], ['West Dark World Gap', 'Dark World Potion Shop', 'East Dark World Broken Bridge Pass', 'NEDW Flute', 'Dark Lake Hylia Teleporter']), + 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']), 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']), + create_dw_region(player, 'Dark Lake Hylia', None, ['East Dark World Pier', 'Dark Lake Hylia Ledge Pier', 'Ice Palace Missing Wall']), + create_dw_region(player, 'Dark Lake Hylia Central Island', None, ['Dark Lake Hylia Shallows', 'Ice Palace', 'Dark Lake Hylia Central Island Teleporter']), create_dw_region(player, 'Dark Lake Hylia Ledge', None, ['Dark Lake Hylia Ledge Drop', 'Dark Lake Hylia Ledge Fairy', 'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Ledge Spike Cave', 'DLHL Flute']), create_cave_region(player, 'Dark Lake Hylia Ledge Hint', 'a storyteller'), create_cave_region(player, 'Dark Lake Hylia Ledge Spike Cave', 'a spiky hint'), @@ -193,8 +196,8 @@ def create_inverted_regions(world, player): 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']), create_dw_region(player, 'Dark Death Mountain (East Bottom)', None, ['Superbunny Cave (Bottom)', 'Cave Shop (Dark Death Mountain)', 'Dark Death Mountain Teleporter (East Bottom)', 'EDDM Flute']), - create_cave_region(player, 'Superbunny Cave', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], - ['Superbunny Cave Exit (Top)', 'Superbunny Cave Exit (Bottom)']), + create_cave_region(player, 'Superbunny Cave (Top)', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], ['Superbunny Cave Exit (Top)']), + create_cave_region(player, 'Superbunny Cave (Bottom)', 'a connector', None, ['Superbunny Cave Climb', 'Superbunny Cave Exit (Bottom)']), create_cave_region(player, 'Spike Cave', 'Spike Cave', ['Spike Cave']), create_cave_region(player, 'Hookshot Cave', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', 'Hookshot Cave - Bottom Left'], ['Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)']), @@ -203,10 +206,10 @@ 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, 'Pyramid Ledge', None, ['Pyramid Drop']), # houlihan room exits here in inverted # 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']) ] diff --git a/ItemList.py b/ItemList.py index a259dcd1..73298c6b 100644 --- a/ItemList.py +++ b/ItemList.py @@ -255,7 +255,7 @@ def generate_itempool(world, player): (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.customitemarray) world.rupoor_cost = min(world.customitemarray[player]["rupoorcost"], 9999) else: - (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.doorShuffle[player]) + (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.doorShuffle[player], world.logic[player]) if player in world.pool_adjustment.keys(): amt = world.pool_adjustment[player] @@ -698,7 +698,7 @@ rupee_chart = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)' 'Rupees (100)': 100, 'Rupees (300)': 300} -def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, door_shuffle): +def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, door_shuffle, logic): pool = [] placed_items = {} precollected_items = [] @@ -717,6 +717,12 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, def want_progressives(): return random.choice([True, False]) if progressive == 'random' else progressive == 'on' + # provide boots to boots glitch dependent modes + if logic in ['owglitches', 'nologic']: + precollected_items.append('Pegasus Boots') + pool.remove('Pegasus Boots') + pool.extend(['Rupees (20)']) + if want_progressives(): pool.extend(progressivegloves) else: @@ -947,21 +953,22 @@ def test(): for swords in ['random', 'assured', 'swordless', 'vanilla']: for progressive in ['on', 'off']: for shuffle in ['full', 'insanity_legacy']: - for retro in [True, False]: - for door_shuffle in ['basic', 'crossed', 'vanilla']: - out = get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, door_shuffle) - count = len(out[0]) + len(out[1]) + for logic in ['noglitches', 'minorglitches', 'owglitches', 'nologic']: + for retro in [True, False]: + for door_shuffle in ['basic', 'crossed', 'vanilla']: + out = get_pool_core(progressive, shuffle, difficulty, 30, timer, goal, mode, swords, retro, door_shuffle, logic) + count = len(out[0]) + len(out[1]) - correct_count = total_items_to_place - if goal == 'pedestal' and swords != 'vanilla': - # pedestal goals generate one extra item - correct_count += 1 - if retro: - correct_count += 28 - try: - assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro)) - except AssertionError as e: - print(e) + correct_count = total_items_to_place + if goal == 'pedestal' and swords != 'vanilla': + # pedestal goals generate one extra item + correct_count += 1 + if retro: + correct_count += 28 + try: + assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro)) + except AssertionError as e: + print(e) if __name__ == '__main__': test() diff --git a/KeyDoorShuffle.py b/KeyDoorShuffle.py index 1a4e1469..549a739c 100644 --- a/KeyDoorShuffle.py +++ b/KeyDoorShuffle.py @@ -1671,7 +1671,7 @@ def val_mire(key_logic, world, player): def val_turtle(key_logic, world, player): # todo: check vanilla key logic when TR back doors are accessible - if world.shuffle[player] == 'vanilla' and world.mode[player] != 'inverted': + if world.shuffle[player] == 'vanilla' and world.mode[player] != 'inverted' and world.logic[player] in ('noglitches', 'minorglitches'): val_rule(key_logic.door_rules['TR Hub NW'], 1) val_rule(key_logic.door_rules['TR Pokey 1 NW'], 2) val_rule(key_logic.door_rules['TR Chain Chomps Down Stairs'], 3) diff --git a/Main.py b/Main.py index ee4d7b9b..9a1b8a01 100644 --- a/Main.py +++ b/Main.py @@ -11,6 +11,7 @@ import zlib from BaseClasses import World, CollectionState, Item, Region, Location, Shop, Entrance, Settings from Items import ItemFactory from KeyDoorShuffle import validate_key_placement +from OverworldGlitchRules import create_owg_connections from PotShuffle import shuffle_pots from Regions import create_regions, create_shops, mark_light_world_regions, create_dungeon_regions, adjust_locations from InvertedRegions import create_inverted_regions, mark_dark_world_regions @@ -28,7 +29,7 @@ from Fill import sell_potions, sell_keys, balance_multiworld_progression, balanc from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops from Utils import output_path, parse_player_names -__version__ = '0.3.1.10u' +__version__ = '0.4.0.0-u' class EnemizerError(RuntimeError): @@ -98,7 +99,8 @@ def main(args, seed=None, fish=None): logger.info( world.fish.translate("cli","cli","app.title") + "\n", ORVersion, - world.seed + world.seed, + Settings.make_code(world, 1) if world.players == 1 else '' ) for k,v in {"DR":__version__,"OR":ORVersion}.items(): @@ -130,6 +132,8 @@ def main(args, seed=None, fish=None): else: create_inverted_regions(world, player) create_owedges(world, player) + if world.logic[player] in ('owglitches', 'nologic'): + create_owg_connections(world, player) create_dungeon_regions(world, player) create_shops(world, player) create_doors(world, player) @@ -407,6 +411,8 @@ def copy_world(world): create_shops(ret, player) create_rooms(ret, player) create_dungeons(ret, player) + if world.logic[player] in ('owglitches', 'nologic'): + create_owg_connections(ret, player) copy_dynamic_regions_and_locations(world, ret) for player in range(1, world.players + 1): @@ -435,6 +441,8 @@ def copy_world(world): copied_region.is_dark_world = region.is_dark_world copied_region.dungeon = region.dungeon copied_region.locations = [copied_locations[(location.name, location.player)] for location in region.locations] + for location in copied_region.locations: + location.parent_region = copied_region for entrance in region.entrances: ret.get_entrance(entrance.name, entrance.player).connect(copied_region) @@ -442,7 +450,7 @@ def copy_world(world): for location in world.get_locations(): new_location = ret.get_location(location.name, location.player) if location.item is not None: - item = Item(location.item.name, location.item.advancement, location.item.priority, location.item.type, player = location.item.player) + item = Item(location.item.name, location.item.advancement, location.item.priority, location.item.type, player=location.item.player) new_location.item = item item.location = new_location item.world = ret @@ -526,6 +534,7 @@ def create_playthrough(world): # get locations containing progress items prog_locations = [location for location in world.get_filled_locations() if location.item.advancement] + optional_locations = ['Trench 1 Switch', 'Trench 2 Switch', 'Ice Block Drop'] state_cache = [None] collection_spheres = [] state = CollectionState(world) @@ -551,7 +560,7 @@ def create_playthrough(world): logging.getLogger('').debug(world.fish.translate("cli", "cli", "building.calculating.spheres"), len(collection_spheres), len(sphere), len(prog_locations)) if not sphere: logging.getLogger('').error(world.fish.translate("cli", "cli", "cannot.reach.items"), [world.fish.translate("cli","cli","cannot.reach.item") % (location.item.name, location.item.player, location.name, location.player) for location in sphere_candidates]) - if any([world.accessibility[location.item.player] != 'none' for location in sphere_candidates]): + if any([location.name not in optional_locations and world.accessibility[location.item.player] != 'none' for location in sphere_candidates]): raise RuntimeError(world.fish.translate("cli", "cli", "cannot.reach.progression")) else: old_world.spoiler.unreachables = sphere_candidates.copy() diff --git a/Mystery.py b/Mystery.py index b26e6ff9..45b8d5f3 100644 --- a/Mystery.py +++ b/Mystery.py @@ -3,34 +3,12 @@ import logging import random import urllib.request import urllib.parse -import re +import yaml from DungeonRandomizer import parse_cli from Main import main as DRMain from source.classes.BabelFish import BabelFish -def parse_yaml(txt): - def strip(s): - s = s.strip() - return '' if not s else s.strip('"') if s[0] == '"' else s.strip("'") if s[0] == "'" else s - ret = {} - indents = {len(txt) - len(txt.lstrip(' ')): ret} - for line in txt.splitlines(): - line = re.sub(r'#.*', '', line) - if not line: - continue - name, val = line.split(':', 1) - val = strip(val) - spaces = len(name) - len(name.lstrip(' ')) - name = strip(name) - if val: - indents[spaces][name] = val - else: - newdict = {} - indents[spaces][name] = newdict - indents[spaces+2] = newdict - return ret - def main(): parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255)) @@ -106,15 +84,11 @@ def main(): def get_weights(path): try: if urllib.parse.urlparse(path).scheme: - yaml = str(urllib.request.urlopen(path).read(), "utf-8") - else: - with open(path, 'rb') as f: - yaml = str(f.read(), "utf-8") + return yaml.load(urllib.request.urlopen(path), Loader=yaml.FullLoader) + with open(path, 'r', encoding='utf-8') as f: + return yaml.load(f, Loader=yaml.SafeLoader) except Exception as e: - print('Failed to read weights (%s)' % e) - return - - return parse_yaml(yaml) + raise Exception(f'Failed to read weights file: {e}') def roll_settings(weights): def get_choice(option, root=weights): @@ -209,11 +183,13 @@ def roll_settings(weights): ret.item_functionality = get_choice('item_functionality') - ret.shufflebosses = {'none': 'none', - 'simple': 'basic', - 'full': 'normal', - 'random': 'chaos' - }[get_choice('boss_shuffle')] + old_style_bosses = {'simple': 'basic', + 'full': 'normal', + 'random': 'chaos'} + boss_choice = get_choice('boss_shuffle') + if boss_choice in old_style_bosses.keys(): + boss_choice = old_style_bosses[boss_choice] + ret.shufflebosses = boss_choice ret.shuffleenemies = {'none': 'none', 'shuffled': 'shuffled', diff --git a/OverworldGlitchRules.py b/OverworldGlitchRules.py new file mode 100644 index 00000000..e369bd0f --- /dev/null +++ b/OverworldGlitchRules.py @@ -0,0 +1,284 @@ +""" +Helper functions to deliver entrance/exit/region sets to OWG rules. +""" + +from BaseClasses import Entrance + + +def get_sword_required_superbunny_mirror_regions(): + """ + Cave regions that superbunny can get through - but only with a sword. + """ + yield 'Spiral Cave (Top)' + +def get_boots_required_superbunny_mirror_regions(): + """ + Cave regions that superbunny can get through - but only with boots. + """ + yield 'Two Brothers House' + +def get_boots_required_superbunny_mirror_locations(): + """ + Cave locations that superbunny can access - but only with boots. + """ + yield 'Sahasrahla\'s Hut - Left' + yield 'Sahasrahla\'s Hut - Middle' + yield 'Sahasrahla\'s Hut - Right' + + +def get_invalid_mirror_bunny_entrances(): + """ + Entrances that can't be superbunny-mirrored into. + """ + yield 'Skull Woods Final Section' + yield 'Hype Cave' + yield 'Bonk Fairy (Dark)' + yield 'Thieves Town' + yield 'Dark World Hammer Peg Cave' + yield 'Brewery' + yield 'Hookshot Cave' + yield 'Dark Lake Hylia Ledge Fairy' + yield 'Dark Lake Hylia Ledge Spike Cave' + yield 'Palace of Darkness' + yield 'Misery Mire' + yield 'Turtle Rock' + 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' + yield 'Sanctuary Grave' + yield 'Hyrule Castle Secret Entrance Drop' + yield 'Skull Woods Second Section Hole' + yield 'Skull Woods First Section Hole (North)' + + +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_non_mandatory_exits(inverted): + """ + Entrances that can be reached with full equipment using overworld glitches and don't need to be an exit. + The following are still be mandatory exits: + + Open: + Turtle Rock Isolated Ledge Entrance + Skull Woods Second Section Door (West) (or Skull Woods Final Section) + + Inverted: + Two Brothers House (West) + Desert Palace Entrance (East) + """ + + yield 'Bumper Cave (Top)' + yield 'Death Mountain Return Cave (West)' + yield 'Hookshot Cave Back Entrance' + + if inverted: + yield 'Desert Palace Entrance (North)' + yield 'Desert Palace Entrance (West)' + yield 'Inverted Ganons Tower' + yield 'Hyrule Castle Entrance (West)' + yield 'Hyrule Castle Entrance (East)' + else: + yield 'Dark Death Mountain Ledge (West)' + yield 'Dark Death Mountain Ledge (East)' + yield 'Mimic Cave' + yield 'Desert Palace Entrance (East)' + + +def get_boots_clip_exits_lw(inverted = False): + """ + Special Light World region exits that require boots clips. + """ + + 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): + """ + 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') + yield ('DW Floating Island Clip Spot', 'Dark Death Mountain (East Bottom)', 'Death Mountain Floating Island (Dark World)') + + 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(): + """ + Out of bounds transitions using the mirror + """ + yield ('Dark Death Mountain Bunny Descent Mirror Spot', 'Dark Death Mountain (West Bottom)', 'Dark Death Mountain Bunny Descent Area') + yield ('West Dark World Bunny Descent', 'Dark Death Mountain Bunny Descent Area', 'West Dark World') + yield ('Dark Death Mountain (East Bottom) Jump', 'Dark Death Mountain Bunny Descent Area', 'Dark Death Mountain (East Bottom)') + yield ('Desert East Mirror Clip', 'Dark Desert', 'Desert Palace Lone Stairs') + + +def get_mirror_offset_spots_dw(): + """ + Mirror shenanigans placing a mirror portal with a broken camera + """ + yield ('Dark Death Mountain Offset Mirror', 'Dark Death Mountain (West Bottom)', 'East Dark World') + + +def get_mirror_offset_spots_lw(player): + """ + Mirror shenanigans placing a mirror portal with a broken camera + """ + yield ('Death Mountain Offset Mirror', 'Death Mountain', 'Light World') + yield ('Death Mountain Offset Mirror (Houlihan Exit)', 'Death Mountain', 'Hyrule Castle Ledge', lambda state: state.has_Mirror(player) and state.can_boots_clip_dw(player) and state.has_Pearl(player)) + + +def create_owg_connections(world, player): + """ + Add OWG transitions to player's world without logic + """ + create_no_logic_connections(player, world, get_boots_clip_exits_lw(world.mode[player] == 'inverted')) + create_no_logic_connections(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted')) + + # Glitched speed drops. + create_no_logic_connections(player, world, get_glitched_speed_drops_dw(world.mode[player] == 'inverted')) + + # Mirror clip spots. + if world.mode[player] != 'inverted': + create_no_logic_connections(player, world, get_mirror_clip_spots_dw()) + create_no_logic_connections(player, world, get_mirror_offset_spots_dw()) + else: + create_no_logic_connections(player, world, get_mirror_offset_spots_lw(player)) + + +def overworld_glitches_rules(world, player): + # Boots-accessible locations. + set_owg_rules(player, world, get_boots_clip_exits_lw(world.mode[player] == 'inverted'), lambda state: state.can_boots_clip_lw(player)) + set_owg_rules(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted'), lambda state: state.can_boots_clip_dw(player)) + + # Glitched speed drops. + set_owg_rules(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': + set_owg_rules(player, world, get_mirror_clip_spots_dw(), lambda state: state.has_Mirror(player)) + set_owg_rules(player, world, get_mirror_offset_spots_dw(), lambda state: state.has_Mirror(player) and state.can_boots_clip_lw(player)) + else: + set_owg_rules(player, world, get_mirror_offset_spots_lw(player), lambda state: state.has_Mirror(player) and state.can_boots_clip_dw(player)) + + # Regions that require the boots and some other stuff. + if world.mode[player] != 'inverted': + 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 Cave Entry', player), lambda state: state.has('Moon Pearl', player) or state.has_Boots(player)) + else: + add_alternate_rule(world.get_entrance('Waterfall of Wishing Cave Entry', player), lambda state: state.has('Moon Pearl', player)) + + world.get_entrance('Dark Desert Teleporter', player).access_rule = lambda state: (state.can_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_no_logic_connections(player, world, connections): + for entrance, parent_region, target_region, *rule_override in connections: + parent = world.get_region(parent_region, player) + target = world.get_region(target_region, player) + connection = Entrance(player, entrance, parent) + parent.exits.append(connection) + connection.connect(target) + + +def set_owg_rules(player, world, connections, default_rule): + for entrance, parent_region, target_region, *rule_override in connections: + connection = world.get_entrance(entrance, player) + rule = rule_override[0] if len(rule_override) > 0 else default_rule + connection.access_rule = rule diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 735d49b2..882fc70d 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -316,6 +316,8 @@ mandatory_connections = [('Flute Spot 1', 'West Death Mountain (Bottom)'), ('Death Mountain Entrance Rock', 'Death Mountain Entrance'), ('Death Mountain Entrance Drop', 'Mountain Entry Area'), ('Death Mountain Return Drop', 'Mountain Entry Area'), + ('Waterfall of Wishing Cave Entry', 'Waterfall of Wishing Cave'), + ('Zora Approach Water Drop', 'Zora Approach Area'), ('Bonk Rock Ledge Drop', 'Sanctuary Area'), ('Kings Grave Outer Rocks', 'Kings Grave Area'), ('Kings Grave Inner Rocks', 'Graveyard Area'), diff --git a/PotShuffle.py b/PotShuffle.py index 5fb99a86..0f4ca4d8 100644 --- a/PotShuffle.py +++ b/PotShuffle.py @@ -24,7 +24,7 @@ vanilla_pots = { 9: [Pot(12, 4, PotItem.OneRupee, 'PoD Shooter Room'), Pot(48, 4, PotItem.Heart, 'PoD Shooter Room'), Pot(12, 12, PotItem.Switch, 'PoD Shooter Room')], 10: [Pot(96, 8, PotItem.Heart, 'PoD Stalfos Basement'), Pot(104, 8, PotItem.Heart, 'PoD Stalfos Basement'), Pot(204, 11, PotItem.Switch, 'PoD Stalfos Basement'), Pot(100, 9, PotItem.Nothing, 'PoD Stalfos Basement'), Pot(156, 17, PotItem.Bomb, 'PoD Basement Ledge', PotFlags.SwitchLogicChange), Pot(160, 17, PotItem.FiveArrows, 'PoD Basement Ledge', PotFlags.SwitchLogicChange)], - 11: [Pot(202, 3, PotItem.Bomb, 'PoD Dark Pegs'), Pot(202, 12, PotItem.Bomb, 'PoD Dark Pegs')], + 11: [Pot(202, 3, PotItem.Bomb, 'PoD Dark Pegs Left'), Pot(202, 12, PotItem.Bomb, 'PoD Dark Pegs Left')], 17: [Pot(152, 19, PotItem.Nothing, 'Sewers Secret Room'), Pot(152, 15, PotItem.Nothing, 'Sewers Secret Room'), Pot(144, 15, PotItem.Heart, 'Sewers Secret Room'), Pot(160, 15, PotItem.Heart, 'Sewers Secret Room'), Pot(144, 19, PotItem.Heart, 'Sewers Secret Room'), Pot(160, 19, PotItem.Heart, 'Sewers Secret Room')], 21: [Pot(96, 4, PotItem.Bomb, 'TR Pipe Pit'), Pot(100, 4, PotItem.SmallMagic, 'TR Pipe Pit'), Pot(104, 4, PotItem.Heart, 'TR Pipe Pit'), Pot(108, 4, PotItem.SmallMagic, 'TR Pipe Pit'), Pot(112, 4, PotItem.FiveArrows, 'TR Pipe Pit'), @@ -68,8 +68,8 @@ vanilla_pots = { 57: [Pot(12, 20, PotItem.Heart, 'Skull Spike Corner'), Pot(48, 28, PotItem.FiveArrows, 'Skull Spike Corner'), Pot(100, 22, PotItem.SmallMagic, 'Skull Final Drop'), Pot(100, 26, PotItem.FiveArrows, 'Skull Final Drop')], 60: [Pot(24, 8, PotItem.SmallMagic, 'Hookshot Cave'), Pot(64, 12, PotItem.FiveRupees, 'Hookshot Cave'), Pot(20, 14, PotItem.OneRupee, 'Hookshot Cave'), Pot(20, 19, PotItem.Nothing, 'Hookshot Cave'), Pot(68, 18, PotItem.FiveRupees, 'Hookshot Cave'), Pot(96, 19, PotItem.Heart, 'Hookshot Cave'), Pot(64, 20, PotItem.FiveRupees, 'Hookshot Cave'), Pot(64, 26, PotItem.FiveRupees, 'Hookshot Cave')], - 61: [Pot(76, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(112, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(24, 22, PotItem.Heart, 'GT Crystal Circles'), Pot(40, 22, PotItem.FiveArrows, 'GT Crystal Circles'), - Pot(32, 24, PotItem.Heart, 'GT Crystal Circles'), Pot(20, 26, PotItem.FiveRupees, 'GT Crystal Circles'), Pot(36, 26, PotItem.BigMagic, 'GT Crystal Circles')], + 61: [Pot(76, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(112, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(24, 22, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(40, 22, PotItem.FiveArrows, 'GT Crystal Inner Circle'), + Pot(32, 24, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(20, 26, PotItem.FiveRupees, 'GT Crystal Inner Circle'), Pot(36, 26, PotItem.BigMagic, 'GT Crystal Inner Circle')], 62: [Pot(96, 6, PotItem.Bomb, 'Ice Stalfos Hint'), Pot(100, 6, PotItem.SmallMagic, 'Ice Stalfos Hint'), Pot(88, 10, PotItem.Heart, 'Ice Stalfos Hint'), Pot(92, 10, PotItem.SmallMagic, 'Ice Stalfos Hint')], 63: [Pot(12, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(20, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(12, 26, PotItem.Bomb, 'Ice Hammer Block'), Pot(20, 26, PotItem.Bomb, 'Ice Hammer Block'), Pot(12, 27, PotItem.Switch, 'Ice Hammer Block'), Pot(20, 27, PotItem.Heart, 'Ice Hammer Block'), Pot(28, 23, PotItem.Key, 'Ice Hammer Block')], @@ -166,9 +166,9 @@ vanilla_pots = { 150: [Pot(14, 18, PotItem.Nothing, 'GT Torch Cross'), Pot(32, 5, PotItem.Nothing, 'GT Torch Cross'), Pot(32, 17, PotItem.SmallMagic, 'GT Torch Cross'), Pot(32, 24, PotItem.SmallMagic, 'GT Torch Cross'), Pot(14, 24, PotItem.Nothing, 'GT Torch Cross'), Pot(76, 21, PotItem.Heart, 'GT Staredown'), Pot(112, 21, PotItem.BigMagic, 'GT Staredown')], 153: [Pot(40, 20, PotItem.SmallMagic, 'Eastern Darkness'), Pot(84, 20, PotItem.Heart, 'Eastern Darkness')], - 155: [Pot(48, 4, PotItem.SmallMagic, 'GT Double Switch Key Spot'), Pot(48, 12, PotItem.Key, 'GT Double Switch Key Spot'), Pot(28, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section'), Pot(32, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section')], + 155: [Pot(48, 4, PotItem.SmallMagic, 'GT Double Switch Pot Corners'), Pot(48, 12, PotItem.Key, 'GT Double Switch Pot Corners'), Pot(28, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section'), Pot(32, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section')], 156: [Pot(56, 8, PotItem.SmallMagic, 'GT Invisible Catwalk'), Pot(56, 9, PotItem.FiveArrows, 'GT Invisible Catwalk')], - 157: [Pot(76, 4, PotItem.Bomb, 'GT Crystal Conveyor'), Pot(84, 4, PotItem.SmallMagic, 'GT Crystal Conveyor'), Pot(32, 7, PotItem.Nothing, 'GT Compass Room'), Pot(40, 9, PotItem.Nothing, 'GT Compass Room')], + 157: [Pot(76, 4, PotItem.Bomb, 'GT Crystal Conveyor Left'), Pot(84, 4, PotItem.SmallMagic, 'GT Crystal Conveyor Left'), Pot(32, 7, PotItem.Nothing, 'GT Compass Room'), Pot(40, 9, PotItem.Nothing, 'GT Compass Room')], 159: [Pot(138, 20, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 19, PotItem.Heart, 'Ice Many Pots'), Pot(178, 19, PotItem.Heart, 'Ice Many Pots'), Pot(40, 21, PotItem.Switch, 'Ice Many Pots'), Pot(138, 21, PotItem.Key, 'Ice Many Pots'), Pot(20, 27, PotItem.Heart, 'Ice Many Pots'), Pot(138, 27, PotItem.Heart, 'Ice Many Pots'), Pot(178, 28, PotItem.Heart, 'Ice Many Pots'), Pot(178, 21, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 20, PotItem.Nothing, 'Ice Many Pots'), Pot(40, 27, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 27, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 26, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 28, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 26, PotItem.Nothing, 'Ice Many Pots'), @@ -211,8 +211,8 @@ vanilla_pots = { Pot(48, 28, PotItem.SmallMagic, 'Ice Refill')], 192: [Pot(48, 10, PotItem.Bomb, 'Tower Dark Pits'), Pot(12, 14, PotItem.FiveRupees, 'Tower Dark Pits'), Pot(12, 26, PotItem.Heart, 'Tower Dark Pits'), Pot(28, 27, PotItem.OneRupee, 'Tower Dark Pits')], 194: [Pot(180, 7, PotItem.Switch, 'Mire Hub Switch'), Pot(100, 46, PotItem.SmallMagic, 'Mire Hub Right'), Pot(68, 48, PotItem.OneRupee, 'Mire Hub'), Pot(64, 52, PotItem.FiveArrows, 'Mire Hub')], - 196: [Pot(84, 9, PotItem.Bomb, 'TR Crystal Maze'), Pot(24, 14, PotItem.Heart, 'TR Crystal Maze'), Pot(56, 17, PotItem.FiveRupees, 'TR Crystal Maze'), Pot(84, 17, PotItem.Bomb, 'TR Crystal Maze'), - Pot(12, 21, PotItem.FiveArrows, 'TR Crystal Maze'), Pot(76, 23, PotItem.OneRupee, 'TR Crystal Maze'), Pot(48, 25, PotItem.SmallMagic, 'TR Crystal Maze'), Pot(12, 26, PotItem.Heart, 'TR Crystal Maze')], + 196: [Pot(84, 9, PotItem.Bomb, 'TR Crystal Maze Interior'), Pot(24, 14, PotItem.Heart, 'TR Crystal Maze Interior'), Pot(56, 17, PotItem.FiveRupees, 'TR Crystal Maze Interior'), Pot(84, 17, PotItem.Bomb, 'TR Crystal Maze Interior'), + Pot(12, 21, PotItem.FiveArrows, 'TR Crystal Maze Interior'), Pot(76, 23, PotItem.OneRupee, 'TR Crystal Maze Interior'), Pot(48, 25, PotItem.SmallMagic, 'TR Crystal Maze Interior'), Pot(12, 26, PotItem.Heart, 'TR Crystal Maze Interior')], 198: [Pot(12, 7, PotItem.BigMagic, 'TR Hub'), Pot(12, 25, PotItem.Heart, 'TR Hub')], 199: [Pot(12, 10, PotItem.Heart, 'TR Torches'), Pot(12, 11, PotItem.BigMagic, 'TR Torches'), Pot(12, 22, PotItem.SmallMagic, 'TR Torches Ledge'), Pot(12, 28, PotItem.FiveArrows, 'TR Torches Ledge')], 201: [Pot(30, 22, PotItem.OneRupee, 'Eastern Lobby'), Pot(94, 22, PotItem.OneRupee, 'Eastern Lobby'), Pot(60, 22, PotItem.Switch, 'Eastern Lobby')], diff --git a/README.md b/README.md index 2616d0ce..5fede2be 100644 --- a/README.md +++ b/README.md @@ -26,15 +26,19 @@ This is a very new mode of LTTPR so the tools and info is very limited. There is All feedback and dev conversation happens in the #ow-rando channel on the [ALTTP Randomizer discord](https://discordapp.com/invite/alttprandomizer). -# Installation +# Installation from source -Install Python 3 +See these instructions. -Run ```pip install python-bps-continued```. On Linux, you should use pip3. On Windows, you may need to run ```python -m pip install python-bps-continued``` or ```py -m pip install python-bps-continued```. +https://github.com/codemann8/ALttPDoorRandomizer/blob/OverworldShuffle/docs/BUILDING.md -Clone this repository then run ```DungeonRandomizer.py```. +When installing platform specific dependencies, don't forget to run the appropriate command from the bottom of the page! Those will install missing pip dependencies. -Alternatively, run ```Gui.py``` for a simple graphical user interface. (WIP) +Running the MultiServer and MultiClient for multiworld should run resources/ci/common/local_install.py for those dependencies as well. + +To use the CLI, run ```DungeonRandomizer.py```. + +Alternatively, run ```Gui.py``` for a simple graphical user interface. # Settings diff --git a/RELEASENOTES.md b/RELEASENOTES.md index cec7a59c..7161a8cc 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,135 +1,31 @@ # New Features -## Shopsanity +## OWG Glitch Logic ---shopsanity added. This adds 32 shop locations (9 more in retro) to the general location pool. +Thanks to qadan, cheuer, & compiling -Multi-world supported. Thanks go to Pepper and CaitSith2 for figuring out several items related to this major feature. +# Bug Fixes and Notes. -Shop locations: -* Lake Hylia Cave Shop (3 items) -* Kakariko Village Shop (3 items) -* Potion Shop (3 new items) -* Paradox Cave Shop (3 items) -* Capacity Upgrade Fairy (2 items) -* Dark Lake Hylia Shop (3 items) -* Curiosity/Red Shield Shop (3 items) -* Dark Lumberjack Shop (3 items) -* Dark Potion Shop (3 items) -* Village of Outcast Hammer Peg Shop (3 items) -* Dark Death Mountain Shop (3 items) +* 0.4.0.1 + * Moved stonewall pre-opening to not happen in experimental +* 0.4.0.0 + * Mystery yaml parser updated to a package maintained version (Thanks StructuralMike) + * Bomb-logic and extend crystal switch logic (Thanks StructuralMike) + * Fixed logic for moved locations in playthrough (Thanks compiling) + * OWG Glitch logic added -Item Pool changes: To accommodate the new locations, new items are added to the pool, as follows: +# Known Issues -* 10 - Red Potion Refills -* 9 - Ten Bombs -* 4 - Small Hearts -* 4 - Blue Shields -* 1 - Red Shield -* 1 - Bee -* 1 - Ten Arrows -* 1 - Green Potion Refill -* 1 - Blue Potion Refill -* 1 - +5 Bomb Capacity -* 1 - +5 Arrow Capacity +* Shopsanity Issues + * Hints for items in shops can be misleading + * Capacity upgrades present in hard/expert item pools + * Forfeit in Multiworld not granting all shop items +* Potential keylocks in multi-entrance dungeons +* Incorrect vanilla key logic for Mire -1. Initially, 1 of each type of potion refill is shuffled to the shops. (the Capacity Fairy is excluded from this, see step 4). This ensures that potions can be bought somewhere. -2. The rest of the shop pool is shuffled with the rest of the item pool. -3. At this time, only Ten Bombs, Ten Arrows, Capacity upgrades, Small Hearts, and the non-progressive shields can appear outside of shops. Any other shop items are replaced with rupees of various amounts. This is because of one reason: potion refills and the Bee are indistinguishable from Bottles with that item in them. Receiving those items without a bottle or empty bottle is essentially a nothing item but looks like a bottle. Note, the non-progressive Shields interact fine with Progressive Shields (you never get downgraded) but are usually also a nothing item most of the time. -4. The Capacity Fairy cannot sell Potion Refills because the graphics are incompatible. 300 Rupees will replace any potion refill that ends up there. -5. For capacity upgrades, if any shop sells capacity upgrades, then it will sell all seven of that type. Otherwise, if plain bombs or arrows are sold somewhere, then the other six capacity upgrades will be purchasable first at those locations and then replaced by the underlying ammo. If no suitable spot is found, then no more capacity upgrades will be available for that seed. (There is always one somewhere in the pool.) -6. Any shop item that is originally sold by shops can be bought indefinitely, but only the first purchase counts toward total checks on the credits screen & item counter. All other items can be bought only once. +## Other Notes -All items in the general item pool may appear in shops. This includes normal progression items and dungeon items in the appropriate keysanity settings. - -#### Pricing Guide - -#### Sphere effects - -Design goal: Shops in early spheres may be discounted below the base price while shops in later spheres will likely exceed the base price range. This is an attempt to balance out the rupees in the item pool vs. the prices the shops charges. Poorer item pools like Triforce Hunt may have early shop prices be adjusted downward while rupee rich item pools will have prices increased, but later in the game. - -Detailed explanation: It is calculated how much money is available in the item pool and various rupee sources. If this amount exceeds the total amount of money needed for shop prices for items, then shops that are not in sphere 1 will raise their prices by a calculated amount to help balance out the money. Conversely, if the amount is below the money needed, then shops in sphere 1 will be discounted by a calculated amount to help ensure everything is purchase-able with minimal grinding. - -#### Base prices - -All prices range approx. from half the base price to twice the base price (as a max) in increments of 5, the exact price is chosen randomly within the range subject to adjustments by the sphere effects above. - -| Category | Items | Base Price | Typical Range | -| ----------------- | ------- |:----------:|:-------------:| -| Major Progression | Hammer, Hookshot, Mirror, Ocarina, Boots, Somaria, Fire Rod, Ice Rod | 250 | 125-500 -| | Moon Pearl | 200 | 100-400 -| | Lamp, Progressive Bows, Gloves, & Swords | 150 | 75-300 -| | Triforce Piece | 100 | 50-200 -| Medallions | Bombos, Ether, Quake | 100 | 50-200 -| Safety/Fetch | Cape, Mushroom, Shovel, Powder, Bug Net, Byrna, Progressive Armor & Shields, Half Magic | 50 | 25-100 -| Bottles | Empty Bottle or Bee Bottle | 50 | 25-100 -| | Green Goo or Good Bee | 60 | 30-120 -| | Red Goo or Fairy | 70 | 35-140 -| | Blue Goo | 80 | 40-160 -| Health | Heart Container | 40 | 20-80 -| | Sanctuary Heart | 50 | 25-100 -| | Piece of Heart | 10 | 5-20 -| Dungeon | Big Keys | 60 | 30-120 -| | Small Keys | 40 | 20-80 -| | Info Maps | 20 | 10-40 -| | Other Maps & Compasses | 10 | 5-20 -| Rupees | Green | Free | Free -| | Blue | 2 | 2-4 -| | Red | 10 | 5-20 -| | Fifty | 25 | 15-50 -| | One Hundred | 50 | 25-100 -| | Three Hundred | 150 | 75-300 -| Ammo | Three Bombs | 15 | 10-30 -| | Single Arrow | 3 | 3-6 -| Original Shop Items | Other Ammo, Refills, Non-Progressive Shields, Capacity Upgrades, Small Hearts, Retro Quiver, Universal Key | Original | .5 - 2 * Original - -#### Rupee Balancing Algorithm - -To prevent needed to grind for rupees to buy things in Sphere 1 and later, a money balancing algorithm has been developed to counteract the need for rupees. Basic logic: it assumes you buy nothing until you are blocked by a shop, a check that requires money, or blocked by Kiki. Then you must have enough to make all purchases. If not, any free rupees encountered may be swapped with higher denominations that have not been encountered. Ammo may also be swapped, if necessary. - -(Checks that require money: Bottle Merchant, King Zora, Digging Game, Chest Game, Blacksmith, anything blocked by Kiki e.g. all of Palace of Darkness when ER is vanilla) - -The Houlihan room is not in logic but the five dungeon rooms that provide rupees are. Pots with rupees, the arrow game, and all other gambling games are not counted for determining income. - -Currently this is applied to seeds without shopsanity on so early money is slightly more likely if progression is on a check that requires money even if Shopsanity is not turned on. - -#### Retro and Shopsanity - -9 new locations are added. - -The four "Take Any" caves are converted into "Take Both" caves. Those and the old man cave are included in the shuffle. The sword is returned to the pool, and the 4 heart containers and 4 blue potion refills are also added to the general item pool. All items found in the retro caves are free to take once. Potion refills will disappear after use. - -Arrow Capacity upgrades are now replaced by Rupees wherever it might end up. - -The Ten Arrows and 5 randomly selected Small Hearts or Blue Shields are replaced by the quiver item (represented by the Single Arrow in game.) 5 Red Potion refills are replaced by the Universal small key. It is assured that at least one shop sells Universal Small Keys. The quiver may thus not be found in shops. The quiver and small keys retain their original base price, but may be discounted. - -##### Misc Notes - -The location counter both experimental and the credits now reflects the total and current checks made. Original retro for example is 221 while shopsanity by itself is 248. Keydropshuffle+sanity+retro can reach up to 290. - -## In-Room Staircases/Ladders - -In intensity level 2 and higher the in-floor staircases/ladders that take you between tiles can now be shuffled with -any N/S connections. (those that appear to go up one floor are North connection and those that go down are South ones) - -Big thanks to Catobat for doing all the hard work. - -## Enemizer change - -The attic/maiden sequence is now active and required when Blind is the boss of Theives' Town even when bosses are shuffled. - -## Settings code - -File names have changed with a settings code instead of listing major settings chosen. Mystery games omit this for obvious reasons. Also found in the spoiler. - -Added to CLI only now. With more testing, this will be added to the GUI to be able to save use settings codes for generation. - -## Mystery fixes - -The Mystery.py file has been updated for those who like to use that for generating games. Supports keydropshuffle, -shopsanity, and other settings that have been added. - -## Triforce Hunt Options +### Triforce Hunt Options Thanks to deathFouton! @@ -142,87 +38,4 @@ Also, to the Mystery.py he added the following options: * triforce_pool_max * triforce_min_difference -See the example yaml file for demonstrated usage. - -## Experimental Item Counter - -New item counter modified to show total - -# Bug Fixes and Notes. - -* 0.3.1.10u - * Standard generation fixes -* 0.3.1.9-u - * Generation improvements for standard - * Removed link sprite from repo -* 0.3.1.8-u - * Fix for retro generation - * Shopsanity - rebalance pricing - later prices can be are higher -* 0.3.1.7-u - * TFH counter off in modes where it should be off - * Fixed Big Bomb logic for inverted (bad merge) - * Updated pip requirements for MultiClient - * Updated local_install.py and instructions (Thanks MikeTrethewey) -* 0.3.1.6-u - * Fix for inverted. AT or GT vanilla lobby in intensity 3 should not softlock on exit in non-ER modes. - * Backward compatibility for "chaos" enemizer flags. (Thanks krebel) - * Fix for potshuffle and swamp trench generation errors (Thanks StructuralMike) - * Fix for TFH playthrough (Thanks StructuralMike) - * Fix for Standard+Retro (Thanks StructuralMike) - * New options for TFH in CLI and Mystery (Thanks deathFouton) - * A few price adjustments for Shopsanity - * Fixed a subtle problem with Progressive Shields introduced by Shopsanity -* 0.3.1.5-u - * Ganon hints fixed for shops - * Added support for a settings file so SahasrahBot and the main website can use it easier. (Thanks Synack) - * Fix for Skull Pinball during re-generation attempts (thank compiling) - * Fix for multiworld progression balancing and shopsanity -* 0.3.1.4-u - * Fix for Blind when shuffled to TT and another dungeon - * Remove use of RaceRandom - * Minor update to GameType field -* 0.3.1.3-u - * Fix for the Rom field on the GUI -* 0.3.1.2-u - * Include base ER updates - * Goal sign should now indicate whether Aga 2 is required or not - * Inverted logic fixes - * Potion shop (powder) item now properly replaced with rupees - * Removed Arrow Capacity upgrades in retro (non-shopsanity) - * Intensity level 3 fixes courtesy of Catobat - * Scrolling issue in Desert Cannonball -* 0.3.1.1-u - * Potion shop crash in non-shopsanity -* 0.3.1.0-u - * Shopsanity introduced - * Blind sequence restored when Blind is in Theives Town in boss shuffle - * Settings code added to file name - * Minor fix to Standard generation -* 0.3.0.4-u - * QoL fixes from Mike - * Allow PoD Mimics 2 as a lobby in non-keysanity seeds (Thanks @Catobat) - * Fix for double-counting Hera key in keydropshuffle -* 0.3.0.3-u - * Disallowed Swamp Lobby in Hyrule Castle in Standard mode - * Prevent defeating Aga 1 before Zelda is delivered to the Sanctuary. (He can't take damage) - * Fix for Ice Jelly room when going backward and enemizer is on - * Fix for inverted - don't start as a bunny in Dark Sanctuary - * Fix for non-ER Inverted with Lobby shuffle. Aga Tower's exit works properly now. - * Fix for In-Room Stairs with Trap Doors - * Key logic fix - * Fix for door gen re-start - * More lenient keys in DR+Retro - * Fix for shufflepots option -* 0.3.0.2-u - * Introduced in-room staircases/ladders -* 0.3.0.1-u - * Problem with lobbies on re-rolls corrected - * Potential playthrough problem addressed -* 0.3.0.0-u - * Generation improvements. Basic >95% success. Crossed >80% success. - * Possible increased generation times as certain generation problem tries a partial re-roll - -# Known Issues - -* Potential keylocks in multi-entrance dungeons -* Incorrect vanilla key logic for Mire \ No newline at end of file +See the example yaml file for demonstrated usage. \ No newline at end of file diff --git a/Regions.py b/Regions.py index bd7dc908..5e54ebf8 100644 --- a/Regions.py +++ b/Regions.py @@ -33,7 +33,8 @@ def create_regions(world, player): create_lw_region(player, 'Potion Shop Water', None, ['Potion Shop WN', 'Potion Shop EN']), create_lw_region(player, 'Zora Warning Area', None, ['Zora Warning Water Drop', 'Zora Warning WC', 'Zora Warning NE']), create_lw_region(player, 'Zora Warning Water', None, ['Zora Warning WN']), - create_lw_region(player, 'Zora Approach Area', None, ['Waterfall of Wishing', 'Zora Approach SE', 'Zora Approach NE', 'Zora Whirlpool']), + create_lw_region(player, 'Zora Approach Area', None, ['Waterfall of Wishing Cave Entry', 'Zora Approach SE', 'Zora Approach NE', 'Zora Whirlpool']), + create_lw_region(player, 'Waterfall of Wishing Cave', None, ['Waterfall of Wishing', 'Zora Approach Water Drop']), create_lw_region(player, 'Zoras Domain', ['King Zora', 'Zora\'s Ledge'], ['Zoras Domain SW']), create_lw_region(player, 'Kakariko Area', ['Bottle Merchant'], ['Kakariko Well Drop', 'Kakariko Well Cave', 'Blinds Hideout', 'Elder House (West)', 'Elder House (East)', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Chicken House', 'Sick Kids House', 'Bush Covered House', 'Light World Bomb Hut', @@ -305,11 +306,11 @@ def create_regions(world, player): create_dw_region(player, 'Dark Death Mountain Floating Island', None, ['Floating Island Drop', 'Hookshot Cave Back Entrance', 'Floating Island Mirror Spot']), create_dw_region(player, 'Turtle Rock Area', None, ['Turtle Rock', 'TR Pegs Area Mirror Spot', 'Turtle Rock WN']), create_dw_region(player, 'Turtle Rock Ledge', None, ['Turtle Rock Ledge Drop']), - create_cave_region(player, 'Superbunny Cave', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], - ['Superbunny Cave Exit (Top)', 'Superbunny Cave Exit (Bottom)']), + create_cave_region(player, 'Superbunny Cave (Top)', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], ['Superbunny Cave Exit (Top)']), + create_cave_region(player, 'Superbunny Cave (Bottom)', 'a connector', None, ['Superbunny Cave Climb', 'Superbunny Cave Exit (Bottom)']), create_cave_region(player, 'Spike Cave', 'Spike Cave', ['Spike Cave']), create_cave_region(player, 'Hookshot Cave', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', 'Hookshot Cave - Bottom Left'], - ['Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)']), + ['Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)']) ] @@ -450,14 +451,26 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Desert Boss', 'Desert Palace', ['Desert Palace - Boss', 'Desert Palace - Prize'], ['Desert Boss SW']), # Hera - create_dungeon_region(player, 'Hera Lobby', 'Tower of Hera', ['Tower of Hera - Map Chest'], ['Hera Lobby Down Stairs', 'Hera Lobby Key Stairs', 'Hera Lobby Up Stairs', 'Hera Lobby S']), - create_dungeon_region(player, 'Hera Basement Cage', 'Tower of Hera', ['Tower of Hera - Basement Cage'], ['Hera Basement Cage Up Stairs']), + create_dungeon_region(player, 'Hera Lobby', 'Tower of Hera', None, ['Hera Lobby S', 'Hera Lobby to Crystal', 'Hera Lobby to Front Barrier - Blue']), + create_dungeon_region(player, 'Hera Lobby - Crystal', 'Tower of Hera', None, ['Hera Lobby Crystal Exit']), + create_dungeon_region(player, 'Hera Front', 'Tower of Hera', None, ['Hera Front to Crystal', 'Hera Front to Lobby Barrier - Blue', 'Hera Front to Down Stairs Barrier - Blue', 'Hera Front to Up Stairs Barrier - Orange', 'Hera Front to Back Barrier - Orange', 'Hera Front to Back Bypass']), + create_dungeon_region(player, 'Hera Front - Crystal', 'Tower of Hera', None, ['Hera Front Crystal Exit']), + create_dungeon_region(player, 'Hera Down Stairs Landing', 'Tower of Hera', None, ['Hera Lobby Down Stairs', 'Hera Down Stairs to Front Barrier - Blue', 'Hera Down Stairs Landing to Ranged Crystal']), + create_dungeon_region(player, 'Hera Down Stairs Landing - Ranged Crystal', 'Tower of Hera', None, ['Hera Down Stairs Landing Ranged Crystal Exit']), + create_dungeon_region(player, 'Hera Up Stairs Landing', 'Tower of Hera', None, ['Hera Up Stairs to Front Barrier - Orange', 'Hera Lobby Up Stairs', 'Hera Up Stairs Landing to Ranged Crystal']), + create_dungeon_region(player, 'Hera Up Stairs Landing - Ranged Crystal', 'Tower of Hera', None, ['Hera Up Stairs Landing Ranged Crystal Exit']), + create_dungeon_region(player, 'Hera Back', 'Tower of Hera', ['Tower of Hera - Map Chest'], ['Hera Back to Front Barrier - Orange', 'Hera Lobby Key Stairs', 'Hera Back to Ranged Crystal']), + create_dungeon_region(player, 'Hera Back - Ranged Crystal', 'Tower of Hera', None, ['Hera Back Ranged Crystal Exit']), + create_dungeon_region(player, 'Hera Basement Cage', 'Tower of Hera', ['Tower of Hera - Basement Cage'], ['Hera Basement Cage to Crystal', 'Hera Basement Cage Up Stairs']), + create_dungeon_region(player, 'Hera Basement Cage - Crystal', 'Tower of Hera', None, ['Hera Basement Cage Crystal Exit']), create_dungeon_region(player, 'Hera Tile Room', 'Tower of Hera', None, ['Hera Tile Room Up Stairs', 'Hera Tile Room EN']), - create_dungeon_region(player, 'Hera Tridorm', 'Tower of Hera', None, ['Hera Tridorm WN', 'Hera Tridorm SE']), + create_dungeon_region(player, 'Hera Tridorm', 'Tower of Hera', None, ['Hera Tridorm WN', 'Hera Tridorm SE', 'Hera Tridorm to Crystal']), + create_dungeon_region(player, 'Hera Tridorm - Crystal', 'Tower of Hera', None, ['Hera Tridorm Crystal Exit']), create_dungeon_region(player, 'Hera Torches', 'Tower of Hera', ['Tower of Hera - Big Key Chest'], ['Hera Torches NE']), - create_dungeon_region(player, 'Hera Beetles', 'Tower of Hera', None, ['Hera Beetles Down Stairs', 'Hera Beetles WS', 'Hera Beetles Holes']), - create_dungeon_region(player, 'Hera Startile Corner', 'Tower of Hera', None, ['Hera Startile Corner ES', 'Hera Startile Corner NW', 'Hera Startile Corner Holes']), - create_dungeon_region(player, 'Hera Startile Wide', 'Tower of Hera', None, ['Hera Startile Wide SW', 'Hera Startile Wide Up Stairs', 'Hera Startile Wide Holes']), + create_dungeon_region(player, 'Hera Beetles', 'Tower of Hera', None, ['Hera Beetles Down Stairs', 'Hera Beetles WS', 'Hera Beetles Holes Front', 'Hera Beetles Holes Landing']), + create_dungeon_region(player, 'Hera Startile Corner', 'Tower of Hera', None, ['Hera Startile Corner ES', 'Hera Startile Corner NW', 'Hera Startile Corner Holes Front', 'Hera Startile Corner Holes Landing']), + create_dungeon_region(player, 'Hera Startile Wide', 'Tower of Hera', None, ['Hera Startile Wide SW', 'Hera Startile Wide Up Stairs', 'Hera Startile Wide Holes', 'Hera Startile Wide to Crystal']), + create_dungeon_region(player, 'Hera Startile Wide - Crystal', 'Tower of Hera', None, ['Hera Startile Wide Crystal Exit']), create_dungeon_region(player, 'Hera 4F', 'Tower of Hera', ['Tower of Hera - Compass Chest'], ['Hera 4F Down Stairs', 'Hera 4F Up Stairs', 'Hera Big Chest Hook Path', 'Hera 4F Holes']), create_dungeon_region(player, 'Hera Big Chest Landing', 'Tower of Hera', ['Tower of Hera - Big Chest'], ['Hera Big Chest Landing Exit', 'Hera Big Chest Landing Holes']), create_dungeon_region(player, 'Hera 5F', 'Tower of Hera', None, ['Hera 5F Down Stairs', 'Hera 5F Up Stairs', 'Hera 5F Star Hole', 'Hera 5F Pothole Chain', 'Hera 5F Normal Holes']), @@ -491,13 +504,19 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'PoD Shooter Room', 'Palace of Darkness', ['Palace of Darkness - Shooter Room'], ['PoD Shooter Room Up Stairs']), create_dungeon_region(player, 'PoD Pit Room', 'Palace of Darkness', None, ['PoD Pit Room S', 'PoD Pit Room NW', 'PoD Pit Room Bomb Hole', 'PoD Pit Room Block Path N']), create_dungeon_region(player, 'PoD Pit Room Blocked', 'Palace of Darkness', None, ['PoD Pit Room NE', 'PoD Pit Room Freefall', 'PoD Pit Room Block Path S']), - create_dungeon_region(player, 'PoD Arena Main', 'Palace of Darkness', None, ['PoD Arena Main SW', 'PoD Arena Main Crystal Path', 'PoD Arena Main Orange Barrier', 'PoD Arena Bonk Path']), - create_dungeon_region(player, 'PoD Arena North', 'Palace of Darkness', None, ['PoD Arena Main NW', 'PoD Arena Main NE', 'PoD Arena North Drop Down']), - create_dungeon_region(player, 'PoD Arena Crystal', 'Palace of Darkness', None, ['PoD Arena Crystals E', 'PoD Arena Crystal Path']), - create_dungeon_region(player, 'PoD Arena Bridge', 'Palace of Darkness', ['Palace of Darkness - The Arena - Bridge'], ['PoD Arena Bridge SE', 'PoD Arena Bridge Drop Down']), - create_dungeon_region(player, 'PoD Arena Ledge', 'Palace of Darkness', ['Palace of Darkness - The Arena - Ledge'], ['PoD Arena Ledge ES']), + create_dungeon_region(player, 'PoD Arena Main', 'Palace of Darkness', None, ['PoD Arena Main SW', 'PoD Arena Main to Ranged Crystal', 'PoD Arena Main to Landing Barrier - Blue', 'PoD Arena Main to Landing Bypass', 'PoD Arena Main to Right Bypass']), + create_dungeon_region(player, 'PoD Arena Main - Ranged Crystal', 'Palace of Darkness', None, ['PoD Arena Main Ranged Crystal Exit']), + create_dungeon_region(player, 'PoD Arena North', 'Palace of Darkness', None, ['PoD Arena Main NW', 'PoD Arena Main NE', 'PoD Arena North Drop Down', 'PoD Arena North to Landing Barrier - Orange']), + create_dungeon_region(player, 'PoD Arena Bridge', 'Palace of Darkness', ['Palace of Darkness - The Arena - Bridge'], ['PoD Arena Bridge SE', 'PoD Arena Bridge Drop Down', 'PoD Arena Bridge to Ranged Crystal']), + create_dungeon_region(player, 'PoD Arena Bridge - Ranged Crystal', 'Palace of Darkness', None, ['PoD Arena Bridge Ranged Crystal Exit']), + create_dungeon_region(player, 'PoD Arena Landing', 'Palace of Darkness', None, ['PoD Arena Landing to Main Barrier - Blue', 'PoD Arena Landing to Right Barrier - Blue', 'PoD Arena Landing to North Barrier - Orange', 'PoD Arena Landing Bonk Path']), + create_dungeon_region(player, 'PoD Arena Right', 'Palace of Darkness', None, ['PoD Arena Crystals E', 'PoD Arena Right to Landing Barrier - Blue', 'PoD Arena Right to Ranged Crystal']), + create_dungeon_region(player, 'PoD Arena Right - Ranged Crystal', 'Palace of Darkness', None, ['PoD Arena Right Ranged Crystal Exit']), + create_dungeon_region(player, 'PoD Arena Ledge', 'Palace of Darkness', ['Palace of Darkness - The Arena - Ledge'], ['PoD Arena Ledge ES', 'PoD Arena Ledge to Ranged Crystal']), + create_dungeon_region(player, 'PoD Arena Ledge - Ranged Crystal', 'Palace of Darkness', None, ['PoD Arena Ledge Ranged Crystal Exit']), create_dungeon_region(player, 'PoD Sexy Statue', 'Palace of Darkness', None, ['PoD Sexy Statue W', 'PoD Sexy Statue NW']), - create_dungeon_region(player, 'PoD Map Balcony', 'Palace of Darkness', ['Palace of Darkness - Map Chest'], ['PoD Map Balcony WS', 'PoD Map Balcony South Stairs', 'PoD Map Balcony Drop Down']), + create_dungeon_region(player, 'PoD Map Balcony', 'Palace of Darkness', ['Palace of Darkness - Map Chest'], ['PoD Map Balcony to Ranged Crystal', 'PoD Map Balcony WS', 'PoD Map Balcony South Stairs', 'PoD Map Balcony Drop Down']), + create_dungeon_region(player, 'PoD Map Balcony - Ranged Crystal', 'Palace of Darkness', None, ['PoD Map Balcony Ranged Crystal Exit']), create_dungeon_region(player, 'PoD Conveyor', 'Palace of Darkness', None, ['PoD Conveyor North Stairs', 'PoD Conveyor SW']), create_dungeon_region(player, 'PoD Mimics 1', 'Palace of Darkness', None, ['PoD Mimics 1 NW', 'PoD Mimics 1 SW']), create_dungeon_region(player, 'PoD Jelly Hall', 'Palace of Darkness', None, ['PoD Jelly Hall NW', 'PoD Jelly Hall NE']), @@ -514,11 +533,17 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'PoD Dark Basement', 'Palace of Darkness', ['Palace of Darkness - Dark Basement - Left', 'Palace of Darkness - Dark Basement - Right'], ['PoD Dark Basement W Up Stairs', 'PoD Dark Basement E Up Stairs']), create_dungeon_region(player, 'PoD Harmless Hellway', 'Palace of Darkness', ['Palace of Darkness - Harmless Hellway'], ['PoD Harmless Hellway NE', 'PoD Harmless Hellway SE']), create_dungeon_region(player, 'PoD Mimics 2', 'Palace of Darkness', None, ['PoD Mimics 2 SW', 'PoD Mimics 2 NW']), - create_dungeon_region(player, 'PoD Bow Statue', 'Palace of Darkness', None, ['PoD Bow Statue SW', 'PoD Bow Statue Crystal Path']), - create_dungeon_region(player, 'PoD Bow Statue Moving Wall', 'Palace of Darkness', None, ['PoD Bow Statue Moving Wall Path', 'PoD Bow Statue Down Ladder', 'PoD Bow Statue Moving Wall Cane Path']), - create_dungeon_region(player, 'PoD Dark Pegs', 'Palace of Darkness', None, ['PoD Dark Pegs Hammer Path', 'PoD Dark Pegs WN']), - create_dungeon_region(player, 'PoD Dark Pegs Ladder', 'Palace of Darkness', None, ['PoD Dark Pegs Up Ladder', 'PoD Dark Pegs Ladder Hammer Path', 'PoD Dark Pegs Ladder Cane Path']), - create_dungeon_region(player, 'PoD Dark Pegs Switch', 'Palace of Darkness', None, ['PoD Dark Pegs Switch Path']), + create_dungeon_region(player, 'PoD Bow Statue Left', 'Palace of Darkness', None, ['PoD Bow Statue SW', 'PoD Bow Statue Left to Right Barrier - Orange', 'PoD Bow Statue Left to Right Bypass', 'PoD Bow Statue Left to Crystal']), + create_dungeon_region(player, 'PoD Bow Statue Left - Crystal', 'Palace of Darkness', None, ['PoD Bow Statue Left Crystal Exit']), + create_dungeon_region(player, 'PoD Bow Statue Right', 'Palace of Darkness', None, ['PoD Bow Statue Right to Left Barrier - Orange', 'PoD Bow Statue Right to Ranged Crystal', 'PoD Bow Statue Down Ladder']), + create_dungeon_region(player, 'PoD Bow Statue Right - Ranged Crystal', 'Palace of Darkness', None, ['PoD Bow Statue Ranged Crystal Exit']), + create_dungeon_region(player, 'PoD Dark Pegs Landing', 'Palace of Darkness', None, ['PoD Dark Pegs Up Ladder', 'PoD Dark Pegs Landing to Right', 'PoD Dark Pegs Landing to Ranged Crystal']), + create_dungeon_region(player, 'PoD Dark Pegs Right', 'Palace of Darkness', None, ['PoD Dark Pegs Right to Landing', 'PoD Dark Pegs Right to Middle Barrier - Orange', 'PoD Dark Pegs Right to Middle Bypass']), + create_dungeon_region(player, 'PoD Dark Pegs Middle', 'Palace of Darkness', None, ['PoD Dark Pegs Middle to Right Barrier - Orange', 'PoD Dark Pegs Middle to Left Barrier - Blue', 'PoD Dark Pegs Middle to Ranged Crystal', 'PoD Dark Pegs Middle to Left Bypass']), + create_dungeon_region(player, 'PoD Dark Pegs Left', 'Palace of Darkness', None, ['PoD Dark Pegs WN', 'PoD Dark Pegs Left to Middle Barrier - Blue', 'PoD Dark Pegs Left to Ranged Crystal']), + create_dungeon_region(player, 'PoD Dark Pegs Landing - Ranged Crystal', 'Palace of Darkness', None, ['PoD Dark Pegs Landing Ranged Crystal Exit']), + create_dungeon_region(player, 'PoD Dark Pegs Middle - Ranged Crystal', 'Palace of Darkness', None, ['PoD Dark Pegs Middle Ranged Crystal Exit']), + create_dungeon_region(player, 'PoD Dark Pegs Left - Ranged Crystal', 'Palace of Darkness', None, ['PoD Dark Pegs Left Ranged Crystal Exit']), create_dungeon_region(player, 'PoD Lonely Turtle', 'Palace of Darkness', None, ['PoD Lonely Turtle SW', 'PoD Lonely Turtle EN']), create_dungeon_region(player, 'PoD Turtle Party', 'Palace of Darkness', None, ['PoD Turtle Party ES', 'PoD Turtle Party NW']), create_dungeon_region(player, 'PoD Dark Alley', 'Palace of Darkness', None, ['PoD Dark Alley NE']), @@ -542,7 +567,10 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Swamp Donut Top', 'Swamp Palace', None, ['Swamp Donut Top N', 'Swamp Donut Top SE']), create_dungeon_region(player, 'Swamp Donut Bottom', 'Swamp Palace', None, ['Swamp Donut Bottom NE', 'Swamp Donut Bottom NW']), create_dungeon_region(player, 'Swamp Compass Donut', 'Swamp Palace', ['Swamp Palace - Compass Chest'], ['Swamp Compass Donut SW', 'Swamp Compass Donut Push Block']), - create_dungeon_region(player, 'Swamp Crystal Switch', 'Swamp Palace', ['Trench 2 Switch'], ['Swamp Crystal Switch EN', 'Swamp Crystal Switch SE']), + create_dungeon_region(player, 'Swamp Crystal Switch Outer', 'Swamp Palace', None, ['Swamp Crystal Switch EN', 'Swamp Crystal Switch SE', 'Swamp Crystal Switch Outer to Inner Barrier - Blue', 'Swamp Crystal Switch Outer to Ranged Crystal', 'Swamp Crystal Switch Outer to Inner Bypass']), + create_dungeon_region(player, 'Swamp Crystal Switch Outer - Ranged Crystal', 'Swamp Palace', None, ['Swamp Crystal Switch Outer Ranged Crystal Exit']), + create_dungeon_region(player, 'Swamp Crystal Switch Inner', 'Swamp Palace', ['Trench 2 Switch'], ['Swamp Crystal Switch Inner to Crystal', 'Swamp Crystal Switch Inner to Outer Bypass', 'Swamp Crystal Switch Inner to Outer Barrier - Blue']), + create_dungeon_region(player, 'Swamp Crystal Switch Inner - Crystal', 'Swamp Palace', None, ['Swamp Crystal Switch Inner Crystal Exit']), create_dungeon_region(player, 'Swamp Shortcut', 'Swamp Palace', None, ['Swamp Shortcut NE', 'Swamp Shortcut Blue Barrier']), create_dungeon_region(player, 'Swamp Trench 2 Pots', 'Swamp Palace', None, ['Swamp Trench 2 Pots ES', 'Swamp Trench 2 Pots Blue Barrier', 'Swamp Trench 2 Pots Dry', 'Swamp Trench 2 Pots Wet']), create_dungeon_region(player, 'Swamp Trench 2 Blocks', 'Swamp Palace', None, ['Swamp Trench 2 Blocks Pots', 'Swamp Trench 2 Blocks N']), @@ -588,7 +616,7 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Skull Big Key', 'Skull Woods', ['Skull Woods - Big Key Chest'], ['Skull Big Key SW', 'Skull Big Key EN']), create_dungeon_region(player, 'Skull Lone Pot', 'Skull Woods', None, ['Skull Lone Pot WN']), create_dungeon_region(player, 'Skull Small Hall', 'Skull Woods', None, ['Skull Small Hall ES', 'Skull Small Hall WS']), - create_dungeon_region(player, 'Skull Back Drop', 'Skull Woods', None, ['Skull Back Drop Star Path', ]), + create_dungeon_region(player, 'Skull Back Drop', 'Skull Woods', None, ['Skull Back Drop Star Path']), create_dungeon_region(player, 'Skull 2 West Lobby', 'Skull Woods', ['Skull Woods - West Lobby Pot Key'], ['Skull 2 West Lobby ES', 'Skull 2 West Lobby NW', 'Skull 2 West Lobby S']), create_dungeon_region(player, 'Skull X Room', 'Skull Woods', None, ['Skull X Room SW']), create_dungeon_region(player, 'Skull 3 Lobby', 'Skull Woods', None, ['Skull 3 Lobby NW', 'Skull 3 Lobby EN', 'Skull 3 Lobby SW']), @@ -649,7 +677,8 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Ice Big Key', 'Ice Palace', ['Ice Palace - Big Key Chest'], ['Ice Big Key Push Block', 'Ice Big Key Down Ladder']), create_dungeon_region(player, 'Ice Bomb Drop', 'Ice Palace', None, ['Ice Bomb Drop SE', 'Ice Bomb Drop Hole']), create_dungeon_region(player, 'Ice Stalfos Hint', 'Ice Palace', None, ['Ice Stalfos Hint SE']), - create_dungeon_region(player, 'Ice Conveyor', 'Ice Palace', ['Ice Palace - Conveyor Key Drop'], ['Ice Conveyor NE', 'Ice Conveyor SW']), + create_dungeon_region(player, 'Ice Conveyor', 'Ice Palace', ['Ice Palace - Conveyor Key Drop'], ['Ice Conveyor NE', 'Ice Conveyor to Crystal', 'Ice Conveyor SW']), + create_dungeon_region(player, 'Ice Conveyor - Crystal', 'Ice Palace', None, ['Ice Conveyor Crystal Exit']), create_dungeon_region(player, 'Ice Bomb Jump Ledge', 'Ice Palace', None, ['Ice Bomb Jump NW', 'Ice Bomb Jump Ledge Orange Barrier']), create_dungeon_region(player, 'Ice Bomb Jump Catwalk', 'Ice Palace', None, ['Ice Bomb Jump Catwalk Orange Barrier', 'Ice Bomb Jump EN']), create_dungeon_region(player, 'Ice Narrow Corridor', 'Ice Palace', None, ['Ice Narrow Corridor WN', 'Ice Narrow Corridor Down Stairs']), @@ -678,7 +707,8 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Ice Backwards Room', 'Ice Palace', None, ['Ice Backwards Room SE', 'Ice Backwards Room Down Stairs', 'Ice Backwards Room Hole']), create_dungeon_region(player, 'Ice Anti-Fairy', 'Ice Palace', None, ['Ice Anti-Fairy Up Stairs', 'Ice Anti-Fairy SE']), create_dungeon_region(player, 'Ice Switch Room', 'Ice Palace', None, ['Ice Switch Room NE', 'Ice Switch Room ES', 'Ice Switch Room SE']), - create_dungeon_region(player, 'Ice Refill', 'Ice Palace', None, ['Ice Refill WS']), + create_dungeon_region(player, 'Ice Refill', 'Ice Palace', None, ['Ice Refill WS', 'Ice Refill to Crystal']), + create_dungeon_region(player, 'Ice Refill - Crystal', 'Ice Palace', None, ['Ice Refill Crystal Exit']), create_dungeon_region(player, 'Ice Fairy', 'Ice Palace', None, ['Ice Fairy Warp']), create_dungeon_region(player, 'Ice Antechamber', 'Ice Palace', None, ['Ice Antechamber NE', 'Ice Antechamber Hole']), create_dungeon_region(player, 'Ice Boss', 'Ice Palace', ['Ice Palace - Boss', 'Ice Palace - Prize']), @@ -708,13 +738,14 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Mire Over Bridge', 'Misery Mire', None, ['Mire Over Bridge E', 'Mire Over Bridge W']), create_dungeon_region(player, 'Mire Right Bridge', 'Misery Mire', ['Misery Mire - Bridge Chest'], ['Mire Right Bridge SE']), create_dungeon_region(player, 'Mire Left Bridge', 'Misery Mire', None, ['Mire Left Bridge S', 'Mire Left Bridge Down Stairs', 'Mire Left Bridge Hook Path']), - create_dungeon_region(player, 'Mire Fishbone', 'Misery Mire', ['Misery Mire - Fishbone Pot Key'], ['Mire Fishbone E', 'Mire Fishbone Blue Barrier']), + create_dungeon_region(player, 'Mire Fishbone', 'Misery Mire', ['Misery Mire - Fishbone Pot Key'], ['Mire Fishbone E', 'Mire Fishbone Blue Barrier', 'Mire Fishbone Blue Barrier Bypass']), create_dungeon_region(player, 'Mire South Fish', 'Misery Mire', None, ['Mire South Fish Blue Barrier', 'Mire Fishbone SE']), create_dungeon_region(player, 'Mire Spike Barrier', 'Misery Mire', None, ['Mire Spike Barrier NE', 'Mire Spike Barrier SE', 'Mire Spike Barrier ES']), create_dungeon_region(player, 'Mire Square Rail', 'Misery Mire', None, ['Mire Square Rail WS', 'Mire Square Rail NW']), create_dungeon_region(player, 'Mire Lone Warp', 'Misery Mire', None, ['Mire Lone Warp SW', 'Mire Lone Warp Warp']), create_dungeon_region(player, 'Mire Wizzrobe Bypass', 'Misery Mire', None, ['Mire Wizzrobe Bypass WN', 'Mire Wizzrobe Bypass EN', 'Mire Wizzrobe Bypass NE']), - create_dungeon_region(player, 'Mire Conveyor Crystal', 'Misery Mire', ['Misery Mire - Conveyor Crystal Key Drop'], ['Mire Conveyor Crystal WS', 'Mire Conveyor Crystal ES', 'Mire Conveyor Crystal SE']), + create_dungeon_region(player, 'Mire Conveyor Crystal', 'Misery Mire', ['Misery Mire - Conveyor Crystal Key Drop'], ['Mire Conveyor to Crystal', 'Mire Conveyor Crystal WS', 'Mire Conveyor Crystal ES', 'Mire Conveyor Crystal SE']), + create_dungeon_region(player, 'Mire Conveyor - Crystal', 'Misery Mire', None, ['Mire Conveyor Crystal Exit']), create_dungeon_region(player, 'Mire Tile Room', 'Misery Mire', None, ['Mire Tile Room ES', 'Mire Tile Room NW', 'Mire Tile Room SW']), create_dungeon_region(player, 'Mire Compass Room', 'Misery Mire', None, ['Mire Compass Room SW', 'Mire Compass Room EN', 'Mire Compass Blue Barrier']), create_dungeon_region(player, 'Mire Compass Chest', 'Misery Mire', ['Misery Mire - Compass Chest'], ['Mire Compass Chest Exit']), @@ -729,7 +760,8 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Mire Dark Shooters', 'Misery Mire', None, ['Mire Dark Shooters Up Stairs', 'Mire Dark Shooters SW', 'Mire Dark Shooters SE']), create_dungeon_region(player, 'Mire Key Rupees', 'Misery Mire', None, ['Mire Key Rupees NE']), create_dungeon_region(player, 'Mire Block X', 'Misery Mire', None, ['Mire Block X NW', 'Mire Block X WS']), - create_dungeon_region(player, 'Mire Tall Dark and Roomy', 'Misery Mire', None, ['Mire Tall Dark and Roomy ES', 'Mire Tall Dark and Roomy WS', 'Mire Tall Dark and Roomy WN']), + create_dungeon_region(player, 'Mire Tall Dark and Roomy', 'Misery Mire', None, ['Mire Tall Dark and Roomy ES', 'Mire Tall Dark and Roomy WS', 'Mire Tall Dark and Roomy WN', 'Mire Tall Dark and Roomy to Ranged Crystal']), + create_dungeon_region(player, 'Mire Tall Dark and Roomy - Ranged Crystal', 'Misery Mire', None, ['Mire Tall Dark and Roomy Ranged Crystal Exit']), create_dungeon_region(player, 'Mire Crystal Right', 'Misery Mire', None, ['Mire Crystal Right ES', 'Mire Crystal Right Orange Barrier']), create_dungeon_region(player, 'Mire Crystal Mid', 'Misery Mire', None, ['Mire Crystal Mid Orange Barrier', 'Mire Crystal Mid Blue Barrier', 'Mire Crystal Mid NW']), create_dungeon_region(player, 'Mire Crystal Left', 'Misery Mire', None, ['Mire Crystal Left Blue Barrier', 'Mire Crystal Left WS']), @@ -751,13 +783,19 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'TR Tile Room', 'Turtle Rock', None, ['TR Tile Room SE', 'TR Tile Room NE']), create_dungeon_region(player, 'TR Refill', 'Turtle Rock', None, ['TR Refill SE']), create_dungeon_region(player, 'TR Pokey 1', 'Turtle Rock', ['Turtle Rock - Pokey 1 Key Drop'], ['TR Pokey 1 SW', 'TR Pokey 1 NW']), - create_dungeon_region(player, 'TR Chain Chomps', 'Turtle Rock', ['Turtle Rock - Chain Chomps'], ['TR Chain Chomps SW', 'TR Chain Chomps Down Stairs']), + create_dungeon_region(player, 'TR Chain Chomps Top', 'Turtle Rock', ['Turtle Rock - Chain Chomps'], ['TR Chain Chomps Top to Crystal', 'TR Chain Chomps Down Stairs', 'TR Chain Chomps Top to Bottom Barrier - Orange']), + create_dungeon_region(player, 'TR Chain Chomps Top - Crystal', 'Turtle Rock', None, ['TR Chain Chomps Top Crystal Exit']), + create_dungeon_region(player, 'TR Chain Chomps Bottom', 'Turtle Rock', None, ['TR Chain Chomps SW', 'TR Chain Chomps Bottom to Top Barrier - Orange', 'TR Chain Chomps Bottom to Ranged Crystal']), + create_dungeon_region(player, 'TR Chain Chomps Bottom - Ranged Crystal', 'Turtle Rock', None, ['TR Chain Chomps Bottom Ranged Crystal Exit']), create_dungeon_region(player, 'TR Pipe Pit', 'Turtle Rock', None, ['TR Pipe Pit Up Stairs', 'TR Pipe Pit WN']), create_dungeon_region(player, 'TR Pipe Ledge', 'Turtle Rock', None, ['TR Pipe Ledge WS', 'TR Pipe Ledge Drop Down']), create_dungeon_region(player, 'TR Lava Dual Pipes', 'Turtle Rock', None, ['TR Lava Dual Pipes EN', 'TR Lava Dual Pipes WN', 'TR Lava Dual Pipes SW']), create_dungeon_region(player, 'TR Lava Island', 'Turtle Rock', ['Turtle Rock - Big Key Chest'], ['TR Lava Island WS', 'TR Lava Island ES']), create_dungeon_region(player, 'TR Lava Escape', 'Turtle Rock', None, ['TR Lava Escape SE', 'TR Lava Escape NW']), - create_dungeon_region(player, 'TR Pokey 2', 'Turtle Rock', ['Turtle Rock - Pokey 2 Key Drop'], ['TR Pokey 2 EN', 'TR Pokey 2 ES']), + create_dungeon_region(player, 'TR Pokey 2 Top', 'Turtle Rock', None, ['TR Pokey 2 EN', 'TR Pokey 2 Top to Bottom Barrier - Blue', 'TR Pokey 2 Top to Crystal']), + create_dungeon_region(player, 'TR Pokey 2 Top - Crystal', 'Turtle Rock', None, ['TR Pokey 2 Top Crystal Exit']), + create_dungeon_region(player, 'TR Pokey 2 Bottom', 'Turtle Rock', ['Turtle Rock - Pokey 2 Key Drop'], ['TR Pokey 2 ES', 'TR Pokey 2 Bottom to Top Barrier - Blue', 'TR Pokey 2 Bottom to Ranged Crystal']), + create_dungeon_region(player, 'TR Pokey 2 Bottom - Ranged Crystal', 'Turtle Rock', None, ['TR Pokey 2 Bottom Ranged Crystal Exit']), create_dungeon_region(player, 'TR Twin Pokeys', 'Turtle Rock', None, ['TR Twin Pokeys NW', 'TR Twin Pokeys EN', 'TR Twin Pokeys SW']), create_dungeon_region(player, 'TR Hallway', 'Turtle Rock', None, ['TR Hallway NW', 'TR Hallway ES', 'TR Hallway WS']), create_dungeon_region(player, 'TR Dodgers', 'Turtle Rock', None, ['TR Dodgers WN', 'TR Dodgers SE', 'TR Dodgers NE']), @@ -768,14 +806,23 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'TR Dash Room', 'Turtle Rock', None, ['TR Dash Room SW', 'TR Dash Room ES', 'TR Dash Room NW']), create_dungeon_region(player, 'TR Tongue Pull', 'Turtle Rock', None, ['TR Tongue Pull WS', 'TR Tongue Pull NE']), create_dungeon_region(player, 'TR Rupees', 'Turtle Rock', None, ['TR Rupees SE']), - create_dungeon_region(player, 'TR Crystaroller', 'Turtle Rock', ['Turtle Rock - Crystaroller Room'], ['TR Crystaroller SW', 'TR Crystaroller Down Stairs']), + create_dungeon_region(player, 'TR Crystaroller Bottom' , 'Turtle Rock', None, ['TR Crystaroller Bottom to Middle Barrier - Orange', 'TR Crystaroller Bottom to Ranged Crystal', 'TR Crystaroller SW']), + create_dungeon_region(player, 'TR Crystaroller Middle', 'Turtle Rock', None, ['TR Crystaroller Middle to Bottom Barrier - Orange', 'TR Crystaroller Middle to Chest Barrier - Blue', 'TR Crystaroller Middle to Top Barrier - Orange', 'TR Crystaroller Middle to Ranged Crystal', 'TR Crystaroller Middle to Bottom Bypass']), + create_dungeon_region(player, 'TR Crystaroller Top', 'Turtle Rock', None, ['TR Crystaroller Top to Middle Barrier - Orange', 'TR Crystaroller Down Stairs', 'TR Crystaroller Top to Crystal']), + create_dungeon_region(player, 'TR Crystaroller Top - Crystal', 'Turtle Rock', None, ['TR Crystaroller Top Crystal Exit']), + create_dungeon_region(player, 'TR Crystaroller Chest', 'Turtle Rock', ['Turtle Rock - Crystaroller Room'], ['TR Crystaroller Chest to Middle Barrier - Blue']), + create_dungeon_region(player, 'TR Crystaroller Middle - Ranged Crystal', 'Turtle Rock', None, ['TR Crystaroller Middle Ranged Crystal Exit']), + create_dungeon_region(player, 'TR Crystaroller Bottom - Ranged Crystal', 'Turtle Rock', None, ['TR Crystaroller Bottom Ranged Crystal Exit']), create_dungeon_region(player, 'TR Dark Ride', 'Turtle Rock', None, ['TR Dark Ride Up Stairs', 'TR Dark Ride SW']), create_dungeon_region(player, 'TR Dash Bridge', 'Turtle Rock', None, ['TR Dash Bridge NW', 'TR Dash Bridge SW', 'TR Dash Bridge WS']), create_dungeon_region(player, 'TR 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'], - ['TR Eye Bridge SW', 'TR Eye Bridge NW']), - create_dungeon_region(player, 'TR Crystal Maze', 'Turtle Rock', None, ['TR Crystal Maze ES', 'TR Crystal Maze Forwards Path']), - create_dungeon_region(player, 'TR Crystal Maze End', 'Turtle Rock', None, ['TR Crystal Maze Blue Path', 'TR Crystal Maze Cane Path', 'TR Crystal Maze North Stairs']), + ['TR Eye Bridge SW', 'TR Eye Bridge NW']), + create_dungeon_region(player, 'TR Crystal Maze Start', 'Turtle Rock', None, ['TR Crystal Maze ES', 'TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze Start to Crystal']), + create_dungeon_region(player, 'TR Crystal Maze Start - Crystal', 'Turtle Rock', None, ['TR Crystal Maze Start Crystal Exit']), + create_dungeon_region(player, 'TR Crystal Maze Interior', 'Turtle Rock', None, ['TR Crystal Maze Interior to End Barrier - Blue', 'TR Crystal Maze Interior to Start Barrier - Blue', 'TR Crystal Maze Interior to Start Bypass', 'TR Crystal Maze Interior to End Bypass']), + create_dungeon_region(player, 'TR Crystal Maze End', 'Turtle Rock', None, ['TR Crystal Maze North Stairs', 'TR Crystal Maze End to Interior Barrier - Blue', 'TR Crystal Maze End to Ranged Crystal']), + create_dungeon_region(player, 'TR Crystal Maze End - Ranged Crystal', 'Turtle Rock', None, ['TR Crystal Maze End Ranged Crystal Exit']), create_dungeon_region(player, 'TR Final Abyss', 'Turtle Rock', None, ['TR Final Abyss South Stairs', 'TR Final Abyss NW']), create_dungeon_region(player, 'TR Boss', 'Turtle Rock', ['Turtle Rock - Boss', 'Turtle Rock - Prize'], ['TR Boss SW']), @@ -790,7 +837,12 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'GT Speed Torch', 'Ganon\'s Tower', None, ['GT Speed Torch WS', 'GT Speed Torch SE', 'GT Speed Torch North Path']), create_dungeon_region(player, 'GT Speed Torch Upper', 'Ganon\'s Tower', None, ['GT Speed Torch WN', 'GT Speed Torch NE', 'GT Speed Torch South Path']), create_dungeon_region(player, 'GT Pots n Blocks', 'Ganon\'s Tower', None, ['GT Pots n Blocks ES']), - create_dungeon_region(player, 'GT Crystal Conveyor', 'Ganon\'s Tower', None, ['GT Crystal Conveyor NE', 'GT Crystal Conveyor WN']), + create_dungeon_region(player, 'GT Crystal Conveyor', 'Ganon\'s Tower', None, ['GT Crystal Conveyor NE', 'GT Crystal Conveyor to Corner Barrier - Blue', 'GT Crystal Conveyor to Ranged Crystal']), + create_dungeon_region(player, 'GT Crystal Conveyor Corner', 'Ganon\'s Tower', None, ['GT Crystal Conveyor Corner to Barrier - Blue', 'GT Crystal Conveyor Corner to Barrier - Orange', 'GT Crystal Conveyor Corner to Ranged Crystal', 'GT Crystal Conveyor Corner to Left Bypass']), + create_dungeon_region(player, 'GT Crystal Conveyor Left', 'Ganon\'s Tower', None, ['GT Crystal Conveyor WN', 'GT Crystal Conveyor Left to Corner Barrier - Orange']), + create_dungeon_region(player, 'GT Crystal Conveyor - Ranged Crystal', 'Ganon\'s Tower', None, ['GT Crystal Conveyor Ranged Crystal Exit']), + create_dungeon_region(player, 'GT Crystal Conveyor Corner - Ranged Crystal', 'Ganon\'s Tower', None, ['GT Crystal Conveyor Corner Ranged Crystal Exit']), + create_dungeon_region(player, 'GT 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'], ['GT Compass Room EN', 'GT Compass Room Warp']), create_dungeon_region(player, 'GT Invisible Bridges', 'Ganon\'s Tower', None, ['GT Invisible Bridges WS']), @@ -798,15 +850,20 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'GT Conveyor Cross', 'Ganon\'s Tower', ['Ganons Tower - Conveyor Cross Pot Key'], ['GT Conveyor Cross EN', 'GT Conveyor Cross WN']), create_dungeon_region(player, 'GT Hookshot East Platform', 'Ganon\'s Tower', None, ['GT Hookshot EN', 'GT Hookshot East-North Path', 'GT Hookshot East-South Path']), create_dungeon_region(player, 'GT Hookshot North Platform', 'Ganon\'s Tower', None, ['GT Hookshot NW', 'GT Hookshot North-East Path', 'GT Hookshot North-South Path']), - create_dungeon_region(player, 'GT Hookshot South Platform', 'Ganon\'s Tower', None, ['GT Hookshot ES', 'GT Hookshot South-East Path', 'GT Hookshot South-North Path', 'GT Hookshot Platform Blue Barrier']), - create_dungeon_region(player, 'GT Hookshot South Entry', 'Ganon\'s Tower', None, ['GT Hookshot SW', 'GT Hookshot Entry Blue Barrier', 'GT Hookshot Entry Boomerang Path']), + create_dungeon_region(player, 'GT Hookshot South Platform', 'Ganon\'s Tower', None, ['GT Hookshot ES', 'GT Hookshot South-East Path', 'GT Hookshot South-North Path', 'GT Hookshot Platform Blue Barrier', 'GT Hookshot Platform Barrier Bypass']), + create_dungeon_region(player, 'GT Hookshot South Entry', 'Ganon\'s Tower', None, ['GT Hookshot SW', 'GT Hookshot Entry Blue Barrier', 'GT Hookshot South Entry to Ranged Crystal']), + create_dungeon_region(player, 'GT Hookshot South Entry - Ranged Crystal', 'Ganon\'s Tower', None, ['GT HookShot South Entry Ranged Crystal Exit']), create_dungeon_region(player, 'GT Map Room', 'Ganon\'s Tower', ['Ganons Tower - Map Chest'], ['GT Map Room WS']), - create_dungeon_region(player, 'GT Double Switch Entry', 'Ganon\'s Tower', None, ['GT Double Switch NW', 'GT Double Switch Orange Barrier', 'GT Double Switch Orange Barrier 2']), - create_dungeon_region(player, 'GT Double Switch Switches', 'Ganon\'s Tower', None, ['GT Double Switch Blue Path', 'GT Double Switch Orange Path']), - create_dungeon_region(player, 'GT Double Switch Transition', 'Ganon\'s Tower', None, ['GT Double Switch Transition Blue']), - create_dungeon_region(player, 'GT Double Switch Key Spot', 'Ganon\'s Tower', ['Ganons Tower - Double Switch Pot Key'], ['GT Double Switch Key Blue Path', 'GT Double Switch Key Orange Path']), - create_dungeon_region(player, 'GT Double Switch Exit', 'Ganon\'s Tower', None, ['GT Double Switch EN', 'GT Double Switch Blue Barrier']), - create_dungeon_region(player, 'GT Spike Crystals', 'Ganon\'s Tower', None, ['GT Spike Crystals WN', 'GT Spike Crystals Warp']), + + create_dungeon_region(player, 'GT Double Switch Entry', 'Ganon\'s Tower', None, ['GT Double Switch NW', 'GT Double Switch Entry to Left Barrier - Orange', 'GT Double Switch Entry to Pot Corners Barrier - Orange', 'GT Double Switch Entry to Ranged Switches']), + create_dungeon_region(player, 'GT Double Switch Entry - Ranged Switches', 'Ganon\'s Tower', None, ['GT Double Switch Entry Ranged Switches Exit']), + create_dungeon_region(player, 'GT Double Switch Left', 'Ganon\'s Tower', None, ['GT Double Switch Left to Entry Barrier - Orange', 'GT Double Switch Left to Entry Bypass', 'GT Double Switch Left to Pot Corners Bypass', 'GT Double Switch Left to Exit Bypass']), + create_dungeon_region(player, 'GT Double Switch Pot Corners', 'Ganon\'s Tower', ['Ganons Tower - Double Switch Pot Key'], ['GT Double Switch Pot Corners to Entry Barrier - Orange', 'GT Double Switch Pot Corners to Exit Barrier - Blue', 'GT Double Switch Pot Corners to Ranged Switches']), + create_dungeon_region(player, 'GT Double Switch Pot Corners - Ranged Switches', 'Ganon\'s Tower', None, ['GT Double Switch Pot Corners Ranged Switches Exit']), + create_dungeon_region(player, 'GT Double Switch Exit', 'Ganon\'s Tower', None, ['GT Double Switch EN', 'GT Double Switch Exit to Blue Barrier']), + + create_dungeon_region(player, 'GT Spike Crystal Left', 'Ganon\'s Tower', None, ['GT Spike Crystals WN', 'GT Spike Crystal Left to Right Barrier - Orange', 'GT Spike Crystal Left to Right Bypass']), + create_dungeon_region(player, 'GT Spike Crystal Right', 'Ganon\'s Tower', None, ['GT Spike Crystals Warp', 'GT Spike Crystal Right to Left Barrier - Orange']), create_dungeon_region(player, 'GT Warp Maze - Left Section', 'Ganon\'s Tower', None, ['GT Warp Maze - Left Section Warp']), create_dungeon_region(player, 'GT Warp Maze - Mid Section', 'Ganon\'s Tower', None, ['GT Warp Maze - Mid Section Left Warp', 'GT Warp Maze - Mid Section Right Warp']), create_dungeon_region(player, 'GT Warp Maze - Right Section', 'Ganon\'s Tower', None, ['GT Warp Maze - Right Section Warp']), @@ -857,7 +914,11 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'GT Mini Helmasaur Room', 'Ganon\'s Tower', ['Ganons Tower - Mini Helmasaur Room - Left', 'Ganons Tower - Mini Helmasaur Room - Right', 'Ganons Tower - Mini Helmasaur Key Drop'], ['GT Mini Helmasaur Room SE', 'GT Mini Helmasaur Room WN']), create_dungeon_region(player, 'GT Bomb Conveyor', 'Ganon\'s Tower', None, ['GT Bomb Conveyor EN', 'GT Bomb Conveyor SW']), - create_dungeon_region(player, 'GT Crystal Circles', 'Ganon\'s Tower', ['Ganons Tower - Pre-Moldorm Chest'], ['GT Crystal Circles NW', 'GT Crystal Circles SW']), + + create_dungeon_region(player, 'GT Crystal Circles', 'Ganon\'s Tower', None, ['GT Crystal Circles NW', 'GT Crystal Circles SW', 'GT Crystal Circles Barrier - Orange', 'GT Crystal Circles to Ranged Crystal']), + create_dungeon_region(player, 'GT Crystal Inner Circle', 'Ganon\'s Tower', ['Ganons Tower - Pre-Moldorm Chest'], ['GT Crystal Inner Circle Barrier - Orange']), + create_dungeon_region(player, 'GT Crystal Circles - Ranged Crystal', 'Ganon\'s Tower', None, ['GT Crystal Circles Ranged Crystal Exit']), + create_dungeon_region(player, 'GT Left Moldorm Ledge', 'Ganon\'s Tower', None, ['GT Left Moldorm Ledge Drop Down', 'GT Left Moldorm Ledge NW']), create_dungeon_region(player, 'GT Right Moldorm Ledge', 'Ganon\'s Tower', None, ['GT Right Moldorm Ledge Down Stairs', 'GT Right Moldorm Ledge Drop Down']), create_dungeon_region(player, 'GT Moldorm', 'Ganon\'s Tower', None, ['GT Moldorm Hole', 'GT Moldorm Gap']), @@ -870,40 +931,61 @@ def create_dungeon_regions(world, player): ] world.initialize_regions() - world.get_region('Hera Lobby', player).crystal_switch = True - world.get_region('Hera Basement Cage', player).crystal_switch = True + world.get_region('Hera Lobby - Crystal', player).crystal_switch = True + world.get_region('Hera Front - Crystal', player).crystal_switch = True + world.get_region('Hera Down Stairs Landing - Ranged Crystal', player).crystal_switch = True + world.get_region('Hera Up Stairs Landing - Ranged Crystal', player).crystal_switch = True + world.get_region('Hera Back - Ranged Crystal', player).crystal_switch = True + world.get_region('Hera Basement Cage - Crystal', player).crystal_switch = True world.get_region('Hera Tile Room', player).crystal_switch = True # INTERIOR not accessible (maybe with cane) - world.get_region('Hera Tridorm', player).crystal_switch = True - world.get_region('Hera Startile Wide', player).crystal_switch = True - world.get_region('PoD Arena Main', player).crystal_switch = True - world.get_region('PoD Arena Bridge', player).crystal_switch = True # RANGED Weapon Required + world.get_region('Hera Beetles', player).crystal_switch = True + world.get_region('Hera Tridorm - Crystal', player).crystal_switch = True + world.get_region('Hera Startile Wide - Crystal', player).crystal_switch = True + world.get_region('PoD Arena Main - Ranged Crystal', player).crystal_switch = True + world.get_region('PoD Arena Bridge - Ranged Crystal', player).crystal_switch = True + world.get_region('PoD Arena Right - Ranged Crystal', player).crystal_switch = True + world.get_region('PoD Arena Ledge - Ranged Crystal', player).crystal_switch = True + world.get_region('PoD Map Balcony - Ranged Crystal', player).crystal_switch = True world.get_region('PoD Sexy Statue', player).crystal_switch = True - world.get_region('PoD Bow Statue', player).crystal_switch = True - world.get_region('PoD Dark Pegs Switch', player).crystal_switch = True - world.get_region('PoD Dark Pegs', player).crystal_switch = True - world.get_region('Swamp Crystal Switch', player).crystal_switch = True + world.get_region('PoD Bow Statue Left - Crystal', player).crystal_switch = True + world.get_region('PoD Bow Statue Right - Ranged Crystal', player).crystal_switch = True + world.get_region('PoD Dark Pegs Landing - Ranged Crystal', player).crystal_switch = True + world.get_region('PoD Dark Pegs Right', player).crystal_switch = True + world.get_region('PoD Dark Pegs Middle - Ranged Crystal', player).crystal_switch = True + world.get_region('PoD Dark Pegs Left - Ranged Crystal', player).crystal_switch = True + world.get_region('Swamp Crystal Switch Inner - Crystal', player).crystal_switch = True + world.get_region('Swamp Crystal Switch Outer - Ranged Crystal', player).crystal_switch = True world.get_region('Thieves Spike Switch', player).crystal_switch = True world.get_region('Ice Bomb Drop', player).crystal_switch = True - world.get_region('Ice Conveyor', player).crystal_switch = True - world.get_region('Ice Refill', player).crystal_switch = True + world.get_region('Ice Conveyor - Crystal', player).crystal_switch = True + world.get_region('Ice Refill - Crystal', player).crystal_switch = True world.get_region('Mire Fishbone', player).crystal_switch = True - world.get_region('Mire Conveyor Crystal', player).crystal_switch = True - world.get_region('Mire Tall Dark and Roomy', player).crystal_switch = True + world.get_region('Mire Conveyor - Crystal', player).crystal_switch = True + world.get_region('Mire Tall Dark and Roomy - Ranged Crystal', player).crystal_switch = True world.get_region('Mire Crystal Top', player).crystal_switch = True world.get_region('Mire Falling Foes', player).crystal_switch = True - world.get_region('TR Chain Chomps', player).crystal_switch = True - world.get_region('TR Pokey 2', player).crystal_switch = True - world.get_region('TR Crystaroller', player).crystal_switch = True - world.get_region('TR Crystal Maze', player).crystal_switch = True - world.get_region('GT Crystal Conveyor', player).crystal_switch = True # INTERIOR not accessible + world.get_region('TR Chain Chomps Top - Crystal', player).crystal_switch = True + world.get_region('TR Chain Chomps Bottom - Ranged Crystal', player).crystal_switch = True + world.get_region('TR Pokey 2 Top - Crystal', player).crystal_switch = True + world.get_region('TR Pokey 2 Bottom - Ranged Crystal', player).crystal_switch = True + world.get_region('TR Crystaroller Top - Crystal', player).crystal_switch = True + world.get_region('TR Crystaroller Bottom - Ranged Crystal', player).crystal_switch = True + world.get_region('TR Crystaroller Middle - Ranged Crystal', player).crystal_switch = True + world.get_region('TR Crystal Maze Start - Crystal', player).crystal_switch = True + world.get_region('TR Crystal Maze Interior', player).crystal_switch = True + world.get_region('TR Crystal Maze End - Ranged Crystal', player).crystal_switch = True + world.get_region('GT Crystal Conveyor - Ranged Crystal', player).crystal_switch = True + world.get_region('GT Crystal Conveyor Corner - Ranged Crystal', player).crystal_switch = True world.get_region('GT Hookshot South Platform', player).crystal_switch = True - # Relevant to indicate north door can access c_switch - world.get_region('GT Double Switch Switches', player).crystal_switch = True - world.get_region('GT Spike Crystals', player).crystal_switch = True + world.get_region('GT Hookshot South Entry - Ranged Crystal', player).crystal_switch = True + world.get_region('GT Double Switch Left', player).crystal_switch = True + world.get_region('GT Double Switch Entry - Ranged Switches', player).crystal_switch = True + world.get_region('GT Double Switch Pot Corners - Ranged Switches', player).crystal_switch = True + world.get_region('GT Spike Crystal Left', player).crystal_switch = True world.get_region('GT Crystal Paths', player).crystal_switch = True world.get_region('GT Hidden Spikes', player).crystal_switch = True - world.get_region('GT Crystal Circles', player).crystal_switch = True - + world.get_region('GT Crystal Inner Circle', player).crystal_switch = True + world.get_region('GT Crystal Circles - Ranged Crystal', player).crystal_switch = True def create_menu_region(player, name, locations=None, exits=None): return _create_region(player, name, RegionType.Menu, 'Menu', locations, exits) diff --git a/Rom.py b/Rom.py index ce0ad5be..0068522f 100644 --- a/Rom.py +++ b/Rom.py @@ -723,13 +723,13 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_bytes(paired_door.address_a(world, player), paired_door.rom_data_a(world, player)) rom.write_bytes(paired_door.address_b(world, player), paired_door.rom_data_b(world, player)) if world.doorShuffle[player] != 'vanilla': - - for builder in world.dungeon_layouts[player].values(): - for stonewall in builder.pre_open_stonewalls: - if stonewall.name == 'Desert Wall Slide NW': - dr_flags |= DROptions.Open_Desert_Wall - elif stonewall.name == 'PoD Bow Statue Down Ladder': - dr_flags |= DROptions.Open_PoD_Wall + if not world.experimental[player]: + for builder in world.dungeon_layouts[player].values(): + for stonewall in builder.pre_open_stonewalls: + if stonewall.name == 'Desert Wall Slide NW': + dr_flags |= DROptions.Open_Desert_Wall + elif stonewall.name == 'PoD Bow Statue Down Ladder': + dr_flags |= DROptions.Open_PoD_Wall for name, pair in boss_indicator.items(): dungeon_id, boss_door = pair opposite_door = world.get_door(boss_door, player).dest @@ -1153,15 +1153,15 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_byte(0x180211, gametype) # Game type # assorted fixes - rom.write_byte(0x1800A2, 0x01) # remain in real dark world when dying in dark world dungeon before killing aga1 + rom.write_byte(0x1800A2, 0x01 if world.fix_fake_world else 0x00) # remain in real dark world when dying in dark world dungeon before killing aga1 rom.write_byte(0x180169, 0x01 if world.lock_aga_door_in_escape else 0x00) # Lock or unlock aga tower door during escape sequence. if world.mode[player] == 'inverted': rom.write_byte(0x180169, 0x02) # lock aga/ganon tower door with crystals in inverted rom.write_byte(0x180171, 0x01 if world.ganon_at_pyramid[player] else 0x00) # Enable respawning on pyramid after ganon death rom.write_byte(0x180173, 0x01) # Bob is enabled rom.write_byte(0x180168, 0x08) # Spike Cave Damage - rom.write_bytes(0x18016B, [0x04, 0x02, 0x01]) #Set spike cave and MM spike room Cape usage - rom.write_bytes(0x18016E, [0x04, 0x08, 0x10]) #Set spike cave and MM spike room Cape usage + rom.write_bytes(0x18016B, [0x04, 0x02, 0x01]) # Set spike cave and MM spike room Byrna usage + rom.write_bytes(0x18016E, [0x04, 0x08, 0x10]) # Set spike cave and MM spike room Cape usage rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest rom.write_byte(0x50599, 0x00) # disable below ganon chest rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest @@ -1313,6 +1313,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): if item.name != 'Piece of Heart' or equip[0x36B] == 0: equip[0x36C] = min(equip[0x36C] + 0x08, 0xA0) equip[0x36D] = min(equip[0x36D] + 0x08, 0xA0) + elif item.name == 'Pegasus Boots': + rom.write_byte(0x183015, 0x01) + ability_flags |= 0b00000100 else: raise RuntimeError(f'Unsupported item in starting equipment: {item.name}') diff --git a/Rules.py b/Rules.py index 53666aa2..ba52be93 100644 --- a/Rules.py +++ b/Rules.py @@ -1,8 +1,11 @@ +import collections import logging from collections import deque +import OverworldGlitchRules from BaseClasses import CollectionState, RegionType, DoorType, Entrance, CrystalBarrier from RoomData import DoorKind +from OverworldGlitchRules import overworld_glitches_rules def set_rules(world, player): @@ -28,10 +31,21 @@ def set_rules(world, player): else: raise NotImplementedError('Not implemented yet') + bomb_rules(world, player) + if world.logic[player] == 'noglitches': no_glitches_rules(world, player) elif world.logic[player] == 'minorglitches': logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.') + no_glitches_rules(world, player) + fake_flipper_rules(world, player) + elif world.logic[player] == 'owglitches': + logging.getLogger('').info('There is a chance OWG has bugged edge case rulesets, especially in inverted. Definitely file a report on GitHub if you see anything strange.') + # Initially setting no_glitches_rules to set the baseline rules for some + # entrances. The overworld_glitches_rules set is primarily additive. + no_glitches_rules(world, player) + fake_flipper_rules(world, player) + overworld_glitches_rules(world, player) else: raise NotImplementedError('Not implemented yet') @@ -46,6 +60,9 @@ def set_rules(world, player): if world.mode[player] != 'inverted': set_big_bomb_rules(world, player) + if world.logic[player] == 'owglitches' and world.shuffle[player] not in ('insanity', 'insanity_legacy'): + path_to_courtyard = mirrorless_path_to_castle_courtyard(world, player) + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.world.get_entrance('Dark Death Mountain Offset Mirror', player).can_reach(state) and all(rule(state) for rule in path_to_courtyard), 'or') else: set_inverted_big_bomb_rules(world, player) @@ -53,10 +70,30 @@ def set_rules(world, player): if not world.swamp_patch_required[player]: add_rule(world.get_entrance('Swamp Lobby Moat', player), lambda state: state.has_Mirror(player)) - if world.mode[player] != 'inverted': - set_bunny_rules(world, player) - else: - set_inverted_bunny_rules(world, player) + set_bunny_rules(world, player, world.mode[player] == 'inverted') + + if world.mode[player] != 'inverted' and world.logic[player] == 'owglitches': + add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.world.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or') + + +def mirrorless_path_to_castle_courtyard(world, player): + # If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch. + # Only considering the secret passage for now (in non-insanity shuffle). Basically, if it's Ganon you need the master sword. + start = world.get_entrance('Hyrule Castle Secret Entrance Drop', player) + if start.connected_region == world.get_region('Sewer Drop', player): + return [lambda state: False] # not handling dungeons for now + target = world.get_region('Hyrule Castle Courtyard', player) + seen = {start.parent_region, start.connected_region} + queue = collections.deque([(start.connected_region, [])]) + while queue: + (current, path) = queue.popleft() + for entrance in current.exits: + if entrance.connected_region not in seen: + new_path = path + [entrance.access_rule] + if entrance.connected_region == target: + return new_path + else: + queue.append((entrance.connected_region, new_path)) def set_rule(spot, rule): spot.access_rule = rule @@ -200,15 +237,16 @@ def global_rules(world, player): set_rule(world.get_entrance('Tower Altar NW', player), lambda state: state.has_sword(player)) set_defeat_dungeon_boss_rule(world.get_location('Agahnim 1', player)) - set_rule(world.get_entrance('PoD Arena Bonk Path', player), lambda state: state.has_Boots(player)) + + set_rule(world.get_entrance('PoD Arena Landing Bonk Path', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('PoD Mimics 1 NW', player), lambda state: state.can_shoot_arrows(player)) set_rule(world.get_entrance('PoD Mimics 2 NW', player), lambda state: state.can_shoot_arrows(player)) set_rule(world.get_entrance('PoD Bow Statue Down Ladder', player), lambda state: state.can_shoot_arrows(player)) set_rule(world.get_entrance('PoD Map Balcony Drop Down', player), lambda state: state.has('Hammer', player)) - set_rule(world.get_entrance('PoD Dark Pegs Hammer Path', player), lambda state: state.has('Hammer', player)) - set_rule(world.get_entrance('PoD Dark Pegs Ladder Hammer Path', player), lambda state: state.has('Hammer', player)) - set_rule(world.get_entrance('PoD Dark Pegs Ladder Cane Path', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('PoD Bow Statue Moving Wall Cane Path', player), lambda state: state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('PoD Dark Pegs Landing to Right', player), lambda state: state.has('Hammer', player)) + set_rule(world.get_entrance('PoD Dark Pegs Right to Landing', player), lambda state: state.has('Hammer', player)) + set_rule(world.get_entrance('PoD Turtle Party NW', player), lambda state: state.has('Hammer', player)) + set_rule(world.get_entrance('PoD Turtle Party ES', player), lambda state: state.has('Hammer', player)) set_defeat_dungeon_boss_rule(world.get_location('Palace of Darkness - Boss', player)) set_defeat_dungeon_boss_rule(world.get_location('Palace of Darkness - Prize', player)) @@ -255,6 +293,7 @@ def global_rules(world, player): set_defeat_dungeon_boss_rule(world.get_location('Skull Woods - Prize', player)) # blind can't have the small key? - not necessarily true anymore - but likely still + set_rule(world.get_location('Thieves\' Town - Big Chest', player), lambda state: state.has('Hammer', player)) for entrance in ['Thieves Basement Block Path', 'Thieves Blocked Entry Path', 'Thieves Conveyor Block Path', 'Thieves Conveyor Bridge Block Path']: set_rule(world.get_entrance(entrance, player), lambda state: state.can_lift_rocks(player)) @@ -294,6 +333,7 @@ def global_rules(world, player): set_rule(world.get_entrance('Mire Tile Room NW', player), lambda state: state.has_fire_source(player)) set_rule(world.get_entrance('Mire Attic Hint Hole', player), lambda state: state.has_fire_source(player)) set_rule(world.get_entrance('Mire Dark Shooters SW', player), lambda state: state.has('Cane of Somaria', player)) + set_defeat_dungeon_boss_rule(world.get_location('Misery Mire - Boss', player)) set_defeat_dungeon_boss_rule(world.get_location('Misery Mire - Prize', player)) @@ -310,7 +350,6 @@ def global_rules(world, player): set_rule(world.get_entrance('TR Big Chest Gap', player), lambda state: state.has('Cane of Somaria', player) or state.has_Boots(player)) set_rule(world.get_entrance('TR Dark Ride Up Stairs', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('TR Dark Ride SW', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('TR Crystal Maze Cane Path', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('TR Final Abyss South Stairs', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('TR Final Abyss NW', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) @@ -332,8 +371,8 @@ def global_rules(world, player): set_rule(world.get_entrance('GT Hookshot East-South Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player)) set_rule(world.get_entrance('GT Hookshot North-East Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player)) set_rule(world.get_entrance('GT Hookshot North-South Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player)) - set_rule(world.get_entrance('GT Hookshot Entry Boomerang Path', player), lambda state: state.has('Blue Boomerang', player) or state.has('Red Boomerang', player)) set_rule(world.get_entrance('GT Firesnake Room Hook Path', player), lambda state: state.has('Hookshot', player)) + # I am tempted to stick an invincibility rule for getting across falling bridge set_rule(world.get_entrance('GT Ice Armos NE', player), lambda state: world.get_region('GT Ice Armos', player).dungeon.bosses['bottom'].can_defeat(state)) set_rule(world.get_entrance('GT Ice Armos WS', player), lambda state: world.get_region('GT Ice Armos', player).dungeon.bosses['bottom'].can_defeat(state)) @@ -369,17 +408,93 @@ def global_rules(world, player): else: set_rule(world.get_entrance('Thieves Attic ES', player), lambda state: state.can_reach_orange(world.get_region('Thieves Attic', player), player)) - set_rule(world.get_entrance('PoD Arena Crystal Path', player), lambda state: state.can_reach_blue(world.get_region('PoD Arena Crystal', player), player)) + set_rule(world.get_entrance('Hera Lobby to Front Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('Hera Lobby', player), player)) + set_rule(world.get_entrance('Hera Front to Lobby Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('Hera Front', player), player)) + set_rule(world.get_entrance('Hera Front to Down Stairs Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('Hera Front', player), player)) + set_rule(world.get_entrance('Hera Down Stairs to Front Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('Hera Down Stairs Landing', player), player)) + set_rule(world.get_entrance('Hera Front to Up Stairs Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('Hera Front', player), player)) + set_rule(world.get_entrance('Hera Up Stairs to Front Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('Hera Up Stairs Landing', player), player)) + set_rule(world.get_entrance('Hera Front to Back Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('Hera Front', player), player)) + set_rule(world.get_entrance('Hera Back to Front Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('Hera Back', player), player)) + set_rule(world.get_location('Tower of Hera - Basement Cage', player), lambda state: state.can_reach_orange(world.get_region('Hera Basement Cage', player), player)) + set_rule(world.get_entrance('Hera Tridorm WN', player), lambda state: state.can_reach_blue(world.get_region('Hera Tridorm', player), player)) + set_rule(world.get_entrance('Hera Tridorm SE', player), lambda state: state.can_reach_orange(world.get_region('Hera Tridorm', player), player)) + set_rule(world.get_entrance('Hera Tile Room EN', player), lambda state: state.can_reach_blue(world.get_region('Hera Tile Room', player), player)) + + set_rule(world.get_entrance('Hera Lobby to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('Hera Front to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('Hera Down Stairs Landing to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('Hera Down Stairs Landing', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('Hera Up Stairs Landing to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('Hera Up Stairs Landing', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('Hera Back to Ranged Crystal', player), lambda state: False) # state.can_shoot_arrows(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or state.has_beam_sword(player) or (state.has('Hookshot', player) and state.has('Red Boomerang', player)) + set_rule(world.get_entrance('Hera Front to Back Bypass', player), lambda state: state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player) or state.has('Cane of Somaria', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player)) # or state.has_beam_sword(player) + set_rule(world.get_entrance('Hera Basement Cage to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('Hera Tridorm to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('Hera Startile Wide to Crystal', player), lambda state: state.can_hit_crystal(player)) + + set_rule(world.get_entrance('PoD Arena North to Landing Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('PoD Arena North', player), player)) + set_rule(world.get_entrance('PoD Arena Landing to North Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('PoD Arena Landing', player), player)) + set_rule(world.get_entrance('PoD Arena Main to Landing Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('PoD Arena Main', player), player)) + set_rule(world.get_entrance('PoD Arena Landing to Main Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('PoD Arena Landing', player), player)) + set_rule(world.get_entrance('PoD Arena Landing to Right Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('PoD Arena Landing', player), player)) + set_rule(world.get_entrance('PoD Arena Right to Landing Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('PoD Arena Right', player), player)) + set_rule(world.get_entrance('PoD Bow Statue Left to Right Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('PoD Bow Statue Left', player), player)) + set_rule(world.get_entrance('PoD Bow Statue Right to Left Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('PoD Bow Statue Right', player), player)) + set_rule(world.get_entrance('PoD Dark Pegs Right to Middle Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('PoD Dark Pegs Right', player), player)) + set_rule(world.get_entrance('PoD Dark Pegs Middle to Right Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('PoD Dark Pegs Middle', player), player)) + set_rule(world.get_entrance('PoD Dark Pegs Middle to Left Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('PoD Dark Pegs Middle', player), player)) + set_rule(world.get_entrance('PoD Dark Pegs Left to Middle Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('PoD Dark Pegs Left', player), player)) + + set_rule(world.get_entrance('PoD Arena Main to Ranged Crystal', player), lambda state: True) # Can always throw pots here + set_rule(world.get_entrance('PoD Arena Main to Landing Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('PoD Arena Main to Right Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('PoD Arena Bridge to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_beam_sword(player) + set_rule(world.get_entrance('PoD Arena Right to Ranged Crystal', player), lambda state: False) # (state.has('Cane of Somaria', player) and state.has_Boots(player)) + set_rule(world.get_entrance('PoD Arena Ledge to Ranged Crystal', player), lambda state: False) # state.has('Cane of Somaria', player) or state.has_beam_sword(player) + set_rule(world.get_entrance('PoD Map Balcony to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) # or state.has('Red Boomerang', player) + set_rule(world.get_entrance('PoD Bow Statue Left to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('PoD Bow Statue Right to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('PoD Bow Statue Left to Right Bypass', player), lambda state: state.has('Cane of Somaria', player)) # or state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has_beam_sword(player) or state.has('Red Boomrang', player) or state.has('Ice Rod', player) or state.has('Fire Rod', player) + set_rule(world.get_entrance('PoD Dark Pegs Landing to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) # or state.can_use_bombs(player) or state.has('Blue boomerang', player) or state.has('Red boomerang', player) + set_rule(world.get_entrance('PoD Dark Pegs Middle to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.can_use_bombs(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('PoD Dark Pegs Middle', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('PoD Dark Pegs Left to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_beam_sword(player) + set_rule(world.get_entrance('PoD Dark Pegs Right to Middle Bypass', player), lambda state: state.has('Blue Boomerang', player)) + set_rule(world.get_entrance('PoD Dark Pegs Middle to Left Bypass', player), lambda state: state.can_use_bombs(player)) + + set_rule(world.get_entrance('Swamp Crystal Switch Outer to Inner Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('Swamp Trench 2 Pots', player), player)) + set_rule(world.get_entrance('Swamp Crystal Switch Inner to Outer Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('Swamp Trench 2 Pots', player), player)) set_rule(world.get_entrance('Swamp Trench 2 Pots Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Swamp Trench 2 Pots', player), player)) set_rule(world.get_entrance('Swamp Shortcut Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Swamp Shortcut', player), player)) + set_rule(world.get_entrance('Swamp Barrier Ledge - Orange', player), lambda state: state.can_reach_orange(world.get_region('Swamp Barrier Ledge', player), player)) + set_rule(world.get_entrance('Swamp Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('Swamp Barrier', player), player)) + + set_rule(world.get_entrance('Swamp Crystal Switch Inner to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('Swamp Crystal Switch Outer to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_beam_sword(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('Swamp Crystal Switch Outer', player), player))) # It is the length of the sword, not the beam itself that allows this + set_rule(world.get_entrance('Swamp Crystal Switch Outer to Inner Bypass', player), lambda state: state.world.can_take_damage or state.has('Cape', player) or state.has('Cane of Byrna', player)) + set_rule(world.get_entrance('Swamp Crystal Switch Inner to Outer Bypass', player), lambda state: state.world.can_take_damage or state.has('Cape', player) or state.has('Cane of Byrna', player)) + set_rule(world.get_entrance('Thieves Hellway Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Thieves Hellway', player), player)) + set_rule(world.get_entrance('Thieves Hellway Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Thieves Hellway', player), player)) set_rule(world.get_entrance('Thieves Hellway Crystal Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Thieves Hellway N Crystal', player), player)) + set_rule(world.get_entrance('Thieves Hellway Crystal Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Thieves Hellway S Crystal', player), player)) set_rule(world.get_entrance('Thieves Triple Bypass SE', player), lambda state: state.can_reach_blue(world.get_region('Thieves Triple Bypass', player), player)) set_rule(world.get_entrance('Thieves Triple Bypass WN', player), lambda state: state.can_reach_blue(world.get_region('Thieves Triple Bypass', player), player)) set_rule(world.get_entrance('Thieves Triple Bypass EN', player), lambda state: state.can_reach_blue(world.get_region('Thieves Triple Bypass', player), player)) + set_rule(world.get_entrance('Ice Crystal Right Blue Hole', player), lambda state: state.can_reach_blue(world.get_region('Ice Crystal Right', player), player)) + set_rule(world.get_entrance('Ice Crystal Right Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Ice Crystal Right', player), player)) set_rule(world.get_entrance('Ice Crystal Left Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Ice Crystal Left', player), player)) + set_rule(world.get_entrance('Ice Crystal Left Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Ice Crystal Left', player), player)) set_rule(world.get_entrance('Ice Backwards Room Hole', player), lambda state: state.can_reach_blue(world.get_region('Ice Backwards Room', player), player)) + set_rule(world.get_entrance('Ice Bomb Jump Ledge Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Ice Bomb Jump Ledge', player), player)) + set_rule(world.get_entrance('Ice Bomb Jump Catwalk Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Ice Bomb Jump Catwalk', player), player)) + + set_rule(world.get_entrance('Ice Conveyor to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('Ice Refill to Crystal', player), lambda state: state.can_hit_crystal(player) or state.can_reach_blue(world.get_region('Ice Refill', player), player)) + + set_rule(world.get_entrance('Mire Crystal Right Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Mire Crystal Right', player), player)) + set_rule(world.get_entrance('Mire Crystal Mid Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Mire Crystal Mid', player), player)) + set_rule(world.get_entrance('Mire Firesnake Skip Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Mire Firesnake Skip', player), player)) + set_rule(world.get_entrance('Mire Antechamber Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Mire Antechamber', player), player)) set_rule(world.get_entrance('Mire Hub Upper Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Mire Hub', player), player)) set_rule(world.get_entrance('Mire Hub Lower Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Mire Hub', player), player)) set_rule(world.get_entrance('Mire Hub Right Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Mire Hub Right', player), player)) @@ -394,37 +509,183 @@ def global_rules(world, player): set_rule(world.get_entrance('Mire Compass Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Mire Compass Room', player), player)) set_rule(world.get_entrance('Mire Crystal Mid Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Mire Crystal Mid', player), player)) set_rule(world.get_entrance('Mire Crystal Left Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Mire Crystal Left', player), player)) - set_rule(world.get_entrance('TR Crystal Maze Blue Path', player), lambda state: state.can_reach_blue(world.get_region('TR Crystal Maze End', player), player)) - set_rule(world.get_entrance('GT Hookshot Entry Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('GT Hookshot South Entry', player), player)) - set_rule(world.get_entrance('GT Double Switch Key Blue Path', player), lambda state: state.can_reach_blue(world.get_region('GT Double Switch Key Spot', player), player)) - set_rule(world.get_entrance('GT Double Switch Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('GT Double Switch Switches', player), player)) - set_rule(world.get_entrance('GT Double Switch Transition Blue', player), lambda state: state.can_reach_blue(world.get_region('GT Double Switch Transition', player), player)) - set_rule(world.get_entrance('Swamp Barrier Ledge - Orange', player), lambda state: state.can_reach_orange(world.get_region('Swamp Barrier Ledge', player), player)) - set_rule(world.get_entrance('Swamp Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('Swamp Barrier', player), player)) - set_rule(world.get_entrance('Thieves Hellway Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Thieves Hellway', player), player)) - set_rule(world.get_entrance('Thieves Hellway Crystal Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Thieves Hellway S Crystal', player), player)) - set_rule(world.get_entrance('Ice Bomb Jump Ledge Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Ice Bomb Jump Ledge', player), player)) - set_rule(world.get_entrance('Ice Bomb Jump Catwalk Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Ice Bomb Jump Catwalk', player), player)) - set_rule(world.get_entrance('Ice Crystal Right Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Ice Crystal Right', player), player)) - set_rule(world.get_entrance('Ice Crystal Left Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Ice Crystal Left', player), player)) - set_rule(world.get_entrance('Mire Crystal Right Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Mire Crystal Right', player), player)) - set_rule(world.get_entrance('Mire Crystal Mid Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Mire Crystal Mid', player), player)) - set_rule(world.get_entrance('Mire Firesnake Skip Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Mire Firesnake Skip', player), player)) - set_rule(world.get_entrance('Mire Antechamber Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Mire Antechamber', player), player)) - set_rule(world.get_entrance('GT Double Switch Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('GT Double Switch Entry', player), player)) - set_rule(world.get_entrance('GT Double Switch Orange Barrier 2', player), lambda state: state.can_reach_orange(world.get_region('GT Double Switch Entry', player), player)) - set_rule(world.get_entrance('GT Double Switch Orange Path', player), lambda state: state.can_reach_orange(world.get_region('GT Double Switch Switches', player), player)) - set_rule(world.get_entrance('GT Double Switch Key Orange Path', player), lambda state: state.can_reach_orange(world.get_region('GT Double Switch Key Spot', player), player)) + set_rule(world.get_entrance('Mire Conveyor to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('Mire Tall Dark and Roomy to Ranged Crystal', player), lambda state: True) # Can always throw pots + set_rule(world.get_entrance('Mire Fishbone Blue Barrier Bypass', player), lambda state: False) # (state.world.can_take_damage or state.has('Cape', player) or state.has('Cane of Byrna', player)) and state.can_tastate.can_use_bombs(player) // Easy to do but obscure. Should it be in logic? + + set_rule(world.get_location('Turtle Rock - Chain Chomps', player), lambda state: state.can_reach('TR Chain Chomps Top', 'Region', player) and state.can_hit_crystal_through_barrier(player)) + set_rule(world.get_entrance('TR Chain Chomps Top to Bottom Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('TR Chain Chomps Top', player), player)) + set_rule(world.get_entrance('TR Chain Chomps Bottom to Top Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('TR Chain Chomps Bottom', player), player)) + set_rule(world.get_entrance('TR Pokey 2 Top to Bottom Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('TR Pokey 2 Top', player), player)) + set_rule(world.get_entrance('TR Pokey 2 Bottom to Top Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('TR Pokey 2 Bottom', player), player)) + set_rule(world.get_entrance('TR Crystaroller Bottom to Middle Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('TR Crystaroller Bottom', player), player)) + set_rule(world.get_entrance('TR Crystaroller Middle to Bottom Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('TR Crystaroller Middle', player), player)) + set_rule(world.get_entrance('TR Crystaroller Middle to Chest Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('TR Crystaroller Middle', player), player)) + set_rule(world.get_entrance('TR Crystaroller Middle to Top Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('TR Crystaroller Middle', player), player)) + set_rule(world.get_entrance('TR Crystaroller Top to Middle Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('TR Crystaroller Top', player), player)) + set_rule(world.get_entrance('TR Crystaroller Chest to Middle Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('TR Crystaroller Chest', player), player)) + set_rule(world.get_entrance('TR Crystal Maze Start to Interior Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('TR Crystal Maze Start', player), player)) + set_rule(world.get_entrance('TR Crystal Maze Interior to End Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('TR Crystal Maze Interior', player), player)) + set_rule(world.get_entrance('TR Crystal Maze Interior to Start Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('TR Crystal Maze Interior', player), player)) + set_rule(world.get_entrance('TR Crystal Maze End to Interior Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('TR Crystal Maze End', player), player)) + + set_rule(world.get_entrance('TR Chain Chomps Top to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('TR Pokey 2 Top to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('TR Crystaroller Top to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('TR Crystal Maze Start to Crystal', player), lambda state: state.can_hit_crystal(player)) + set_rule(world.get_entrance('TR Chain Chomps Bottom to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Chain Chomps Bottom', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('TR Pokey 2 Bottom to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('TR Pokey 2 Bottom', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('TR Crystaroller Bottom to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Crystaroller Bottom', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('TR Crystaroller Middle to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Crystaroller Middle', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('TR Crystaroller Middle to Bottom Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Blue Boomerang', player)) + set_rule(world.get_entrance('TR Crystal Maze End to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) # or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) // These work by clipping the rang through the two stone blocks, which works sometimes. + set_rule(world.get_entrance('TR Crystal Maze Interior to End Bypass', player), lambda state: state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # Beam sword does NOT work + set_rule(world.get_entrance('TR Crystal Maze Interior to Start Bypass', player), lambda state: True) # Can always grab a pot from the interior and walk it to the start region and throw it there + + set_rule(world.get_entrance('GT Hookshot Platform Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('GT Hookshot South Platform', player), player)) + set_rule(world.get_entrance('GT Hookshot Entry Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('GT Hookshot South Entry', player), player)) + set_rule(world.get_entrance('GT Double Switch Entry to Pot Corners Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Double Switch Entry', player), player)) + set_rule(world.get_entrance('GT Double Switch Entry to Left Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Double Switch Entry', player), player)) + set_rule(world.get_entrance('GT Double Switch Left to Entry Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Double Switch Left', player), player)) + set_rule(world.get_entrance('GT Double Switch Pot Corners to Entry Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Double Switch Pot Corners', player), player)) + set_rule(world.get_entrance('GT Double Switch Pot Corners to Exit Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('GT Double Switch Pot Corners', player), player)) + set_rule(world.get_entrance('GT Double Switch Exit to Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('GT Double Switch Exit', player), player)) + set_rule(world.get_entrance('GT Spike Crystal Left to Right Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Spike Crystal Left', player), player)) + set_rule(world.get_entrance('GT Spike Crystal Right to Left Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Spike Crystal Right', player), player)) + set_rule(world.get_entrance('GT Crystal Conveyor to Corner Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('GT Crystal Conveyor', player), player)) + set_rule(world.get_entrance('GT Crystal Conveyor Corner to Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('GT Crystal Conveyor Corner', player), player)) + set_rule(world.get_entrance('GT Crystal Conveyor Corner to Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Crystal Conveyor Corner', player), player)) + set_rule(world.get_entrance('GT Crystal Conveyor Left to Corner Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Crystal Conveyor Left', player), player)) + set_rule(world.get_entrance('GT Crystal Circles Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Crystal Circles', player), player)) + + set_rule(world.get_entrance('GT Hookshot Platform Barrier Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) or state.has('Cane of Somaria', player)) # or state.has_Boots(player) /// There is a super precise trick where you can throw a pot and climp into the blue barrier, then sprint out of them. + set_rule(world.get_entrance('GT Hookshot South Entry to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) or state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('GT Double Switch Entry to Ranged Switches', player), lambda state: False) # state.has('Cane of Somaria', player) + set_rule(world.get_entrance('GT Double Switch Left to Entry Bypass', player), lambda state: True) # Can always use pots + set_rule(world.get_entrance('GT Double Switch Left to Pot Corners Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player) or state.has('Red Boomerang', player)) # or (state.has('Blue Boomerang', player) and state.has('Hookshot', player)) or (state.has('Ice Rod', player) and state.has('Hookshot', player)) or state.has('Hookshot', player) /// You can do this with just a pot and a hookshot + set_rule(world.get_entrance('GT Double Switch Left to Exit Bypass', player), lambda state: False) # state.can_use_bombs(player) or (state.has('Cane of Somaria', player) and (state.has('Red Boomerang', player) or (state.has('Hookshot', player) and state.has('Blue Boomerang', player)) or (state.has('Hookshot', player) and state.has('Ice Rod', player)))) + set_rule(world.get_entrance('GT Double Switch Pot Corners to Ranged Switches', player), lambda state: False) # state.can_use_bombs(player) or state.has('Cane of Somaria', player) or (state.has('Cane of Somaria', player) and state.has_Boots(player)) /// There's two ways to interact with the switch. Somaria bounce at the top corner, or timed throws at the bottom corner. + set_rule(world.get_entrance('GT Spike Crystal Left to Right Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player)) # or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.can_use_beam_sword(player) + set_rule(world.get_entrance('GT Crystal Conveyor to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('GT Crystal Conveyor Corner to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('GT Crystal Conveyor Corner to Left Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('GT Crystal Circles to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_blunt_weapon(player) or state.has('Cane of Byrna', player)) # or state.has_beam_sword(player) add_key_logic_rules(world, player) - # End of door rando rules. set_rule(world.get_location('Ganon', player), lambda state: state.has_beam_sword(player) and state.has_fire_source(player) and state.has_crystals(world.crystals_needed_for_ganon[player], player) and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or (state.has('Silver Arrows', player) and state.can_shoot_arrows(player)) or state.has('Lamp', player) or state.can_extend_magic(player, 12))) # need to light torch a sufficient amount of times set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop +def bomb_rules(world, player): + bonkable_doors = ['Two Brothers House Exit (West)', 'Two Brothers House Exit (East)'] # Technically this is incorrectly defined, but functionally the same as what is intended. + bombable_doors = ['Ice Rod Cave', 'Light World Bomb Hut', 'Light World Death Mountain Shop', 'Mini Moldorm Cave', + 'Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)', 'Dark Lake Hylia Ledge Fairy', 'Hype Cave', 'Brewery'] + for entrance in bonkable_doors: + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + for entrance in bombable_doors: + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + + bonkable_items = ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right'] + bombable_items = ['Blind\'s Hideout - Top', 'Kakariko Well - Top', 'Chicken House', 'Aginah\'s Cave', 'Graveyard Cave', + 'Paradox Cave Upper - Left', 'Paradox Cave Upper - Right', + 'Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left', 'Hype Cave - Bottom'] + for location in bonkable_items: + add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + for location in bombable_items: + add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player)) + + cave_kill_locations = ['Mini Moldorm Cave - Far Left', 'Mini Moldorm Cave - Far Right', 'Mini Moldorm Cave - Left', 'Mini Moldorm Cave - Right', 'Mini Moldorm Cave - Generous Guy'] + for location in cave_kill_locations: + add_rule(world.get_location(location, player), lambda state: state.can_kill_most_things(player) or state.can_use_bombs(player)) + + paradox_switch_chests = ['Paradox Cave Lower - Far Left', 'Paradox Cave Lower - Left', 'Paradox Cave Lower - Right', 'Paradox Cave Lower - Far Right', 'Paradox Cave Lower - Middle'] + for location in paradox_switch_chests: + add_rule(world.get_location(location, player), lambda state: state.can_hit_crystal_through_barrier(player)) + + # Dungeon bomb logic + easy_kill_rooms = [ # Door, bool-bombable + ('Hyrule Dungeon Armory S', True), # One green guard + ('Hyrule Dungeon Armory ES', True), # One green guard + ('Hyrule Dungeon Armory Boomerang WS', True), # One blue guard + ('Desert Compass NW', True), # Three popos + ('Desert Four Statues NW', True), # Four popos + ('Desert Four Statues ES', True), # Four popos + ('Hera Beetles WS', False), # Three blue beetles and only two pots, and bombs don't work. + ('Thieves Basement Block WN', True), # One blue and one red zazak and one Stalfos. Two pots. Need to kill the third enemy somehow. + ('Ice Pengator Trap NE', False), # Five pengators. Bomb-doable? + ('TR Twin Pokeys EN', False), # Two pokeys + ('TR Twin Pokeys SW', False), # Two pokeys + ('GT Petting Zoo SE', False), # Dont make anyone do this room with bombs and/or pots. + ('GT DMs Room SW', False) # Four red stalfos + ] + for killdoor,bombable in easy_kill_rooms: + if bombable: + add_rule(world.get_entrance(killdoor, player), lambda state: (state.can_use_bombs(player) or state.can_kill_most_things(player))) + else: + add_rule(world.get_entrance(killdoor, player), lambda state: state.can_kill_most_things(player)) + add_rule(world.get_entrance('Ice Stalfos Hint SE', player), lambda state: state.can_use_bombs(player)) # Need bombs for big stalfos knights + add_rule(world.get_entrance('Mire Cross ES', player), lambda state: state.can_kill_most_things(player)) # 4 Sluggulas. Bombs don't work // or (state.can_use_bombs(player) and state.has('Magic Powder'), player) + + enemy_kill_drops = [ # Location, bool-bombable + ('Hyrule Castle - Map Guard Key Drop', True), + ('Hyrule Castle - Boomerang Guard Key Drop', True), + ('Hyrule Castle - Key Rat Key Drop', True), +# ('Hyrule Castle - Big Key Drop', True), # Pots are available +# ('Eastern Palace - Dark Eyegore Key Drop', True), # Pots are available + ('Castle Tower - Dark Archer Key Drop', True), +# ('Castle Tower - Circle of Pots Key Drop', True), # Pots are available +# ('Skull Woods - Spike Corner Key Drop', True), # Pots are available + ('Ice Palace - Jelly Key Drop', True), + ('Ice Palace - Conveyor Key Drop', True), + ('Misery Mire - Conveyor Crystal Key Drop', True), + ('Turtle Rock - Pokey 1 Key Drop', True), + ('Turtle Rock - Pokey 2 Key Drop', True), +# ('Ganons Tower - Mini Helmasaur Key Drop', True) # Pots are available + ('Castle Tower - Room 03', True), # Two spring soliders + ('Ice Palace - Compass Chest', True) # Pengators + ] + for location,bombable in enemy_kill_drops: + if bombable: + add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player) or state.can_kill_most_things(player)) + else: + add_rule(world.get_location(location, player), lambda state: state.can_kill_most_things(player)) + + add_rule(world.get_location('Attic Cracked Floor', player), lambda state: state.can_use_bombs(player)) + bombable_floors = ['PoD Pit Room Bomb Hole', 'Ice Bomb Drop Hole', 'Ice Freezors Bomb Hole', 'GT Bob\'s Room Hole'] + for entrance in bombable_floors: + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + + if world.doorShuffle[player] == 'vanilla': + add_rule(world.get_entrance('TR Lazy Eyes SE', player), lambda state: state.can_use_bombs(player)) # ToDo: Add always true for inverted, cross-entrance, and door-variants and so on. + add_rule(world.get_entrance('Turtle Rock Ledge Exit (West)', player), lambda state: state.can_use_bombs(player)) # Is this the same as above? + + dungeon_bonkable = ['PoD Warp Hint SE', 'PoD Jelly Hall NW', 'PoD Jelly Hall NE', 'PoD Mimics 1 SW', + 'Thieves Ambush E', 'Thieves Rail Ledge W', + 'TR Dash Room NW', 'TR Crystaroller SW', 'TR Dash Room ES', + 'GT Four Torches NW','GT Fairy Abyss SW' + ] + dungeon_bombable = ['PoD Map Balcony WS', 'PoD Arena Ledge ES', 'PoD Dark Maze E', 'PoD Big Chest Balcony W', + 'Swamp Pot Row WN','Swamp Map Ledge EN', 'Swamp Hammer Switch WN', 'Swamp Hub Dead Ledge EN', 'Swamp Waterway N', 'Swamp I S', + 'Skull Pot Circle WN', 'Skull Pull Switch EN', 'Skull Big Key EN', 'Skull Lone Pot WN', + 'Thieves Rail Ledge NW', 'Thieves Pot Alcove Bottom SW', + 'Ice Bomb Drop Hole', 'Ice Freezors Bomb Hole', + 'Mire Crystal Mid NW', 'Mire Tall Dark and Roomy WN', 'Mire Shooter Rupees EN', 'Mire Crystal Top SW', + 'GT Warp Maze (Rails) WS', 'GT Bob\'s Room Hole', 'GT Randomizer Room ES', 'GT Bomb Conveyor SW', 'GT Crystal Circles NW', 'GT Cannonball Bridge SE', 'GT Refill NE' + ] + for entrance in dungeon_bonkable: + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + for entrance in dungeon_bombable: + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + else: + doors_to_bomb_check = [x for x in world.doors if x.player == player and x.type in [DoorType.Normal, DoorType.Interior]] + for door in doors_to_bomb_check: + if door.kind(world) in [DoorKind.Dashable]: + add_rule(door.entrance, lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + elif door.kind(world) in [DoorKind.Bombable]: + add_rule(door.entrance, lambda state: state.can_use_bombs(player)) def default_rules(world, player): # Underworld Logic @@ -459,7 +720,6 @@ def default_rules(world, player): set_rule(world.get_entrance('Thieves Town', player), lambda state: state.has_Pearl(player)) # bunny cannot pull set_rule(world.get_entrance('Brewery', player), lambda state: state.has_Pearl(player)) # bomb required set_rule(world.get_entrance('Dark World Hammer Peg Cave', player), lambda state: state.has_Pearl(player) and state.has('Hammer', player)) - set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player]) set_rule(world.get_entrance('Bonk Fairy (Dark)', player), lambda state: state.has_Pearl(player) and state.has_Boots(player)) set_rule(world.get_entrance('Hype Cave', player), lambda state: state.has_Pearl(player)) # bomb required set_rule(world.get_entrance('Palace of Darkness', player), lambda state: state.has_Pearl(player)) # kiki needs pearl @@ -522,6 +782,8 @@ def default_rules(world, player): set_rule(world.get_entrance('Flute Away', player), lambda state: state.can_flute(player)) + set_rule(world.get_entrance('Waterfall of Wishing Cave Entry', player), lambda state: state.has('Flippers', player)) + set_rule(world.get_entrance('Zora Approach Water Drop', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Zora Warning Water Drop', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Potion Shop Water Drop', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Potion Shop Northeast Water Drop', player), lambda state: state.has('Flippers', player)) @@ -654,9 +916,8 @@ def default_rules(world, player): set_rule(world.get_entrance('Floating Island Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('TR Pegs Area Mirror Spot', player), lambda state: state.has_Mirror(player)) - # Final Rules - set_rule(world.get_entrance('Ganons Tower', player), lambda state: False) # This is a safety for the TR function below to not require GT entrance in its key logic. - + set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player]) + if world.swords[player] == 'swordless': swordless_rules(world, player) @@ -671,10 +932,11 @@ def inverted_rules(world, player): set_rule(world.get_location('Ice Rod Cave', player), lambda state: state.has_Pearl(player)) set_rule(world.get_location('Maze Race', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: state.has_Pearl(player)) + set_rule(world.get_entrance('Ice Rod Cave', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Potion Shop Pier', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player)) set_rule(world.get_entrance('Light World Pier', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player)) - set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has_Boots(player) and state.can_lift_heavy_rocks(player) and state.has_Pearl(player)) + set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has_Boots(player) and state.has_Pearl(player)) set_rule(world.get_entrance('Kings Grave Outer Rocks', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Pearl(player)) set_rule(world.get_entrance('Kings Grave Inner Rocks', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Pearl(player)) set_rule(world.get_entrance('Potion Shop Inner Bushes', player), lambda state: state.has_Pearl(player)) @@ -685,7 +947,6 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Graveyard Cave Outer Bushes', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Secret Passage Inner Bushes', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Secret Passage Outer Bushes', player), lambda state: state.has_Pearl(player)) - # Caution: If king's grave is releaxed at all to account for reaching it via a two way cave's exit in insanity mode, then the bomb shop logic will need to be updated (that would involve create a small ledge-like Region for it) set_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has_Boots(player) and state.has_Pearl(player)) set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player) and state.has_Pearl(player)) set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has_Pearl(player) and state.has('Beat Agahnim 1', player)) @@ -705,7 +966,8 @@ def inverted_rules(world, player): set_rule(world.get_location('Flute Spot', player), lambda state: state.has('Shovel', player) and state.has_Pearl(player)) set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player)) - set_rule(world.get_entrance('Waterfall of Wishing', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player)) # can be fake flippered into, but is in weird state inside that might prevent you from doing things. Can be improved in future Todo + set_rule(world.get_entrance('Waterfall of Wishing Cave', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player)) + set_rule(world.get_entrance('Northeast Light World Return', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player)) set_rule(world.get_location('Frog', player), lambda state: state.can_lift_heavy_rocks(player) and (state.has_Pearl(player) or state.has('Beat Agahnim 1', player)) or (state.can_reach('Light World', 'Region', player) and state.has_Mirror(player))) # Need LW access using Mirror or Portal @@ -715,6 +977,7 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Bush Covered Lawn Outer Bushes', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Bomb Hut Inner Bushes', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Bomb Hut Outer Bushes', player), lambda state: state.has_Pearl(player)) + set_rule(world.get_entrance('Light World Bomb Hut', player), lambda state: state.has_Pearl(player)) # need bomb set_rule(world.get_entrance('North Fairy Cave Drop', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Lost Woods Hideout Drop', player), lambda state: state.has_Pearl(player)) set_rule(world.get_location('Potion Shop', player), lambda state: state.has('Mushroom', player) and (state.can_reach('Potion Shop Area', 'Region', player))) # new inverted region, need pearl for bushes or access to potion shop door/waterfall fairy @@ -732,7 +995,7 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Dark Death Mountain Teleporter (East)', player), lambda state: state.can_lift_heavy_rocks(player) and state.has('Hammer', player) and state.has_Pearl(player)) # bunny cannot use hammer set_rule(world.get_entrance('East Death Mountain (Top)', player), lambda state: state.has('Hammer', player) and state.has_Pearl(player)) # bunny can not use hammer - set_rule(world.get_location('Catfish', player), lambda state: state.can_lift_rocks(player) or (state.has('Flippers', player) and state.has_Mirror(player) and state.has_Pearl(player) and state.can_reach('Light World', 'Region', player))) + set_rule(world.get_entrance('Catfish Entrance Rock', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Northeast Dark World Broken Bridge Pass', player), lambda state: ((state.can_lift_rocks(player) or state.has('Hammer', player)) or state.has('Flippers', player))) set_rule(world.get_entrance('East Dark World Broken Bridge Pass', player), lambda state: (state.can_lift_rocks(player) or state.has('Hammer', player))) set_rule(world.get_entrance('South Dark World Bridge', player), lambda state: state.has('Hammer', player)) @@ -740,10 +1003,11 @@ def inverted_rules(world, player): set_rule(world.get_entrance('West Dark World Gap', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Ice Lake Drop (East)', player), lambda state: state.has('Flippers', player)) set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) - set_rule(world.get_entrance('Ice Lake Drop (South)', player), lambda state: state.has('Flippers', player)) # ToDo any fake flipper set up? - set_rule(world.get_entrance('Ice Lake Ledge Pier', player), lambda state: state.has('Flippers', player)) - set_rule(world.get_entrance('Ice Lake Ledge Spike Cave', player), lambda state: state.can_lift_rocks(player)) - set_rule(world.get_entrance('Ice Lake Teleporter', player), lambda state: state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) # Fake Flippers + set_rule(world.get_entrance('Dark Lake Hylia Drop (South)', player), lambda state: state.has('Flippers', player)) # ToDo any fake flipper set up? + set_rule(world.get_entrance('Dark Lake Hylia Ledge Pier', player), lambda state: state.has('Flippers', player)) + set_rule(world.get_entrance('Dark Lake Hylia Ledge Spike Cave', player), lambda state: state.can_lift_rocks(player)) + set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player)) # Fake Flippers + set_rule(world.get_entrance('Dark Lake Hylia Shallows', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Village of Outcasts Heavy Rock', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('East Dark World Bridge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has_Mirror(player)) @@ -770,7 +1034,6 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Dark Death Mountain Ledge Mirror Spot (East)', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Dark Death Mountain Ledge Mirror Spot (West)', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Laser Bridge Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('Superbunny Cave Exit (Bottom)', player), lambda state: False) # Cannot get to bottom exit from top. Just exists for shuffling set_rule(world.get_entrance('Floating Island Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_sword(player) and state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock (Top)', 'Region', player)) # sword required to cast magic (!) @@ -782,7 +1045,7 @@ def inverted_rules(world, player): set_rule(world.get_entrance('East Dark World Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('West Dark World Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('South Dark World Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('Northeast Dark World Mirror Spot', player), lambda state: state.has_Mirror(player)) + set_rule(world.get_entrance('Catfish Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Potion Shop Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Shopping Mall Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Maze Race Mirror Spot', player), lambda state: state.has_Mirror(player)) @@ -806,8 +1069,6 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Hammer Peg Area Flute', player), lambda state: state.can_flute(player)) set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player]) - set_rule(world.get_entrance('Inverted Ganons Tower', player), lambda state: False) # This is a safety for the TR function below to not require GT entrance in its key logic. - if world.swords[player] == 'swordless': swordless_rules(world, player) @@ -842,19 +1103,49 @@ def no_glitches_rules(world, player): # for location in DMs_room_chests: # add_rule(world.get_location(location, 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) + 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)) + 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) + + +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'] + for location in DMs_room_chests: + add_rule(world.get_location(location, player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Paradox Cave Bomb Jump', player), lambda state: False) - # Light cones in standard depend on which world we actually are in, not which one the location would normally be - # We add Lamp requirements only to those locations which lie in the dark world (or everything if open - DW_Entrances = ['Bumper Cave (Bottom)', 'Superbunny Cave (Top)', 'Superbunny Cave (Bottom)', 'Hookshot Cave', 'Bumper Cave (Top)', 'Hookshot Cave Back Entrance', 'Dark Death Mountain Ledge (East)', - 'Turtle Rock Isolated Ledge Entrance', 'Thieves Town', 'Skull Woods Final Section', 'Ice Palace', 'Misery Mire', 'Palace of Darkness', 'Swamp Palace', 'Turtle Rock', 'Dark Death Mountain Ledge (West)'] +# Light cones in standard depend on which world we actually are in, not which one the location would normally be +# We add Lamp requirements only to those locations which lie in the dark world (or everything if open +DW_Entrances = ['Bumper Cave (Bottom)', 'Superbunny Cave (Top)', 'Superbunny Cave (Bottom)', 'Hookshot Cave', 'Bumper Cave (Top)', 'Hookshot Cave Back Entrance', 'Dark Death Mountain Ledge (East)', + 'Turtle Rock Isolated Ledge Entrance', 'Thieves Town', 'Skull Woods Final Section', 'Ice Palace', 'Misery Mire', 'Palace of Darkness', 'Swamp Palace', 'Turtle Rock', 'Dark Death Mountain Ledge (West)'] - def check_is_dark_world(region): - for entrance in region.entrances: - if entrance.name in DW_Entrances: - return True - return False +def check_is_dark_world(region): + for entrance in region.entrances: + if entrance.name in DW_Entrances: + return True + return False +def add_conditional_lamps(world, player): def add_conditional_lamp(spot, region, spottype='Location'): if spottype == 'Location': spot = world.get_location(spot, player) @@ -868,7 +1159,7 @@ def no_glitches_rules(world, player): 'Mire Dark Shooters': {'sewer': False, 'entrances': ['Mire Dark Shooters Up Stairs', 'Mire Dark Shooters SW', 'Mire Dark Shooters SE'], 'locations': []}, 'Mire Key Rupees': {'sewer': False, 'entrances': ['Mire Key Rupees NE'], 'locations': []}, 'Mire Block X': {'sewer': False, 'entrances': ['Mire Block X NW', 'Mire Block X WS'], 'locations': []}, - 'Mire Tall Dark and Roomy': {'sewer': False, 'entrances': ['Mire Tall Dark and Roomy ES', 'Mire Tall Dark and Roomy WS', 'Mire Tall Dark and Roomy WN'], 'locations': []}, + 'Mire Tall Dark and Roomy': {'sewer': False, 'entrances': ['Mire Tall Dark and Roomy ES', 'Mire Tall Dark and Roomy WS', 'Mire Tall Dark and Roomy WN', 'Mire Tall Dark and Roomy to Ranged Crystal'], 'locations': []}, 'Mire Crystal Right': {'sewer': False, 'entrances': ['Mire Crystal Right ES'], 'locations': []}, 'Mire Crystal Mid': {'sewer': False, 'entrances': ['Mire Crystal Mid NW'], 'locations': []}, 'Mire Crystal Left': {'sewer': False, 'entrances': ['Mire Crystal Left WS'], 'locations': []}, @@ -878,9 +1169,8 @@ def no_glitches_rules(world, player): 'PoD Callback': {'sewer': False, 'entrances': ['PoD Callback WS', 'PoD Callback Warp'], 'locations': []}, 'PoD Turtle Party': {'sewer': False, 'entrances': ['PoD Turtle Party ES', 'PoD Turtle Party NW'], 'locations': []}, 'PoD Lonely Turtle': {'sewer': False, 'entrances': ['PoD Lonely Turtle SW', 'PoD Lonely Turtle EN'], 'locations': []}, - 'PoD Dark Pegs': {'sewer': False, 'entrances': ['PoD Dark Pegs Hammer Path', 'PoD Dark Pegs WN'], 'locations': []}, - 'PoD Dark Pegs Ladder': {'sewer': False, 'entrances': ['PoD Dark Pegs Up Ladder', 'PoD Dark Pegs Ladder Hammer Path', 'PoD Dark Pegs Ladder Cane Path'], 'locations': []}, - 'PoD Dark Pegs Switch': {'sewer': False, 'entrances': ['PoD Dark Pegs Switch Path'], 'locations': []}, + 'PoD Dark Pegs Landing': {'sewer': False, 'entrances': ['PoD Dark Pegs Up Ladder', 'PoD Dark Pegs Landing to Right', 'PoD Dark Pegs Landing to Ranged Crystal'], 'locations': []}, + 'PoD Dark Pegs Left': {'sewer': False, 'entrances': ['PoD Dark Pegs WN', 'PoD Dark Pegs Left to Middle Barrier - Blue', 'PoD Dark Pegs Left to Ranged Crystal'], 'locations': []}, 'PoD Dark Basement': {'sewer': False, 'entrances': ['PoD Dark Basement W Up Stairs', 'PoD Dark Basement E Up Stairs'], 'locations': ['Palace of Darkness - Dark Basement - Left', 'Palace of Darkness - Dark Basement - Right']}, 'PoD Dark Maze': {'sewer': False, 'entrances': ['PoD Dark Maze EN', 'PoD Dark Maze E'], 'locations': ['Palace of Darkness - Dark Maze - Top', 'Palace of Darkness - Dark Maze - Bottom']}, 'Eastern Dark Square': {'sewer': False, 'entrances': ['Eastern Dark Square NW', 'Eastern Dark Square Key Door WN', 'Eastern Dark Square EN'], 'locations': []}, @@ -956,36 +1246,35 @@ def swordless_rules(world, player): std_kill_rooms = { - 'Hyrule Dungeon Armory Main': ['Hyrule Dungeon Armory S'], - 'Hyrule Dungeon Armory Boomerang': ['Hyrule Dungeon Armory Boomerang WS'], - 'Eastern Stalfos Spawn': ['Eastern Stalfos Spawn ES', 'Eastern Stalfos Spawn NW'], - 'Desert Compass Room': ['Desert Compass NW'], - 'Desert Four Statues': ['Desert Four Statues NW', 'Desert Four Statues ES'], - 'Hera Beetles': ['Hera Beetles WS'], - 'Tower Gold Knights': ['Tower Gold Knights SW', 'Tower Gold Knights EN'], - 'Tower Dark Archers': ['Tower Dark Archers WN'], - 'Tower Red Spears': ['Tower Red Spears WN'], - 'Tower Red Guards': ['Tower Red Guards EN', 'Tower Red Guards SW'], - 'Tower Circle of Pots': ['Tower Circle of Pots NW'], - 'PoD Turtle Party': ['PoD Turtle Party ES', 'PoD Turtle Party NW'], # todo: hammer req. in main rules - 'Thieves Basement Block': ['Thieves Basement Block WN'], - 'Ice Stalfos Hint': ['Ice Stalfos Hint SE'], - 'Ice Pengator Trap': ['Ice Pengator Trap NE'], - 'Mire 2': ['Mire 2 NE'], - 'Mire Cross': ['Mire Cross ES'], - 'TR Twin Pokeys': ['TR Twin Pokeys EN', 'TR Twin Pokeys SW'], - 'GT Petting Zoo': ['GT Petting Zoo SE'], - 'GT DMs Room': ['GT DMs Room SW'], - 'GT Gauntlet 1': ['GT Gauntlet 1 WN'], - 'GT Gauntlet 2': ['GT Gauntlet 2 EN', 'GT Gauntlet 2 SW'], - 'GT Gauntlet 3': ['GT Gauntlet 3 NW', 'GT Gauntlet 3 SW'], - 'GT Gauntlet 4': ['GT Gauntlet 4 NW', 'GT Gauntlet 4 SW'], - 'GT Gauntlet 5': ['GT Gauntlet 5 NW', 'GT Gauntlet 5 WS'], - 'GT Wizzrobes 1': ['GT Wizzrobes 1 SW'], - 'GT Wizzrobes 2': ['GT Wizzrobes 2 SE', 'GT Wizzrobes 2 NE'] + 'Hyrule Dungeon Armory Main': ['Hyrule Dungeon Armory S', 'Hyrule Dungeon Armory ES'], # One green guard + 'Hyrule Dungeon Armory Boomerang': ['Hyrule Dungeon Armory Boomerang WS'], # One blue guard + 'Eastern Stalfos Spawn': ['Eastern Stalfos Spawn ES', 'Eastern Stalfos Spawn NW'], # Can use pots + 'Desert Compass Room': ['Desert Compass NW'], # Three popos + 'Desert Four Statues': ['Desert Four Statues NW', 'Desert Four Statues ES'], # Four popos + 'Hera Beetles': ['Hera Beetles WS'], # Three blue beetles and only two pots, and bombs don't work. + 'Tower Gold Knights': ['Tower Gold Knights SW', 'Tower Gold Knights EN'], # Two ball and chain + 'Tower Dark Archers': ['Tower Dark Archers WN'], # Not a kill room + 'Tower Red Spears': ['Tower Red Spears WN'], # Two spear soldiers + 'Tower Red Guards': ['Tower Red Guards EN', 'Tower Red Guards SW'], # Two usain bolts + 'Tower Circle of Pots': ['Tower Circle of Pots NW'], # Two spear soldiers. Plenty of pots. + 'PoD Turtle Party': ['PoD Turtle Party ES', 'PoD Turtle Party NW'], # Lots of turtles. + 'Thieves Basement Block': ['Thieves Basement Block WN'], # One blue and one red zazak and one Stalfos. Two pots. Need weapon. + 'Ice Stalfos Hint': ['Ice Stalfos Hint SE'], # Need bombs for big stalfos knights + 'Ice Pengator Trap': ['Ice Pengator Trap NE'], # Five pengators. Bomb-doable? + 'Mire 2': ['Mire 2 NE'], # Wizzrobes. Bombs dont work. + 'Mire Cross': ['Mire Cross ES'], # 4 Sluggulas. Bombs don't work + 'TR Twin Pokeys': ['TR Twin Pokeys EN', 'TR Twin Pokeys SW'], # Two pokeys + 'GT Petting Zoo': ['GT Petting Zoo SE'], # Dont make anyone do this room with bombs. + 'GT DMs Room': ['GT DMs Room SW'], # Four red stalfos + 'GT Gauntlet 1': ['GT Gauntlet 1 WN'], # Stalfos/zazaks + 'GT Gauntlet 2': ['GT Gauntlet 2 EN', 'GT Gauntlet 2 SW'], # Red stalfos + 'GT Gauntlet 3': ['GT Gauntlet 3 NW', 'GT Gauntlet 3 SW'], # Blue zazaks + 'GT Gauntlet 4': ['GT Gauntlet 4 NW', 'GT Gauntlet 4 SW'], # Red zazaks + 'GT Gauntlet 5': ['GT Gauntlet 5 NW', 'GT Gauntlet 5 WS'], # Stalfos and zazak + 'GT Wizzrobes 1': ['GT Wizzrobes 1 SW'], # Wizzrobes. Bombs don't work + 'GT Wizzrobes 2': ['GT Wizzrobes 2 SE', 'GT Wizzrobes 2 NE'] # Wizzrobes. Bombs don't work } # all trap rooms? - def add_connection(parent_name, target_name, entrance_name, world, player): parent = world.get_region(parent_name, player) target = world.get_region(target_name, player) @@ -1021,7 +1310,7 @@ def standard_rules(world, player): return loc.item and loc.item.name == 'Bombs (10)' def standard_escape_rule(state): - return state.can_kill_most_things(player) or bomb_escape_rule() + return state.can_kill_most_things(player) or bomb_escape_rule() add_item_rule(world.get_location('Link\'s Uncle', player), uncle_item_rule) @@ -1446,7 +1735,7 @@ def set_inverted_big_bomb_rules(world, player): 'Hookshot Cave', 'Turtle Rock Isolated Ledge Entrance', 'Hookshot Cave Back Entrance', - 'Inverted Agahnims Tower',] + 'Inverted Agahnims Tower'] LW_walkable_entrances = ['Dark Lake Hylia Ledge Fairy', 'Dark Lake Hylia Ledge Spike Cave', 'Dark Lake Hylia Ledge Hint', @@ -1463,13 +1752,7 @@ def set_inverted_big_bomb_rules(world, player): 'Spectacle Rock Cave (Bottom)'] set_rule(world.get_entrance('Pyramid Fairy', player), - lambda state: state.can_reach('East Dark World', 'Region', player) - and state.can_reach('Inverted Big Bomb Shop', 'Region', player) - and state.has('Crystal 5', player) and state.has('Crystal 6', player)) - - # crossing peg bridge starting from the southern dark world - def cross_peg_bridge(state): - return state.has('Hammer', player) + lambda state: state.can_reach('East Dark World', 'Region', player) and state.can_reach('Inverted Big Bomb Shop', 'Region', player) and state.has('Crystal 5', player) and state.has('Crystal 6', player)) # Key for below abbreviations: # P = pearl @@ -1489,41 +1772,37 @@ def set_inverted_big_bomb_rules(world, player): elif bombshop_entrance.name in Northern_DW_entrances: # You can just fly with the Flute, you can take a long walk with Mitts and Hammer, # or you can leave a Mirror portal nearby and then walk to the castle to Mirror again. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or - (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or - (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player))) + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player))) elif bombshop_entrance.name in Southern_DW_entrances: # This is the same as north DW without the Mitts rock present. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: cross_peg_bridge(state) or state.can_flute(player) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player))) + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Hammer', player) or state.can_flute(player) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player))) elif bombshop_entrance.name in Isolated_DW_entrances: # There's just no way to escape these places with the bomb and no Flute. add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player)) elif bombshop_entrance.name in LW_walkable_entrances: # You can fly with the flute, or leave a mirror portal and walk through the light world - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) or - (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player))) + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player))) elif bombshop_entrance.name in LW_bush_entrances: # These entrances are behind bushes in LW so you need either Pearl or the tools to solve NDW bomb shop locations. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and (state.can_flute(player) or state.has_Pearl(player) or (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)))) - #todo: I stopped here - + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and (state.can_flute(player) or state.has_Pearl(player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)))) elif bombshop_entrance.name == 'Dark World Shop': # This is mostly the same as NDW but the Mirror path requires the Pearl, or using the Hammer add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player) and (state.has_Pearl(player) or state.has('Hammer', player)))) elif bombshop_entrance.name == 'Bumper Cave (Bottom)': # This is mostly the same as NDW but the Mirror path requires being able to lift a rock. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (state.has_Mirror(player) and state.can_lift_rocks(player) and state.can_reach('Light World', 'Region', player))) + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_lift_rocks(player) and state.can_reach('Light World', 'Region', player))) elif bombshop_entrance.name == 'Old Man Cave (West)': # The three paths back are Mirror and DW walk, Mirror and Flute, or LW walk and then Mirror. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and ((state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (state.can_lift_rocks(player) and state.has_Pearl(player)) or state.can_flute(player))) + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and ((state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.can_lift_rocks(player) and state.has_Pearl(player)) or state.can_flute(player))) elif bombshop_entrance.name == 'Dark World Potion Shop': # You either need to Flute to 5 or cross the rock/hammer choice pass to the south. add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) or state.has('Hammer', player) or state.can_lift_rocks(player)) elif bombshop_entrance.name == 'Kings Grave': # Either lift the rock and walk to the castle to Mirror or Mirror immediately and Flute. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or state.can_lift_heavy_rocks(player)) and state.has_Mirror(player)) + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or (state.has_Pearl(player) and state.can_lift_heavy_rocks(player))) and state.has_Mirror(player)) elif bombshop_entrance.name == 'Two Brothers House (West)': # First you must Mirror. Then you can either Flute, cross the peg bridge, or use the Agah 1 portal to Mirror again. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or cross_peg_bridge(state) or state.has('Beat Agahnim 1', player)) and state.has_Mirror(player)) + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or state.has('Hammer', player) or state.has('Beat Agahnim 1', player)) and state.has_Mirror(player)) elif bombshop_entrance.name == 'Waterfall of Wishing': # You absolutely must be able to swim to return it from here. add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player) and state.has_Mirror(player)) @@ -1533,6 +1812,9 @@ def set_inverted_big_bomb_rules(world, player): elif bombshop_entrance.name == 'Capacity Upgrade': # You must Mirror but then can use either Ice Palace return path. add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Flippers', player) or state.can_flute(player)) and state.has_Mirror(player)) + elif bombshop_entrance.name == 'Two Brothers House (West)': + # First you must Mirror. Then you can either Flute, cross the peg bridge, or use the Agah 1 portal to Mirror again. + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or state.has('Hammer', player) or state.has('Beat Agahnim 1', player)) and state.has_Mirror(player)) elif bombshop_entrance.name in LW_inaccessible_entrances: # You can't get to the pyramid from these entrances without bomb duping. raise Exception('No valid path to open Pyramid Fairy. (Could not route from %s)' % bombshop_entrance.name) @@ -1543,7 +1825,7 @@ def set_inverted_big_bomb_rules(world, player): raise Exception('No logic found for routing from %s to the pyramid.' % bombshop_entrance.name) -def set_bunny_rules(world, player): +def set_bunny_rules(world, player, inverted): # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. @@ -1551,7 +1833,25 @@ def set_bunny_rules(world, player): 'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)'] bunny_accessible_locations = ['Link\'s House', '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'] + 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', + 'Spectacle Rock', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest', 'Blacksmith', + 'Missing Smith', 'Master Sword Pedestal', 'Bottle Merchant', 'Sunken Treasure', 'Desert Ledge', + 'Kakariko Shop - Left', 'Kakariko Shop - Middle', 'Kakariko Shop - Right', + 'Lake Hylia Shop - Left', 'Lake Hylia Shop - Middle', 'Lake Hylia Shop - Right', + 'Potion Shop - Left', 'Potion Shop - Middle', 'Potion Shop - Right', + 'Capacity Upgrade - Left', 'Capacity Upgrade - Right', + 'Village of Outcasts Shop - Left', 'Village of Outcasts Shop - Middle', 'Village of Outcasts Shop - Right', + 'Dark Lake Hylia Shop - Left', 'Dark Lake Hylia Shop - Middle', 'Dark Lake Hylia Shop - Right', + 'Dark Death Mountain Shop - Left', 'Dark Death Mountain Shop - Middle', 'Dark Death Mountain Shop - Right', + 'Dark Lumberjack Shop - Left', 'Dark Lumberjack Shop - Middle', 'Dark Lumberjack Shop - Right', + 'Dark Potion Shop - Left', 'Dark Potion Shop - Middle', 'Dark Potion Shop - Right', + 'Red Shield Shop - Left', 'Red Shield Shop - Middle', 'Red Shield Shop - Right', + 'Old Man Sword Cave Item 1', + 'Take - Any # 1 Item 1', 'Take - Any # 1 Item 2', + 'Take - Any # 2 Item 1', 'Take - Any # 2 Item 2', + 'Take - Any # 3 Item 1', 'Take - Any # 3 Item 2', + 'Take - Any # 4 Item 1', 'Take - Any # 4 Item 2', + ] def path_to_access_rule(path, entrance): return lambda state: state.can_reach(entrance) and all(rule_func(state) for rule_func in path) @@ -1559,9 +1859,30 @@ def set_bunny_rules(world, player): def options_to_access_rule(options): return lambda state: any(rule_func(state) for rule_func in options) - def get_rule_to_add(start_region): - if not start_region.is_light_world: - return lambda state: state.has_Pearl(player) + # Helper functions to determine if the moon pearl is required + def is_bunny(region): + if inverted: + return region.is_light_world + else: + return region.is_dark_world + def is_link(region): + if inverted: + return region.is_dark_world + else: + return region.is_light_world + + def get_rule_to_add(region, location = None, connecting_entrance = None): + # In OWG, a location can potentially be superbunny-mirror accessible or + # bunny revival accessible. + if world.logic[player] == 'owglitches': + if region.type != RegionType.Dungeon \ + and (location is None or location.name not in OverworldGlitchRules.get_superbunny_accessible_locations()) \ + and not is_link(region): + return lambda state: state.has_Pearl(player) + else: + if not is_link(region): + return lambda state: state.has_Pearl(player) + # in this case we are mixed region. # we collect possible options. @@ -1573,170 +1894,167 @@ def set_bunny_rules(world, player): # for each such entrance a new option is added that consist of: # a) being able to reach it, and # b) being able to access all entrances from there to `region` - seen = {start_region} - queue = deque([(start_region, [])]) + seen = {region} + queue = deque([(region, [])]) while queue: (current, path) = queue.popleft() for entrance in current.entrances: new_region = entrance.parent_region - if new_region in seen: + if new_region.type in (RegionType.Cave, RegionType.Dungeon) and new_region in seen: continue new_path = path + [entrance.access_rule] seen.add(new_region) - if not new_region.is_light_world: - continue # we don't care about pure dark world entrances - if new_region.is_dark_world: + if not is_link(new_region): + if world.logic[player] == 'owglitches': + if region.type == RegionType.Dungeon and new_region.type != RegionType.Dungeon: + if entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances(): + continue + if entrance.name in drop_dungeon_entrances: + lobby = entrance.connected_region + else: + lobby = next(exit.connected_region for exit in current.exits if exit.connected_region.type == RegionType.Dungeon) + if lobby.name in bunny_revivable_entrances: + possible_options.append(path_to_access_rule(new_path, entrance)) + elif lobby.name in superbunny_revivable_entrances: + possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player)], entrance)) + elif lobby.name in superbunny_sword_revivable_entrances: + possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_sword(player)], entrance)) + continue + elif region.type == RegionType.Cave and new_region.type != RegionType.Cave: + if entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances(): + continue + if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions(): + possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_sword(player)], entrance)) + elif region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions(): + possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_Boots(player)], entrance)) + elif location and location.name in OverworldGlitchRules.get_superbunny_accessible_locations(): + if location.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_locations(): + possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_Boots(player)], entrance)) + elif region.name == 'Kakariko Well (top)': + possible_options.append(path_to_access_rule(new_path, entrance)) + else: + possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player)], entrance)) + continue + elif region.name == 'Superbunny Cave (Top)' and new_region.name == 'Superbunny Cave (Bottom)' and location and location.name in OverworldGlitchRules.get_superbunny_accessible_locations(): + possible_options.append(path_to_access_rule(new_path, entrance)) + else: + continue + if is_bunny(new_region): queue.append((new_region, new_path)) else: # we have reached pure light world, so we have a new possible option possible_options.append(path_to_access_rule(new_path, entrance)) return options_to_access_rule(possible_options) - # Add requirements for bunny-impassible caves if they occur in the dark world - for region in [world.get_region(name, player) for name in bunny_impassable_caves]: - - if not region.is_dark_world: - continue - rule = get_rule_to_add(region) - for ext in region.exits: - add_rule(ext, rule) - - paradox_shop = world.get_region('Light World Death Mountain Shop', player) - if paradox_shop.is_dark_world: - add_rule(paradox_shop.entrances[0], get_rule_to_add(paradox_shop)) - - for ent_name in bunny_impassible_doors: - bunny_exit = world.get_entrance(ent_name, player) - if bunny_exit.parent_region.is_dark_world: - add_rule(bunny_exit, get_rule_to_add(bunny_exit.parent_region)) - - doors_to_check = [x for x in world.doors if x.player == player and x not in bunny_impassible_doors] - doors_to_check = [x for x in doors_to_check if x.type in [DoorType.Normal, DoorType.Interior] and not x.blocked] - for door in doors_to_check: - room = world.get_room(door.roomIndex, player) - if door.entrance.parent_region.is_dark_world and room.kind(door) in [DoorKind.Dashable, DoorKind.Bombable, DoorKind.Hidden]: - add_rule(door.entrance, get_rule_to_add(door.entrance.parent_region)) - - # Add requirements for all locations that are actually in the dark world, except those available to the bunny - for location in world.get_locations(): - if location.player == player and location.parent_region.is_dark_world: - - if location.name in bunny_accessible_locations: - continue - - add_rule(location, get_rule_to_add(location.parent_region)) - - -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', - 'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)', 'The Sky'] - bunny_accessible_locations = ['Link\'s House', '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'] - - def path_to_access_rule(path, entrance): - return lambda state: state.can_reach(entrance) and all(rule_func(state) for rule_func in path) - - def options_to_access_rule(options): - return lambda state: any(rule_func(state) for rule_func in options) - - def get_rule_to_add(start_region): - if not start_region.is_dark_world: - return lambda state: state.has_Pearl(player) - # in this case we are mixed region. - # we collect possible options. - - # The base option is having the moon pearl - possible_options = [lambda state: state.has_Pearl(player)] - - # We will search entrances recursively until we find - # one that leads to an exclusively dark world region - # for each such entrance a new option is added that consist of: - # a) being able to reach it, and - # b) being able to access all entrances from there to `region` - seen = {start_region} - queue = deque([(start_region, [])]) - while queue: - (current, path) = queue.popleft() - for entrance in current.entrances: - new_region = entrance.parent_region - if new_region in seen: - continue - new_path = path + [entrance.access_rule] - seen.add(new_region) - if not new_region.is_dark_world: - continue # we don't care about pure light world entrances - if new_region.is_light_world: - queue.append((new_region, new_path)) - else: - # we have reached pure dark world, so we have a new possible option - possible_options.append(path_to_access_rule(new_path, entrance)) - return options_to_access_rule(possible_options) - # Add requirements for bunny-impassible caves if they occur in the light world for region in [world.get_region(name, player) for name in bunny_impassable_caves]: - if not region.is_light_world: + if not is_bunny(region): continue rule = get_rule_to_add(region) for ext in region.exits: add_rule(ext, rule) paradox_shop = world.get_region('Light World Death Mountain Shop', player) - if paradox_shop.is_light_world: + if is_bunny(paradox_shop): add_rule(paradox_shop.entrances[0], get_rule_to_add(paradox_shop)) for ent_name in bunny_impassible_doors: bunny_exit = world.get_entrance(ent_name, player) - if bunny_exit.parent_region.is_light_world: + if is_bunny(bunny_exit.parent_region): add_rule(bunny_exit, get_rule_to_add(bunny_exit.parent_region)) doors_to_check = [x for x in world.doors if x.player == player and x not in bunny_impassible_doors] doors_to_check = [x for x in doors_to_check if x.type in [DoorType.Normal, DoorType.Interior] and not x.blocked] for door in doors_to_check: room = world.get_room(door.roomIndex, player) - if door.entrance.parent_region.is_light_world and room.kind(door) in [DoorKind.Dashable, DoorKind.Bombable, DoorKind.Hidden]: + if is_bunny(door.entrance.parent_region) and room.kind(door) in [DoorKind.Dashable, DoorKind.Bombable, DoorKind.Hidden]: add_rule(door.entrance, get_rule_to_add(door.entrance.parent_region)) - # Add requirements for all locations that are actually in the light world, except those available to the bunny - for location in world.get_locations(): - if location.player == player and location.parent_region.is_light_world: + for region in world.get_regions(): + if region.player == player and is_bunny(region): + for location in region.locations: + if location.name in bunny_accessible_locations: + continue + add_rule(location, get_rule_to_add(region, location)) - if location.name in bunny_accessible_locations: - continue - add_rule(location, get_rule_to_add(location.parent_region)) +drop_dungeon_entrances = { + "Sewer Drop", + "Skull Left Drop", + "Skull Pinball", + "Skull Pot Circle", + "Skull Back Drop" +} +bunny_revivable_entrances = { + "Sewers Pull Switch", "TR Dash Room", "Swamp Boss", "Hera Boss", + "Tower Agahnim 1", "Ice Lobby", "Sewers Rat Path", "PoD Falling Bridge", + "PoD Harmless Hellway", "PoD Mimics 2", "Ice Cross Bottom", "GT Agahnim 2", + "Sewers Water", "TR Lazy Eyes", "TR Big Chest Entrance", "Swamp Push Statue", + "PoD Arena Main", "PoD Arena Bridge", "PoD Map Balcony", "Sewers Dark Cross", + "Desert Boss", "Swamp Hub", "Skull Spike Corner", "PoD Pit Room", + "PoD Conveyor", "GT Crystal Circles", "Sewers Behind Tapestry", + "Desert Tiles 2", "Skull Star Pits", "Hyrule Castle West Hall", + "Hyrule Castle Throne Room", "Hyrule Castle East Hall", "Skull 2 West Lobby", + "Skull 2 East Lobby", "Skull Pot Prison", "Skull 1 Lobby", "Skull Map Room", + "Skull 3 Lobby", "PoD Boss", "GT Hidden Spikes", "GT Gauntlet 3", + "Ice Spike Cross", "Hyrule Castle West Lobby", "Hyrule Castle Lobby", + "Hyrule Castle East Lobby", "Desert Back Lobby", "Hyrule Dungeon Armory Main", + "Hyrule Dungeon North Abyss", "Desert Sandworm Corner", "Desert Dead End", + "Desert North Hall", "Desert Arrow Pot Corner", "GT DMs Room", + "GT Petting Zoo", "Ice Tall Hint", "Desert West Lobby", "Desert Main Lobby", + "Desert East Lobby", "GT Big Chest", "GT Bob\'s Room", "GT Speed Torch", + "Mire Boss", "GT Conveyor Bridge", "Mire Lobby", "Eastern Darkness", + "Ice Many Pots", "Mire South Fish", "Mire Right Bridge", "Mire Left Bridge", + "TR Boss", "Eastern Hint Tile Blocked Path", "Thieves Spike Switch", + "Thieves Boss", "Mire Spike Barrier", "Mire Cross", "Mire Hidden Shooters", + "Mire Spikes", "TR Final Abyss", "TR Dark Ride", "TR Pokey 1", "TR Tile Room", + "TR Roller Room", "Eastern Cannonball", "Thieves Hallway", "Ice Switch Room", + "Mire Tile Room", "Mire Conveyor Crystal", "Mire Hub", "TR Dash Bridge", + "TR Hub", "Eastern Boss", "Eastern Lobby", "Thieves Ambush", + "Thieves BK Corner", "TR Eye Bridge", "Thieves Lobby", "Tower Lobby", + "Sewer Drop", "Skull Left Drop", "Skull Pinball", "Skull Back Drop", + "Skull Pot Circle", # You automatically get superbunny by dropping +} + +# Revive as superbunny or use superbunny to get the item in a dead end +superbunny_revivable_entrances = { + "TR Main Lobby", "Sanctuary", "Thieves Pot Alcove Bottom" +} + +superbunny_sword_revivable_entrances = { + "Hera Lobby" +} + bunny_impassible_doors = { - 'Hyrule Dungeon Armory S', 'Hyrule Dungeon Armory ES', 'Sewers Secret Room Push Block', 'Sewers Pull Switch S', + 'Hyrule Dungeon Armory S', 'Hyrule Dungeon Armory ES', 'Sewers Pull Switch S', 'Eastern Lobby N', 'Eastern Courtyard Ledge W', 'Eastern Courtyard Ledge E', 'Eastern Pot Switch SE', - 'Eastern Map Balcony Hook Path', 'Eastern Stalfos Spawn ES', 'Eastern Stalfos Spawn NW', - 'Eastern Hint Tile Push Block', 'Eastern Darkness S', 'Eastern Darkness NE', 'Eastern Darkness Up Stairs', + 'Eastern Map Balcony Hook Path', 'Eastern Stalfos Spawn ES', 'Eastern Stalfos Spawn NW', + 'Eastern Darkness S', 'Eastern Darkness NE', 'Eastern Darkness Up Stairs', 'Eastern Attic Start WS', 'Eastern Single Eyegore NE', 'Eastern Duo Eyegores NE', 'Desert Main Lobby Left Path', 'Desert Main Lobby Right Path', 'Desert Left Alcove Path', 'Desert Right Alcove Path', 'Desert Compass NW', 'Desert West Lobby NW', 'Desert Back Lobby NW', 'Desert Four Statues NW', 'Desert Four Statues ES', - 'Desert Beamos Hall WS', 'Desert Beamos Hall NE', 'Desert Wall Slide NW', 'Hera Lobby Down Stairs', - 'Hera Lobby Key Stairs', 'Hera Lobby Up Stairs', 'Hera Tile Room EN', 'Hera Tridorm SE', 'Hera Beetles WS', + 'Desert Beamos Hall WS', 'Desert Beamos Hall NE', 'Desert Wall Slide NW', + 'Hera Lobby to Front Barrier - Blue', 'Hera Front to Lobby Barrier - Blue', 'Hera Front to Down Stairs Barrier - Blue', + 'Hera Down Stairs to Front Barrier - Blue', 'Hera Tile Room EN', 'Hera Tridorm SE', 'Hera Beetles WS', 'Hera 4F Down Stairs', 'Tower Gold Knights SW', 'Tower Dark Maze EN', 'Tower Dark Pits ES', 'Tower Dark Archers WN', 'Tower Red Spears WN', 'Tower Red Guards EN', 'Tower Red Guards SW', 'Tower Circle of Pots NW', 'Tower Altar NW', - 'PoD Left Cage SW', 'PoD Middle Cage SE', 'PoD Pit Room Bomb Hole', 'PoD Pit Room Block Path N', - 'PoD Pit Room Block Path S', 'PoD Stalfos Basement Warp', 'PoD Arena Main SW', 'PoD Arena Main Crystal Path', - 'PoD Arena Bonk Path', 'PoD Arena Crystal Path', 'PoD Sexy Statue NW', 'PoD Map Balcony Drop Down', - 'PoD Mimics 1 NW', 'PoD Warp Hint Warp', 'PoD Falling Bridge Path N', 'PoD Falling Bridge Path S', - 'PoD Mimics 2 NW', 'PoD Bow Statue Down Ladder', 'PoD Dark Pegs Up Ladder', 'PoD Dark Pegs WN', + 'PoD Left Cage SW', 'PoD Middle Cage SE', 'PoD Pit Room Bomb Hole', 'PoD Stalfos Basement Warp', + 'PoD Arena Main to Landing Barrier - Blue', 'PoD Arena Landing to Right Barrier - Blue', + 'PoD Arena Right to Landing Barrier - Blue', 'PoD Arena Main to Landing Barrier - Blue', + 'PoD Arena Landing Bonk Path', 'PoD Sexy Statue NW', 'PoD Map Balcony Drop Down', + 'PoD Mimics 1 NW', 'PoD Falling Bridge Path N', 'PoD Falling Bridge Path S', + 'PoD Mimics 2 NW', 'PoD Bow Statue Down Ladder', 'PoD Dark Pegs Landing to Right', + 'PoD Dark Pegs Left to Middle Barrier - Blue', 'PoD Dark Pegs Left to Ranged Crystal', 'PoD Turtle Party ES', 'PoD Turtle Party NW', 'PoD Callback Warp', 'Swamp Lobby Moat', 'Swamp Entrance Moat', 'Swamp Trench 1 Approach Swim Depart', 'Swamp Trench 1 Approach Key', 'Swamp Trench 1 Key Approach', 'Swamp Trench 1 Key Ledge Depart', 'Swamp Trench 1 Departure Approach', 'Swamp Trench 1 Departure Key', - 'Swamp Hub Hook Path', 'Swamp Compass Donut Push Block', - 'Swamp Shortcut Blue Barrier', 'Swamp Trench 2 Pots Blue Barrier', 'Swamp Trench 2 Pots Wet', - 'Swamp Trench 2 Departure Wet', 'Swamp West Shallows Push Blocks', 'Swamp West Ledge Hook Path', - 'Swamp Barrier Ledge Hook Path', 'Swamp Attic Left Pit', 'Swamp Attic Right Pit', 'Swamp Push Statue NW', - 'Swamp Push Statue NE', 'Swamp Drain Right Switch', 'Swamp Waterway NE', 'Swamp Waterway N', 'Swamp Waterway NW', + 'Swamp Hub Hook Path', 'Swamp Shortcut Blue Barrier', 'Swamp Trench 2 Pots Blue Barrier', + 'Swamp Trench 2 Pots Wet', 'Swamp Trench 2 Departure Wet', 'Swamp West Ledge Hook Path', 'Swamp Barrier Ledge Hook Path', + 'Swamp Attic Left Pit', 'Swamp Attic Right Pit', 'Swamp Push Statue NW', 'Swamp Push Statue NE', + 'Swamp Drain Right Switch', 'Swamp Waterway NE', 'Swamp Waterway N', 'Swamp Waterway NW', 'Skull Pot Circle WN', 'Skull Pot Circle Star Path', 'Skull Pull Switch S', 'Skull Big Chest N', 'Skull Big Chest Hookpath', 'Skull 2 East Lobby NW', 'Skull Back Drop Star Path', 'Skull 2 West Lobby NW', 'Skull 3 Lobby EN', 'Skull Star Pits SW', 'Skull Star Pits ES', 'Skull Torch Room WN', 'Skull Vines NW', @@ -1744,9 +2062,7 @@ bunny_impassible_doors = { 'Thieves Hellway Blue Barrier', 'Thieves Hellway Crystal Blue Barrier', 'Thieves Attic ES', 'Thieves Basement Block Path', 'Thieves Blocked Entry Path', 'Thieves Conveyor Bridge Block Path', 'Thieves Conveyor Block Path', 'Ice Lobby WS', 'Ice Cross Left Push Block', 'Ice Cross Bottom Push Block Left', - 'Ice Cross Bottom Push Block Right', 'Ice Cross Right Push Block Top', 'Ice Cross Right Push Block Bottom', - 'Ice Cross Top Push Block Bottom', 'Ice Cross Top Push Block Right', 'Ice Bomb Drop Hole', 'Ice Pengator Switch WS', - 'Ice Pengator Switch ES', 'Ice Big Key Push Block', 'Ice Stalfos Hint SE', 'Ice Bomb Jump EN', + 'Ice Bomb Drop Hole', 'Ice Pengator Switch WS', 'Ice Pengator Switch ES', 'Ice Big Key Push Block', 'Ice Stalfos Hint SE', 'Ice Bomb Jump EN', 'Ice Pengator Trap NE', 'Ice Hammer Block ES', 'Ice Tongue Pull WS', 'Ice Freezors Bomb Hole', 'Ice Tall Hint WS', 'Ice Hookshot Ledge Path', 'Ice Hookshot Balcony Path', 'Ice Many Pots SW', 'Ice Many Pots WS', 'Ice Crystal Right Blue Hole', 'Ice Crystal Left Blue Barrier', 'Ice Big Chest Landing Push Blocks', @@ -1755,22 +2071,20 @@ bunny_impassible_doors = { 'Mire Hub Right Blue Barrier', 'Mire Hub Top Blue Barrier', 'Mire Hub Switch Blue Barrier N', 'Mire Hub Switch Blue Barrier S', 'Mire Falling Bridge WN', 'Mire Map Spike Side Blue Barrier', 'Mire Map Spot Blue Barrier', 'Mire Crystal Dead End Left Barrier', 'Mire Crystal Dead End Right Barrier', - 'Mire Cross ES', 'Mire Hidden Shooters Block Path S', 'Mire Hidden Shooters Block Path N', - 'Mire Left Bridge Hook Path', 'Mire Fishbone Blue Barrier', + 'Mire Cross ES', 'Mire Left Bridge Hook Path', 'Mire Fishbone Blue Barrier', 'Mire South Fish Blue Barrier', 'Mire Tile Room NW', 'Mire Compass Blue Barrier', 'Mire Attic Hint Hole', 'Mire Dark Shooters SW', 'Mire Crystal Mid Blue Barrier', 'Mire Crystal Left Blue Barrier', 'TR Main Lobby Gap', 'TR Lobby Ledge Gap', 'TR Hub SW', 'TR Hub SE', 'TR Hub ES', 'TR Hub EN', 'TR Hub NW', 'TR Hub NE', 'TR Torches NW', - 'TR Pokey 2 EN', 'TR Pokey 2 ES', 'TR Twin Pokeys SW', 'TR Twin Pokeys EN', 'TR Big Chest Gap', + 'TR Pokey 2 Bottom to Top Barrier - Blue', 'TR Pokey 2 Top to Bottom Barrier - Blue', 'TR Twin Pokeys SW', 'TR Twin Pokeys EN', 'TR Big Chest Gap', 'TR Big Chest Entrance Gap', 'TR Lazy Eyes ES', 'TR Tongue Pull WS', 'TR Tongue Pull NE', 'TR Dark Ride Up Stairs', - 'TR Dark Ride SW', 'TR Crystal Maze Forwards Path', 'TR Crystal Maze Blue Path', 'TR Crystal Maze Cane Path', + 'TR Dark Ride SW', 'TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze End to Interior Barrier - Blue', 'TR Final Abyss South Stairs', 'TR Final Abyss NW', 'GT Hope Room EN', 'GT Blocked Stairs Block Path', 'GT Bob\'s Room Hole', 'GT Speed Torch SE', 'GT Speed Torch South Path', 'GT Speed Torch North Path', 'GT Crystal Conveyor NE', 'GT Crystal Conveyor WN', 'GT Conveyor Cross EN', 'GT Conveyor Cross WN', 'GT Hookshot East-North Path', 'GT Hookshot East-South Path', 'GT Hookshot North-East Path', 'GT Hookshot North-South Path', 'GT Hookshot South-East Path', 'GT Hookshot South-North Path', - 'GT Hookshot Platform Blue Barrier', 'GT Hookshot Entry Blue Barrier', 'GT Hookshot Entry Boomerang Path', - 'GT Double Switch Blue Path', 'GT Double Switch Key Blue Path', 'GT Double Switch Blue Barrier', - 'GT Double Switch Transition Blue', 'GT Firesnake Room Hook Path', 'GT Falling Bridge WN', 'GT Falling Bridge WS', + 'GT Hookshot Platform Blue Barrier', 'GT Hookshot Entry Blue Barrier', 'GT Double Switch Pot Corners to Exit Barrier - Blue', + 'GT Double Switch Exit to Blue Barrier', 'GT Firesnake Room Hook Path', 'GT Falling Bridge WN', 'GT Falling Bridge WS', 'GT Ice Armos NE', 'GT Ice Armos WS', 'GT Crystal Paths SW', 'GT Mimics 1 NW', 'GT Mimics 1 ES', 'GT Mimics 2 WS', 'GT Mimics 2 NE', 'GT Hidden Spikes EN', 'GT Cannonball Bridge SE', 'GT Gauntlet 1 WN', 'GT Gauntlet 2 EN', 'GT Gauntlet 2 SW', 'GT Gauntlet 3 NW', 'GT Gauntlet 3 SW', 'GT Gauntlet 4 NW', 'GT Gauntlet 4 SW', diff --git a/TestSuite.py b/TestSuite.py index af1d1db4..ede5ae53 100644 --- a/TestSuite.py +++ b/TestSuite.py @@ -51,6 +51,7 @@ def main(args=None): test("Full ", "--shuffle full") test("Crossed ", "--shuffle crossed") test("Insanity ", "--shuffle insanity") + test("OWG ", "--logic owglitches") from tqdm import tqdm with tqdm(concurrent.futures.as_completed(task_mapping), diff --git a/mystery_example.yml b/mystery_example.yml index bd19e6f5..e349063d 100644 --- a/mystery_example.yml +++ b/mystery_example.yml @@ -1,11 +1,11 @@ description: Example door rando weights door_shuffle: - vanilla: 2 - basic: 1 - crossed: 1 + vanilla: 0 + basic: 2 + crossed: 2 intensity: - 1: 1 - 2: 1 + 1: 2 + 2: 2 3: 4 keydropshuffle: on: 1 @@ -38,7 +38,7 @@ fast_ganon: 2 dungeons: 1 pedestal: 2 - triforce-hunt: 0 + triforce-hunt: 2 triforce_goal_min: 10 triforce_goal_max: 30 triforce_pool_min: 20 @@ -55,7 +55,7 @@ default: 5 experimental: on: 1 - off: 0 + off: 1 glitches_required: none: 1 no_logic: 0 @@ -90,23 +90,23 @@ random: 1 enemy_shuffle: none: 3 - shuffled: 1 - random: 0 + shuffled: 2 + random: 1 hints: on: 1 - off: 0 + off: 1 weapons: - randomized: 2 - assured: 1 - vanilla: 1 - swordless: 0 + randomized: 5 + assured: 3 + vanilla: 3 + swordless: 1 item_pool: - normal: 1 - hard: 0 + normal: 3 + hard: 1 expert: 0 item_functionality: - normal: 1 - hard: 0 + normal: 3 + hard: 1 expert: 0 enemy_damage: default: 3 diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 812d1af1..0795b9d0 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -17,6 +17,7 @@ "choices": [ "noglitches", "minorglitches", + "owglitches", "nologic" ] }, diff --git a/resources/app/cli/lang/de.json b/resources/app/cli/lang/de.json index 07936374..d2c5d523 100644 --- a/resources/app/cli/lang/de.json +++ b/resources/app/cli/lang/de.json @@ -1,6 +1,6 @@ { "cli": { - "app.title": "ALttP Tür Randomisier Version %s - Nummer: %d", + "app.title": "ALttP Tür Randomisier Version %s - Nummer: %d, Code: %s", "shuffling.world": "Welt wird durchmischt.", "generating.itempool": "Generier Gegenstandsbasis.", "calc.access.rules": "Berechne Zugriffsregeln.", diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index 7050ebe6..4233b5e8 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -2,7 +2,7 @@ "cli": { "yes": "Yes", "no": "No", - "app.title": "ALttP Door Randomizer Version %s - Seed: %d", + "app.title": "ALttP Door Randomizer Version %s - Seed: %d, Code: %s", "version": "Version", "seed": "Seed", "player": "Player", diff --git a/resources/app/cli/lang/es.json b/resources/app/cli/lang/es.json index 9dcdc2c0..def18849 100644 --- a/resources/app/cli/lang/es.json +++ b/resources/app/cli/lang/es.json @@ -1,6 +1,6 @@ { "cli": { - "app.title": "ALttP Puerta Aleatorizador Versión %s - Número: %d", + "app.title": "ALttP Puerta Aleatorizador Versión %s - Número: %d, Código: %s", "player": "Jugador", "shuffling.world": "Barajando el Mundo", "shuffling.dungeons": "Barajando Mazmorras", diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 4ec592e4..033829ba 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -202,6 +202,7 @@ "randomizer.item.logiclevel": "Logic Level", "randomizer.item.logiclevel.noglitches": "No Glitches", "randomizer.item.logiclevel.minorglitches": "Minor Glitches", + "randomizer.item.logiclevel.owglitches": "Overworld Glitches", "randomizer.item.logiclevel.nologic": "No Logic", "randomizer.item.goal": "Goal", diff --git a/resources/app/gui/randomize/item/widgets.json b/resources/app/gui/randomize/item/widgets.json index fa8681d3..058d03ba 100644 --- a/resources/app/gui/randomize/item/widgets.json +++ b/resources/app/gui/randomize/item/widgets.json @@ -19,6 +19,7 @@ "options": [ "noglitches", "minorglitches", + "owglitches", "nologic" ] }, diff --git a/resources/app/meta/manifests/pip_requirements.txt b/resources/app/meta/manifests/pip_requirements.txt index 595691d2..faa3c48f 100644 --- a/resources/app/meta/manifests/pip_requirements.txt +++ b/resources/app/meta/manifests/pip_requirements.txt @@ -3,4 +3,5 @@ fast-enum python-bps-continued colorama aioconsole -websockets \ No newline at end of file +websockets +pyyaml \ No newline at end of file diff --git a/test/TestBase.py b/test/TestBase.py new file mode 100644 index 00000000..df5c981f --- /dev/null +++ b/test/TestBase.py @@ -0,0 +1,50 @@ +import unittest + +from BaseClasses import CollectionState +from Items import ItemFactory + + +class TestBase(unittest.TestCase): + + _state_cache = {} + + def get_state(self, items): + if (self.world, tuple(items)) in self._state_cache: + return self._state_cache[self.world, tuple(items)] + state = CollectionState(self.world) + for item in items: + item.advancement = True + state.collect(item) + state.sweep_for_events() + self._state_cache[self.world, tuple(items)] = state + return state + + def run_location_tests(self, access_pool): + for location, access, *item_pool in access_pool: + items = item_pool[0] + all_except = item_pool[1] if len(item_pool) > 1 else None + with self.subTest(location=location, access=access, items=items, all_except=all_except): + if all_except and len(all_except) > 0: + items = self.world.itempool[:] + items = [item for item in items if item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)] + items.extend(ItemFactory(item_pool[0], 1)) + else: + items = ItemFactory(items, 1) + state = self.get_state(items) + + self.assertEqual(self.world.get_location(location, 1).can_reach(state), access) + + def run_entrance_tests(self, access_pool): + for entrance, access, *item_pool in access_pool: + items = item_pool[0] + all_except = item_pool[1] if len(item_pool) > 1 else None + with self.subTest(entrance=entrance, access=access, items=items, all_except=all_except): + if all_except and len(all_except) > 0: + items = self.world.itempool[:] + items = [item for item in items if item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)] + items.extend(ItemFactory(item_pool[0], 1)) + else: + items = ItemFactory(items, 1) + state = self.get_state(items) + + self.assertEqual(self.world.get_entrance(entrance, 1).can_reach(state), access) \ No newline at end of file diff --git a/test/TestDeathMountain.py b/test/TestDeathMountain.py deleted file mode 100644 index 089ae52d..00000000 --- a/test/TestDeathMountain.py +++ /dev/null @@ -1,53 +0,0 @@ -from BaseClasses import World -from Dungeons import create_dungeons -from EntranceShuffle import link_entrances -from ItemList import difficulties -from Regions import create_regions -from Rules import set_rules -from test.TestVanilla import TestVanilla - - -class TestDeathMountain(TestVanilla): - def setUp(self): - self.world = World(1, 'vanilla', 'noglitches', 'open', 'random', 'normal', 'normal', 'none', 'on', 'ganon', 'balanced', - True, False, False, False, False, False, False, False, False, None, - 'none', False) - self.world.difficulty_requirements = difficulties['normal'] - create_regions(self.world, 1) - create_dungeons(self.world, 1) - link_entrances(self.world, 1) - set_rules(self.world, 1) - - def testWestDeathMountain(self): - self.run_tests([ - ["Ether Tablet", False, []], - ["Ether Tablet", False, [], ['Progressive Glove', 'Ocarina']], - ["Ether Tablet", False, [], ['Lamp', 'Ocarina']], - ["Ether Tablet", False, [], ['Magic Mirror', 'Hookshot']], - ["Ether Tablet", False, [], ['Magic Mirror', 'Hammer']], - ["Ether Tablet", False, ['Progressive Sword'], ['Progressive Sword']], - ["Ether Tablet", False, [], ['Book of Mudora']], - ["Ether Tablet", True, ['Ocarina', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], - ["Ether Tablet", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], - ["Ether Tablet", True, ['Ocarina', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], - ["Ether Tablet", True, ['Progressive Glove', 'Lamp', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], - - ["Old Man", False, []], - ["Old Man", False, [], ['Progressive Glove', 'Ocarina']], - ["Old Man", False, [], ['Lamp']], - ["Old Man", True, ['Ocarina', 'Lamp']], - ["Old Man", True, ['Progressive Glove', 'Lamp']], - - ["Spectacle Rock Cave", False, []], - ["Spectacle Rock Cave", False, [], ['Progressive Glove', 'Ocarina']], - ["Spectacle Rock Cave", False, [], ['Lamp', 'Ocarina']], - ["Spectacle Rock Cave", True, ['Ocarina']], - ["Spectacle Rock Cave", True, ['Progressive Glove', 'Lamp']], - - ["Spectacle Rock", False, []], - ["Spectacle Rock", False, [], ['Progressive Glove', 'Ocarina']], - ["Spectacle Rock", False, [], ['Lamp', 'Ocarina']], - ["Spectacle Rock", False, [], ['Magic Mirror']], - ["Spectacle Rock", True, ['Ocarina', 'Magic Mirror']], - ["Spectacle Rock", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], - ]) diff --git a/test/TestVanilla.py b/test/TestVanilla.py deleted file mode 100644 index 3bf4a67e..00000000 --- a/test/TestVanilla.py +++ /dev/null @@ -1,41 +0,0 @@ -import unittest - -from BaseClasses import World, CollectionState -from Dungeons import create_dungeons, get_dungeon_item_pool -from EntranceShuffle import link_entrances -from InvertedRegions import mark_dark_world_regions -from ItemList import difficulties -from Items import ItemFactory -from Regions import create_regions -from Rules import set_rules - - -class TestVanilla(unittest.TestCase): - def setUp(self): - self.world = World(1, 'vanilla', 'noglitches', 'open', 'random', 'normal', 'normal', 'none', 'on', 'ganon', 'balanced', - True, False, False, False, False, False, False, False, False, None, - 'none', False) - self.world.difficulty_requirements = difficulties['normal'] - create_regions(self.world, 1) - create_dungeons(self.world, 1) - link_entrances(self.world, 1) - mark_dark_world_regions(self.world) - set_rules(self.world, 1) - - def run_tests(self, access_pool): - for location, access, *item_pool in access_pool: - items = item_pool[0] - all_except = item_pool[1] if len(item_pool) > 1 else None - with self.subTest(location=location, access=access, items=items, all_except=all_except): - if all_except and len(all_except) > 0: - items = self.world.itempool[:] - items = [item for item in items if item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)] - items.extend(ItemFactory(item_pool[0], 1)) - else: - items = ItemFactory(items, 1) - state = CollectionState(self.world) - for item in items: - item.advancement = True - state.collect(item) - - self.assertEqual(self.world.get_location(location, 1).can_reach(state), access) \ No newline at end of file diff --git a/test/inverted/TestInverted.py b/test/inverted/TestInverted.py index 82e1c0f0..06d7a655 100644 --- a/test/inverted/TestInverted.py +++ b/test/inverted/TestInverted.py @@ -1,28 +1,36 @@ from BaseClasses import World +from DoorShuffle import link_doors +from Doors import create_doors from Dungeons import create_dungeons, get_dungeon_item_pool from EntranceShuffle import link_inverted_entrances from InvertedRegions import create_inverted_regions from ItemList import generate_itempool, difficulties from Items import ItemFactory -from Regions import mark_light_world_regions +from Regions import mark_light_world_regions, create_dungeon_regions, create_shops +from RoomData import create_rooms from Rules import set_rules -from test.TestVanilla import TestVanilla +from test.TestBase import TestBase -class TestInverted(TestVanilla): +class TestInverted(TestBase): def setUp(self): - self.world = World(1, 'vanilla', 'noglitches', 'inverted', 'random', 'normal', 'normal', 'none', 'on', 'ganon', 'balanced', - True, False, False, False, False, False, False, False, False, None, - 'none', False) - self.world.difficulty_requirements = difficulties['normal'] + self.world = World(1, {1: 'vanilla'}, {1: 'vanilla'}, {1: 'noglitches'}, {1: 'inverted'}, {1: 'random'}, {1: 'normal'}, {1: 'normal'}, 'none', 'on', {1: 'ganon'}, 'balanced', {1: 'items'}, + {1: True}, {1: False}, False, None, {1: False}) + self.world.difficulty_requirements[1] = difficulties['normal'] + self.world.intensity = {1: 1} create_inverted_regions(self.world, 1) + create_dungeon_regions(self.world, 1) + create_shops(self.world, 1) + create_doors(self.world, 1) + create_rooms(self.world, 1) create_dungeons(self.world, 1) link_inverted_entrances(self.world, 1) + link_doors(self.world, 1) generate_itempool(self.world, 1) self.world.required_medallions[1] = ['Ether', 'Quake'] self.world.itempool.extend(get_dungeon_item_pool(self.world)) self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) self.world.get_location('Agahnim 1', 1).item = None self.world.get_location('Agahnim 2', 1).item = None - mark_light_world_regions(self.world) + mark_light_world_regions(self.world, 1) set_rules(self.world, 1) diff --git a/test/inverted/TestInvertedBombRules.py b/test/inverted/TestInvertedBombRules.py index 4914d2e3..bbcf43dd 100644 --- a/test/inverted/TestInvertedBombRules.py +++ b/test/inverted/TestInvertedBombRules.py @@ -7,17 +7,10 @@ from EntranceShuffle import connect_entrance, Inverted_LW_Entrances, Inverted_LW from InvertedRegions import create_inverted_regions from ItemList import difficulties from Rules import set_inverted_big_bomb_rules +from test.inverted.TestInverted import TestInverted -class TestInvertedBombRules(unittest.TestCase): - - def setUp(self): - self.world = World(1, 'vanilla', 'noglitches', 'inverted', 'random', 'normal', 'normal', 'none', 'on', 'ganon', 'balanced', - True, False, False, False, False, False, False, False, False, None, - 'none', False) - self.world.difficulty_requirements = difficulties['normal'] - create_inverted_regions(self.world, 1) - create_dungeons(self.world, 1) +class TestInvertedBombRules(TestInverted): #TODO: Just making sure I haven't missed an entrance. It would be good to test the rules make sense as well. def testInvertedBombRulesAreComplete(self): @@ -26,6 +19,8 @@ class TestInvertedBombRules(unittest.TestCase): for entrance_name in (entrances + must_exits): if entrance_name not in ['Desert Palace Entrance (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave (Bottom)']: entrance = self.world.get_entrance(entrance_name, 1) + entrance.connected_region = None + self.world.get_region('Inverted Big Bomb Shop', 1).entrances = [] connect_entrance(self.world, entrance, 'Inverted Big Bomb Shop', 1) set_inverted_big_bomb_rules(self.world, 1) entrance.connected_region.entrances.remove(entrance) @@ -40,6 +35,7 @@ class TestInvertedBombRules(unittest.TestCase): def testInvalidEntrances(self): for entrance_name in ['Desert Palace Entrance (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave (Bottom)']: entrance = self.world.get_entrance(entrance_name, 1) + self.world.get_region('Inverted Big Bomb Shop', 1).entrances = [] connect_entrance(self.world, entrance, 'Inverted Big Bomb Shop', 1) with self.assertRaises(Exception): set_inverted_big_bomb_rules(self.world, 1) diff --git a/test/inverted/TestInvertedDarkWorld.py b/test/inverted/TestInvertedDarkWorld.py index c2249c7e..58a4c8b1 100644 --- a/test/inverted/TestInvertedDarkWorld.py +++ b/test/inverted/TestInvertedDarkWorld.py @@ -4,7 +4,7 @@ from test.inverted.TestInverted import TestInverted class TestInvertedDeathMountain(TestInverted): def testNorthWest(self): - self.run_tests([ + self.run_location_tests([ ["Brewery", True, []], ["C-Shaped House", True, []], @@ -45,7 +45,7 @@ class TestInvertedDeathMountain(TestInverted): ]) def testNorthEast(self): - self.run_tests([ + self.run_location_tests([ ["Catfish", False, []], ["Catfish", False, [], ['Progressive Glove', 'Flippers']], ["Catfish", False, [], ['Progressive Glove', 'Magic Mirror']], @@ -80,7 +80,7 @@ class TestInvertedDeathMountain(TestInverted): ]) def testSouth(self): - self.run_tests([ + self.run_location_tests([ ["Hype Cave - Top", True, []], ["Hype Cave - Middle Right", True, []], @@ -99,7 +99,7 @@ class TestInvertedDeathMountain(TestInverted): ]) def testMireArea(self): - self.run_tests([ + self.run_location_tests([ ["Mire Shed - Left", False, []], ["Mire Shed - Left", False, [], ['Ocarina', 'Magic Mirror']], ["Mire Shed - Left", True, ['Moon Pearl', 'Ocarina', 'Progressive Glove', 'Progressive Glove']], diff --git a/test/inverted/TestInvertedDeathMountain.py b/test/inverted/TestInvertedDeathMountain.py index fbd75ddd..30f67448 100644 --- a/test/inverted/TestInvertedDeathMountain.py +++ b/test/inverted/TestInvertedDeathMountain.py @@ -4,7 +4,7 @@ from test.inverted.TestInverted import TestInverted class TestInvertedDeathMountain(TestInverted): def testWestDeathMountain(self): - self.run_tests([ + self.run_location_tests([ ["Old Man", False, []], ["Old Man", False, [], ['Progressive Glove', 'Ocarina']], ["Old Man", False, [], ['Lamp']], @@ -23,7 +23,7 @@ class TestInvertedDeathMountain(TestInverted): ]) def testEastDeathMountain(self): - self.run_tests([ + self.run_location_tests([ ["Spiral Cave", False, []], ["Spiral Cave", False, [], ['Moon Pearl']], ["Spiral Cave", False, [], ['Progressive Glove', 'Ocarina']], @@ -158,7 +158,7 @@ class TestInvertedDeathMountain(TestInverted): ]) def testEastDarkWorldDeathMountain(self): - self.run_tests([ + self.run_location_tests([ ["Superbunny Cave - Top", False, []], ["Superbunny Cave - Top", False, [], ['Progressive Glove', 'Ocarina']], ["Superbunny Cave - Top", True, ['Progressive Glove', 'Lamp']], @@ -204,17 +204,17 @@ class TestInvertedDeathMountain(TestInverted): ]) def testWestDarkWorldDeathMountain(self): - self.run_tests([ + self.run_location_tests([ ["Spike Cave", False, []], ["Spike Cave", False, [], ['Progressive Glove']], ["Spike Cave", False, [], ['Hammer']], ["Spike Cave", False, [], ['Cape', 'Cane of Byrna']], ["Spike Cave", False, [], ['Cane of Byrna', 'AnyBottle', 'Magic Upgrade (1/2)']], ["Spike Cave", False, [], ['AnyBottle', 'Magic Upgrade (1/2)', 'Pegasus Boots', 'Boss Heart Container', 'Piece of Heart', 'Sanctuary Heart Container']], - ["Spike Cave", False, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']], + ["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']], # blue potion added to dark world ["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Cape']], ["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Ocarina', 'Moon Pearl', 'Cape']], - ["Spike Cave", False, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']], + ["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']], # blue potion added to dark world ["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Cane of Byrna']], ["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Ocarina', 'Moon Pearl', 'Cane of Byrna']], ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']], diff --git a/test/inverted/TestInvertedEntrances.py b/test/inverted/TestInvertedEntrances.py new file mode 100644 index 00000000..89b3e000 --- /dev/null +++ b/test/inverted/TestInvertedEntrances.py @@ -0,0 +1,118 @@ +from test.inverted.TestInverted import TestInverted + + +class TestEntrances(TestInverted): + + def testDungeonEntrances(self): + self.run_entrance_tests([ + ["Hyrule Castle Entrance (South)", False, []], + ["Hyrule Castle Entrance (South)", False, [], ["Beat Agahnim 1", "Moon Pearl"]], + ["Hyrule Castle Entrance (South)", False, [], ["Beat Agahnim 1", "Progressive Glove"]], + ["Hyrule Castle Entrance (South)", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]], + ["Hyrule Castle Entrance (South)", True, ["Beat Agahnim 1"]], + ["Hyrule Castle Entrance (South)", True, ["Moon Pearl", "Hammer", "Progressive Glove"]], + ["Hyrule Castle Entrance (South)", True, ["Moon Pearl", "Progressive Glove", "Progressive Glove"]], + + ["Eastern Palace", False, []], + ["Eastern Palace", False, [], ["Beat Agahnim 1", "Moon Pearl"]], + ["Eastern Palace", False, [], ["Beat Agahnim 1", "Progressive Glove"]], + ["Eastern Palace", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]], + ["Eastern Palace", True, ["Beat Agahnim 1"]], + ["Eastern Palace", True, ["Moon Pearl", "Hammer", "Progressive Glove"]], + ["Eastern Palace", True, ["Moon Pearl", "Progressive Glove", "Progressive Glove"]], + + ["Desert Palace Entrance (South)", False, []], + ["Desert Palace Entrance (South)", False, [], ["Book of Mudora"]], + ["Desert Palace Entrance (South)", False, [], ["Beat Agahnim 1", "Moon Pearl"]], + ["Desert Palace Entrance (South)", False, [], ["Beat Agahnim 1", "Progressive Glove"]], + ["Desert Palace Entrance (South)", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]], + ["Desert Palace Entrance (South)", True, ["Book of Mudora", "Beat Agahnim 1"]], + ["Desert Palace Entrance (South)", True, ["Book of Mudora", "Moon Pearl", "Hammer", "Progressive Glove"]], + ["Desert Palace Entrance (South)", True, ["Book of Mudora", "Moon Pearl", "Progressive Glove", "Progressive Glove"]], + ["Desert Palace Entrance (North)", False, []], + ["Desert Palace Entrance (North)", False, [], ["Book of Mudora"]], + ["Desert Palace Entrance (North)", False, [], ["Progressive Glove"]], + ["Desert Palace Entrance (North)", False, [], ["Moon Pearl"]], + ["Desert Palace Entrance (North)", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]], + ["Desert Palace Entrance (North)", True, ["Moon Pearl", "Book of Mudora", "Progressive Glove", "Hammer"]], + ["Desert Palace Entrance (North)", True, ["Moon Pearl", "Book of Mudora", "Progressive Glove", "Progressive Glove"]], + ["Desert Palace Entrance (North)", True, ["Moon Pearl", "Book of Mudora", "Progressive Glove", "Beat Agahnim 1"]], + + ["Tower of Hera", False, []], + ["Tower of Hera", False, [], ["Moon Pearl"]], + ["Tower of Hera", False, [], ["Hammer"]], + ["Tower of Hera", False, ["Progressive Glove"], ["Hookshot", "Progressive Glove"]], + ["Tower of Hera", False, [], ["Ocarina", "Lamp"]], + ["Tower of Hera", False, [], ["Ocarina", "Progressive Glove"]], + ["Tower of Hera", True, ["Moon Pearl", "Hammer", "Progressive Glove", "Progressive Glove", "Lamp"]], + ["Tower of Hera", True, ["Moon Pearl", "Hammer", "Hookshot", "Progressive Glove", "Lamp"]], + ["Tower of Hera", True, ["Moon Pearl", "Hammer", "Hookshot", "Progressive Glove", "Ocarina"]], + ["Tower of Hera", True, ["Moon Pearl", "Hammer", "Beat Agahnim 1", "Ocarina", "Hookshot"]], + + ["Inverted Agahnims Tower", False, []], + ["Inverted Agahnims Tower", False, [], ["Ocarina", "Lamp"]], + ["Inverted Agahnims Tower", False, [], ["Ocarina", "Progressive Glove"]], + ["Inverted Agahnims Tower", False, [], ["Moon Pearl", "Lamp"]], + ["Inverted Agahnims Tower", False, [], ["Moon Pearl", "Progressive Glove"]], + ["Inverted Agahnims Tower", True, ["Lamp", "Progressive Glove"]], + ["Inverted Agahnims Tower", True, ["Ocarina", "Beat Agahnim 1", "Moon Pearl"]], + ["Inverted Agahnims Tower", True, ["Ocarina", "Progressive Glove", "Progressive Glove", "Moon Pearl"]], + ["Inverted Agahnims Tower", True, ["Ocarina", "Progressive Glove", "Hammer", "Moon Pearl"]], + + ["Palace of Darkness", False, []], + ["Palace of Darkness", False, [], ["Hammer", "Flippers", "Magic Mirror", "Ocarina"]], + ["Palace of Darkness", True, ["Hammer"]], + ["Palace of Darkness", True, ["Flippers"]], + ["Palace of Darkness", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl", "Ocarina"]], + ["Palace of Darkness", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl", "Magic Mirror"]], + ["Palace of Darkness", True, ["Beat Agahnim 1", "Moon Pearl", "Ocarina"]], + ["Palace of Darkness", True, ["Beat Agahnim 1", "Moon Pearl", "Magic Mirror"]], + + ["Swamp Palace", True, []], + + ["Thieves Town", True, []], + + ["Skull Woods First Section Door", True, []], + + ["Skull Woods Final Section", False, []], + ["Skull Woods Final Section", False, [], ["Fire Rod"]], + ["Skull Woods Final Section", True, ["Fire Rod"]], + + ["Ice Palace", False, []], + ["Ice Palace", False, [], ["Flippers"]], + ["Ice Palace", True, ["Flippers"]], + + ["Misery Mire", False, []], + ["Misery Mire", False, [], ["Ocarina", "Magic Mirror"]], + ["Misery Mire", False, [], ["Moon Pearl", "Magic Mirror"]], + ["Misery Mire", False, [], ["Ether"]], + ["Misery Mire", False, [], ["Progressive Sword"]], + ["Misery Mire", True, ["Progressive Sword", "Ether", "Beat Agahnim 1", "Magic Mirror"]], + ["Misery Mire", True, ["Progressive Sword", "Ether", "Beat Agahnim 1", "Moon Pearl", "Ocarina"]], + ["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Hammer", "Progressive Glove", "Magic Mirror"]], + ["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Hammer", "Progressive Glove", "Ocarina"]], + ["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Progressive Glove", "Progressive Glove", "Magic Mirror"]], + ["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Progressive Glove", "Progressive Glove", "Ocarina"]], + + ["Turtle Rock", False, []], + ["Turtle Rock", False, [], ["Quake"]], + ["Turtle Rock", False, [], ["Progressive Sword"]], + ["Turtle Rock", False, [], ["Lamp", "Ocarina"]], + ["Turtle Rock", False, [], ["Progressive Glove", "Ocarina"]], + ["Turtle Rock", True, ["Quake", "Progressive Sword", "Progressive Glove", "Lamp"]], + ["Turtle Rock", True, ["Quake", "Progressive Sword", "Progressive Glove", "Progressive Glove", "Moon Pearl", "Ocarina"]], + ["Turtle Rock", True, ["Quake", "Progressive Sword", "Progressive Glove", "Hammer", "Moon Pearl", "Ocarina"]], + ["Turtle Rock", True, ["Quake", "Progressive Sword", "Beat Agahnim 1", "Moon Pearl", "Ocarina"]], + + ["Inverted Ganons Tower", False, []], + ["Inverted Ganons Tower", False, [], ["Crystal 1"]], + ["Inverted Ganons Tower", False, [], ["Crystal 2"]], + ["Inverted Ganons Tower", False, [], ["Crystal 3"]], + ["Inverted Ganons Tower", False, [], ["Crystal 4"]], + ["Inverted Ganons Tower", False, [], ["Crystal 5"]], + ["Inverted Ganons Tower", False, [], ["Crystal 6"]], + ["Inverted Ganons Tower", False, [], ["Crystal 7"]], + ["Inverted Ganons Tower", True, ["Beat Agahnim 1", "Crystal 1", "Crystal 2", "Crystal 3", "Crystal 4", "Crystal 5", "Crystal 6", "Crystal 7"]], + ["Inverted Ganons Tower", True, ["Moon Pearl", "Progressive Glove", "Progressive Glove", "Crystal 1", "Crystal 2", "Crystal 3", "Crystal 4", "Crystal 5", "Crystal 6", "Crystal 7"]], + ["Inverted Ganons Tower", True, ["Moon Pearl", "Hammer", "Progressive Glove", "Progressive Glove", "Crystal 1", "Crystal 2", "Crystal 3", "Crystal 4", "Crystal 5", "Crystal 6", "Crystal 7"]], + ]) \ No newline at end of file diff --git a/test/inverted/TestInvertedLightWorld.py b/test/inverted/TestInvertedLightWorld.py index 6a1e5baf..014ccb66 100644 --- a/test/inverted/TestInvertedLightWorld.py +++ b/test/inverted/TestInvertedLightWorld.py @@ -6,7 +6,7 @@ class TestInvertedLightWorld(TestInverted): super().setUp() def testLostWoods(self): - self.run_tests([ + self.run_location_tests([ ["Master Sword Pedestal", False, []], ["Master Sword Pedestal", False, [], ['Green Pendant']], ["Master Sword Pedestal", False, [], ['Red Pendant']], @@ -37,7 +37,7 @@ class TestInvertedLightWorld(TestInverted): ]) def testKakariko(self): - self.run_tests([ + self.run_location_tests([ ["Kakariko Tavern", False, []], ["Kakariko Tavern", False, [], ['Moon Pearl']], ["Kakariko Tavern", True, ['Moon Pearl', 'Beat Agahnim 1']], @@ -171,7 +171,7 @@ class TestInvertedLightWorld(TestInverted): ]) def testSouthLightWorld(self): - self.run_tests([ + self.run_location_tests([ ["Desert Ledge", False, []], ["Desert Ledge", False, [], ['Book of Mudora']], ["Desert Ledge", False, [], ['Moon Pearl']], @@ -251,7 +251,7 @@ class TestInvertedLightWorld(TestInverted): ]) def testZoraArea(self): - self.run_tests([ + self.run_location_tests([ ["King Zora", False, []], ["King Zora", False, [], ['Progressive Glove', 'Flippers']], ["King Zora", False, [], ['Moon Pearl']], @@ -284,7 +284,7 @@ class TestInvertedLightWorld(TestInverted): ]) def testLightWorld(self): - self.run_tests([ + self.run_location_tests([ ["Link's Uncle", False, []], ["Link's Uncle", False, [], ['Moon Pearl']], ["Link's Uncle", True, ['Moon Pearl', 'Beat Agahnim 1']], diff --git a/test/inverted/TestInvertedTurtleRock.py b/test/inverted/TestInvertedTurtleRock.py index 7975abeb..63fc840b 100644 --- a/test/inverted/TestInvertedTurtleRock.py +++ b/test/inverted/TestInvertedTurtleRock.py @@ -4,7 +4,8 @@ from test.inverted.TestInverted import TestInverted class TestInvertedTurtleRock(TestInverted): def testTurtleRock(self): - self.run_tests([ + return # Door rando makes this harder + self.run_location_tests([ ["Turtle Rock - Compass Chest", False, []], ["Turtle Rock - Compass Chest", False, [], ['Cane of Somaria']], ["Turtle Rock - Compass Chest", False, [], ['Quake', 'Magic Mirror']], diff --git a/test/inverted_owg/TestDarkWorld.py b/test/inverted_owg/TestDarkWorld.py new file mode 100644 index 00000000..89dff120 --- /dev/null +++ b/test/inverted_owg/TestDarkWorld.py @@ -0,0 +1,78 @@ +from test.inverted_owg.TestInvertedOWG import TestInvertedOWG + + +class TestDarkWorld(TestInvertedOWG): + + def testSouthDarkWorld(self): + self.run_location_tests([ + ["Hype Cave - Top", True, []], + + ["Hype Cave - Middle Right", True, []], + + ["Hype Cave - Middle Left", True, []], + + ["Hype Cave - Bottom", True, []], + + ["Hype Cave - Generous Guy", True, []], + + ["Stumpy", True, []], + + ["Digging Game", True, []], + ]) + + def testWestDarkWorld(self): + self.run_location_tests([ + ["Brewery", True, []], + + ["C-Shaped House", True, []], + + ["Chest Game", True, []], + + ["Peg Cave", False, []], + ["Peg Cave", False, [], ['Hammer']], + ["Peg Cave", True, ['Hammer', 'Pegasus Boots']], + + ["Bumper Cave Ledge", False, []], + ["Bumper Cave Ledge", True, ['Pegasus Boots']], + + ["Blacksmith", False, []], + ["Blacksmith", True, ['Magic Mirror', 'Pegasus Boots']], + ["Blacksmith", True, ['Progressive Glove', 'Progressive Glove', 'Pegasus Boots', 'Moon Pearl']], + + ["Purple Chest", False, []], + ["Purple Chest", True, ['Magic Mirror', 'Pegasus Boots']], + ["Purple Chest", True, ['Progressive Glove', 'Progressive Glove', 'Pegasus Boots', 'Moon Pearl']], + ]) + + def testEastDarkWorld(self): + self.run_location_tests([ + ["Catfish", False, []], + ["Catfish", True, ['Pegasus Boots']], + + #todo: Qirn Jump + #["Pyramid", True, []], + ["Pyramid", False, []], + ["Pyramid", True, ['Pegasus Boots']], + ["Pyramid", True, ['Flippers']], + + ["Pyramid Fairy - Left", False, []], + ["Pyramid Fairy - Left", False, [], ['Magic Mirror']], + ["Pyramid Fairy - Left", False, [], ['Crystal 5']], + ["Pyramid Fairy - Left", False, [], ['Crystal 6']], + ["Pyramid Fairy - Left", True, ['Crystal 5', 'Crystal 6', 'Magic Mirror', 'Pegasus Boots']], + + ["Pyramid Fairy - Right", False, []], + ["Pyramid Fairy - Right", False, [], ['Magic Mirror']], + ["Pyramid Fairy - Right", False, [], ['Crystal 5']], + ["Pyramid Fairy - Right", False, [], ['Crystal 6']], + ["Pyramid Fairy - Right", True, ['Crystal 5', 'Crystal 6', 'Magic Mirror', 'Pegasus Boots']], + ]) + + def testMireArea(self): + self.run_location_tests([ + ["Mire Shed - Left", False, []], + ["Mire Shed - Left", True, ['Pegasus Boots']], + + ["Mire Shed - Right", False, []], + ["Mire Shed - Right", True, ['Pegasus Boots']], + ]) \ No newline at end of file diff --git a/test/inverted_owg/TestDeathMountain.py b/test/inverted_owg/TestDeathMountain.py new file mode 100644 index 00000000..093331c2 --- /dev/null +++ b/test/inverted_owg/TestDeathMountain.py @@ -0,0 +1,113 @@ +from test.inverted_owg.TestInvertedOWG import TestInvertedOWG + + +class TestDeathMountain(TestInvertedOWG): + + def testWestDeathMountain(self): + self.run_location_tests([ + ["Old Man", False, []], + ["Old Man", False, [], ['Lamp']], + ["Old Man", True, ['Pegasus Boots', 'Lamp']], + + ["Spectacle Rock Cave", False, []], + ["Spectacle Rock Cave", True, ['Pegasus Boots']], + ]) + + 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']], + + ["Paradox Cave Lower - Far Left", False, []], + ["Paradox Cave Lower - Far Left", False, [], ['Moon Pearl']], + ["Paradox Cave Lower - Far Left", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Paradox Cave Lower - Left", False, []], + ["Paradox Cave Lower - Left", False, [], ['Moon Pearl']], + ["Paradox Cave Lower - Left", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Paradox Cave Lower - Middle", False, []], + ["Paradox Cave Lower - Middle", False, [], ['Moon Pearl']], + ["Paradox Cave Lower - Middle", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Paradox Cave Lower - Right", False, []], + ["Paradox Cave Lower - Right", False, [], ['Moon Pearl']], + ["Paradox Cave Lower - Right", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Paradox Cave Lower - Far Right", False, []], + ["Paradox Cave Lower - Far Right", False, [], ['Moon Pearl']], + ["Paradox Cave Lower - Far Right", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Paradox Cave Upper - Left", False, []], + ["Paradox Cave Upper - Left", False, [], ['Moon Pearl']], + ["Paradox Cave Upper - Left", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Paradox Cave Upper - Right", False, []], + ["Paradox Cave Upper - Right", False, [], ['Moon Pearl']], + ["Paradox Cave Upper - Right", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Mimic Cave", False, []], + ["Mimic Cave", False, [], ['Moon Pearl']], + ["Mimic Cave", False, [], ['Hammer']], + ["Mimic Cave", True, ['Moon Pearl', 'Hammer', 'Pegasus Boots']], + + ["Ether Tablet", False, []], + ["Ether Tablet", False, ['Progressive Sword'], ['Progressive Sword']], + ["Ether Tablet", False, [], ['Book of Mudora']], + ["Ether Tablet", False, [], ['Moon Pearl']], + ["Ether Tablet", True, ['Pegasus Boots', 'Moon Pearl', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + + ["Spectacle Rock", False, []], + ["Spectacle Rock", False, [], ['Moon Pearl']], + ["Spectacle Rock", True, ['Moon Pearl', 'Pegasus Boots']], + ]) + + + def testWestDarkWorldDeathMountain(self): + self.run_location_tests([ + ["Spike Cave", False, []], + ["Spike Cave", False, [], ['Progressive Glove']], + ["Spike Cave", False, [], ['Hammer']], + ["Spike Cave", False, [], ['Cape', 'Cane of Byrna']], + # ER doesn't put in an extra potion + #["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Pegasus Boots', 'Cape']], + ["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Pegasus Boots', 'Cape', 'Moon Pearl']], + ["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Pegasus Boots', 'Cane of Byrna']], + ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Pegasus Boots', 'Cape']], + ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Pegasus Boots', 'Cane of Byrna']], + ["Spike Cave", True, ['Magic Upgrade (1/4)', 'Hammer', 'Progressive Glove', 'Pegasus Boots', 'Cape']], + ["Spike Cave", True, ['Magic Upgrade (1/4)', 'Hammer', 'Progressive Glove', 'Pegasus Boots', 'Cane of Byrna']], + ]) + + def testEastDarkWorldDeathMountain(self): + self.run_location_tests([ + ["Superbunny Cave - Top", False, []], + ["Superbunny Cave - Top", True, ['Pegasus Boots']], + + ["Superbunny Cave - Bottom", False, []], + ["Superbunny Cave - Bottom", True, ['Pegasus Boots']], + + ["Hookshot Cave - Bottom Right", False, []], + ["Hookshot Cave - Bottom Right", False, [], ['Hookshot', 'Pegasus Boots']], + ["Hookshot Cave - Bottom Right", False, [], ['Progressive Glove', 'Pegasus Boots', 'Magic Mirror']], + ["Hookshot Cave - Bottom Right", True, ['Pegasus Boots']], + + ["Hookshot Cave - Bottom Left", False, []], + ["Hookshot Cave - Bottom Left", False, [], ['Hookshot']], + ["Hookshot Cave - Bottom Left", False, [], ['Progressive Glove', 'Pegasus Boots', 'Magic Mirror']], + ["Hookshot Cave - Bottom Left", True, ['Pegasus Boots', 'Hookshot']], + + ["Hookshot Cave - Top Left", False, []], + ["Hookshot Cave - Top Left", False, [], ['Hookshot']], + ["Hookshot Cave - Top Left", False, [], ['Progressive Glove', 'Pegasus Boots', 'Magic Mirror']], + ["Hookshot Cave - Top Left", True, ['Pegasus Boots', 'Hookshot']], + + ["Hookshot Cave - Top Right", False, []], + ["Hookshot Cave - Top Right", False, [], ['Hookshot']], + ["Hookshot Cave - Top Right", False, [], ['Progressive Glove', 'Pegasus Boots', 'Magic Mirror']], + ["Hookshot Cave - Top Right", True, ['Pegasus Boots', 'Hookshot']], + ]) \ No newline at end of file diff --git a/test/inverted_owg/TestDungeons.py b/test/inverted_owg/TestDungeons.py new file mode 100644 index 00000000..72cdb1aa --- /dev/null +++ b/test/inverted_owg/TestDungeons.py @@ -0,0 +1,116 @@ +from test.inverted_owg.TestInvertedOWG import TestInvertedOWG + +class TestDungeons(TestInvertedOWG): + + def testFirstDungeonChests(self): + self.run_location_tests([ + ["Hyrule Castle - Map Chest", False, []], + ["Hyrule Castle - Map Chest", True, ['Beat Agahnim 1']], + ["Hyrule Castle - Map Chest", True, ['Moon Pearl', 'Pegasus Boots']], + ["Hyrule Castle - Map Chest", True, ['Magic Mirror', 'Pegasus Boots']], + + ["Sanctuary", False, []], + ["Sanctuary", False, ['Beat Agahnim 1']], + ["Sanctuary", True, ['Magic Mirror', 'Beat Agahnim 1']], + ["Sanctuary", True, ['Lamp', 'Beat Agahnim 1', 'Small Key (Escape)']], + ["Sanctuary", True, ['Moon Pearl', 'Pegasus Boots']], + ["Sanctuary", True, ['Magic Mirror', 'Pegasus Boots']], + + ["Sewers - Secret Room - Left", False, []], + ["Sewers - Secret Room - Left", True, ['Moon Pearl', 'Progressive Glove', 'Pegasus Boots']], + ["Sewers - Secret Room - Left", True, ['Moon Pearl', 'Pegasus Boots', 'Lamp', 'Small Key (Escape)']], + ["Sewers - Secret Room - Left", True, + ['Magic Mirror', 'Pegasus Boots', 'Lamp', 'Small Key (Escape)']], + ["Sewers - Secret Room - Left", True, ['Beat Agahnim 1', 'Lamp', 'Small Key (Escape)']], + + ["Eastern Palace - Compass Chest", False, []], + ["Eastern Palace - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots']], + ["Eastern Palace - Compass Chest", True, ['Magic Mirror', 'Pegasus Boots']], + ["Eastern Palace - Compass Chest", True, ['Beat Agahnim 1']], + + ["Desert Palace - Map Chest", False, []], + ["Desert Palace - Map Chest", True, ['Moon Pearl', 'Pegasus Boots']], + ["Desert Palace - Map Chest", True, ['Book of Mudora', 'Magic Mirror', 'Pegasus Boots']], + + ["Desert Palace - Boss", False, []], + ["Desert Palace - Boss", False, [], ['Small Key (Desert Palace)']], + ["Desert Palace - Boss", False, [], ['Big Key (Desert Palace)']], + ["Desert Palace - Boss", False, [], ['Lamp', 'Fire Rod']], + ["Desert Palace - Boss", True, ['Progressive Sword', 'Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Moon Pearl', 'Pegasus Boots', 'Lamp']], + ["Desert Palace - Boss", True, ['Progressive Sword', 'Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Moon Pearl', 'Pegasus Boots', 'Fire Rod']], + + ["Tower of Hera - Basement Cage", False, []], + ["Tower of Hera - Basement Cage", False, [], ['Moon Pearl']], + ["Tower of Hera - Basement Cage", True, ['Pegasus Boots', 'Moon Pearl']], + + ["Castle Tower - Room 03", False, []], + ["Castle Tower - Room 03", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], + ["Castle Tower - Room 03", True, ['Pegasus Boots', 'Progressive Sword']], + ["Castle Tower - Room 03", True, ['Pegasus Boots', 'Progressive Bow']], + + #todo: Qirn Jump + #["Palace of Darkness - Shooter Room", True, []], + ["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']], + ["Palace of Darkness - Shooter Room", True, ['Pegasus Boots', 'Magic Mirror']], + + ["Swamp Palace - Entrance", False, []], + ["Swamp Palace - Entrance", False, [], ['Magic Mirror']], + ["Swamp Palace - Entrance", False, [], ['Flippers']], + ["Swamp Palace - Entrance", True, ['Magic Mirror', 'Flippers', 'Pegasus Boots']], + ["Swamp Palace - Entrance", True, ['Magic Mirror', 'Flippers', 'Beat Agahnim 1']], + + ["Skull Woods - Compass Chest", True, []], + + ["Skull Woods - Big Chest", False, []], + ["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']], + ["Skull Woods - Big Chest", True, ['Big Key (Skull Woods)']], + + ["Skull Woods - Big Key Chest", True, []], + + ["Skull Woods - Bridge Room", False, []], + ["Skull Woods - Bridge Room", False, [], ['Fire Rod']], + ["Skull Woods - Bridge Room", True, ['Fire Rod']], + + ["Thieves' Town - Map Chest", True, []], + + ["Ice Palace - Compass Chest", False, []], + ["Ice Palace - Compass Chest", False, [], ['Fire Rod', 'Bombos', 'Progressive Sword']], + #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', 'Fire Rod']], + ["Ice Palace - Compass Chest", True, ['Pegasus Boots', 'Bombos', 'Progressive Sword', 'Small Key (Ice Palace)']], + + ["Misery Mire - Bridge Chest", False, []], + ["Misery Mire - Bridge Chest", False, [], ['Ether']], + ["Misery Mire - Bridge Chest", False, [], ['Progressive Sword']], + ["Misery Mire - Bridge Chest", True, ['Pegasus Boots', 'Ether', 'Progressive Sword']], + + ["Turtle Rock - Compass Chest", False, []], + ["Turtle Rock - Compass Chest", False, [], ['Cane of Somaria']], + ["Turtle Rock - Compass Chest", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Compass Chest", True, ['Pegasus Boots', 'Quake', 'Progressive Sword', 'Cane of Somaria']], + + ["Turtle Rock - Chain Chomps", False, []], + ["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl']], + + ["Turtle Rock - Crystaroller Room", False, []], + ["Turtle Rock - Crystaroller Room", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl', 'Big Key (Turtle Rock)']], + ["Turtle Rock - Crystaroller Room", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl', 'Lamp', 'Cane of Somaria']], + + ["Ganons Tower - Hope Room - Left", False, []], + ["Ganons Tower - Hope Room - Left", False, [], ['Crystal 1']], + ["Ganons Tower - Hope Room - Left", False, [], ['Crystal 2']], + ["Ganons Tower - Hope Room - Left", False, [], ['Crystal 3']], + ["Ganons Tower - Hope Room - Left", False, [], ['Crystal 4']], + ["Ganons Tower - Hope Room - Left", False, [], ['Crystal 5']], + ["Ganons Tower - Hope Room - Left", False, [], ['Crystal 6']], + ["Ganons Tower - Hope Room - Left", False, [], ['Crystal 7']], + #todo: smarter dungeon revive logic + #["Ganons Tower - Hope Room - Left", True, ['Beat Agahnim 1', 'Hookshot', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7']], + #["Ganons Tower - Hope Room - Left", True, ['Pegasus Boots', 'Magic Mirror', 'Hookshot', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7']], + ["Ganons Tower - Hope Room - Left", True, ['Pegasus Boots', 'Moon Pearl', 'Hookshot', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7']], + ]) \ No newline at end of file diff --git a/test/inverted_owg/TestInvertedOWG.py b/test/inverted_owg/TestInvertedOWG.py new file mode 100644 index 00000000..b772468f --- /dev/null +++ b/test/inverted_owg/TestInvertedOWG.py @@ -0,0 +1,40 @@ +from BaseClasses import World +from DoorShuffle import link_doors +from Doors import create_doors +from Dungeons import create_dungeons, get_dungeon_item_pool +from EntranceShuffle import link_inverted_entrances +from InvertedRegions import create_inverted_regions +from ItemList import generate_itempool, difficulties +from Items import ItemFactory +from OverworldGlitchRules import create_owg_connections +from Regions import mark_light_world_regions, create_dungeon_regions, create_shops +from RoomData import create_rooms +from Rules import set_rules +from test.TestBase import TestBase + + +class TestInvertedOWG(TestBase): + def setUp(self): + self.world = World(1, {1: 'vanilla'}, {1: 'vanilla'}, {1: 'owglitches'}, {1: 'inverted'}, {1: 'random'}, {1: 'normal'}, {1: 'normal'}, 'none', 'on', {1: 'ganon'}, 'balanced', {1: 'items'}, + {1: True}, {1: False}, False, None, {1: False}) + self.world.difficulty_requirements[1] = difficulties['normal'] + self.world.intensity = {1: 1} + create_inverted_regions(self.world, 1) + create_dungeon_regions(self.world, 1) + create_shops(self.world, 1) + create_doors(self.world, 1) + create_rooms(self.world, 1) + create_dungeons(self.world, 1) + create_owg_connections(self.world, 1) + link_inverted_entrances(self.world, 1) + link_doors(self.world, 1) + generate_itempool(self.world, 1) + self.world.required_medallions[1] = ['Ether', 'Quake'] + self.world.itempool.extend(get_dungeon_item_pool(self.world)) + self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) + self.world.get_location('Agahnim 1', 1).item = None + self.world.get_location('Agahnim 2', 1).item = None + self.world.precollected_items.clear() + self.world.itempool.append(ItemFactory('Pegasus Boots', 1)) + mark_light_world_regions(self.world, 1) + set_rules(self.world, 1) diff --git a/test/inverted_owg/TestLightWorld.py b/test/inverted_owg/TestLightWorld.py new file mode 100644 index 00000000..ad833017 --- /dev/null +++ b/test/inverted_owg/TestLightWorld.py @@ -0,0 +1,312 @@ +from test.inverted_owg.TestInvertedOWG import TestInvertedOWG + + +class TestLightWorld(TestInvertedOWG): + + def testLightWorld(self): + self.run_location_tests([ + ["Master Sword Pedestal", False, []], + ["Master Sword Pedestal", False, [], ['Green Pendant']], + ["Master Sword Pedestal", False, [], ['Red Pendant']], + ["Master Sword Pedestal", False, [], ['Blue Pendant']], + ["Master Sword Pedestal", True, ['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Moon Pearl', 'Pegasus Boots']], + ["Master Sword Pedestal", True, ['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Magic Mirror', 'Pegasus Boots']], + + ["Link's Uncle", False, []], + ["Link's Uncle", False, [], ['Moon Pearl']], + ["Link's Uncle", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Secret Passage", False, []], + ["Secret Passage", False, [], ['Moon Pearl']], + ["Secret Passage", True, ['Moon Pearl', 'Pegasus Boots']], + + ["King's Tomb", False, []], + ["King's Tomb", False, [], ['Pegasus Boots']], + ["King's Tomb", False, [], ['Moon Pearl']], + ["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']], + + ["Kakariko Tavern", False, []], + ["Kakariko Tavern", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Kakariko Tavern", True, ['Moon Pearl', 'Pegasus Boots']], + ["Kakariko Tavern", True, ['Magic Mirror', 'Pegasus Boots']], + ["Kakariko Tavern", True, ['Beat Agahnim 1', 'Moon Pearl']], + ["Kakariko Tavern", True, ['Beat Agahnim 1', 'Magic Mirror']], + + ["Chicken House", False, []], + ["Chicken House", False, [], ['Moon Pearl']], + ["Chicken House", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Aginah's Cave", False, []], + ["Aginah's Cave", False, [], ['Moon Pearl']], + ["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', 'Pegasus Boots']], + ["Sahasrahla's Hut - Left", True, ['Moon Pearl', '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', '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, ['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', '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, ['Beat Agahnim 1', 'Pegasus Boots']], + ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], + + ["Kakariko Well - Top", False, []], + ["Kakariko Well - Top", False, [], ['Moon Pearl']], + ["Kakariko Well - Top", True, ['Moon Pearl', 'Pegasus Boots']], + + ["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, []], + ["Blind's Hideout - Top", False, [], ['Moon Pearl']], + ["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']], + + ["Bonk Rock Cave", False, []], + ["Bonk Rock Cave", False, [], ['Pegasus Boots']], + ["Bonk Rock Cave", False, [], ['Moon Pearl']], + ["Bonk Rock Cave", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Mini Moldorm Cave - Far Left", False, []], + ["Mini Moldorm Cave - Far Left", False, [], ['Moon Pearl']], + ["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Pegasus Boots']], + + ["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']], + ["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Pegasus Boots']], + + ["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']], + ["Ice Rod Cave", True, ['Moon Pearl', 'Pegasus Boots']], + #I don't think so + #["Ice Rod Cave", True, ['Magic Mirror', 'Pegasus Boots', 'BigRedBomb']], + #["Ice Rod Cave", True, ['Magic Mirror', 'Beat Agahnim 1', 'BigRedBomb']], + + ["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']], + ["Magic Bat", False, [], ['Moon Pearl']], + ["Magic Bat", True, ['Magic Powder', 'Pegasus Boots', 'Moon Pearl']], + + ["Sick Kid", False, []], + ["Sick Kid", False, [], ['AnyBottle']], + ["Sick Kid", False, ['Bottle (Bee)']], + ["Sick Kid", False, ['Bottle (Fairy)']], + ["Sick Kid", False, ['Bottle (Red Potion)']], + ["Sick Kid", False, ['Bottle (Green Potion)']], + ["Sick Kid", False, ['Bottle (Blue Potion)']], + ["Sick Kid", False, ['Bottle']], + ["Sick Kid", False, ['Bottle (Good Bee)']], + ["Sick Kid", True, ['Bottle (Bee)', 'Magic Mirror', 'Pegasus Boots']], + ["Sick Kid", True, ['Bottle (Bee)', 'Moon Pearl', 'Pegasus Boots']], + ["Sick Kid", True, ['Bottle (Fairy)', 'Magic Mirror', 'Pegasus Boots']], + ["Sick Kid", True, ['Bottle (Fairy)', 'Moon Pearl', 'Pegasus Boots']], + ["Sick Kid", True, ['Bottle (Red Potion)', 'Magic Mirror', 'Pegasus Boots']], + ["Sick Kid", True, ['Bottle (Red Potion)', 'Moon Pearl', 'Pegasus Boots']], + ["Sick Kid", True, ['Bottle (Green Potion)', 'Magic Mirror', 'Pegasus Boots']], + ["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 (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']], + ["Hobo", True, ['Moon Pearl', 'Pegasus Boots']], + ["Hobo", True, ['Moon Pearl', 'Beat Agahnim 1']], + + ["Bombos Tablet", False, []], + ["Bombos Tablet", False, ['Progressive Sword'], ['Progressive Sword']], + ["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']], + ["King Zora", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Lost Woods Hideout", False, []], + ["Lost Woods Hideout", False, [], ['Moon Pearl']], + ["Lost Woods Hideout", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Lumberjack Tree", False, []], + ["Lumberjack Tree", False, [], ['Beat Agahnim 1']], + ["Lumberjack Tree", False, [], ['Pegasus Boots']], + ["Lumberjack Tree", False, [], ['Moon Pearl']], + ["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']], + + ["Graveyard Cave", False, []], + ["Graveyard Cave", False, [], ['Moon Pearl']], + ["Graveyard Cave", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Checkerboard Cave", False, []], + ["Checkerboard Cave", False, [], ['Progressive Glove']], + ["Checkerboard Cave", False, [], ['Moon Pearl']], + ["Checkerboard Cave", True, ['Progressive Glove', 'Pegasus Boots', 'Moon Pearl']], + + ["Library", False, []], + ["Library", False, [], ['Pegasus Boots']], + ["Library", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Library", True, ['Pegasus Boots', 'Moon Pearl']], + ["Library", True, ['Pegasus Boots', 'Magic Mirror']], + + ["Mushroom", False, []], + ["Mushroom", False, [], ['Moon Pearl']], + ["Mushroom", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Potion Shop", False, []], + ["Potion Shop", False, [], ['Mushroom']], + ["Potion Shop", False, [], ['Moon Pearl']], + ["Potion Shop", True, ['Mushroom', 'Moon Pearl', 'Pegasus Boots']], + + ["Maze Race", False, []], + ["Maze Race", False, [], ['Moon Pearl']], + ["Maze Race", True, ['Moon Pearl', 'Pegasus Boots']], + + ["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']], + + ["Lake Hylia Island", False, []], + ["Lake Hylia Island", False, [], ['Moon Pearl']], + ["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']], + + ["Zora's Ledge", False, []], + ["Zora's Ledge", False, [], ['Moon Pearl']], + ["Zora's Ledge", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Flute Spot", False, []], + ["Flute Spot", False, [], ['Shovel']], + ["Flute Spot", False, [], ['Moon Pearl']], + ["Flute Spot", True, ['Shovel', 'Moon Pearl', 'Pegasus Boots']], + + ["Waterfall Fairy - Left", False, []], + ["Waterfall Fairy - Left", False, [], ['Moon Pearl']], + ["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']], + ["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, []], + # ["Bomb Merchant", False, [], ['Crystal 5']], + # ["Bomb Merchant", False, [], ['Crystal 6']], + # ["Bomb Merchant", True, ['Crystal 5', 'Crystal 6', 'Moon Pearl', 'Pegasus Boots']], + # ["Bomb Merchant", True, ['Crystal 5', 'Crystal 6', 'Magic Mirror', 'Pegasus Boots']], + # ["Bomb Merchant", True, ['Crystal 5', 'Crystal 6', 'Beat Agahnim 1']], + + ["Ganon", False, []], + ]) \ No newline at end of file diff --git a/test/inverted_owg/__init__.py b/test/inverted_owg/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/owg/TestDarkWorld.py b/test/owg/TestDarkWorld.py new file mode 100644 index 00000000..a5f9ed0f --- /dev/null +++ b/test/owg/TestDarkWorld.py @@ -0,0 +1,206 @@ +from test.owg.TestVanillaOWG import TestVanillaOWG + + +class TestDarkWorld(TestVanillaOWG): + + def testSouthDarkWorld(self): + self.run_location_tests([ + ["Hype Cave - Top", False, []], + ["Hype Cave - Top", False, [], ['Moon Pearl']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Pegasus Boots']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Hype Cave - Middle Right", False, []], + ["Hype Cave - Middle Right", False, [], ['Moon Pearl']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Pegasus Boots']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Hype Cave - Middle Left", False, []], + ["Hype Cave - Middle Left", False, [], ['Moon Pearl']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Pegasus Boots']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Hype Cave - Bottom", False, []], + ["Hype Cave - Bottom", False, [], ['Moon Pearl']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Pegasus Boots']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Hype Cave - Generous Guy", False, []], + ["Hype Cave - Generous Guy", False, [], ['Moon Pearl']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Pegasus Boots']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Stumpy", False, []], + ["Stumpy", False, [], ['Moon Pearl']], + ["Stumpy", True, ['Moon Pearl', 'Pegasus Boots']], + ["Stumpy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Stumpy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Stumpy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Stumpy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Stumpy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Digging Game", False, []], + ["Digging Game", False, [], ['Moon Pearl']], + ["Digging Game", True, ['Moon Pearl', 'Pegasus Boots']], + ["Digging Game", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Digging Game", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Digging Game", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Digging Game", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Digging Game", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']] + ]) + + def testEastDarkWorld(self): + self.run_location_tests([ + ["Catfish", False, []], + ["Catfish", False, [], ['Moon Pearl']], + ["Catfish", False, [], ['Progressive Glove', 'Pegasus Boots']], + ["Catfish", True, ['Moon Pearl', 'Pegasus Boots']], + ["Catfish", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove']], + ["Catfish", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Catfish", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Flippers']], + + ["Pyramid", False, []], + ["Pyramid", False, [], ['Beat Agahnim 1', 'Moon Pearl', 'Magic Mirror']], + ["Pyramid", False, [], ['Beat Agahnim 1', 'Moon Pearl', 'Pegasus Boots']], + ["Pyramid", True, ['Moon Pearl', 'Pegasus Boots']], + ["Pyramid", True, ['Magic Mirror', 'Pegasus Boots']], + ["Pyramid", True, ['Beat Agahnim 1']], + ["Pyramid", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Pyramid", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Flippers']], + + ["Pyramid Fairy - Left", False, []], + ["Pyramid Fairy - Left", False, [], ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']], + ["Pyramid Fairy - Left", False, [], ['Pegasus Boots', 'Moon Pearl', 'Crystal 5']], + ["Pyramid Fairy - Left", False, [], ['Pegasus Boots', 'Moon Pearl', 'Crystal 6']], + ["Pyramid Fairy - Left", False, [], ['Magic Mirror', 'Crystal 5']], + ["Pyramid Fairy - Left", False, [], ['Magic Mirror', 'Crystal 6']], + ["Pyramid Fairy - Left", False, [], ['Magic Mirror', 'Moon Pearl']], + ["Pyramid Fairy - Left", True, ['Magic Mirror', 'Pegasus Boots']], + ["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Hammer']], + ["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Progressive Glove', 'Hammer']], + ["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']], + ["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot', 'Magic Mirror']], + ["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Flippers', 'Hookshot', 'Magic Mirror']], + ["Pyramid Fairy - Left", True, ['Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Ocarina', 'Magic Mirror']], + ["Pyramid Fairy - Left", True, ['Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Lamp', 'Magic Mirror']], + + ["Pyramid Fairy - Right", False, []], + ["Pyramid Fairy - Right", False, [], ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']], + ["Pyramid Fairy - Right", False, [], ['Pegasus Boots', 'Moon Pearl', 'Crystal 5']], + ["Pyramid Fairy - Right", False, [], ['Pegasus Boots', 'Moon Pearl', 'Crystal 6']], + ["Pyramid Fairy - Right", False, [], ['Magic Mirror', 'Crystal 5']], + ["Pyramid Fairy - Right", False, [], ['Magic Mirror', 'Crystal 6']], + ["Pyramid Fairy - Right", False, [], ['Magic Mirror', 'Moon Pearl']], + ["Pyramid Fairy - Right", True, ['Magic Mirror', 'Pegasus Boots']], + ["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Hammer']], + ["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Progressive Glove', 'Hammer']], + ["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']], + ["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot', 'Magic Mirror']], + ["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Flippers', 'Hookshot', 'Magic Mirror']], + ["Pyramid Fairy - Right", True, ['Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Ocarina', 'Magic Mirror']], + ["Pyramid Fairy - Right", True, ['Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Lamp', 'Magic Mirror']], + + ["Ganon", False, []], + ["Ganon", False, [], ['Moon Pearl']], + ["Ganon", False, [], ['Beat Agahnim 2']], + ]) + + def testWestDarkWorld(self): + self.run_location_tests([ + ["Brewery", False, []], + ["Brewery", False, [], ['Moon Pearl']], + ["Brewery", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot', 'Progressive Glove']], + ["Brewery", True, ['Moon Pearl', 'Pegasus Boots']], + ["Brewery", True, ['Moon Pearl', 'Ocarina', 'Magic Mirror']], + ["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["C-Shaped House", False, []], + ["C-Shaped House", False, [], ['Moon Pearl', 'Magic Mirror']], + ["C-Shaped House", True, ['Moon Pearl', 'Pegasus Boots']], + ["C-Shaped House", True, ['Magic Mirror', 'Pegasus Boots']], + ["C-Shaped House", True, ['Magic Mirror', 'Ocarina']], + ["C-Shaped House", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["C-Shaped House", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["C-Shaped House", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["C-Shaped House", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Chest Game", False, []], + ["Chest Game", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Chest Game", True, ['Moon Pearl', 'Pegasus Boots']], + ["Chest Game", True, ['Magic Mirror', 'Pegasus Boots']], + ["Chest Game", True, ['Magic Mirror', 'Ocarina']], + ["Chest Game", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Chest Game", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Chest Game", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Chest Game", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Peg Cave", False, []], + ["Peg Cave", False, [], ['Moon Pearl']], + ["Peg Cave", False, [], ['Hammer']], + ["Peg Cave", False, ['Progressive Glove'], ['Pegasus Boots', 'Progressive Glove']], + ["Peg Cave", True, ['Moon Pearl', 'Hammer', 'Pegasus Boots']], + ["Peg Cave", True, ['Moon Pearl', 'Hammer', 'Progressive Glove', 'Progressive Glove']], + + ["Bumper Cave Ledge", False, []], + ["Bumper Cave Ledge", False, [], ['Moon Pearl']], + ["Bumper Cave Ledge", False, [], ['Cape', 'Pegasus Boots']], + ["Bumper Cave Ledge", False, [], ['Progressive Glove', 'Pegasus Boots']], + ["Bumper Cave Ledge", True, ['Moon Pearl', 'Pegasus Boots']], + ["Bumper Cave Ledge", True, ['Moon Pearl', 'Cape', 'Progressive Glove', 'Progressive Glove']], + ["Bumper Cave Ledge", True, ['Moon Pearl', 'Cape', 'Progressive Glove', 'Hammer']], + ["Bumper Cave Ledge", True, ['Moon Pearl', 'Cape', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + + ["Blacksmith", False, []], + ["Blacksmith", False, ['Progressive Glove'], ['Progressive Glove']], + ["Blacksmith", False, [], ['Moon Pearl']], + ["Blacksmith", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + + ["Purple Chest", False, []], + ["Purple Chest", False, ['Progressive Glove'], ['Progressive Glove']], + ["Purple Chest", False, [], ['Moon Pearl']], + ["Purple Chest", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']] + + + ]) + + def testMireArea(self): + self.run_location_tests([ + ["Mire Shed - Left", False, []], + ["Mire Shed - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Pegasus Boots']], + ["Mire Shed - Left", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Mire Shed - Left", False, [], ['Ocarina', 'Pegasus Boots']], + ["Mire Shed - Left", True, ['Moon Pearl', 'Ocarina', 'Progressive Glove', 'Progressive Glove']], + ["Mire Shed - Left", True, ['Moon Pearl', 'Pegasus Boots']], + ["Mire Shed - Left", True, ['Magic Mirror', 'Ocarina', 'Progressive Glove', 'Progressive Glove']], + + ["Mire Shed - Right", False, []], + ["Mire Shed - Right", False, [], ['Moon Pearl', 'Magic Mirror']], + ["Mire Shed - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Pegasus Boots']], + ["Mire Shed - Right", False, [], ['Ocarina', 'Pegasus Boots']], + ["Mire Shed - Right", True, ['Moon Pearl', 'Pegasus Boots']], + ["Mire Shed - Right", True, ['Magic Mirror', 'Ocarina', 'Progressive Glove', 'Progressive Glove']], + ["Mire Shed - Right", True, ['Moon Pearl', 'Ocarina', 'Progressive Glove', 'Progressive Glove']], + ]) \ No newline at end of file diff --git a/test/owg/TestDeathMountain.py b/test/owg/TestDeathMountain.py new file mode 100644 index 00000000..60d1e7e5 --- /dev/null +++ b/test/owg/TestDeathMountain.py @@ -0,0 +1,201 @@ +from test.owg.TestVanillaOWG import TestVanillaOWG + + +class TestDeathMountain(TestVanillaOWG): + + def testWestDeathMountain(self): + self.run_location_tests([ + ["Ether Tablet", False, []], + ["Ether Tablet", False, ['Progressive Sword'], ['Progressive Sword']], + ["Ether Tablet", False, [], ['Book of Mudora']], + ["Ether Tablet", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Ether Tablet", False, [], ['Pegasus Boots', 'Lamp', 'Ocarina']], + ["Ether Tablet", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], + ["Ether Tablet", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hammer']], + ["Ether Tablet", True, ['Pegasus Boots', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + ["Ether Tablet", True, ['Ocarina', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + ["Ether Tablet", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + ["Ether Tablet", True, ['Ocarina', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + ["Ether Tablet", True, ['Progressive Glove', 'Lamp', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + + ["Old Man", False, []], + ["Old Man", False, [], ['Lamp']], + ["Old Man", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Old Man", True, ['Pegasus Boots', 'Lamp']], + ["Old Man", True, ['Ocarina', 'Lamp']], + ["Old Man", True, ['Progressive Glove', 'Lamp']], + + ["Spectacle Rock Cave", False, []], + ["Spectacle Rock Cave", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Spectacle Rock Cave", False, [], ['Pegasus Boots', 'Lamp', 'Ocarina']], + ["Spectacle Rock Cave", True, ['Pegasus Boots']], + ["Spectacle Rock Cave", True, ['Ocarina']], + ["Spectacle Rock Cave", True, ['Progressive Glove', 'Lamp']], + + ["Spectacle Rock", False, []], + ["Spectacle Rock", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Spectacle Rock", False, [], ['Pegasus Boots', 'Lamp', 'Ocarina']], + ["Spectacle Rock", False, [], ['Pegasus Boots', 'Magic Mirror']], + ["Spectacle Rock", True, ['Pegasus Boots']], + ["Spectacle Rock", True, ['Ocarina', 'Magic Mirror']], + ["Spectacle Rock", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ]) + + def testEastDeathMountain(self): + self.run_location_tests([ + ["Mimic Cave", False, []], + ["Mimic Cave", False, [], ['Magic Mirror']], + ["Mimic Cave", False, [], ['Hammer']], + ["Mimic Cave", False, [], ['Pegasus Boots', 'Ocarina', 'Lamp']], + ["Mimic Cave", False, [], ['Pegasus Boots', 'Ocarina', 'Progressive Glove']], + ["Mimic Cave", True, ['Magic Mirror', 'Hammer', 'Pegasus Boots']], + ["Mimic Cave", True, ['Magic Mirror', 'Hammer', 'Progressive Glove', 'Lamp']], + ["Mimic Cave", True, ['Magic Mirror', 'Hammer', 'Ocarina']], + + ["Spiral Cave", False, []], + ["Spiral Cave", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Spiral Cave", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], + ["Spiral Cave", True, ['Pegasus Boots']], + ["Spiral Cave", True, ['Ocarina', 'Hookshot']], + ["Spiral Cave", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Spiral Cave", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Spiral Cave", True, ['Ocarina', 'Magic Mirror']], + + ["Paradox Cave Lower - Far Left", False, []], + ["Paradox Cave Lower - Far Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Paradox Cave Lower - Far Left", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], + ["Paradox Cave Lower - Far Left", True, ['Pegasus Boots']], + ["Paradox Cave Lower - Far Left", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Far Left", True, ['Ocarina', 'Magic Mirror']], + + ["Paradox Cave Lower - Left", False, []], + ["Paradox Cave Lower - Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Paradox Cave Lower - Left", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], + ["Paradox Cave Lower - Left", True, ['Pegasus Boots']], + ["Paradox Cave Lower - Left", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Left", True, ['Ocarina', 'Magic Mirror']], + + ["Paradox Cave Lower - Middle", False, []], + ["Paradox Cave Lower - Middle", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Paradox Cave Lower - Middle", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], + ["Paradox Cave Lower - Middle", True, ['Pegasus Boots']], + ["Paradox Cave Lower - Middle", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Middle", True, ['Ocarina', 'Magic Mirror']], + + ["Paradox Cave Lower - Right", False, []], + ["Paradox Cave Lower - Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Paradox Cave Lower - Right", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], + ["Paradox Cave Lower - Right", True, ['Pegasus Boots']], + ["Paradox Cave Lower - Right", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Right", True, ['Ocarina', 'Magic Mirror']], + + ["Paradox Cave Lower - Far Right", False, []], + ["Paradox Cave Lower - Far Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Paradox Cave Lower - Far Right", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], + ["Paradox Cave Lower - Far Right", True, ['Pegasus Boots']], + ["Paradox Cave Lower - Far Right", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Far Right", True, ['Ocarina', 'Magic Mirror']], + + ["Paradox Cave Upper - Left", False, []], + ["Paradox Cave Upper - Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Paradox Cave Upper - Left", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Pegasus Boots']], + ["Paradox Cave Upper - Left", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Upper - Left", True, ['Ocarina', 'Magic Mirror']], + + ["Paradox Cave Upper - Right", False, []], + ["Paradox Cave Upper - Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Ocarina']], + ["Paradox Cave Upper - Right", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Pegasus Boots']], + ["Paradox Cave Upper - Right", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Upper - Right", True, ['Ocarina', 'Magic Mirror']], + ]) + + def testWestDarkWorldDeathMountain(self): + self.run_location_tests([ + ["Spike Cave", False, []], + ["Spike Cave", False, [], ['Progressive Glove']], + ["Spike Cave", False, [], ['Moon Pearl']], + ["Spike Cave", False, [], ['Hammer']], + ["Spike Cave", False, [], ['Cape', 'Cane of Byrna']], + ["Spike Cave", True, ['Bottle', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']], + ["Spike Cave", True, ['Bottle', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cape']], + ["Spike Cave", True, ['Bottle', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']], + ["Spike Cave", True, ['Bottle', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cane of Byrna']], + ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']], + ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cape']], + ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']], + ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cane of Byrna']], + ["Spike Cave", True, ['Magic Upgrade (1/4)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']], + ["Spike Cave", True, ['Magic Upgrade (1/4)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cape']], + ["Spike Cave", True, ['Magic Upgrade (1/4)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']], + ["Spike Cave", True, ['Magic Upgrade (1/4)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cane of Byrna']], + ]) + + def testEastDarkWorldDeathMountain(self): + self.run_location_tests([ + ["Superbunny Cave - Top", False, []], + ["Superbunny Cave - Top", True, ['Progressive Glove', 'Progressive Glove', 'Pegasus Boots']], + ["Superbunny Cave - Top", True, ['Hammer', 'Pegasus Boots']], + ["Superbunny Cave - Top", True, ['Moon Pearl', 'Pegasus Boots']], + ["Superbunny Cave - Top", True, ['Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Superbunny Cave - Top", True, ['Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Ocarina']], + ["Superbunny Cave - Top", True, ['Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + ["Superbunny Cave - Top", True, ['Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Lamp']], + + ["Superbunny Cave - Bottom", False, []], + ["Superbunny Cave - Bottom", True, ['Progressive Glove', 'Progressive Glove', 'Pegasus Boots']], + ["Superbunny Cave - Bottom", True, ['Hammer', 'Pegasus Boots']], + ["Superbunny Cave - Bottom", True, ['Moon Pearl', 'Pegasus Boots']], + ["Superbunny Cave - Bottom", True, ['Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Superbunny Cave - Bottom", True, ['Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Ocarina']], + ["Superbunny Cave - Bottom", True, ['Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + ["Superbunny Cave - Bottom", True, ['Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Lamp']], + + ["Hookshot Cave - Bottom Right", False, []], + ["Hookshot Cave - Bottom Right", False, [], ['Progressive Glove', 'Pegasus Boots']], + ["Hookshot Cave - Bottom Right", False, [], ['Moon Pearl']], + ["Hookshot Cave - Bottom Right", True, ['Moon Pearl', 'Pegasus Boots']], + ["Hookshot Cave - Bottom Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Hookshot Cave - Bottom Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Ocarina', 'Pegasus Boots']], + ["Hookshot Cave - Bottom Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + ["Hookshot Cave - Bottom Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Lamp', 'Pegasus Boots']], + + ["Hookshot Cave - Bottom Left", False, []], + ["Hookshot Cave - Bottom Left", False, [], ['Progressive Glove', 'Pegasus Boots']], + ["Hookshot Cave - Bottom Left", False, [], ['Moon Pearl']], + ["Hookshot Cave - Bottom Left", False, [], ['Hookshot']], + ["Hookshot Cave - Bottom Left", True, ['Moon Pearl', 'Pegasus Boots', 'Hookshot']], + ["Hookshot Cave - Bottom Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Hookshot Cave - Bottom Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + + ["Hookshot Cave - Top Left", False, []], + ["Hookshot Cave - Top Left", False, [], ['Progressive Glove', 'Pegasus Boots']], + ["Hookshot Cave - Top Left", False, [], ['Moon Pearl']], + ["Hookshot Cave - Top Left", False, [], ['Hookshot']], + ["Hookshot Cave - Top Left", True, ['Moon Pearl', 'Pegasus Boots', 'Hookshot']], + ["Hookshot Cave - Top Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Hookshot Cave - Top Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + + ["Hookshot Cave - Top Right", False, []], + ["Hookshot Cave - Top Right", False, [], ['Progressive Glove', 'Pegasus Boots']], + ["Hookshot Cave - Top Right", False, [], ['Moon Pearl']], + ["Hookshot Cave - Top Right", False, [], ['Hookshot']], + ["Hookshot Cave - Top Right", True, ['Moon Pearl', 'Pegasus Boots', 'Hookshot']], + ["Hookshot Cave - Top Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Hookshot Cave - Top Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + ]) \ No newline at end of file diff --git a/test/owg/TestDungeons.py b/test/owg/TestDungeons.py new file mode 100644 index 00000000..3ae69aaa --- /dev/null +++ b/test/owg/TestDungeons.py @@ -0,0 +1,133 @@ +from test.owg.TestVanillaOWG import TestVanillaOWG + + +class TestDungeons(TestVanillaOWG): + + def testFirstDungeonChests(self): + self.run_location_tests([ + ["Hyrule Castle - Map Chest", True, []], + + ["Sanctuary", True, []], + + ["Sewers - Secret Room - Left", False, []], + ["Sewers - Secret Room - Left", True, ['Progressive Glove']], + ["Sewers - Secret Room - Left", True, ['Lamp', 'Small Key (Escape)']], + + ["Eastern Palace - Compass Chest", True, []], + + ["Desert Palace - Map Chest", False, []], + ["Desert Palace - Map Chest", True, ['Pegasus Boots']], + ["Desert Palace - Map Chest", True, ['Book of Mudora']], + ["Desert Palace - Map Chest", True, ['Ocarina', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']], + + ["Desert Palace - Boss", False, []], + ["Desert Palace - Boss", False, [], ['Small Key (Desert Palace)']], + ["Desert Palace - Boss", False, [], ['Big Key (Desert Palace)']], + ["Desert Palace - Boss", False, [], ['Lamp', 'Fire Rod']], + ["Desert Palace - Boss", True, ['Progressive Sword', 'Small Key (Desert Palace)', 'Pegasus Boots', 'Lamp', 'Big Key (Desert Palace)']], + ["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Pegasus Boots', 'Fire Rod', 'Big Key (Desert Palace)']], + + ["Tower of Hera - Basement Cage", False, []], + ["Tower of Hera - Basement Cage", False, [], ['Pegasus Boots', "Ocarina", "Progressive Glove"]], + ["Tower of Hera - Basement Cage", False, [], ['Pegasus Boots', "Ocarina", "Lamp"]], + ["Tower of Hera - Basement Cage", False, [], ['Pegasus Boots', "Magic Mirror", "Hammer"]], + ["Tower of Hera - Basement Cage", False, [], ['Pegasus Boots', "Magic Mirror", "Hookshot"]], + ["Tower of Hera - Basement Cage", True, ['Pegasus Boots']], + ["Tower of Hera - Basement Cage", True, ["Ocarina", "Magic Mirror"]], + ["Tower of Hera - Basement Cage", True, ["Progressive Glove", "Lamp", "Magic Mirror"]], + ["Tower of Hera - Basement Cage", True, ["Ocarina", "Hookshot", "Hammer"]], + ["Tower of Hera - Basement Cage", True, ["Progressive Glove", "Lamp", "Magic Mirror"]], + + ["Castle Tower - Room 03", False, []], + ["Castle Tower - Room 03", False, ['Progressive Sword'], ['Progressive Sword', 'Cape', 'Beat Agahnim 1']], + ["Castle Tower - Room 03", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], + ["Castle Tower - Room 03", True, ['Progressive Sword', 'Progressive Sword']], + ["Castle Tower - Room 03", True, ['Cape', 'Progressive Bow']], + ["Castle Tower - Room 03", True, ['Beat Agahnim 1', 'Fire Rod']], + + ["Palace of Darkness - Shooter Room", False, []], + ["Palace of Darkness - Shooter Room", False, [], ['Moon Pearl']], + ["Palace of Darkness - Shooter Room", True, ['Moon Pearl', 'Pegasus Boots']], + ["Palace of Darkness - Shooter Room", True, ['Moon Pearl', 'Beat Agahnim 1']], + ["Palace of Darkness - Shooter Room", True, ['Moon Pearl', 'Hammer', 'Progressive Glove']], + #todo: Qirn jump in logic? + #["Palace of Darkness - Shooter Room", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Palace of Darkness - Shooter Room", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Flippers']], + + ["Swamp Palace - Entrance", False, []], + ["Swamp Palace - Entrance", False, [], ['Magic Mirror']], + ["Swamp Palace - Entrance", False, [], ['Moon Pearl']], + ["Swamp Palace - Entrance", False, [], ['Flippers']], + ["Swamp Palace - Entrance", True, ['Magic Mirror', 'Moon Pearl', 'Flippers', 'Pegasus Boots']], + ["Swamp Palace - Entrance", True, ['Magic Mirror', 'Moon Pearl', 'Flippers', 'Ocarina']], + ["Swamp Palace - Entrance", True, ['Magic Mirror', 'Moon Pearl', 'Flippers', 'Hammer', 'Progressive Glove']], + ["Swamp Palace - Entrance", True, ['Magic Mirror', 'Moon Pearl', 'Flippers', 'Progressive Glove', 'Progressive Glove']], + + ["Skull Woods - Compass Chest", False, []], + ["Skull Woods - Compass Chest", True, ['Magic Mirror', 'Pegasus Boots']], + ["Skull Woods - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Skull Woods - Big Chest", False, []], + ["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']], + #todo: Bomb Jump in logic? + #["Skull Woods - Big Chest", True, ['Magic Mirror', 'Pegasus Boots', 'Big Key (Skull Woods)']], + ["Skull Woods - Big Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Big Key (Skull Woods)']], + + ["Skull Woods - Big Key Chest", False, []], + ["Skull Woods - Big Key Chest", True, ['Magic Mirror', 'Pegasus Boots']], + ["Skull Woods - Big Key Chest", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Skull Woods - Bridge Room", False, []], + ["Skull Woods - Bridge Room", False, [], ['Moon Pearl']], + ["Skull Woods - Bridge Room", False, [], ['Fire Rod']], + ["Skull Woods - Bridge Room", True, ['Moon Pearl', 'Pegasus Boots', 'Fire Rod']], + + ["Thieves' Town - Map Chest", False, []], + ["Thieves' Town - Map Chest", False, [], ['Moon Pearl']], + ["Thieves' Town - Map Chest", True, ['Moon Pearl', 'Pegasus Boots']], + + ["Ice Palace - Compass Chest", False, []], + ["Ice Palace - Compass Chest", False, [], ['Fire Rod', 'Bombos']], + ["Ice Palace - Compass Chest", False, [], ['Fire Rod', 'Progressive Sword']], + ["Ice Palace - Compass Chest", False, ['Progressive Glove'], ['Progressive Glove']], + #["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']], + + ["Misery Mire - Bridge Chest", False, []], + ["Misery Mire - Bridge Chest", False, [], ['Moon Pearl']], + ["Misery Mire - Bridge Chest", False, [], ['Ether']], + ["Misery Mire - Bridge Chest", False, [], ['Progressive Sword']], + ["Misery Mire - Bridge Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Ether', 'Progressive Sword']], + + ["Turtle Rock - Compass Chest", False, []], + ["Turtle Rock - Compass Chest", False, [], ['Cane of Somaria']], + #todo: does clip require sword? + #["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Progressive Sword']], + ["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Cane of Somaria', 'Progressive Sword', 'Quake', 'Hammer']], + ["Turtle Rock - Compass Chest", True, ['Pegasus Boots', 'Magic Mirror', 'Hammer', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + + ["Turtle Rock - Chain Chomps", False, []], + #todo: does clip require sword? + #["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Pegasus Boots']], + ["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Pegasus Boots', 'Progressive Sword']], + ["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror', 'Hammer']], + ["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + + ["Turtle Rock - Crystaroller Room", False, []], + ["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)']], + #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, []], + ["Ganons Tower - Hope Room - Left", False, ['Moon Pearl', 'Crystal 1']], + ["Ganons Tower - Hope Room - Left", False, ['Pegasus Boots', 'Crystal 1']], + ["Ganons Tower - Hope Room - Left", True, ['Moon Pearl', 'Pegasus Boots']], + #todo: more advanced bunny revive logic + #["Ganons Tower - Hope Room - Left", True, ['Pegasus Boots', 'Hammer', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7']], + ]) \ No newline at end of file diff --git a/test/owg/TestLightWorld.py b/test/owg/TestLightWorld.py new file mode 100644 index 00000000..02ea2f3b --- /dev/null +++ b/test/owg/TestLightWorld.py @@ -0,0 +1,194 @@ +from test.owg.TestVanillaOWG import TestVanillaOWG + + +class TestLightWorld(TestVanillaOWG): + + def testLightWorld(self): + self.run_location_tests([ + ["Master Sword Pedestal", False, []], + ["Master Sword Pedestal", False, [], ['Green Pendant']], + ["Master Sword Pedestal", False, [], ['Red Pendant']], + ["Master Sword Pedestal", False, [], ['Blue Pendant']], + ["Master Sword Pedestal", True, ['Green Pendant', 'Red Pendant', 'Blue Pendant']], + + ["Link's Uncle", True, []], + + ["Secret Passage", True, []], + + ["King's Tomb", False, []], + ["King's Tomb", False, [], ['Pegasus Boots']], + ["King's Tomb", True, ['Pegasus Boots']], + + ["Floodgate Chest", True, []], + + ["Link's House", True, []], + + ["Kakariko Tavern", True, []], + + ["Chicken House", True, []], + + ["Aginah's Cave", True, []], + + ["Sahasrahla's Hut - Left", True, []], + + ["Sahasrahla's Hut - Middle", True, []], + + ["Sahasrahla's Hut - Right", True, []], + + ["Kakariko Well - Top", True, []], + + ["Kakariko Well - Left", True, []], + + ["Kakariko Well - Middle", True, []], + + ["Kakariko Well - Right", True, []], + + ["Kakariko Well - Bottom", True, []], + + ["Blind's Hideout - Top", True, []], + + ["Blind's Hideout - Left", True, []], + + ["Blind's Hideout - Right", True, []], + + ["Blind's Hideout - Far Left", True, []], + + ["Blind's Hideout - Far Right", True, []], + + ["Bonk Rock Cave", False, []], + ["Bonk Rock Cave", False, [], ['Pegasus Boots']], + ["Bonk Rock Cave", True, ['Pegasus Boots']], + + ["Mini Moldorm Cave - Far Left", True, []], + + ["Mini Moldorm Cave - Left", True, []], + + ["Mini Moldorm Cave - Right", True, []], + + ["Mini Moldorm Cave - Far Right", True, []], + + ["Ice Rod Cave", True, []], + + ["Bottle Merchant", True, []], + + ["Sahasrahla", False, []], + ["Sahasrahla", False, [], ['Green Pendant']], + ["Sahasrahla", True, ['Green Pendant']], + + ["Magic Bat", False, []], + ["Magic Bat", False, [], ['Magic Powder']], + ["Magic Bat", False, [], ['Pegasus Boots', 'Hammer', 'Magic Mirror']], + ["Magic Bat", False, [], ['Pegasus Boots', 'Hammer', 'Moon Pearl']], + ["Magic Bat", False, ['Progressive Glove'], ['Pegasus Boots', 'Hammer', 'Progressive Glove']], + ["Magic Bat", True, ['Magic Powder', 'Pegasus Boots']], + ["Magic Bat", True, ['Magic Powder', 'Hammer']], + ["Magic Bat", True, ['Magic Powder', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Magic Mirror']], + + ["Sick Kid", False, []], + ["Sick Kid", False, [], ['AnyBottle']], + ["Sick Kid", True, ['Bottle (Bee)']], + ["Sick Kid", True, ['Bottle (Fairy)']], + ["Sick Kid", True, ['Bottle (Red Potion)']], + ["Sick Kid", True, ['Bottle (Green Potion)']], + ["Sick Kid", True, ['Bottle (Blue Potion)']], + ["Sick Kid", True, ['Bottle']], + ["Sick Kid", True, ['Bottle (Good Bee)']], + + ["Hobo", True, []], + + ["Bombos Tablet", False, []], + ["Bombos Tablet", False, ['Progressive Sword'], ['Progressive Sword']], + ["Bombos Tablet", False, [], ['Book of Mudora']], + ["Bombos Tablet", True, ['Pegasus Boots', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + + ["King Zora", True, []], + + ["Lost Woods Hideout", True, []], + + ["Lumberjack Tree", False, []], + ["Lumberjack Tree", False, [], ['Pegasus Boots']], + ["Lumberjack Tree", False, [], ['Beat Agahnim 1']], + ["Lumberjack Tree", True, ['Pegasus Boots', 'Beat Agahnim 1']], + + ["Cave 45", False, []], + ["Cave 45", False, [], ['Pegasus Boots', 'Magic Mirror']], + ["Cave 45", False, [], ['Pegasus Boots', 'Moon Pearl', 'Ocarina', 'Lamp']], + ["Cave 45", False, [], ['Pegasus Boots', 'Moon Pearl', 'Ocarina', 'Progressive Glove']], + ["Cave 45", True, ['Pegasus Boots']], + ["Cave 45", True, ['Ocarina', 'Magic Mirror']], + ["Cave 45", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Cave 45", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Cave 45", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], + ["Cave 45", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer']], + ["Cave 45", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Cave 45", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Graveyard Cave", False, []], + ["Graveyard Cave", False, [], ['Pegasus Boots', 'Magic Mirror']], + ["Graveyard Cave", False, [], ['Pegasus Boots', 'Moon Pearl']], + ["Graveyard Cave", True, ['Pegasus Boots']], + ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], + ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], + ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Checkerboard Cave", False, []], + ["Checkerboard Cave", False, [], ['Progressive Glove']], + ["Checkerboard Cave", False, [], ['Pegasus Boots', 'Ocarina']], + ["Checkerboard Cave", False, [], ['Pegasus Boots', 'Magic Mirror']], + ["Checkerboard Cave", True, ['Pegasus Boots', 'Progressive Glove']], + ["Checkerboard Cave", True, ['Ocarina', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + + ["Mini Moldorm Cave - Generous Guy", True, []], + + ["Library", False, []], + ["Library", False, [], ['Pegasus Boots']], + ["Library", True, ['Pegasus Boots']], + + ["Mushroom", True, []], + + ["Potion Shop", False, []], + ["Potion Shop", False, [], ['Mushroom']], + ["Potion Shop", True, ['Mushroom']], + + ["Maze Race", True, []], + + ["Desert Ledge", False, []], + ["Desert Ledge", False, [], ['Pegasus Boots', 'Book of Mudora', 'Ocarina']], + ["Desert Ledge", False, [], ['Pegasus Boots', 'Book of Mudora', 'Magic Mirror']], + ["Desert Ledge", False, ['Progressive Glove'], ['Pegasus Boots', 'Book of Mudora', 'Progressive Glove']], + ["Desert Ledge", True, ['Pegasus Boots']], + ["Desert Ledge", True, ['Book of Mudora']], + ["Desert Ledge", True, ['Ocarina', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + + ["Lake Hylia Island", False, []], + ["Lake Hylia Island", False, [], ['Pegasus Boots', 'Magic Mirror']], + ["Lake Hylia Island", False, [], ['Pegasus Boots', 'Moon Pearl']], + ["Lake Hylia Island", False, [], ['Pegasus Boots', 'Flippers']], + ["Lake Hylia Island", True, ['Pegasus Boots']], + ["Lake Hylia Island", True, ['Flippers', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Lake Hylia Island", True, ['Flippers', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], + ["Lake Hylia Island", True, ['Flippers', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1']], + + ["Sunken Treasure", True, []], + + ["Zora's Ledge", False, []], + ["Zora's Ledge", False, [], ['Pegasus Boots', 'Flippers']], + ["Zora's Ledge", True, ['Pegasus Boots']], + ["Zora's Ledge", True, ['Flippers']], + + ["Flute Spot", False, []], + ["Flute Spot", False, [], ['Shovel']], + ["Flute Spot", True, ['Shovel']], + + ["Waterfall Fairy - Left", False, []], + ["Waterfall Fairy - Left", True, ['Flippers']], + ["Waterfall Fairy - Left", True, ['Moon Pearl']], + ["Waterfall Fairy - Left", True, ['Pegasus Boots']], + + ["Waterfall Fairy - Right", False, []], + ["Waterfall Fairy - Right", True, ['Flippers']], + ["Waterfall Fairy - Right", True, ['Moon Pearl']], + ["Waterfall Fairy - Right", True, ['Pegasus Boots']] + ]) \ No newline at end of file diff --git a/test/owg/TestVanillaOWG.py b/test/owg/TestVanillaOWG.py new file mode 100644 index 00000000..0eb4271f --- /dev/null +++ b/test/owg/TestVanillaOWG.py @@ -0,0 +1,40 @@ +from BaseClasses import World +from DoorShuffle import link_doors +from Doors import create_doors +from Dungeons import create_dungeons, get_dungeon_item_pool +from EntranceShuffle import link_entrances +from InvertedRegions import mark_dark_world_regions +from ItemList import difficulties, generate_itempool +from Items import ItemFactory +from OverworldGlitchRules import create_owg_connections +from Regions import create_regions, create_dungeon_regions, create_shops +from RoomData import create_rooms +from Rules import set_rules +from test.TestBase import TestBase + + +class TestVanillaOWG(TestBase): + def setUp(self): + self.world = World(1, {1:'vanilla'}, {1:'vanilla'}, {1:'owglitches'}, {1:'open'}, {1:'random'}, {1:'normal'}, {1:'normal'}, 'none', 'on', {1:'ganon'}, 'balanced', {1:'items'}, + {1:True}, {1:False}, False, None, {1:False}) + self.world.difficulty_requirements[1] = difficulties['normal'] + self.world.intensity = {1:1} + create_regions(self.world, 1) + create_dungeon_regions(self.world, 1) + create_shops(self.world, 1) + create_doors(self.world, 1) + create_rooms(self.world, 1) + create_dungeons(self.world, 1) + link_entrances(self.world, 1) + link_doors(self.world, 1) + create_owg_connections(self.world, 1) + generate_itempool(self.world, 1) + self.world.required_medallions[1] = ['Ether', 'Quake'] + self.world.itempool.extend(get_dungeon_item_pool(self.world)) + self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) + self.world.get_location('Agahnim 1', 1).item = None + self.world.get_location('Agahnim 2', 1).item = None + self.world.precollected_items.clear() + self.world.itempool.append(ItemFactory('Pegasus Boots', 1)) + mark_dark_world_regions(self.world, 1) + set_rules(self.world, 1) \ No newline at end of file diff --git a/test/owg/__init__.py b/test/owg/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/vanilla/TestDarkWorld.py b/test/vanilla/TestDarkWorld.py new file mode 100644 index 00000000..b5c331c7 --- /dev/null +++ b/test/vanilla/TestDarkWorld.py @@ -0,0 +1,166 @@ +from test.vanilla.TestVanilla import TestVanilla + + +class TestDarkWorld(TestVanilla): + + def testSouthDarkWorld(self): + self.run_location_tests([ + ["Hype Cave - Top", False, []], + ["Hype Cave - Top", False, [], ['Moon Pearl']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Hype Cave - Middle Right", False, []], + ["Hype Cave - Middle Right", False, [], ['Moon Pearl']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Hype Cave - Middle Left", False, []], + ["Hype Cave - Middle Left", False, [], ['Moon Pearl']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Hype Cave - Bottom", False, []], + ["Hype Cave - Bottom", False, [], ['Moon Pearl']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Hype Cave - Generous Guy", False, []], + ["Hype Cave - Generous Guy", False, [], ['Moon Pearl']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Stumpy", False, []], + ["Stumpy", False, [], ['Moon Pearl']], + ["Stumpy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Stumpy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Stumpy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Stumpy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Stumpy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Digging Game", False, []], + ["Digging Game", False, [], ['Moon Pearl']], + ["Digging Game", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Digging Game", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Digging Game", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Digging Game", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Digging Game", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']] + ]) + + def testWestDarkWorld(self): + self.run_location_tests([ + ["Brewery", False, []], + ["Brewery", False, [], ['Moon Pearl']], + ["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["C-Shaped House", False, []], + ["C-Shaped House", False, [], ['Moon Pearl']], + ["C-Shaped House", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["C-Shaped House", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["C-Shaped House", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["C-Shaped House", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Chest Game", False, []], + ["Chest Game", False, [], ['Moon Pearl']], + ["Chest Game", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Chest Game", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Chest Game", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Chest Game", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Peg Cave", False, []], + ["Peg Cave", False, [], ['Moon Pearl']], + ["Peg Cave", False, [], ['Hammer']], + ["Peg Cave", False, [], ['Progressive Glove']], + ["Peg Cave", True, ['Moon Pearl', 'Hammer', 'Progressive Glove', 'Progressive Glove']], + + ["Bumper Cave Ledge", False, []], + ["Bumper Cave Ledge", False, [], ['Moon Pearl']], + ["Bumper Cave Ledge", False, [], ['Cape']], + ["Bumper Cave Ledge", False, [], ['Progressive Glove']], + ["Bumper Cave Ledge", True, ['Moon Pearl', 'Cape', 'Progressive Glove', 'Progressive Glove']], + ["Bumper Cave Ledge", True, ['Moon Pearl', 'Cape', 'Progressive Glove', 'Hammer']], + ["Bumper Cave Ledge", True, ['Moon Pearl', 'Cape', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + + ["Blacksmith", False, []], + ["Blacksmith", False, [], ['Progressive Glove']], + ["Blacksmith", False, [], ['Moon Pearl']], + ["Blacksmith", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + + ["Purple Chest", False, []], + ["Purple Chest", False, [], ['Progressive Glove']], + ["Purple Chest", False, [], ['Moon Pearl']], + ["Purple Chest", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']] + ]) + + def testEastDarkWorld(self): + self.run_location_tests([ + ["Catfish", False, []], + ["Catfish", False, [], ['Progressive Glove']], + ["Catfish", False, [], ['Moon Pearl']], + ["Catfish", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove']], + ["Catfish", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Catfish", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Flippers']], + + ["Pyramid", False, []], + ["Pyramid", False, [], ['Beat Agahnim 1', 'Moon Pearl']], + ["Pyramid", True, ['Beat Agahnim 1']], + ["Pyramid", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Pyramid", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Flippers']], + + ["Pyramid Fairy - Left", False, []], + ["Pyramid Fairy - Left", False, [], ['Moon Pearl']], + ["Pyramid Fairy - Left", False, [], ['Crystal 5']], + ["Pyramid Fairy - Left", False, [], ['Crystal 6']], + ["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Hammer']], + ["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Progressive Glove', 'Hammer']], + ["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']], + ["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot', 'Magic Mirror']], + ["Pyramid Fairy - Left", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Flippers', 'Hookshot', 'Magic Mirror']], + + ["Pyramid Fairy - Right", False, []], + ["Pyramid Fairy - Right", False, [], ['Moon Pearl']], + ["Pyramid Fairy - Right", False, [], ['Crystal 5']], + ["Pyramid Fairy - Right", False, [], ['Crystal 6']], + ["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Hammer']], + ["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Progressive Glove', 'Hammer']], + ["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']], + ["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot', 'Magic Mirror']], + ["Pyramid Fairy - Right", True, ['Moon Pearl', 'Crystal 5', 'Crystal 6', 'Beat Agahnim 1', 'Flippers', 'Hookshot', 'Magic Mirror']], + + ["Ganon", False, []], + ["Ganon", False, [], ['Moon Pearl']], + ["Ganon", False, [], ['Beat Agahnim 2']], + ]) + + def testMireArea(self): + self.run_location_tests([ + ["Mire Shed - Left", False, []], + ["Mire Shed - Left", False, [], ['Progressive Glove']], + ["Mire Shed - Left", False, [], ['Moon Pearl']], + ["Mire Shed - Left", False, [], ['Ocarina']], + ["Mire Shed - Left", True, ['Moon Pearl', 'Ocarina', 'Progressive Glove', 'Progressive Glove']], + + ["Mire Shed - Right", False, []], + ["Mire Shed - Right", False, [], ['Progressive Glove']], + ["Mire Shed - Right", False, [], ['Moon Pearl']], + ["Mire Shed - Right", False, [], ['Ocarina']], + ["Mire Shed - Right", True, ['Moon Pearl', 'Ocarina', 'Progressive Glove', 'Progressive Glove']], + ]) diff --git a/test/vanilla/TestDeathMountain.py b/test/vanilla/TestDeathMountain.py new file mode 100644 index 00000000..cac104d0 --- /dev/null +++ b/test/vanilla/TestDeathMountain.py @@ -0,0 +1,230 @@ +from test.vanilla.TestVanilla import TestVanilla + + +class TestDeathMountain(TestVanilla): + + def testWestDeathMountain(self): + self.run_location_tests([ + ["Ether Tablet", False, []], + ["Ether Tablet", False, [], ['Progressive Glove', 'Ocarina']], + ["Ether Tablet", False, [], ['Lamp', 'Ocarina']], + ["Ether Tablet", False, [], ['Magic Mirror', 'Hookshot']], + ["Ether Tablet", False, [], ['Magic Mirror', 'Hammer']], + ["Ether Tablet", False, ['Progressive Sword'], ['Progressive Sword']], + ["Ether Tablet", False, [], ['Book of Mudora']], + ["Ether Tablet", True, ['Ocarina', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + ["Ether Tablet", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + ["Ether Tablet", True, ['Ocarina', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + ["Ether Tablet", True, ['Progressive Glove', 'Lamp', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']], + + ["Old Man", False, []], + ["Old Man", False, [], ['Progressive Glove', 'Ocarina']], + ["Old Man", False, [], ['Lamp']], + ["Old Man", True, ['Ocarina', 'Lamp']], + ["Old Man", True, ['Progressive Glove', 'Lamp']], + + ["Spectacle Rock Cave", False, []], + ["Spectacle Rock Cave", False, [], ['Progressive Glove', 'Ocarina']], + ["Spectacle Rock Cave", False, [], ['Lamp', 'Ocarina']], + ["Spectacle Rock Cave", True, ['Ocarina']], + ["Spectacle Rock Cave", True, ['Progressive Glove', 'Lamp']], + + ["Spectacle Rock", False, []], + ["Spectacle Rock", False, [], ['Progressive Glove', 'Ocarina']], + ["Spectacle Rock", False, [], ['Lamp', 'Ocarina']], + ["Spectacle Rock", False, [], ['Magic Mirror']], + ["Spectacle Rock", True, ['Ocarina', 'Magic Mirror']], + ["Spectacle Rock", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ]) + + def testEastDeathMountain(self): + self.run_location_tests([ + ["Mimic Cave", False, []], + ["Mimic Cave", False, [], ['Quake']], + ["Mimic Cave", False, [], ['Progressive Sword']], + ["Mimic Cave", False, ['Progressive Glove'], ['Progressive Glove']], + ["Mimic Cave", False, [], ['Hammer']], + ["Mimic Cave", False, [], ['Magic Mirror']], + ["Mimic Cave", False, [], ['Moon Pearl']], + ["Mimic Cave", False, [], ['Cane of Somaria']], + ["Mimic Cave", False, ['Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']], + ["Mimic Cave", True, ['Quake', 'Progressive Sword', 'Ocarina', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Moon Pearl', 'Cane of Somaria', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + + ["Spiral Cave", False, []], + ["Spiral Cave", False, [], ['Progressive Glove', 'Ocarina']], + ["Spiral Cave", False, [], ['Magic Mirror', 'Hammer', 'Hookshot']], + ["Spiral Cave", False, [], ['Magic Mirror', 'Hookshot']], + ["Spiral Cave", False, [], ['Hammer', 'Hookshot']], + ["Spiral Cave", False, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Spiral Cave", False, ['Progressive Glove', 'Hookshot']], + ["Spiral Cave", False, ['Ocarina', 'Magic Mirror']], + ["Spiral Cave", False, ['Ocarina', 'Hammer']], + ["Spiral Cave", True, ['Ocarina', 'Hookshot']], + ["Spiral Cave", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Spiral Cave", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Spiral Cave", True, ['Ocarina', 'Magic Mirror', 'Hammer']], + + ["Paradox Cave Lower - Far Left", False, []], + ["Paradox Cave Lower - Far Left", False, [], ['Progressive Glove', 'Ocarina']], + ["Paradox Cave Lower - Far Left", False, [], ['Magic Mirror', 'Hammer', 'Hookshot']], + ["Paradox Cave Lower - Far Left", False, [], ['Magic Mirror', 'Hookshot']], + ["Paradox Cave Lower - Far Left", False, [], ['Hammer', 'Hookshot']], + ["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot']], + ["Paradox Cave Lower - Far Left", False, ['Ocarina', 'Magic Mirror']], + ["Paradox Cave Lower - Far Left", False, ['Ocarina', 'Hammer']], + ["Paradox Cave Lower - Far Left", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Far Left", True, ['Ocarina', 'Magic Mirror', 'Hammer']], + + ["Paradox Cave Lower - Left", False, []], + ["Paradox Cave Lower - Left", False, [], ['Progressive Glove', 'Ocarina']], + ["Paradox Cave Lower - Left", False, [], ['Magic Mirror', 'Hammer', 'Hookshot']], + ["Paradox Cave Lower - Left", False, [], ['Magic Mirror', 'Hookshot']], + ["Paradox Cave Lower - Left", False, [], ['Hammer', 'Hookshot']], + ["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot']], + ["Paradox Cave Lower - Left", False, ['Ocarina', 'Magic Mirror']], + ["Paradox Cave Lower - Left", False, ['Ocarina', 'Hammer']], + ["Paradox Cave Lower - Left", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Left", True, ['Ocarina', 'Magic Mirror', 'Hammer']], + + ["Paradox Cave Lower - Middle", False, []], + ["Paradox Cave Lower - Middle", False, [], ['Progressive Glove', 'Ocarina']], + ["Paradox Cave Lower - Middle", False, [], ['Magic Mirror', 'Hammer', 'Hookshot']], + ["Paradox Cave Lower - Middle", False, [], ['Magic Mirror', 'Hookshot']], + ["Paradox Cave Lower - Middle", False, [], ['Hammer', 'Hookshot']], + ["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot']], + ["Paradox Cave Lower - Middle", False, ['Ocarina', 'Magic Mirror']], + ["Paradox Cave Lower - Middle", False, ['Ocarina', 'Hammer']], + ["Paradox Cave Lower - Middle", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Middle", True, ['Ocarina', 'Magic Mirror', 'Hammer']], + + ["Paradox Cave Lower - Right", False, []], + ["Paradox Cave Lower - Right", False, [], ['Progressive Glove', 'Ocarina']], + ["Paradox Cave Lower - Right", False, [], ['Magic Mirror', 'Hammer', 'Hookshot']], + ["Paradox Cave Lower - Right", False, [], ['Magic Mirror', 'Hookshot']], + ["Paradox Cave Lower - Right", False, [], ['Hammer', 'Hookshot']], + ["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot']], + ["Paradox Cave Lower - Right", False, ['Ocarina', 'Magic Mirror']], + ["Paradox Cave Lower - Right", False, ['Ocarina', 'Hammer']], + ["Paradox Cave Lower - Right", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Right", True, ['Ocarina', 'Magic Mirror', 'Hammer']], + + ["Paradox Cave Lower - Far Right", False, []], + ["Paradox Cave Lower - Far Right", False, [], ['Progressive Glove', 'Ocarina']], + ["Paradox Cave Lower - Far Right", False, [], ['Magic Mirror', 'Hammer', 'Hookshot']], + ["Paradox Cave Lower - Far Right", False, [], ['Magic Mirror', 'Hookshot']], + ["Paradox Cave Lower - Far Right", False, [], ['Hammer', 'Hookshot']], + ["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot']], + ["Paradox Cave Lower - Far Right", False, ['Ocarina', 'Magic Mirror']], + ["Paradox Cave Lower - Far Right", False, ['Ocarina', 'Hammer']], + ["Paradox Cave Lower - Far Right", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Far Right", True, ['Ocarina', 'Magic Mirror', 'Hammer']], + + ["Paradox Cave Upper - Left", False, []], + ["Paradox Cave Upper - Left", False, [], ['Progressive Glove', 'Ocarina']], + ["Paradox Cave Upper - Left", False, [], ['Magic Mirror', 'Hammer', 'Hookshot']], + ["Paradox Cave Upper - Left", False, [], ['Magic Mirror', 'Hookshot']], + ["Paradox Cave Upper - Left", False, [], ['Hammer', 'Hookshot']], + ["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot']], + ["Paradox Cave Upper - Left", False, ['Ocarina', 'Magic Mirror']], + ["Paradox Cave Upper - Left", False, ['Ocarina', 'Hammer']], + ["Paradox Cave Upper - Left", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Upper - Left", True, ['Ocarina', 'Magic Mirror', 'Hammer']], + + ["Paradox Cave Upper - Right", False, []], + ["Paradox Cave Upper - Right", False, [], ['Progressive Glove', 'Ocarina']], + ["Paradox Cave Upper - Right", False, [], ['Magic Mirror', 'Hammer', 'Hookshot']], + ["Paradox Cave Upper - Right", False, [], ['Magic Mirror', 'Hookshot']], + ["Paradox Cave Upper - Right", False, [], ['Hammer', 'Hookshot']], + ["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot']], + ["Paradox Cave Upper - Right", False, ['Ocarina', 'Magic Mirror']], + ["Paradox Cave Upper - Right", False, ['Ocarina', 'Hammer']], + ["Paradox Cave Upper - Right", True, ['Ocarina', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Upper - Right", True, ['Ocarina', 'Magic Mirror', 'Hammer']], + ]) + + def testWestDarkWorldDeathMountain(self): + self.run_location_tests([ + ["Spike Cave", False, []], + ["Spike Cave", False, [], ['Progressive Glove']], + ["Spike Cave", False, [], ['Moon Pearl']], + ["Spike Cave", False, [], ['Hammer']], + ["Spike Cave", False, [], ['Cape', 'Cane of Byrna']], + ["Spike Cave", True, ['Bottle', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']], + ["Spike Cave", True, ['Bottle', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cape']], + ["Spike Cave", True, ['Bottle', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']], + ["Spike Cave", True, ['Bottle', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cane of Byrna']], + ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']], + ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cape']], + ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']], + ["Spike Cave", True, ['Magic Upgrade (1/2)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cane of Byrna']], + ["Spike Cave", True, ['Magic Upgrade (1/4)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']], + ["Spike Cave", True, ['Magic Upgrade (1/4)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cape']], + ["Spike Cave", True, ['Magic Upgrade (1/4)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']], + ["Spike Cave", True, ['Magic Upgrade (1/4)', 'Moon Pearl', 'Hammer', 'Progressive Glove', 'Ocarina', 'Cane of Byrna']], + ]) + + def testEastDarkWorldDeathMountain(self): + self.run_location_tests([ + ["Superbunny Cave - Top", False, []], + ["Superbunny Cave - Top", False, [], ['Progressive Glove']], + ["Superbunny Cave - Top", False, [], ['Moon Pearl']], + ["Superbunny Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Superbunny Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Ocarina']], + ["Superbunny Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + ["Superbunny Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Lamp']], + + ["Superbunny Cave - Bottom", False, []], + ["Superbunny Cave - Bottom", False, [], ['Progressive Glove']], + ["Superbunny Cave - Bottom", False, [], ['Moon Pearl']], + ["Superbunny Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Superbunny Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Ocarina']], + ["Superbunny Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + ["Superbunny Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Lamp']], + + ["Hookshot Cave - Bottom Right", False, []], + ["Hookshot Cave - Bottom Right", False, [], ['Progressive Glove']], + ["Hookshot Cave - Bottom Right", False, [], ['Moon Pearl']], + ["Hookshot Cave - Bottom Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Hookshot Cave - Bottom Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Ocarina', 'Pegasus Boots']], + ["Hookshot Cave - Bottom Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + ["Hookshot Cave - Bottom Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hammer', 'Lamp', 'Pegasus Boots']], + + ["Hookshot Cave - Bottom Left", False, []], + ["Hookshot Cave - Bottom Left", False, [], ['Progressive Glove']], + ["Hookshot Cave - Bottom Left", False, [], ['Moon Pearl']], + ["Hookshot Cave - Bottom Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Hookshot Cave - Bottom Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + + ["Hookshot Cave - Top Left", False, []], + ["Hookshot Cave - Top Left", False, [], ['Progressive Glove']], + ["Hookshot Cave - Top Left", False, [], ['Moon Pearl']], + ["Hookshot Cave - Top Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Hookshot Cave - Top Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + + ["Hookshot Cave - Top Right", False, []], + ["Hookshot Cave - Top Right", False, [], ['Progressive Glove']], + ["Hookshot Cave - Top Right", False, [], ['Moon Pearl']], + ["Hookshot Cave - Top Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Ocarina']], + ["Hookshot Cave - Top Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hookshot', 'Lamp']], + ]) diff --git a/test/vanilla/TestEntrances.py b/test/vanilla/TestEntrances.py new file mode 100644 index 00000000..3be2212c --- /dev/null +++ b/test/vanilla/TestEntrances.py @@ -0,0 +1,133 @@ +from test.vanilla.TestVanilla import TestVanilla + + +class TestEntrances(TestVanilla): + + def testDungeonEntrances(self): + self.run_entrance_tests([ + ["Hyrule Castle Entrance (South)", True, []], + + ["Eastern Palace", True, []], + + ["Desert Palace Entrance (South)", False, []], + ["Desert Palace Entrance (South)", False, [], ["Book of Mudora", "Ocarina"]], + ["Desert Palace Entrance (South)", False, [], ["Book of Mudora", "Magic Mirror"]], + ["Desert Palace Entrance (South)", False, ["Progressive Glove"], ["Book of Mudora", "Progressive Glove"]], + ["Desert Palace Entrance (South)", True, ["Book of Mudora"]], + ["Desert Palace Entrance (South)", True, ["Ocarina", "Progressive Glove", "Progressive Glove", "Magic Mirror"]], + ["Desert Palace Entrance (North)", False, []], + ["Desert Palace Entrance (North)", False, [], ["Progressive Glove"]], + ["Desert Palace Entrance (North)", False, [], ["Book of Mudora", "Ocarina"]], + ["Desert Palace Entrance (North)", False, [], ["Book of Mudora", "Magic Mirror"]], + ["Desert Palace Entrance (North)", True, ["Book of Mudora", "Progressive Glove"]], + ["Desert Palace Entrance (North)", True, ["Ocarina", "Progressive Glove", "Progressive Glove", "Magic Mirror"]], + + ["Tower of Hera", False, []], + ["Tower of Hera", False, [], ["Ocarina", "Progressive Glove"]], + ["Tower of Hera", False, [], ["Ocarina", "Lamp"]], + ["Tower of Hera", False, [], ["Magic Mirror", "Hammer"]], + ["Tower of Hera", False, [], ["Magic Mirror", "Hookshot"]], + ["Tower of Hera", True, ["Ocarina", "Magic Mirror"]], + ["Tower of Hera", True, ["Progressive Glove", "Lamp", "Magic Mirror"]], + ["Tower of Hera", True, ["Ocarina", "Hookshot", "Hammer"]], + ["Tower of Hera", True, ["Progressive Glove", "Lamp", "Magic Mirror"]], + + ["Agahnims Tower", False, []], + ["Agahnims Tower", False, ["Progressive Sword"], ["Cape", "Progressive Sword", "Beat Agahnim 1"]], + ["Agahnims Tower", True, ["Cape"]], + ["Agahnims Tower", True, ["Progressive Sword", "Progressive Sword"]], + ["Agahnims Tower", True, ["Beat Agahnim 1"]], + + ["Palace of Darkness", False, []], + ["Palace of Darkness", False, [], ["Moon Pearl"]], + ["Palace of Darkness", False, [], ["Beat Agahnim 1", "Progressive Glove"]], + ["Palace of Darkness", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]], + ["Palace of Darkness", False, [], ["Beat Agahnim 1", "Hammer", "Flippers"]], + ["Palace of Darkness", True, ["Beat Agahnim 1", "Moon Pearl"]], + ["Palace of Darkness", True, ["Hammer", "Progressive Glove", "Moon Pearl"]], + ["Palace of Darkness", True, ["Progressive Glove", "Progressive Glove", "Flippers", "Moon Pearl"]], + + ["Swamp Palace", False, []], + ["Swamp Palace", False, [], ["Moon Pearl"]], + ["Swamp Palace", False, [], ["Beat Agahnim 1", "Progressive Glove"]], + ["Swamp Palace", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]], + ["Swamp Palace", True, ["Beat Agahnim 1", "Moon Pearl", "Hammer"]], + ["Swamp Palace", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Flippers"]], + ["Swamp Palace", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Progressive Glove"]], + ["Swamp Palace", True, ["Hammer", "Progressive Glove", "Moon Pearl"]], + ["Swamp Palace", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl"]], + + ["Thieves Town", False, []], + ["Thieves Town", False, [], ["Moon Pearl"]], + ["Thieves Town", False, [], ["Beat Agahnim 1", "Progressive Glove"]], + ["Thieves Town", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]], + ["Thieves Town", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Flippers"]], + ["Thieves Town", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Hammer"]], + ["Thieves Town", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Progressive Glove"]], + ["Thieves Town", True, ["Hammer", "Progressive Glove", "Moon Pearl"]], + ["Thieves Town", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl"]], + + ["Skull Woods First Section Door", False, []], + ["Skull Woods First Section Door", False, [], ["Moon Pearl"]], + ["Skull Woods First Section Door", False, [], ["Beat Agahnim 1", "Progressive Glove"]], + ["Skull Woods First Section Door", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]], + ["Skull Woods First Section Door", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Flippers"]], + ["Skull Woods First Section Door", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Hammer"]], + ["Skull Woods First Section Door", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Progressive Glove"]], + ["Skull Woods First Section Door", True, ["Hammer", "Progressive Glove", "Moon Pearl"]], + ["Skull Woods First Section Door", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl"]], + + ["Skull Woods Final Section", False, []], + ["Skull Woods Final Section", False, [], ["Moon Pearl"]], + ["Skull Woods Final Section", False, [], ["Fire Rod"]], + ["Skull Woods Final Section", False, [], ["Beat Agahnim 1", "Progressive Glove"]], + ["Skull Woods Final Section", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]], + ["Skull Woods Final Section", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Flippers", "Fire Rod"]], + ["Skull Woods Final Section", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Hammer", "Fire Rod"]], + ["Skull Woods Final Section", True, ["Beat Agahnim 1", "Moon Pearl", "Hookshot", "Progressive Glove", "Fire Rod"]], + ["Skull Woods Final Section", True, ["Hammer", "Progressive Glove", "Moon Pearl", "Fire Rod"]], + ["Skull Woods Final Section", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl", "Fire Rod"]], + + ["Ice Palace", False, []], + ["Ice Palace", False, [], ["Flippers"]], + ["Ice Palace", False, ["Progressive Glove"], ["Progressive Glove"]], + ["Ice Palace", True, ["Progressive Glove", "Progressive Glove", "Flippers"]], + + ["Misery Mire", False, []], + ["Misery Mire", False, [], ["Moon Pearl"]], + ["Misery Mire", False, [], ["Ocarina"]], + ["Misery Mire", False, [], ["Ether"]], + ["Misery Mire", False, [], ["Progressive Sword"]], + ["Misery Mire", False, ["Progressive Glove"], ["Progressive Glove"]], + ["Misery Mire", True, ["Progressive Glove", "Progressive Glove", "Ocarina", "Moon Pearl", "Ether", "Progressive Sword"]], + + ["Turtle Rock", False, []], + ["Turtle Rock", False, [], ["Moon Pearl"]], + ["Turtle Rock", False, [], ["Hammer"]], + ["Turtle Rock", False, ["Progressive Glove"], ["Progressive Glove"]], + ["Turtle Rock", False, [], ["Quake"]], + ["Turtle Rock", False, [], ["Progressive Sword"]], + ["Turtle Rock", False, [], ["Lamp", "Ocarina"]], + ["Turtle Rock", False, [], ["Hookshot", "Magic Mirror"]], + ["Turtle Rock", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl", "Hammer", "Quake", "Progressive Sword", "Lamp", "Hookshot"]], + ["Turtle Rock", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl", "Hammer", "Quake", "Progressive Sword", "Lamp", "Magic Mirror"]], + ["Turtle Rock", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl", "Hammer", "Quake", "Progressive Sword", "Ocarina", "Hookshot"]], + ["Turtle Rock", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl", "Hammer", "Quake", "Progressive Sword", "Ocarina", "Magic Mirror"]], + + ["Ganons Tower", False, []], + ["Ganons Tower", False, ["Progressive Glove"], ["Progressive Glove"]], + ["Ganons Tower", False, [], ["Lamp", "Ocarina"]], + ["Ganons Tower", False, [], ["Hookshot", "Hammer"]], + ["Ganons Tower", False, [], ["Hookshot", "Magic Mirror"]], + ["Ganons Tower", False, [], ["Crystal 1"]], + ["Ganons Tower", False, [], ["Crystal 2"]], + ["Ganons Tower", False, [], ["Crystal 3"]], + ["Ganons Tower", False, [], ["Crystal 4"]], + ["Ganons Tower", False, [], ["Crystal 5"]], + ["Ganons Tower", False, [], ["Crystal 6"]], + ["Ganons Tower", False, [], ["Crystal 7"]], + ["Ganons Tower", True, ["Lamp", "Magic Mirror", "Hammer", "Progressive Glove", "Progressive Glove", "Crystal 1", "Crystal 2", "Crystal 3", "Crystal 4", "Crystal 5", "Crystal 6", "Crystal 7"]], + ["Ganons Tower", True, ["Lamp", "Hookshot", "Progressive Glove", "Progressive Glove", "Crystal 1", "Crystal 2", "Crystal 3", "Crystal 4", "Crystal 5", "Crystal 6", "Crystal 7"]], + ["Ganons Tower", True, ["Ocarina", "Magic Mirror", "Hammer", "Progressive Glove", "Progressive Glove", "Crystal 1", "Crystal 2", "Crystal 3", "Crystal 4", "Crystal 5", "Crystal 6", "Crystal 7"]], + ["Ganons Tower", True, ["Ocarina", "Hookshot", "Progressive Glove", "Progressive Glove", "Crystal 1", "Crystal 2", "Crystal 3", "Crystal 4", "Crystal 5", "Crystal 6", "Crystal 7"]], + ]) diff --git a/test/vanilla/TestLightWorld.py b/test/vanilla/TestLightWorld.py new file mode 100644 index 00000000..259036c7 --- /dev/null +++ b/test/vanilla/TestLightWorld.py @@ -0,0 +1,197 @@ +from test.vanilla.TestVanilla import TestVanilla + + +class TestLightWorld(TestVanilla): + + def testLightWorld(self): + self.run_location_tests([ + ["Master Sword Pedestal", False, []], + ["Master Sword Pedestal", False, [], ['Green Pendant']], + ["Master Sword Pedestal", False, [], ['Red Pendant']], + ["Master Sword Pedestal", False, [], ['Blue Pendant']], + ["Master Sword Pedestal", True, ['Green Pendant', 'Red Pendant', 'Blue Pendant']], + + ["Link's Uncle", True, []], + + ["Secret Passage", True, []], + + ["King's Tomb", False, []], + ["King's Tomb", False, [], ['Pegasus Boots']], + ["King's Tomb", True, ['Pegasus Boots', 'Progressive Glove', 'Progressive Glove']], + ["King's Tomb", True, ['Pegasus Boots', 'Progressive Glove', 'Hammer', 'Moon Pearl', 'Magic Mirror']], + ["King's Tomb", True, ['Pegasus Boots', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot', 'Moon Pearl', 'Magic Mirror']], + ["King's Tomb", True, ['Pegasus Boots', 'Beat Agahnim 1', 'Hammer', 'Hookshot', 'Moon Pearl', 'Magic Mirror']], + ["King's Tomb", True, ['Pegasus Boots', 'Beat Agahnim 1', 'Flippers', 'Hookshot', 'Moon Pearl', 'Magic Mirror']], + + ["Floodgate Chest", True, []], + + ["Link's House", True, []], + + ["Kakariko Tavern", True, []], + + ["Chicken House", True, []], + + ["Aginah's Cave", True, []], + + ["Sahasrahla's Hut - Left", True, []], + + ["Sahasrahla's Hut - Middle", True, []], + + ["Sahasrahla's Hut - Right", True, []], + + ["Kakariko Well - Top", True, []], + + ["Kakariko Well - Left", True, []], + + ["Kakariko Well - Middle", True, []], + + ["Kakariko Well - Right", True, []], + + ["Kakariko Well - Bottom", True, []], + + ["Blind's Hideout - Top", True, []], + + ["Blind's Hideout - Left", True, []], + + ["Blind's Hideout - Right", True, []], + + ["Blind's Hideout - Far Left", True, []], + + ["Blind's Hideout - Far Right", True, []], + + ["Bonk Rock Cave", False, []], + ["Bonk Rock Cave", False, [], ['Pegasus Boots']], + ["Bonk Rock Cave", True, ['Pegasus Boots']], + + ["Mini Moldorm Cave - Far Left", True, []], + + ["Mini Moldorm Cave - Left", True, []], + + ["Mini Moldorm Cave - Right", True, []], + + ["Mini Moldorm Cave - Far Right", True, []], + + ["Ice Rod Cave", True, []], + + ["Bottle Merchant", True, []], + + ["Sahasrahla", False, []], + ["Sahasrahla", False, [], ['Green Pendant']], + ["Sahasrahla", True, ['Green Pendant']], + + ["Magic Bat", False, []], + ["Magic Bat", False, [], ['Magic Powder']], + ["Magic Bat", False, [], ['Hammer', 'Magic Mirror']], + ["Magic Bat", False, [], ['Hammer', 'Moon Pearl']], + ["Magic Bat", False, ['Progressive Glove'], ['Hammer', 'Progressive Glove']], + ["Magic Bat", True, ['Magic Powder', 'Hammer']], + ["Magic Bat", True, ['Magic Powder', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Magic Mirror']], + + ["Sick Kid", False, []], + ["Sick Kid", False, [], ['AnyBottle']], + ["Sick Kid", True, ['Bottle (Bee)']], + ["Sick Kid", True, ['Bottle (Fairy)']], + ["Sick Kid", True, ['Bottle (Red Potion)']], + ["Sick Kid", True, ['Bottle (Green Potion)']], + ["Sick Kid", True, ['Bottle (Blue Potion)']], + ["Sick Kid", True, ['Bottle']], + ["Sick Kid", True, ['Bottle (Good Bee)']], + + ["Hobo", False, []], + ["Hobo", False, [], ['Flippers']], + ["Hobo", True, ['Flippers']], + + ["Bombos Tablet", False, []], + ["Bombos Tablet", False, [], ['Magic Mirror']], + ["Bombos Tablet", False, ['Progressive Sword'], ['Progressive Sword']], + ["Bombos Tablet", False, [], ['Book of Mudora']], + ["Bombos Tablet", False, [], ['Moon Pearl']], + ["Bombos Tablet", True, ['Moon Pearl', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Progressive Glove']], + ["Bombos Tablet", True, ['Moon Pearl', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Hammer']], + ["Bombos Tablet", True, ['Moon Pearl', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword', 'Beat Agahnim 1', 'Hammer']], + ["Bombos Tablet", True, ['Moon Pearl', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Bombos Tablet", True, ['Moon Pearl', 'Magic Mirror', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["King Zora", False, []], + ["King Zora", False, [], ['Progressive Glove', 'Flippers']], + ["King Zora", True, ['Flippers']], + ["King Zora", True, ['Progressive Glove']], + + ["Lost Woods Hideout", True, []], + + ["Lumberjack Tree", False, []], + ["Lumberjack Tree", False, [], ['Pegasus Boots']], + ["Lumberjack Tree", False, [], ['Beat Agahnim 1']], + ["Lumberjack Tree", True, ['Pegasus Boots', 'Beat Agahnim 1']], + + ["Cave 45", False, []], + ["Cave 45", False, [], ['Magic Mirror']], + ["Cave 45", False, [], ['Moon Pearl']], + ["Cave 45", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Cave 45", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], + ["Cave 45", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer']], + ["Cave 45", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Cave 45", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Graveyard Cave", False, []], + ["Graveyard Cave", False, [], ['Magic Mirror']], + ["Graveyard Cave", False, [], ['Moon Pearl']], + ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], + ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], + ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + + ["Checkerboard Cave", False, []], + ["Checkerboard Cave", False, [], ['Progressive Glove']], + ["Checkerboard Cave", False, [], ['Ocarina']], + ["Checkerboard Cave", False, [], ['Magic Mirror']], + ["Checkerboard Cave", True, ['Ocarina', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + + ["Mini Moldorm Cave - Generous Guy", True, []], + + ["Library", False, []], + ["Library", False, [], ['Pegasus Boots']], + ["Library", True, ['Pegasus Boots']], + + ["Mushroom", True, []], + + ["Potion Shop", False, []], + ["Potion Shop", False, [], ['Mushroom']], + ["Potion Shop", True, ['Mushroom']], + + ["Maze Race", True, []], + + ["Desert Ledge", False, []], + ["Desert Ledge", False, [], ['Book of Mudora', 'Ocarina']], + ["Desert Ledge", False, [], ['Book of Mudora', 'Magic Mirror']], + ["Desert Ledge", False, ['Progressive Glove'], ['Book of Mudora', 'Progressive Glove']], + ["Desert Ledge", True, ['Book of Mudora']], + ["Desert Ledge", True, ['Ocarina', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + + ["Lake Hylia Island", False, []], + ["Lake Hylia Island", False, [], ['Magic Mirror']], + ["Lake Hylia Island", False, [], ['Moon Pearl']], + ["Lake Hylia Island", False, [], ['Flippers']], + ["Lake Hylia Island", True, ['Flippers', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Lake Hylia Island", True, ['Flippers', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], + ["Lake Hylia Island", True, ['Flippers', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1']], + + ["Sunken Treasure", True, []], + + ["Zora's Ledge", False, []], + ["Zora's Ledge", False, [], ['Flippers']], + ["Zora's Ledge", True, ['Flippers']], + + ["Flute Spot", False, []], + ["Flute Spot", False, [], ['Shovel']], + ["Flute Spot", True, ['Shovel']], + + ["Waterfall Fairy - Left", False, []], + ["Waterfall Fairy - Left", False, [], ['Flippers']], + ["Waterfall Fairy - Left", True, ['Flippers']], + + ["Waterfall Fairy - Right", False, []], + ["Waterfall Fairy - Right", False, [], ['Flippers']], + ["Waterfall Fairy - Right", True, ['Flippers']], + ]) \ No newline at end of file diff --git a/test/vanilla/TestVanilla.py b/test/vanilla/TestVanilla.py new file mode 100644 index 00000000..1fc316e9 --- /dev/null +++ b/test/vanilla/TestVanilla.py @@ -0,0 +1,36 @@ +from BaseClasses import World +from DoorShuffle import link_doors +from Doors import create_doors +from Dungeons import create_dungeons, get_dungeon_item_pool +from EntranceShuffle import link_entrances +from InvertedRegions import mark_dark_world_regions +from ItemList import difficulties, generate_itempool +from Items import ItemFactory +from Regions import create_regions, create_dungeon_regions, create_shops +from RoomData import create_rooms +from Rules import set_rules +from test.TestBase import TestBase + + +class TestVanilla(TestBase): + def setUp(self): + self.world = World(1, {1:'vanilla'}, {1:'vanilla'}, {1:'noglitches'}, {1:'open'}, {1:'random'}, {1:'normal'}, {1:'normal'}, 'none', 'on', {1:'ganon'}, 'balanced', {1:'items'}, + {1:True}, {1:False}, False, None, {1:False}) + self.world.difficulty_requirements[1] = difficulties['normal'] + self.world.intensity = {1:1} + create_regions(self.world, 1) + create_dungeon_regions(self.world, 1) + create_shops(self.world, 1) + create_doors(self.world, 1) + create_rooms(self.world, 1) + create_dungeons(self.world, 1) + link_entrances(self.world, 1) + link_doors(self.world, 1) + generate_itempool(self.world, 1) + self.world.required_medallions[1] = ['Ether', 'Quake'] + self.world.itempool.extend(get_dungeon_item_pool(self.world)) + self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) + self.world.get_location('Agahnim 1', 1).item = None + self.world.get_location('Agahnim 2', 1).item = None + mark_dark_world_regions(self.world, 1) + set_rules(self.world, 1) diff --git a/test/vanilla/__init__.py b/test/vanilla/__init__.py new file mode 100644 index 00000000..e69de29b