diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 08f8dfce..79204d88 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -1609,7 +1609,7 @@ def link_inverted_entrances(world, player): # and rentering to find bomb shop. However appended list here is all those that we currently have # bomb shop logic for. # Specifically we could potentially add: 'Dark Death Mountain Ledge (East)' and doors associated with pits - bomb_shop_doors = list(Inverted_Bomb_Shop_Single_Cave_Doors + Inverted_Bomb_Shop_Multi_Cave_Doors + ['Desert Palace Entrance (East)', 'Turtle Rock Isolated Ledge Entrance', 'Bumper Cave (Top)', 'Hookshot Cave Back Entrance']) + bomb_shop_doors = list(Inverted_Bomb_Shop_Single_Cave_Doors + Inverted_Bomb_Shop_Multi_Cave_Doors + ['Turtle Rock Isolated Ledge Entrance', 'Bumper Cave (Top)', 'Hookshot Cave Back Entrance']) blacksmith_doors = list(Inverted_Blacksmith_Single_Cave_Doors + Blacksmith_Multi_Cave_Doors) door_targets = list(Inverted_Single_Cave_Targets) diff --git a/Rules.py b/Rules.py index 0138e09b..fc9c21fe 100644 --- a/Rules.py +++ b/Rules.py @@ -20,8 +20,10 @@ def set_rules(world, player): old_rule = world.get_region('Old Man House', player).can_reach world.get_region('Old Man House', player).can_reach_private = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state) return + + global_rules(world, player) if world.mode != 'inverted': - global_rules(world, player) + default_rules(world, player) if world.mode == 'open': open_rules(world, player) @@ -103,7 +105,6 @@ def item_name(state, location, player): return None return (location.item.name, location.item.player) - def global_rules(world, player): if world.goal == 'triforcehunt': for location in world.get_locations(): @@ -113,6 +114,237 @@ def global_rules(world, player): # ganon can only carry triforce add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player) + # we can s&q to the old man house after we rescue him. This may be somewhere completely different if caves are shuffled! + old_rule = world.get_region('Old Man House', player).can_reach_private + world.get_region('Old Man House', player).can_reach_private = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state) + + set_rule(world.get_location('Sunken Treasure', player), lambda state: state.has('Open Floodgate', player)) + set_rule(world.get_location('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player)) + set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest + set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) + set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) + + set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith + set_rule(world.get_location('Blacksmith', player), lambda state: state.has('Return Smith', player)) + set_rule(world.get_location('Magic Bat', player), lambda state: state.has('Magic Powder', player)) + set_rule(world.get_location('Sick Kid', player), lambda state: state.has_bottle(player)) + set_rule(world.get_location('Library', player), lambda state: state.has_Boots(player)) + set_rule(world.get_location('Mimic Cave', player), lambda state: state.has('Hammer', player)) + set_rule(world.get_location('Sahasrahla', player), lambda state: state.has('Green Pendant', player)) + + + set_rule(world.get_location('Spike Cave', player), lambda state: + state.has('Hammer', player) and state.can_lift_rocks(player) and + ((state.has('Cape', player) and state.can_extend_magic(player, 16, True)) or + (state.has('Cane of Byrna', player) and + (state.can_extend_magic(player, 12, True) or + (state.world.can_take_damage and (state.has_Boots(player) or state.has_hearts(player, 4)))))) + ) + + set_rule(world.get_location('Hookshot Cave - Top Right', player), lambda state: state.has('Hookshot', player)) + set_rule(world.get_location('Hookshot Cave - Top Left', player), lambda state: state.has('Hookshot', player)) + set_rule(world.get_location('Hookshot Cave - Bottom Right', player), lambda state: state.has('Hookshot', player) or state.has('Pegasus Boots', player)) + set_rule(world.get_location('Hookshot Cave - Bottom Left', player), lambda state: state.has('Hookshot', player)) + + set_rule(world.get_entrance('Sewers Door', player), lambda state: state.has_key('Small Key (Escape)', player)) + set_rule(world.get_entrance('Sewers Back Door', player), lambda state: state.has_key('Small Key (Escape)', player)) + set_rule(world.get_entrance('Agahnim 1', player), lambda state: state.has_sword(player) and state.has_key('Small Key (Agahnims Tower)', player, 2)) + set_defeat_dungeon_boss_rule(world.get_location('Agahnim 1', player)) + set_rule(world.get_location('Castle Tower - Dark Maze', player), lambda state: state.has_key('Small Key (Agahnims Tower)', player)) + + set_rule(world.get_location('Eastern Palace - Big Chest', player), lambda state: state.has('Big Key (Eastern Palace)', player)) + set_rule(world.get_location('Eastern Palace - Boss', player), lambda state: state.can_shoot_arrows(player) and state.has('Big Key (Eastern Palace)', player) and world.get_location('Eastern Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) + set_rule(world.get_location('Eastern Palace - Prize', player), lambda state: state.can_shoot_arrows(player) and state.has('Big Key (Eastern Palace)', player) and world.get_location('Eastern Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) + for location in ['Eastern Palace - Boss', 'Eastern Palace - Big Chest']: + forbid_item(world.get_location(location, player), 'Big Key (Eastern Palace)', player) + + set_rule(world.get_location('Desert Palace - Big Chest', player), lambda state: state.has('Big Key (Desert Palace)', player)) + set_rule(world.get_location('Desert Palace - Torch', player), lambda state: state.has_Boots(player)) + set_rule(world.get_entrance('Desert Palace East Wing', player), lambda state: state.has_key('Small Key (Desert Palace)', player)) + set_rule(world.get_location('Desert Palace - Prize', player), lambda state: state.has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and world.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) + set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state.has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and world.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) + for location in ['Desert Palace - Boss', 'Desert Palace - Big Chest']: + forbid_item(world.get_location(location, player), 'Big Key (Desert Palace)', player) + + for location in ['Desert Palace - Boss', 'Desert Palace - Big Key Chest', 'Desert Palace - Compass Chest']: + forbid_item(world.get_location(location, player), 'Small Key (Desert Palace)', player) + + set_rule(world.get_entrance('Tower of Hera Small Key Door', player), lambda state: state.has_key('Small Key (Tower of Hera)', player) or item_name(state, 'Tower of Hera - Big Key Chest', player) == ('Small Key (Tower of Hera)', player)) + set_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: state.has('Big Key (Tower of Hera)', player)) + set_rule(world.get_location('Tower of Hera - Big Chest', player), lambda state: state.has('Big Key (Tower of Hera)', player)) + set_rule(world.get_location('Tower of Hera - Big Key Chest', player), lambda state: state.has_fire_source(player)) + if world.accessibility != 'locations': + set_always_allow(world.get_location('Tower of Hera - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Tower of Hera)' and item.player == player) + set_defeat_dungeon_boss_rule(world.get_location('Tower of Hera - Boss', player)) + set_defeat_dungeon_boss_rule(world.get_location('Tower of Hera - Prize', player)) + for location in ['Tower of Hera - Boss', 'Tower of Hera - Big Chest', 'Tower of Hera - Compass Chest']: + forbid_item(world.get_location(location, player), 'Big Key (Tower of Hera)', player) +# for location in ['Tower of Hera - Big Key Chest']: +# forbid_item(world.get_location(location, player), 'Small Key (Tower of Hera)', player) + + set_rule(world.get_entrance('Swamp Palace Moat', player), lambda state: state.has('Flippers', player) and state.has('Open Floodgate', player)) + set_rule(world.get_entrance('Swamp Palace Small Key Door', player), lambda state: state.has_key('Small Key (Swamp Palace)', player)) + set_rule(world.get_entrance('Swamp Palace (Center)', player), lambda state: state.has('Hammer', player)) + set_rule(world.get_location('Swamp Palace - Big Chest', player), lambda state: state.has('Big Key (Swamp Palace)', player) or item_name(state, 'Swamp Palace - Big Chest', player) == ('Big Key (Swamp Palace)', player)) + if world.accessibility != 'locations': + set_always_allow(world.get_location('Swamp Palace - Big Chest', player), lambda state, item: item.name == 'Big Key (Swamp Palace)' and item.player == player) + set_rule(world.get_entrance('Swamp Palace (North)', player), lambda state: state.has('Hookshot', player)) + set_defeat_dungeon_boss_rule(world.get_location('Swamp Palace - Boss', player)) + set_defeat_dungeon_boss_rule(world.get_location('Swamp Palace - Prize', player)) + for location in ['Swamp Palace - Entrance']: + forbid_item(world.get_location(location, player), 'Big Key (Swamp Palace)', player) + + set_rule(world.get_entrance('Thieves Town Big Key Door', player), lambda state: state.has('Big Key (Thieves Town)', player)) + set_rule(world.get_entrance('Blind Fight', player), lambda state: state.has_key('Small Key (Thieves Town)', player)) + set_defeat_dungeon_boss_rule(world.get_location('Thieves\' Town - Boss', player)) + set_defeat_dungeon_boss_rule(world.get_location('Thieves\' Town - Prize', player)) + set_rule(world.get_location('Thieves\' Town - Big Chest', player), lambda state: (state.has_key('Small Key (Thieves Town)', player) or item_name(state, 'Thieves\' Town - Big Chest', player) == ('Small Key (Thieves Town)', player)) and state.has('Hammer', player)) + if world.accessibility != 'locations': + set_always_allow(world.get_location('Thieves\' Town - Big Chest', player), lambda state, item: item.name == 'Small Key (Thieves Town)' and item.player == player and state.has('Hammer', player)) + set_rule(world.get_location('Thieves\' Town - Attic', player), lambda state: state.has_key('Small Key (Thieves Town)', player)) + for location in ['Thieves\' Town - Attic', 'Thieves\' Town - Big Chest', 'Thieves\' Town - Blind\'s Cell', 'Thieves\' Town - Boss']: + forbid_item(world.get_location(location, player), 'Big Key (Thieves Town)', player) + for location in ['Thieves\' Town - Attic', 'Thieves\' Town - Boss']: + forbid_item(world.get_location(location, player), 'Small Key (Thieves Town)', player) + + set_rule(world.get_entrance('Skull Woods First Section South Door', player), lambda state: state.has_key('Small Key (Skull Woods)', player)) + set_rule(world.get_entrance('Skull Woods First Section (Right) North Door', player), lambda state: state.has_key('Small Key (Skull Woods)', player)) + set_rule(world.get_entrance('Skull Woods First Section West Door', player), lambda state: state.has_key('Small Key (Skull Woods)', player, 2)) # ideally would only be one key, but we may have spent thst key already on escaping the right section + set_rule(world.get_entrance('Skull Woods First Section (Left) Door to Exit', player), lambda state: state.has_key('Small Key (Skull Woods)', player, 2)) + set_rule(world.get_location('Skull Woods - Big Chest', player), lambda state: state.has('Big Key (Skull Woods)', player) or item_name(state, 'Skull Woods - Big Chest', player) == ('Big Key (Skull Woods)', player)) + if world.accessibility != 'locations': + set_always_allow(world.get_location('Skull Woods - Big Chest', player), lambda state, item: item.name == 'Big Key (Skull Woods)' and item.player == player) + set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state.has_key('Small Key (Skull Woods)', player, 3) and state.has('Fire Rod', player) and state.has_sword(player)) # sword required for curtain + set_defeat_dungeon_boss_rule(world.get_location('Skull Woods - Boss', player)) + set_defeat_dungeon_boss_rule(world.get_location('Skull Woods - Prize', player)) + for location in ['Skull Woods - Boss']: + forbid_item(world.get_location(location, player), 'Small Key (Skull Woods)', player) + + set_rule(world.get_entrance('Ice Palace Entrance Room', player), lambda state: state.can_melt_things(player)) + set_rule(world.get_location('Ice Palace - Big Chest', player), lambda state: state.has('Big Key (Ice Palace)', player)) + set_rule(world.get_entrance('Ice Palace (Kholdstare)', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player) and state.has('Big Key (Ice Palace)', player) and (state.has_key('Small Key (Ice Palace)', player, 2) or (state.has('Cane of Somaria', player) and state.has_key('Small Key (Ice Palace)', player, 1)))) + # TODO: investigate change from VT. Changed to hookshot or 2 keys (no checking for big key in specific chests) + set_rule(world.get_entrance('Ice Palace (East)', player), lambda state: (state.has('Hookshot', player) or (item_in_locations(state, 'Big Key (Ice Palace)', player, [('Ice Palace - Spike Room', player), ('Ice Palace - Big Key Chest', player), ('Ice Palace - Map Chest', player)]) and state.has_key('Small Key (Ice Palace)', player))) and (state.world.can_take_damage or state.has('Hookshot', player) or state.has('Cape', player) or state.has('Cane of Byrna', player))) + set_rule(world.get_entrance('Ice Palace (East Top)', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player)) + set_defeat_dungeon_boss_rule(world.get_location('Ice Palace - Boss', player)) + set_defeat_dungeon_boss_rule(world.get_location('Ice Palace - Prize', player)) + for location in ['Ice Palace - Big Chest', 'Ice Palace - Boss']: + forbid_item(world.get_location(location, player), 'Big Key (Ice Palace)', player) + + set_rule(world.get_entrance('Misery Mire Entrance Gap', player), lambda state: (state.has_Boots(player) or state.has('Hookshot', player)) and (state.has_sword(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player))) # need to defeat wizzrobes, bombs don't work ... + set_rule(world.get_location('Misery Mire - Big Chest', player), lambda state: state.has('Big Key (Misery Mire)', player)) + set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player)) + set_rule(world.get_entrance('Misery Mire Big Key Door', player), lambda state: state.has('Big Key (Misery Mire)', player)) + # you can squander the free small key from the pot by opening the south door to the north west switch room, locking you out of accessing a color switch ... + # big key gives backdoor access to that from the teleporter in the north west + set_rule(world.get_location('Misery Mire - Map Chest', player), lambda state: state.has_key('Small Key (Misery Mire)', player, 1) or state.has('Big Key (Misery Mire)', player)) + # in addition, you can open the door to the map room before getting access to a color switch, so this is locked behing 2 small keys or the big key... + set_rule(world.get_location('Misery Mire - Main Lobby', player), lambda state: state.has_key('Small Key (Misery Mire)', player, 2) or state.has_key('Big Key (Misery Mire)', player)) + # we can place a small key in the West wing iff it also contains/blocks the Big Key, as we cannot reach and softlock with the basement key door yet + set_rule(world.get_entrance('Misery Mire (West)', player), lambda state: state.has_key('Small Key (Misery Mire)', player, 2) if ((item_name(state, 'Misery Mire - Compass Chest', player) in [('Big Key (Misery Mire)', player)]) or + (item_name(state, 'Misery Mire - Big Key Chest', player) in [('Big Key (Misery Mire)', player)])) else state.has_key('Small Key (Misery Mire)', player, 3)) + set_rule(world.get_location('Misery Mire - Compass Chest', player), lambda state: state.has_fire_source(player)) + set_rule(world.get_location('Misery Mire - Big Key Chest', player), lambda state: state.has_fire_source(player)) + set_rule(world.get_entrance('Misery Mire (Vitreous)', 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)) + for location in ['Misery Mire - Big Chest', 'Misery Mire - Boss']: + forbid_item(world.get_location(location, player), 'Big Key (Misery Mire)', player) + + set_rule(world.get_entrance('Turtle Rock Entrance Gap', player), lambda state: state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('Turtle Rock Entrance Gap Reverse', player), lambda state: state.has('Cane of Somaria', player)) + set_rule(world.get_location('Turtle Rock - Compass Chest', player), lambda state: state.has('Cane of Somaria', player)) # We could get here from the middle section without Cane as we don't cross the entrance gap! + set_rule(world.get_location('Turtle Rock - Roller Room - Left', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player)) + set_rule(world.get_location('Turtle Rock - Roller Room - Right', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player)) + set_rule(world.get_location('Turtle Rock - Big Chest', player), lambda state: state.has('Big Key (Turtle Rock)', player) and (state.has('Cane of Somaria', player) or state.has('Hookshot', player))) + set_rule(world.get_entrance('Turtle Rock (Big Chest) (North)', player), lambda state: state.has('Cane of Somaria', player) or state.has('Hookshot', player)) + set_rule(world.get_entrance('Turtle Rock Big Key Door', player), lambda state: state.has('Big Key (Turtle Rock)', player)) + set_rule(world.get_entrance('Turtle Rock (Dark Room) (North)', player), lambda state: state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('Turtle Rock (Dark Room) (South)', 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)) + set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) + set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) + set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) + set_rule(world.get_entrance('Turtle Rock (Trinexx)', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 4) and state.has('Big Key (Turtle Rock)', player) and state.has('Cane of Somaria', player)) + set_defeat_dungeon_boss_rule(world.get_location('Turtle Rock - Boss', player)) + set_defeat_dungeon_boss_rule(world.get_location('Turtle Rock - Prize', player)) + + set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: state.can_shoot_arrows(player)) + set_rule(world.get_entrance('Palace of Darkness Hammer Peg Drop', player), lambda state: state.has('Hammer', player)) + set_rule(world.get_entrance('Palace of Darkness Bridge Room', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 1)) # If we can reach any other small key door, we already have back door access to this area + set_rule(world.get_entrance('Palace of Darkness Big Key Door', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6) and state.has('Big Key (Palace of Darkness)', player) and state.can_shoot_arrows(player) and state.has('Hammer', player)) + set_rule(world.get_entrance('Palace of Darkness (North)', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 4)) + set_rule(world.get_location('Palace of Darkness - Big Chest', player), lambda state: state.has('Big Key (Palace of Darkness)', player)) + + set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6) or (item_name(state, 'Palace of Darkness - Big Key Chest', player) in [('Small Key (Palace of Darkness)', player)] and state.has_key('Small Key (Palace of Darkness)', player, 3))) + if world.accessibility != 'locations': + set_always_allow(world.get_location('Palace of Darkness - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Palace of Darkness)' and item.player == player and state.has_key('Small Key (Palace of Darkness)', player, 5)) + else: + forbid_item(world.get_location('Palace of Darkness - Big Key Chest', player), 'Small Key (Palace of Darkness)', player) + + set_rule(world.get_entrance('Palace of Darkness Spike Statue Room Door', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6) or (item_name(state, 'Palace of Darkness - Harmless Hellway', player) in [('Small Key (Palace of Darkness)', player)] and state.has_key('Small Key (Palace of Darkness)', player, 4))) + if world.accessibility != 'locations': + set_always_allow(world.get_location('Palace of Darkness - Harmless Hellway', player), lambda state, item: item.name == 'Small Key (Palace of Darkness)' and item.player == player and state.has_key('Small Key (Palace of Darkness)', player, 5)) + else: + forbid_item(world.get_location('Palace of Darkness - Harmless Hellway', player), 'Small Key (Palace of Darkness)', player) + + set_rule(world.get_entrance('Palace of Darkness Maze Door', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6)) + 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)) + + # these key rules are conservative, you might be able to get away with more lenient rules + randomizer_room_chests = ['Ganons Tower - Randomizer Room - Top Left', 'Ganons Tower - Randomizer Room - Top Right', 'Ganons Tower - Randomizer Room - Bottom Left', 'Ganons Tower - Randomizer Room - Bottom Right'] + compass_room_chests = ['Ganons Tower - Compass Room - Top Left', 'Ganons Tower - Compass Room - Top Right', 'Ganons Tower - Compass Room - Bottom Left', 'Ganons Tower - Compass Room - Bottom Right'] + + set_rule(world.get_location('Ganons Tower - Bob\'s Torch', player), lambda state: state.has_Boots(player)) + set_rule(world.get_entrance('Ganons Tower (Tile Room)', player), lambda state: state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hammer', player)) + + set_rule(world.get_entrance('Ganons Tower (Map Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4) or (item_name(state, 'Ganons Tower - Map Chest', player) in [('Big Key (Ganons Tower)', player), ('Small Key (Ganons Tower)', player)] and state.has_key('Small Key (Ganons Tower)', player, 3))) + if world.accessibility != 'locations': + set_always_allow(world.get_location('Ganons Tower - Map Chest', player), lambda state, item: item.name == 'Small Key (Ganons Tower)' and item.player == player and state.has_key('Small Key (Ganons Tower)', player, 3)) + else: + forbid_item(world.get_location('Ganons Tower - Map Chest', player), 'Small Key (Ganons Tower)', player) + + # It is possible to need more than 2 keys to get through this entance if you spend keys elsewhere. We reflect this in the chest requirements. + # However we need to leave these at the lower values to derive that with 3 keys it is always possible to reach Bob and Ice Armos. + set_rule(world.get_entrance('Ganons Tower (Double Switch Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 2)) + # It is possible to need more than 3 keys .... + set_rule(world.get_entrance('Ganons Tower (Firesnake Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3)) + + #The actual requirements for these rooms to avoid key-lock + set_rule(world.get_location('Ganons Tower - Firesnake Room', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3) or (item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) and state.has_key('Small Key (Ganons Tower)', player, 2))) + for location in randomizer_room_chests: + set_rule(world.get_location(location, player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4) or (item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) and state.has_key('Small Key (Ganons Tower)', player, 3))) + + # Once again it is possible to need more than 3 keys... + set_rule(world.get_entrance('Ganons Tower (Tile Room) Key Door', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3) and state.has('Fire Rod', player)) + # Actual requirements + for location in compass_room_chests: + set_rule(world.get_location(location, player), lambda state: state.has('Fire Rod', player) and (state.has_key('Small Key (Ganons Tower)', player, 4) or (item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(compass_room_chests, [player] * len(compass_room_chests))) and state.has_key('Small Key (Ganons Tower)', player, 3)))) + + set_rule(world.get_location('Ganons Tower - Big Chest', player), lambda state: state.has('Big Key (Ganons Tower)', player)) + + set_rule(world.get_location('Ganons Tower - Big Key Room - Left', player), lambda state: world.get_location('Ganons Tower - Big Key Room - Left', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) + set_rule(world.get_location('Ganons Tower - Big Key Chest', player), lambda state: world.get_location('Ganons Tower - Big Key Chest', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) + set_rule(world.get_location('Ganons Tower - Big Key Room - Right', player), lambda state: world.get_location('Ganons Tower - Big Key Room - Right', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) + + set_rule(world.get_entrance('Ganons Tower Big Key Door', player), lambda state: state.has('Big Key (Ganons Tower)', player) and state.can_shoot_arrows(player)) + set_rule(world.get_entrance('Ganons Tower Torch Rooms', player), lambda state: state.has_fire_source(player) and world.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state)) + set_rule(world.get_location('Ganons Tower - Pre-Moldorm Chest', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3)) + set_rule(world.get_entrance('Ganons Tower Moldorm Door', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4)) + set_rule(world.get_entrance('Ganons Tower Moldorm Gap', player), lambda state: state.has('Hookshot', player) and world.get_entrance('Ganons Tower Moldorm Gap', player).parent_region.dungeon.bosses['top'].can_defeat(state)) + set_defeat_dungeon_boss_rule(world.get_location('Agahnim 2', player)) + for location in ['Ganons Tower - Big Chest', 'Ganons Tower - Mini Helmasaur Room - Left', 'Ganons Tower - Mini Helmasaur Room - Right', + 'Ganons Tower - Pre-Moldorm Chest', 'Ganons Tower - Validation Chest']: + forbid_item(world.get_location(location, player), 'Big Key (Ganons Tower)', player) + + 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) + 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 default_rules(world, player): if world.mode == 'standard': world.get_region('Hyrule Castle Secret Entrance', player).can_reach_private = lambda state: True old_rule = world.get_region('Links House', player).can_reach_private @@ -122,10 +354,6 @@ def global_rules(world, player): world.get_region('Links House', player).can_reach_private = lambda state: True world.get_region('Sanctuary', player).can_reach_private = lambda state: True - # we can s&q to the old man house after we rescue him. This may be somewhere completely different if caves are shuffled! - old_rule = world.get_region('Old Man House', player).can_reach_private - world.get_region('Old Man House', player).can_reach_private = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state) - # overworld requirements set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Kings Grave Outer Rocks', player), lambda state: state.can_lift_heavy_rocks(player)) @@ -133,7 +361,6 @@ def global_rules(world, player): set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(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)) - set_rule(world.get_location('Sunken Treasure', player), lambda state: state.can_reach('Dam', 'Region', player)) set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player)) @@ -150,27 +377,15 @@ def global_rules(world, player): set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot use hammer set_rule(world.get_entrance('Kakariko Teleporter', player), lambda state: ((state.has('Hammer', player) and state.can_lift_rocks(player)) or state.can_lift_heavy_rocks(player)) and state.has_Pearl(player)) # bunny cannot lift bushes set_rule(world.get_location('Flute Spot', player), lambda state: state.has('Shovel', player)) - set_rule(world.get_location('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player)) - set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Waterfall of Wishing', player), lambda state: state.has('Flippers', 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_location('Frog', player), lambda state: state.can_lift_heavy_rocks(player)) # will get automatic moon pearl requirement - set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player)) # Can S&Q with smith - set_rule(world.get_location('Blacksmith', player), lambda state: state.has('Return Smith', player)) - set_rule(world.get_location('Magic Bat', player), lambda state: state.has('Magic Powder', player)) - set_rule(world.get_location('Sick Kid', player), lambda state: state.has_bottle(player)) - set_rule(world.get_location('Library', player), lambda state: state.has_Boots(player)) set_rule(world.get_location('Potion Shop', player), lambda state: state.has('Mushroom', player)) set_rule(world.get_entrance('Desert Palace Entrance (North) Rocks', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Desert Ledge Return Rocks', player), lambda state: state.can_lift_rocks(player)) # should we decide to place something that is not a dungeon end up there at some point set_rule(world.get_entrance('Checkerboard Cave', player), lambda state: state.can_lift_rocks(player)) - set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) - set_rule(world.get_location('Sahasrahla', player), lambda state: state.has('Green Pendant', player)) set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle - set_rule(world.get_entrance('Agahnim 1', player), lambda state: state.has_sword(player) and state.has_key('Small Key (Agahnims Tower)', player, 2)) - set_defeat_dungeon_boss_rule(world.get_location('Agahnim 1', player)) - set_rule(world.get_location('Castle Tower - Dark Maze', player), lambda state: state.has_key('Small Key (Agahnims Tower)', player)) set_rule(world.get_entrance('Top of Pyramid', player), lambda state: state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Old Man Cave Exit (West)', player), lambda state: False) # drop cannot be climbed up set_rule(world.get_entrance('Broken Bridge (West)', player), lambda state: state.has('Hookshot', player)) @@ -180,7 +395,6 @@ def global_rules(world, player): set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: state.has('Mirror', player)) # can erase block set_rule(world.get_entrance('Death Mountain (Top)', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) - set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) set_rule(world.get_entrance('East Death Mountain (Top)', player), lambda state: state.has('Hammer', player)) set_rule(world.get_location('Catfish', player), lambda state: state.can_lift_rocks(player)) @@ -238,220 +452,10 @@ def global_rules(world, player): set_rule(world.get_entrance('Fairy Ascension Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player)) # need to lift flowers set_rule(world.get_entrance('Isolated Ledge 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_location('Spike Cave', player), lambda state: - state.has('Hammer', player) and state.can_lift_rocks(player) and - ((state.has('Cape', player) and state.can_extend_magic(player, 16, True)) or - (state.has('Cane of Byrna', player) and - (state.can_extend_magic(player, 12, True) or - (state.world.can_take_damage and (state.has_Boots(player) or state.has_hearts(player, 4)))))) - ) - - set_rule(world.get_location('Hookshot Cave - Top Right', player), lambda state: state.has('Hookshot', player)) - set_rule(world.get_location('Hookshot Cave - Top Left', player), lambda state: state.has('Hookshot', player)) - set_rule(world.get_location('Hookshot Cave - Bottom Right', player), lambda state: state.has('Hookshot', player) or state.has('Pegasus Boots', player)) - set_rule(world.get_location('Hookshot Cave - Bottom Left', player), lambda state: state.has('Hookshot', player)) 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_Pearl(player) and 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 (!) - set_rule(world.get_location('Mimic Cave', player), lambda state: state.has('Hammer', player)) - set_rule(world.get_entrance('Sewers Door', player), lambda state: state.has_key('Small Key (Escape)', player)) - set_rule(world.get_entrance('Sewers Back Door', player), lambda state: state.has_key('Small Key (Escape)', player)) - - set_rule(world.get_location('Eastern Palace - Big Chest', player), lambda state: state.has('Big Key (Eastern Palace)', player)) - set_rule(world.get_location('Eastern Palace - Boss', player), lambda state: state.can_shoot_arrows(player) and state.has('Big Key (Eastern Palace)', player) and world.get_location('Eastern Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) - set_rule(world.get_location('Eastern Palace - Prize', player), lambda state: state.can_shoot_arrows(player) and state.has('Big Key (Eastern Palace)', player) and world.get_location('Eastern Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) - for location in ['Eastern Palace - Boss', 'Eastern Palace - Big Chest']: - forbid_item(world.get_location(location, player), 'Big Key (Eastern Palace)', player) - - set_rule(world.get_location('Desert Palace - Big Chest', player), lambda state: state.has('Big Key (Desert Palace)', player)) - set_rule(world.get_location('Desert Palace - Torch', player), lambda state: state.has_Boots(player)) - set_rule(world.get_entrance('Desert Palace East Wing', player), lambda state: state.has_key('Small Key (Desert Palace)', player)) - set_rule(world.get_location('Desert Palace - Prize', player), lambda state: state.has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and world.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) - set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state.has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and world.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) - for location in ['Desert Palace - Boss', 'Desert Palace - Big Chest']: - forbid_item(world.get_location(location, player), 'Big Key (Desert Palace)', player) - - for location in ['Desert Palace - Boss', 'Desert Palace - Big Key Chest', 'Desert Palace - Compass Chest']: - forbid_item(world.get_location(location, player), 'Small Key (Desert Palace)', player) - - set_rule(world.get_entrance('Tower of Hera Small Key Door', player), lambda state: state.has_key('Small Key (Tower of Hera)', player) or item_name(state, 'Tower of Hera - Big Key Chest', player) == ('Small Key (Tower of Hera)', player)) - set_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: state.has('Big Key (Tower of Hera)', player)) - set_rule(world.get_location('Tower of Hera - Big Chest', player), lambda state: state.has('Big Key (Tower of Hera)', player)) - set_rule(world.get_location('Tower of Hera - Big Key Chest', player), lambda state: state.has_fire_source(player)) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Tower of Hera - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Tower of Hera)' and item.player == player) - set_defeat_dungeon_boss_rule(world.get_location('Tower of Hera - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Tower of Hera - Prize', player)) - for location in ['Tower of Hera - Boss', 'Tower of Hera - Big Chest', 'Tower of Hera - Compass Chest']: - forbid_item(world.get_location(location, player), 'Big Key (Tower of Hera)', player) -# for location in ['Tower of Hera - Big Key Chest']: -# forbid_item(world.get_location(location, player), 'Small Key (Tower of Hera)', player) - - set_rule(world.get_entrance('Swamp Palace Moat', player), lambda state: state.has('Flippers', player) and state.has('Open Floodgate', player)) - add_rule(world.get_location('Sunken Treasure', player), lambda state: state.has('Open Floodgate', player)) - - set_rule(world.get_entrance('Swamp Palace Small Key Door', player), lambda state: state.has_key('Small Key (Swamp Palace)', player)) - set_rule(world.get_entrance('Swamp Palace (Center)', player), lambda state: state.has('Hammer', player)) - set_rule(world.get_location('Swamp Palace - Big Chest', player), lambda state: state.has('Big Key (Swamp Palace)', player) or item_name(state, 'Swamp Palace - Big Chest', player) == ('Big Key (Swamp Palace)', player)) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Swamp Palace - Big Chest', player), lambda state, item: item.name == 'Big Key (Swamp Palace)' and item.player == player) - set_rule(world.get_entrance('Swamp Palace (North)', player), lambda state: state.has('Hookshot', player)) - set_defeat_dungeon_boss_rule(world.get_location('Swamp Palace - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Swamp Palace - Prize', player)) - for location in ['Swamp Palace - Entrance']: - forbid_item(world.get_location(location, player), 'Big Key (Swamp Palace)', player) - - set_rule(world.get_entrance('Thieves Town Big Key Door', player), lambda state: state.has('Big Key (Thieves Town)', player)) - set_rule(world.get_entrance('Blind Fight', player), lambda state: state.has_key('Small Key (Thieves Town)', player)) - set_defeat_dungeon_boss_rule(world.get_location('Thieves\' Town - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Thieves\' Town - Prize', player)) - set_rule(world.get_location('Thieves\' Town - Big Chest', player), lambda state: (state.has_key('Small Key (Thieves Town)', player) or item_name(state, 'Thieves\' Town - Big Chest', player) == ('Small Key (Thieves Town)', player)) and state.has('Hammer', player)) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Thieves\' Town - Big Chest', player), lambda state, item: item.name == 'Small Key (Thieves Town)' and item.player == player and state.has('Hammer', player)) - set_rule(world.get_location('Thieves\' Town - Attic', player), lambda state: state.has_key('Small Key (Thieves Town)', player)) - for location in ['Thieves\' Town - Attic', 'Thieves\' Town - Big Chest', 'Thieves\' Town - Blind\'s Cell', 'Thieves\' Town - Boss']: - forbid_item(world.get_location(location, player), 'Big Key (Thieves Town)', player) - for location in ['Thieves\' Town - Attic', 'Thieves\' Town - Boss']: - forbid_item(world.get_location(location, player), 'Small Key (Thieves Town)', player) - - set_rule(world.get_entrance('Skull Woods First Section South Door', player), lambda state: state.has_key('Small Key (Skull Woods)', player)) - set_rule(world.get_entrance('Skull Woods First Section (Right) North Door', player), lambda state: state.has_key('Small Key (Skull Woods)', player)) - set_rule(world.get_entrance('Skull Woods First Section West Door', player), lambda state: state.has_key('Small Key (Skull Woods)', player, 2)) # ideally would only be one key, but we may have spent thst key already on escaping the right section - set_rule(world.get_entrance('Skull Woods First Section (Left) Door to Exit', player), lambda state: state.has_key('Small Key (Skull Woods)', player, 2)) - set_rule(world.get_location('Skull Woods - Big Chest', player), lambda state: state.has('Big Key (Skull Woods)', player) or item_name(state, 'Skull Woods - Big Chest', player) == ('Big Key (Skull Woods)', player)) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Skull Woods - Big Chest', player), lambda state, item: item.name == 'Big Key (Skull Woods)' and item.player == player) - set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state.has_key('Small Key (Skull Woods)', player, 3) and state.has('Fire Rod', player) and state.has_sword(player)) # sword required for curtain - set_defeat_dungeon_boss_rule(world.get_location('Skull Woods - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Skull Woods - Prize', player)) - for location in ['Skull Woods - Boss']: - forbid_item(world.get_location(location, player), 'Small Key (Skull Woods)', player) - - set_rule(world.get_entrance('Ice Palace Entrance Room', player), lambda state: state.can_melt_things(player)) - set_rule(world.get_location('Ice Palace - Big Chest', player), lambda state: state.has('Big Key (Ice Palace)', player)) - set_rule(world.get_entrance('Ice Palace (Kholdstare)', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player) and state.has('Big Key (Ice Palace)', player) and (state.has_key('Small Key (Ice Palace)', player, 2) or (state.has('Cane of Somaria', player) and state.has_key('Small Key (Ice Palace)', player, 1)))) - # TODO: investigate change from VT. Changed to hookshot or 2 keys (no checking for big key in specific chests) - set_rule(world.get_entrance('Ice Palace (East)', player), lambda state: (state.has('Hookshot', player) or (item_in_locations(state, 'Big Key (Ice Palace)', player, [('Ice Palace - Spike Room', player), ('Ice Palace - Big Key Chest', player), ('Ice Palace - Map Chest', player)]) and state.has_key('Small Key (Ice Palace)', player))) and (state.world.can_take_damage or state.has('Hookshot', player) or state.has('Cape', player) or state.has('Cane of Byrna', player))) - set_rule(world.get_entrance('Ice Palace (East Top)', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player)) - set_defeat_dungeon_boss_rule(world.get_location('Ice Palace - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Ice Palace - Prize', player)) - for location in ['Ice Palace - Big Chest', 'Ice Palace - Boss']: - forbid_item(world.get_location(location, player), 'Big Key (Ice Palace)', player) - - set_rule(world.get_entrance('Misery Mire Entrance Gap', player), lambda state: (state.has_Boots(player) or state.has('Hookshot', player)) and (state.has_sword(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player))) # need to defeat wizzrobes, bombs don't work ... - set_rule(world.get_location('Misery Mire - Big Chest', player), lambda state: state.has('Big Key (Misery Mire)', player)) - set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player)) - set_rule(world.get_entrance('Misery Mire Big Key Door', player), lambda state: state.has('Big Key (Misery Mire)', player)) - # you can squander the free small key from the pot by opening the south door to the north west switch room, locking you out of accessing a color switch ... - # big key gives backdoor access to that from the teleporter in the north west - set_rule(world.get_location('Misery Mire - Map Chest', player), lambda state: state.has_key('Small Key (Misery Mire)', player, 1) or state.has('Big Key (Misery Mire)', player)) - # in addition, you can open the door to the map room before getting access to a color switch, so this is locked behing 2 small keys or the big key... - set_rule(world.get_location('Misery Mire - Main Lobby', player), lambda state: state.has_key('Small Key (Misery Mire)', player, 2) or state.has_key('Big Key (Misery Mire)', player)) - # we can place a small key in the West wing iff it also contains/blocks the Big Key, as we cannot reach and softlock with the basement key door yet - set_rule(world.get_entrance('Misery Mire (West)', player), lambda state: state.has_key('Small Key (Misery Mire)', player, 2) if ((item_name(state, 'Misery Mire - Compass Chest', player) in [('Big Key (Misery Mire)', player)]) or - (item_name(state, 'Misery Mire - Big Key Chest', player) in [('Big Key (Misery Mire)', player)])) else state.has_key('Small Key (Misery Mire)', player, 3)) - set_rule(world.get_location('Misery Mire - Compass Chest', player), lambda state: state.has_fire_source(player)) - set_rule(world.get_location('Misery Mire - Big Key Chest', player), lambda state: state.has_fire_source(player)) - set_rule(world.get_entrance('Misery Mire (Vitreous)', 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)) - for location in ['Misery Mire - Big Chest', 'Misery Mire - Boss']: - forbid_item(world.get_location(location, player), 'Big Key (Misery Mire)', player) - - set_rule(world.get_entrance('Turtle Rock Entrance Gap', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('Turtle Rock Entrance Gap Reverse', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_location('Turtle Rock - Compass Chest', player), lambda state: state.has('Cane of Somaria', player)) # We could get here from the middle section without Cane as we don't cross the entrance gap! - set_rule(world.get_location('Turtle Rock - Roller Room - Left', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player)) - set_rule(world.get_location('Turtle Rock - Roller Room - Right', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player)) - set_rule(world.get_location('Turtle Rock - Big Chest', player), lambda state: state.has('Big Key (Turtle Rock)', player) and (state.has('Cane of Somaria', player) or state.has('Hookshot', player))) - set_rule(world.get_entrance('Turtle Rock (Big Chest) (North)', player), lambda state: state.has('Cane of Somaria', player) or state.has('Hookshot', player)) - set_rule(world.get_entrance('Turtle Rock Big Key Door', player), lambda state: state.has('Big Key (Turtle Rock)', player)) - set_rule(world.get_entrance('Turtle Rock (Dark Room) (North)', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('Turtle Rock (Dark Room) (South)', 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)) - set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) - set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) - set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) - set_rule(world.get_entrance('Turtle Rock (Trinexx)', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 4) and state.has('Big Key (Turtle Rock)', player) and state.has('Cane of Somaria', player)) - set_defeat_dungeon_boss_rule(world.get_location('Turtle Rock - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Turtle Rock - Prize', player)) - - set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: state.can_shoot_arrows(player)) - set_rule(world.get_entrance('Palace of Darkness Hammer Peg Drop', player), lambda state: state.has('Hammer', player)) - set_rule(world.get_entrance('Palace of Darkness Bridge Room', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 1)) # If we can reach any other small key door, we already have back door access to this area - set_rule(world.get_entrance('Palace of Darkness Big Key Door', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6) and state.has('Big Key (Palace of Darkness)', player) and state.can_shoot_arrows(player) and state.has('Hammer', player)) - set_rule(world.get_entrance('Palace of Darkness (North)', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 4)) - set_rule(world.get_location('Palace of Darkness - Big Chest', player), lambda state: state.has('Big Key (Palace of Darkness)', player)) - - set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6) or (item_name(state, 'Palace of Darkness - Big Key Chest', player) in [('Small Key (Palace of Darkness)', player)] and state.has_key('Small Key (Palace of Darkness)', player, 3))) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Palace of Darkness - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Palace of Darkness)' and item.player == player and state.has_key('Small Key (Palace of Darkness)', player, 5)) - else: - forbid_item(world.get_location('Palace of Darkness - Big Key Chest', player), 'Small Key (Palace of Darkness)', player) - - set_rule(world.get_entrance('Palace of Darkness Spike Statue Room Door', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6) or (item_name(state, 'Palace of Darkness - Harmless Hellway', player) in [('Small Key (Palace of Darkness)', player)] and state.has_key('Small Key (Palace of Darkness)', player, 4))) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Palace of Darkness - Harmless Hellway', player), lambda state, item: item.name == 'Small Key (Palace of Darkness)' and item.player == player and state.has_key('Small Key (Palace of Darkness)', player, 5)) - else: - forbid_item(world.get_location('Palace of Darkness - Harmless Hellway', player), 'Small Key (Palace of Darkness)', player) - - set_rule(world.get_entrance('Palace of Darkness Maze Door', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6)) - 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)) - - # these key rules are conservative, you might be able to get away with more lenient rules - randomizer_room_chests = ['Ganons Tower - Randomizer Room - Top Left', 'Ganons Tower - Randomizer Room - Top Right', 'Ganons Tower - Randomizer Room - Bottom Left', 'Ganons Tower - Randomizer Room - Bottom Right'] - compass_room_chests = ['Ganons Tower - Compass Room - Top Left', 'Ganons Tower - Compass Room - Top Right', 'Ganons Tower - Compass Room - Bottom Left', 'Ganons Tower - Compass Room - Bottom Right'] - - set_rule(world.get_location('Ganons Tower - Bob\'s Torch', player), lambda state: state.has_Boots(player)) - set_rule(world.get_entrance('Ganons Tower (Tile Room)', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hammer', player)) - - set_rule(world.get_entrance('Ganons Tower (Map Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4) or (item_name(state, 'Ganons Tower - Map Chest', player) in [('Big Key (Ganons Tower)', player), ('Small Key (Ganons Tower)', player)] and state.has_key('Small Key (Ganons Tower)', player, 3))) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Ganons Tower - Map Chest', player), lambda state, item: item.name == 'Small Key (Ganons Tower)' and item.player == player and state.has_key('Small Key (Ganons Tower)', player, 3)) - else: - forbid_item(world.get_location('Ganons Tower - Map Chest', player), 'Small Key (Ganons Tower)', player) - - # It is possible to need more than 2 keys to get through this entance if you spend keys elsewhere. We reflect this in the chest requirements. - # However we need to leave these at the lower values to derive that with 3 keys it is always possible to reach Bob and Ice Armos. - set_rule(world.get_entrance('Ganons Tower (Double Switch Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 2)) - # It is possible to need more than 3 keys .... - set_rule(world.get_entrance('Ganons Tower (Firesnake Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3)) - - #The actual requirements for these rooms to avoid key-lock - set_rule(world.get_location('Ganons Tower - Firesnake Room', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3) or (item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) and state.has_key('Small Key (Ganons Tower)', player, 2))) - for location in randomizer_room_chests: - set_rule(world.get_location(location, player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4) or (item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) and state.has_key('Small Key (Ganons Tower)', player, 3))) - - # Once again it is possible to need more than 3 keys... - set_rule(world.get_entrance('Ganons Tower (Tile Room) Key Door', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3) and state.has('Fire Rod', player)) - # Actual requirements - for location in compass_room_chests: - set_rule(world.get_location(location, player), lambda state: state.has('Fire Rod', player) and (state.has_key('Small Key (Ganons Tower)', player, 4) or (item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(compass_room_chests, [player] * len(compass_room_chests))) and state.has_key('Small Key (Ganons Tower)', player, 3)))) - - set_rule(world.get_location('Ganons Tower - Big Chest', player), lambda state: state.has('Big Key (Ganons Tower)', player)) - - set_rule(world.get_location('Ganons Tower - Big Key Room - Left', player), lambda state: world.get_location('Ganons Tower - Big Key Room - Left', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) - set_rule(world.get_location('Ganons Tower - Big Key Chest', player), lambda state: world.get_location('Ganons Tower - Big Key Chest', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) - set_rule(world.get_location('Ganons Tower - Big Key Room - Right', player), lambda state: world.get_location('Ganons Tower - Big Key Room - Right', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) - - set_rule(world.get_entrance('Ganons Tower Big Key Door', player), lambda state: state.has('Big Key (Ganons Tower)', player) and state.can_shoot_arrows(player)) - set_rule(world.get_entrance('Ganons Tower Torch Rooms', player), lambda state: state.has_fire_source(player) and world.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state)) - set_rule(world.get_location('Ganons Tower - Pre-Moldorm Chest', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3)) - set_rule(world.get_entrance('Ganons Tower Moldorm Door', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4)) - set_rule(world.get_entrance('Ganons Tower Moldorm Gap', player), lambda state: state.has('Hookshot', player) and world.get_entrance('Ganons Tower Moldorm Gap', player).parent_region.dungeon.bosses['top'].can_defeat(state)) - set_defeat_dungeon_boss_rule(world.get_location('Agahnim 2', player)) set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player)) - for location in ['Ganons Tower - Big Chest', 'Ganons Tower - Mini Helmasaur Room - Left', 'Ganons Tower - Mini Helmasaur Room - Right', - 'Ganons Tower - Pre-Moldorm Chest', 'Ganons Tower - Validation Chest']: - forbid_item(world.get_location(location, player), 'Big Key (Ganons Tower)', player) - - 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) - 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 - 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. if world.swords == 'swordless': @@ -462,21 +466,11 @@ def global_rules(world, player): set_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt, player)) def inverted_rules(world, player): - if world.goal == 'triforcehunt': - for location in world.get_locations(): - if location.player != player: - forbid_item(location, 'Triforce Piece', player) - - add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player) - # s&q regions. link's house entrance is set to true so the filler knows the chest inside can always be reached world.get_region('Inverted Links House', player).can_reach_private = lambda state: True world.get_region('Inverted Links House', player).entrances[0].can_reach = lambda state: True world.get_region('Inverted Dark Sanctuary', player).entrances[0].parent_region.can_reach_private = lambda state: True - old_rule = world.get_region('Old Man House', player).can_reach_private - world.get_region('Old Man House', player).can_reach_private = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state) - old_rule = world.get_region('Hyrule Castle Ledge', player).can_reach_private world.get_region('Hyrule Castle Ledge', player).can_reach_private = lambda state: (state.has_Mirror(player) and state.has('Beat Agahnim 1', player) and state.can_reach_light_world(player)) or old_rule(state) @@ -499,7 +493,6 @@ def inverted_rules(world, 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)) - add_rule(world.get_location('Sunken Treasure', player), lambda state: state.can_reach('Light World', 'Region', player) and state.has('Open Floodgate', 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)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player) and state.has_Pearl(player)) @@ -516,16 +509,10 @@ def inverted_rules(world, player): set_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot use hammer set_rule(world.get_entrance('West Dark World Teleporter', player), lambda state: ((state.has('Hammer', player) and state.can_lift_rocks(player)) or state.can_lift_heavy_rocks(player)) and state.has_Pearl(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('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player)) - set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest 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_location('Frog', player), lambda state: state.can_lift_heavy_rocks(player) or (state.can_reach('Light World', 'Region', player) and state.has_Mirror(player))) - set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith - set_rule(world.get_location('Blacksmith', player), lambda state: state.has('Return Smith', player)) - set_rule(world.get_location('Magic Bat', player), lambda state: state.has('Magic Powder', player) and state.has_Pearl(player)) - set_rule(world.get_location('Sick Kid', player), lambda state: state.has_bottle(player)) set_rule(world.get_location('Mushroom', player), lambda state: state.has_Pearl(player)) # need pearl to pick up bushes set_rule(world.get_entrance('Bush Covered Lawn Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Bush Covered Lawn Inner Bushes', player), lambda state: state.has_Pearl(player)) @@ -534,16 +521,10 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Bomb Hut Outer Bushes', player), lambda state: state.has_Pearl(player)) 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('Library', player), lambda state: state.has_Boots(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 set_rule(world.get_entrance('Desert Palace Entrance (North) Rocks', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player)) set_rule(world.get_entrance('Desert Ledge Return Rocks', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player)) # should we decide to place something that is not a dungeon end up there at some point set_rule(world.get_entrance('Checkerboard Cave', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player)) - set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) - set_rule(world.get_location('Sahasrahla', player), lambda state: state.has('Green Pendant', player)) - set_rule(world.get_entrance('Agahnim 1', player), lambda state: state.has_sword(player) and state.has_key('Small Key (Agahnims Tower)', player, 2)) - set_defeat_dungeon_boss_rule(world.get_location('Agahnim 1', player)) - set_rule(world.get_location('Castle Tower - Dark Maze', player), lambda state: state.has_key('Small Key (Agahnims Tower)', player)) set_rule(world.get_entrance('Hyrule Castle Secret Entrance Drop', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Old Man Cave Exit (West)', player), lambda state: False) # drop cannot be climbed up set_rule(world.get_entrance('Broken Bridge (West)', player), lambda state: state.has('Hookshot', player) and state.has_Pearl(player)) @@ -553,7 +534,6 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: state.has('Mirror', player)) # can erase block set_rule(world.get_entrance('Death Mountain (Top)', player), lambda state: state.has('Hammer', player) and state.has_Pearl(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_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) 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))) @@ -596,22 +576,8 @@ def inverted_rules(world, 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_location('Spike Cave', player), lambda state: - state.has('Hammer', player) and state.can_lift_rocks(player) and - ((state.has('Cape', player) and state.can_extend_magic(player, 16, True)) or - (state.has('Cane of Byrna', player) and - (state.can_extend_magic(player, 12, True) or - (state.world.can_take_damage and (state.has_Boots(player) or state.has_hearts(player, 4)))))) - ) - - set_rule(world.get_location('Hookshot Cave - Top Right', player), lambda state: state.has('Hookshot', player)) - set_rule(world.get_location('Hookshot Cave - Top Left', player), lambda state: state.has('Hookshot', player)) - set_rule(world.get_location('Hookshot Cave - Bottom Right', player), lambda state: state.has('Hookshot', player) or state.has('Pegasus Boots', player)) - set_rule(world.get_location('Hookshot Cave - Bottom Left', player), lambda state: state.has('Hookshot', player)) 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 (!) - set_rule(world.get_location('Mimic Cave', player), lambda state: state.has('Hammer', player)) # new inverted spots set_rule(world.get_entrance('Post Aga Teleporter', player), lambda state: state.has('Beat Agahnim 1', player)) @@ -644,204 +610,7 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Dark Grassy Lawn Flute', player), lambda state: state.can_flute(player)) set_rule(world.get_entrance('Hammer Peg Area Flute', player), lambda state: state.can_flute(player)) - set_rule(world.get_entrance('Sewers Door', player), lambda state: state.has_key('Small Key (Escape)', player)) - set_rule(world.get_entrance('Sewers Back Door', player), lambda state: state.has_key('Small Key (Escape)', player)) - - set_rule(world.get_location('Eastern Palace - Big Chest', player), lambda state: state.has('Big Key (Eastern Palace)', player)) - set_rule(world.get_location('Eastern Palace - Boss', player), lambda state: state.can_shoot_arrows(player) and state.has('Big Key (Eastern Palace)', player) and world.get_location('Eastern Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) - set_rule(world.get_location('Eastern Palace - Prize', player), lambda state: state.can_shoot_arrows(player) and state.has('Big Key (Eastern Palace)', player) and world.get_location('Eastern Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) - for location in ['Eastern Palace - Boss', 'Eastern Palace - Big Chest']: - forbid_item(world.get_location(location, player), 'Big Key (Eastern Palace)', player) - - set_rule(world.get_location('Desert Palace - Big Chest', player), lambda state: state.has('Big Key (Desert Palace)', player)) - set_rule(world.get_location('Desert Palace - Torch', player), lambda state: state.has_Boots(player)) - set_rule(world.get_entrance('Desert Palace East Wing', player), lambda state: state.has_key('Small Key (Desert Palace)', player)) - set_rule(world.get_location('Desert Palace - Prize', player), lambda state: state.has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and world.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) - set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state.has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and world.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) - for location in ['Desert Palace - Boss', 'Desert Palace - Big Chest']: - forbid_item(world.get_location(location, player), 'Big Key (Desert Palace)', player) - - for location in ['Desert Palace - Boss', 'Desert Palace - Big Key Chest', 'Desert Palace - Compass Chest']: - forbid_item(world.get_location(location, player), 'Small Key (Desert Palace)', player) - - set_rule(world.get_entrance('Tower of Hera Small Key Door', player), lambda state: state.has_key('Small Key (Tower of Hera)', player) or item_name(state, 'Tower of Hera - Big Key Chest', player) == ('Small Key (Tower of Hera)', player)) - set_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: state.has('Big Key (Tower of Hera)', player)) - set_rule(world.get_location('Tower of Hera - Big Chest', player), lambda state: state.has('Big Key (Tower of Hera)', player)) - set_rule(world.get_location('Tower of Hera - Big Key Chest', player), lambda state: state.has_fire_source(player)) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Tower of Hera - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Tower of Hera)' and item.player == player) - set_defeat_dungeon_boss_rule(world.get_location('Tower of Hera - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Tower of Hera - Prize', player)) - for location in ['Tower of Hera - Boss', 'Tower of Hera - Big Chest', 'Tower of Hera - Compass Chest']: - forbid_item(world.get_location(location, player), 'Big Key (Tower of Hera)', player) -# for location in ['Tower of Hera - Big Key Chest']: -# forbid_item(world.get_location(location, player), 'Small Key (Tower of Hera)', player) - - set_rule(world.get_entrance('Swamp Palace Moat', player), lambda state: state.has('Flippers', player) and state.has('Open Floodgate', player)) - add_rule(world.get_location('Sunken Treasure', player), lambda state: state.has('Open Floodgate', player)) - - set_rule(world.get_entrance('Swamp Palace Small Key Door', player), lambda state: state.has_key('Small Key (Swamp Palace)', player)) - set_rule(world.get_entrance('Swamp Palace (Center)', player), lambda state: state.has('Hammer', player)) - set_rule(world.get_location('Swamp Palace - Big Chest', player), lambda state: state.has('Big Key (Swamp Palace)', player) or item_name(state, 'Swamp Palace - Big Chest', player) == ('Big Key (Swamp Palace)', player)) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Swamp Palace - Big Chest', player), lambda state, item: item.name == 'Big Key (Swamp Palace)' and item.player == player) - set_rule(world.get_entrance('Swamp Palace (North)', player), lambda state: state.has('Hookshot', player)) - set_defeat_dungeon_boss_rule(world.get_location('Swamp Palace - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Swamp Palace - Prize', player)) - for location in ['Swamp Palace - Entrance']: - forbid_item(world.get_location(location, player), 'Big Key (Swamp Palace)', player) - - set_rule(world.get_entrance('Thieves Town Big Key Door', player), lambda state: state.has('Big Key (Thieves Town)', player)) - set_rule(world.get_entrance('Blind Fight', player), lambda state: state.has_key('Small Key (Thieves Town)', player)) - set_defeat_dungeon_boss_rule(world.get_location('Thieves\' Town - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Thieves\' Town - Prize', player)) - set_rule(world.get_location('Thieves\' Town - Big Chest', player), lambda state: (state.has_key('Small Key (Thieves Town)', player) or item_name(state, 'Thieves\' Town - Big Chest', player) == ('Small Key (Thieves Town)', player)) and state.has('Hammer', player)) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Thieves\' Town - Big Chest', player), lambda state, item: item.name == 'Small Key (Thieves Town)' and item.player == player and state.has('Hammer', player)) - set_rule(world.get_location('Thieves\' Town - Attic', player), lambda state: state.has_key('Small Key (Thieves Town)', player)) - for location in ['Thieves\' Town - Attic', 'Thieves\' Town - Big Chest', 'Thieves\' Town - Blind\'s Cell', 'Thieves\' Town - Boss']: - forbid_item(world.get_location(location, player), 'Big Key (Thieves Town)', player) - for location in ['Thieves\' Town - Attic', 'Thieves\' Town - Boss']: - forbid_item(world.get_location(location, player), 'Small Key (Thieves Town)', player) - - set_rule(world.get_entrance('Skull Woods First Section South Door', player), lambda state: state.has_key('Small Key (Skull Woods)', player)) - set_rule(world.get_entrance('Skull Woods First Section (Right) North Door', player), lambda state: state.has_key('Small Key (Skull Woods)', player)) - set_rule(world.get_entrance('Skull Woods First Section West Door', player), lambda state: state.has_key('Small Key (Skull Woods)', player, 2)) # ideally would only be one key, but we may have spent thst key already on escaping the right section - set_rule(world.get_entrance('Skull Woods First Section (Left) Door to Exit', player), lambda state: state.has_key('Small Key (Skull Woods)', player, 2)) - set_rule(world.get_location('Skull Woods - Big Chest', player), lambda state: state.has('Big Key (Skull Woods)', player) or item_name(state, 'Skull Woods - Big Chest', player) == ('Big Key (Skull Woods)', player)) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Skull Woods - Big Chest', player), lambda state, item: item.name == 'Big Key (Skull Woods)' and item.player == player) - - set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state.has_key('Small Key (Skull Woods)', player, 3) and state.has('Fire Rod', player) and state.has_sword(player)) # sword required for curtain - set_defeat_dungeon_boss_rule(world.get_location('Skull Woods - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Skull Woods - Prize', player)) - for location in ['Skull Woods - Boss']: - forbid_item(world.get_location(location, player), 'Small Key (Skull Woods)', player) - - set_rule(world.get_entrance('Ice Palace Entrance Room', player), lambda state: state.can_melt_things(player)) - set_rule(world.get_location('Ice Palace - Big Chest', player), lambda state: state.has('Big Key (Ice Palace)', player)) - set_rule(world.get_entrance('Ice Palace (Kholdstare)', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player) and state.has('Big Key (Ice Palace)', player) and (state.has_key('Small Key (Ice Palace)', player, 2) or (state.has('Cane of Somaria', player) and state.has_key('Small Key (Ice Palace)', player, 1)))) - # TODO: investigate change from VT. Changed to hookshot or 2 keys (no checking for big key in specific chests) - set_rule(world.get_entrance('Ice Palace (East)', player), lambda state: (state.has('Hookshot', player) or (item_in_locations(state, 'Big Key (Ice Palace)', player, [('Ice Palace - Spike Room', player), ('Ice Palace - Big Key Chest', player), ('Ice Palace - Map Chest', player)]) and state.has_key('Small Key (Ice Palace)', player))) and (state.world.can_take_damage or state.has('Hookshot', player) or state.has('Cape', player) or state.has('Cane of Byrna', player))) - set_rule(world.get_entrance('Ice Palace (East Top)', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player)) - set_defeat_dungeon_boss_rule(world.get_location('Ice Palace - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Ice Palace - Prize', player)) - for location in ['Ice Palace - Big Chest', 'Ice Palace - Boss']: - forbid_item(world.get_location(location, player), 'Big Key (Ice Palace)', player) - - set_rule(world.get_entrance('Misery Mire Entrance Gap', player), lambda state: (state.has_Boots(player) or state.has('Hookshot', player)) and (state.has_sword(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player))) # need to defeat wizzrobes, bombs don't work ... - set_rule(world.get_location('Misery Mire - Big Chest', player), lambda state: state.has('Big Key (Misery Mire)', player)) - set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player)) - set_rule(world.get_entrance('Misery Mire Big Key Door', player), lambda state: state.has('Big Key (Misery Mire)', player)) - # you can squander the free small key from the pot by opening the south door to the north west switch room, locking you out of accessing a color switch ... - # big key gives backdoor access to that from the teleporter in the north west - set_rule(world.get_location('Misery Mire - Map Chest', player), lambda state: state.has_key('Small Key (Misery Mire)', player, 1) or state.has('Big Key (Misery Mire)', player)) - # in addition, you can open the door to the map room before getting access to a color switch, so this is locked behing 2 small keys or the big key... - set_rule(world.get_location('Misery Mire - Main Lobby', player), lambda state: state.has_key('Small Key (Misery Mire)', player, 2) or state.has_key('Big Key (Misery Mire)', player)) - # we can place a small key in the West wing iff it also contains/blocks the Big Key, as we cannot reach and softlock with the basement key door yet - set_rule(world.get_entrance('Misery Mire (West)', player), lambda state: state.has_key('Small Key (Misery Mire)', player, 2) if ((item_name(state, 'Misery Mire - Compass Chest', player) in [('Big Key (Misery Mire)', player)]) or - (item_name(state, 'Misery Mire - Big Key Chest', player) in [('Big Key (Misery Mire)', player)])) else state.has_key('Small Key (Misery Mire)', player, 3)) - set_rule(world.get_location('Misery Mire - Compass Chest', player), lambda state: state.has_fire_source(player)) - set_rule(world.get_location('Misery Mire - Big Key Chest', player), lambda state: state.has_fire_source(player)) - set_rule(world.get_entrance('Misery Mire (Vitreous)', 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)) - for location in ['Misery Mire - Big Chest', 'Misery Mire - Boss']: - forbid_item(world.get_location(location, player), 'Big Key (Misery Mire)', player) - - set_rule(world.get_entrance('Turtle Rock Entrance Gap', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('Turtle Rock Entrance Gap Reverse', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_location('Turtle Rock - Compass Chest', player), lambda state: state.has('Cane of Somaria', player)) # We could get here from the middle section without Cane as we don't cross the entrance gap! - set_rule(world.get_location('Turtle Rock - Roller Room - Left', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player)) - set_rule(world.get_location('Turtle Rock - Roller Room - Right', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player)) - set_rule(world.get_location('Turtle Rock - Big Chest', player), lambda state: state.has('Big Key (Turtle Rock)', player) and (state.has('Cane of Somaria', player) or state.has('Hookshot', player))) - set_rule(world.get_entrance('Turtle Rock (Big Chest) (North)', player), lambda state: state.has('Cane of Somaria', player) or state.has('Hookshot', player)) - set_rule(world.get_entrance('Turtle Rock Big Key Door', player), lambda state: state.has('Big Key (Turtle Rock)', player)) - set_rule(world.get_entrance('Turtle Rock (Dark Room) (North)', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('Turtle Rock (Dark Room) (South)', 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)) - set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) - set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) - set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) - set_rule(world.get_entrance('Turtle Rock (Trinexx)', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 4) and state.has('Big Key (Turtle Rock)', player) and state.has('Cane of Somaria', player)) - set_defeat_dungeon_boss_rule(world.get_location('Turtle Rock - Boss', player)) - set_defeat_dungeon_boss_rule(world.get_location('Turtle Rock - Prize', player)) - - set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: state.can_shoot_arrows(player)) - set_rule(world.get_entrance('Palace of Darkness Hammer Peg Drop', player), lambda state: state.has('Hammer', player)) - set_rule(world.get_entrance('Palace of Darkness Bridge Room', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 1)) # If we can reach any other small key door, we already have back door access to this area - set_rule(world.get_entrance('Palace of Darkness Big Key Door', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6) and state.has('Big Key (Palace of Darkness)', player) and state.can_shoot_arrows(player) and state.has('Hammer', player)) - set_rule(world.get_entrance('Palace of Darkness (North)', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 4)) - set_rule(world.get_location('Palace of Darkness - Big Chest', player), lambda state: state.has('Big Key (Palace of Darkness)', player)) - - set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6) or (item_name(state, 'Palace of Darkness - Big Key Chest', player) in [('Small Key (Palace of Darkness)', player)] and state.has_key('Small Key (Palace of Darkness)', player, 3))) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Palace of Darkness - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Palace of Darkness)' and item.player == player and state.has_key('Small Key (Palace of Darkness)', player, 5)) - else: - forbid_item(world.get_location('Palace of Darkness - Big Key Chest', player), 'Small Key (Palace of Darkness)', player) - - set_rule(world.get_entrance('Palace of Darkness Spike Statue Room Door', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6) or (item_name(state, 'Palace of Darkness - Harmless Hellway', player) in [('Small Key (Palace of Darkness)', player)] and state.has_key('Small Key (Palace of Darkness)', player, 4))) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Palace of Darkness - Harmless Hellway', player), lambda state, item: item.name == 'Small Key (Palace of Darkness)' and item.player == player and state.has_key('Small Key (Palace of Darkness)', player, 5)) - else: - forbid_item(world.get_location('Palace of Darkness - Harmless Hellway', player), 'Small Key (Palace of Darkness)', player) - - set_rule(world.get_entrance('Palace of Darkness Maze Door', player), lambda state: state.has_key('Small Key (Palace of Darkness)', player, 6)) - 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)) - - # these key rules are conservative, you might be able to get away with more lenient rules - randomizer_room_chests = ['Ganons Tower - Randomizer Room - Top Left', 'Ganons Tower - Randomizer Room - Top Right', 'Ganons Tower - Randomizer Room - Bottom Left', 'Ganons Tower - Randomizer Room - Bottom Right'] - compass_room_chests = ['Ganons Tower - Compass Room - Top Left', 'Ganons Tower - Compass Room - Top Right', 'Ganons Tower - Compass Room - Bottom Left', 'Ganons Tower - Compass Room - Bottom Right'] - - set_rule(world.get_location('Ganons Tower - Bob\'s Torch', player), lambda state: state.has_Boots(player)) - set_rule(world.get_entrance('Ganons Tower (Tile Room)', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hammer', player)) - - set_rule(world.get_entrance('Ganons Tower (Map Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4) or (item_name(state, 'Ganons Tower - Map Chest', player) in [('Big Key (Ganons Tower)', player), ('Small Key (Ganons Tower)', player)] and state.has_key('Small Key (Ganons Tower)', player, 3))) - if world.accessibility != 'locations': - set_always_allow(world.get_location('Ganons Tower - Map Chest', player), lambda state, item: item.name == 'Small Key (Ganons Tower)' and item.player == player and state.has_key('Small Key (Ganons Tower)', player, 3)) - else: - forbid_item(world.get_location('Ganons Tower - Map Chest', player), 'Small Key (Ganons Tower)', player) - - # It is possible to need more than 2 keys to get through this entance if you spend keys elsewhere. We reflect this in the chest requirements. - # However we need to leave these at the lower values to derive that with 3 keys it is always possible to reach Bob and Ice Armos. - set_rule(world.get_entrance('Ganons Tower (Double Switch Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 2)) - # It is possible to need more than 3 keys .... - set_rule(world.get_entrance('Ganons Tower (Firesnake Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3)) - - #The actual requirements for these rooms to avoid key-lock - set_rule(world.get_location('Ganons Tower - Firesnake Room', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3) or (item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) and state.has_key('Small Key (Ganons Tower)', player, 2))) - for location in randomizer_room_chests: - set_rule(world.get_location(location, player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4) or (item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) and state.has_key('Small Key (Ganons Tower)', player, 3))) - - # Once again it is possible to need more than 3 keys... - set_rule(world.get_entrance('Ganons Tower (Tile Room) Key Door', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3) and state.has('Fire Rod', player)) - # Actual requirements - for location in compass_room_chests: - set_rule(world.get_location(location, player), lambda state: state.has('Fire Rod', player) and (state.has_key('Small Key (Ganons Tower)', player, 4) or (item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(compass_room_chests, [player] * len(compass_room_chests))) and state.has_key('Small Key (Ganons Tower)', player, 3)))) - - set_rule(world.get_location('Ganons Tower - Big Chest', player), lambda state: state.has('Big Key (Ganons Tower)', player)) - - set_rule(world.get_location('Ganons Tower - Big Key Room - Left', player), lambda state: world.get_location('Ganons Tower - Big Key Room - Left', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) - set_rule(world.get_location('Ganons Tower - Big Key Chest', player), lambda state: world.get_location('Ganons Tower - Big Key Chest', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) - set_rule(world.get_location('Ganons Tower - Big Key Room - Right', player), lambda state: world.get_location('Ganons Tower - Big Key Room - Right', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) - - set_rule(world.get_entrance('Ganons Tower Big Key Door', player), lambda state: state.has('Big Key (Ganons Tower)', player) and state.can_shoot_arrows(player)) - set_rule(world.get_entrance('Ganons Tower Torch Rooms', player), lambda state: state.has_fire_source(player) and world.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state)) - set_rule(world.get_location('Ganons Tower - Pre-Moldorm Chest', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 3)) - set_rule(world.get_entrance('Ganons Tower Moldorm Door', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4)) - set_rule(world.get_entrance('Ganons Tower Moldorm Gap', player), lambda state: state.has('Hookshot', player) and world.get_entrance('Ganons Tower Moldorm Gap', player).parent_region.dungeon.bosses['top'].can_defeat(state)) - set_defeat_dungeon_boss_rule(world.get_location('Agahnim 2', player)) set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player)) - for location in ['Ganons Tower - Big Chest', 'Ganons Tower - Mini Helmasaur Room - Left', 'Ganons Tower - Mini Helmasaur Room - Right', - 'Ganons Tower - Pre-Moldorm Chest', 'Ganons Tower - Validation Chest']: - forbid_item(world.get_location(location, player), 'Big Key (Ganons Tower)', player) - - 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) - 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 - 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 == 'swordless': @@ -1111,7 +880,6 @@ def set_big_bomb_rules(world, player): 'Bonk Rock Cave', 'Library', 'Potion Shop', - 'Waterfall of Wishing', 'Dam', 'Lumberjack House', 'Lake Hylia Fortune Teller', @@ -1307,6 +1075,10 @@ def set_big_bomb_rules(world, player): # to account for insanity, must consider a way to escape without a cave for basic_routes # -> (M and Mitts) or ((Mitts or Flute or (M and P and West Dark World access)) and BR) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and state.has_Mirror(player)) or ((state.can_lift_heavy_rocks(player) or state.has('Ocarina', player) or (state.can_reach('West Dark World', 'Region', player) and state.has_Pearl(player) and state.has_Mirror(player))) and basic_routes(state))) + elif bombshop_entrance.name == 'Waterfall of Wishing': + # same as the Normal_LW_entrances case except in insanity it's possible you could be here without Flippers which + # means you need an escape route of either Flippers or Flute + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Flippers', player) or state.has('Ocarina', player)) and (basic_routes(state) or state.has_Mirror(player))) def set_inverted_big_bomb_rules(world, player): bombshop_entrance = world.get_region('Inverted Big Bomb Shop', player).entrances[0] @@ -1325,9 +1097,7 @@ def set_inverted_big_bomb_rules(world, player): 'Fortune Teller (Light)', 'Snitch Lady (East)', 'Snitch Lady (West)', - 'Bush Covered House', 'Tavern (Front)', - 'Light World Bomb Hut', 'Kakariko Shop', 'Mini Moldorm Cave', 'Long Fairy Cave', @@ -1338,7 +1108,6 @@ def set_inverted_big_bomb_rules(world, player): 'Bonk Rock Cave', 'Library', 'Potion Shop', - 'Waterfall of Wishing', 'Dam', 'Lumberjack House', 'Lake Hylia Fortune Teller', @@ -1354,14 +1123,33 @@ def set_inverted_big_bomb_rules(world, player): 'Two Brothers House (East)', 'Sanctuary', 'Hyrule Castle Entrance (South)', - 'Hyrule Castle Secret Entrance Stairs'] - LW_walkable_entrances = ['Dark Lake Hylia Ledge Fairy', - 'Dark Lake Hylia Ledge Spike Cave', - 'Dark Lake Hylia Ledge Hint', - 'Mire Shed', - 'Dark Desert Hint', - 'Dark Desert Fairy', - 'Misery Mire'] + 'Hyrule Castle Secret Entrance Stairs', + 'Hyrule Castle Entrance (West)', + 'Hyrule Castle Entrance (East)', + 'Inverted Ganons Tower', + 'Cave 45', + 'Checkerboard Cave'] + LW_DM_entrances = ['Old Man Cave (East)', + 'Old Man House (Bottom)', + 'Old Man House (Top)', + 'Death Mountain Return Cave (East)', + 'Spectacle Rock Cave Peak', + 'Spectacle Rock Cave', + 'Spectacle Rock Cave (Bottom)', + 'Tower of Hera', + 'Death Mountain Return Cave (West)', + 'Paradox Cave (Top)', + 'Fairy Ascension Cave (Top)', + 'Spiral Cave', + 'Paradox Cave (Bottom)', + 'Paradox Cave (Middle)', + 'Hookshot Fairy', + 'Spiral Cave (Bottom)', + 'Mimic Cave', + 'Fairy Ascension Cave (Bottom)', + 'Desert Palace Entrance (West)', + 'Desert Palace Entrance (North)', + 'Desert Palace Entrance (South)'] Northern_DW_entrances = ['Brewery', 'C-Shaped House', 'Chest Game', @@ -1383,10 +1171,8 @@ def set_inverted_big_bomb_rules(world, player): Isolated_DW_entrances = ['Spike Cave', 'Cave Shop (Dark Death Mountain)', 'Dark Death Mountain Fairy', - 'Mimic Cave', 'Skull Woods Second Section Door (West)', 'Skull Woods Final Section', - 'Ice Palace', 'Turtle Rock', 'Dark Death Mountain Ledge (West)', 'Dark Death Mountain Ledge (East)', @@ -1396,37 +1182,17 @@ def set_inverted_big_bomb_rules(world, player): 'Hookshot Cave', 'Turtle Rock Isolated Ledge Entrance', 'Hookshot Cave Back Entrance', - 'Inverted Agahnims Tower'] - Isolated_LW_entrances = ['Capacity Upgrade', - 'Tower of Hera', - 'Death Mountain Return Cave (West)', - 'Paradox Cave (Top)', - 'Fairy Ascension Cave (Top)', - 'Spiral Cave', - 'Desert Palace Entrance (East)'] - West_LW_DM_entrances = ['Old Man Cave (East)', - 'Old Man House (Bottom)', - 'Old Man House (Top)', - 'Death Mountain Return Cave (East)', - 'Spectacle Rock Cave Peak', - 'Spectacle Rock Cave', - 'Spectacle Rock Cave (Bottom)'] - East_LW_DM_entrances = ['Paradox Cave (Bottom)', - 'Paradox Cave (Middle)', - 'Hookshot Fairy', - 'Spiral Cave (Bottom)'] - Mirror_from_SDW_entrances = ['Two Brothers House (West)', - 'Cave 45'] - Castle_ledge_entrances = ['Hyrule Castle Entrance (West)', - 'Hyrule Castle Entrance (East)', - 'Inverted Ganons Tower'] - Desert_mirrorable_ledge_entrances = ['Desert Palace Entrance (West)', - 'Desert Palace Entrance (North)', - 'Desert Palace Entrance (South)', - 'Checkerboard Cave',] - Desert_ledge_entrances = ['Desert Palace Entrance (West)', - 'Desert Palace Entrance (North)', - 'Desert Palace Entrance (South)'] + 'Inverted Agahnims Tower', + 'Dark Lake Hylia Ledge Fairy', + 'Dark Lake Hylia Ledge Spike Cave', + 'Dark Lake Hylia Ledge Hint', + 'Mire Shed', + 'Dark Desert Hint', + 'Dark Desert Fairy', + 'Misery Mire'] + LW_bush_entrances = ['Bush Covered House', + 'Light World Bomb Hut', + 'Graveyard Cave'] 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)) @@ -1441,41 +1207,48 @@ def set_inverted_big_bomb_rules(world, player): # M = Mirror # G = Glove if bombshop_entrance.name in Normal_LW_entrances: + # Just walk to the castle and mirror. add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player)) - elif bombshop_entrance.name in LW_walkable_entrances: - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player)) + elif bombshop_entrance.name in LW_DM_entrances: + # For these entrances, you cannot walk to the castle/pyramid and thus must use Mirror and then Flute. + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and state.has_Mirror(player)) elif bombshop_entrance.name in Northern_DW_entrances: - 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.has('Beat Agahnim 1', player))))) - elif bombshop_entrance.name == 'Bumper Cave (Bottom)': - 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.has('Beat Agahnim 1', player)))) + # 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))) elif bombshop_entrance.name in Southern_DW_entrances: - 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.has('Beat Agahnim 1', player))) + # 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))) 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 Isolated_LW_entrances: - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and state.has_Mirror(player)) - elif bombshop_entrance.name in West_LW_DM_entrances: - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and state.has_Mirror(player)) - elif bombshop_entrance.name in East_LW_DM_entrances: - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and state.has_Mirror(player)) - elif bombshop_entrance.name == 'Fairy Ascension Cave (Bottom)': - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and state.has_Mirror(player)) - elif bombshop_entrance.name in Castle_ledge_entrances: - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player)) - elif bombshop_entrance.name in Desert_ledge_entrances: - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and state.can_flute(player)) - elif bombshop_entrance.name == 'Checkerboard Cave': - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(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)))) + 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))) elif bombshop_entrance.name == 'Old Man Cave (West)': - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and ((state.can_lift_rocks(player) and cross_peg_bridge(state)) or state.can_flute(player))) - elif bombshop_entrance.name == 'Graveyard Cave': - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player)) - elif bombshop_entrance.name in Mirror_from_SDW_entrances: - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and (state.can_flute(player) or cross_peg_bridge(state))) + # 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))) 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': - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Mirror(player)) + # 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)) + 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)) + 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)) + elif bombshop_entrance.name == 'Ice Palace': + # You can swim to the dock or use the Flute to get off the island. + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Flippers', player) or state.can_flute(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)) def set_bunny_rules(world, player):