From 6510968401ce9754f5b05964aab66901976f90e8 Mon Sep 17 00:00:00 2001 From: KrisDavie Date: Tue, 12 Dec 2023 18:48:12 +0100 Subject: [PATCH] Support bunny pocket for SW back and voo hammer house --- BaseClasses.py | 39 +++++++++++++++++++++++++++++++++++++++ OverworldGlitchRules.py | 10 +++++++--- Rules.py | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index cff79a25..fe1f3c96 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -550,6 +550,42 @@ class CollectionState(object): self.placing_items = None # self.trace = None + def can_reach_from(self, spot, start, player=None): + old_state = self.copy() + # old_state.path = {old_state.world.get_region(start, player)} + old_state.stale[player] = False + old_state.reachable_regions[player] = dict() + old_state.blocked_connections[player] = dict() + rrp = old_state.reachable_regions[player] + bc = old_state.blocked_connections[player] + + # init on first call - this can't be done on construction since the regions don't exist yet + start = self.world.get_region(start, player) + if start in self.reachable_regions[player]: + rrp[start] = self.reachable_regions[player][start] + for conn in start.exits: + bc[conn] = self.blocked_connections[player][conn] + else: + rrp[start] = CrystalBarrier.Orange + for conn in start.exits: + bc[conn] = CrystalBarrier.Orange + + queue = deque(old_state.blocked_connections[player].items()) + + old_state.traverse_world(queue, rrp, bc, player) + if old_state.world.key_logic_algorithm[player] == 'default': + unresolved_events = [x for y in old_state.reachable_regions[player] for x in y.locations + if x.event and x.item and (x.item.smallkey or x.item.bigkey or x.item.advancement) + and x not in old_state.locations_checked and x.can_reach(old_state)] + unresolved_events = old_state._do_not_flood_the_keys(unresolved_events) + if len(unresolved_events) == 0: + old_state.check_key_doors_in_dungeons(rrp, player) + + if self.world.get_region(spot, player) in rrp: + return True + else: + return False + def update_reachable_regions(self, player): self.stale[player] = False rrp = self.reachable_regions[player] @@ -1274,6 +1310,9 @@ class CollectionState(object): def can_superbunny_mirror_with_sword(self, player): return self.has_Mirror(player) and self.has_sword(player) + + def can_bunny_pocket(self, player): + return self.has_Boots(player) and (self.has_Mirror(player) or self.has_bottle(player)) def collect(self, item, event=False, location=None): if location: diff --git a/OverworldGlitchRules.py b/OverworldGlitchRules.py index 9ee11a29..7e03b64c 100644 --- a/OverworldGlitchRules.py +++ b/OverworldGlitchRules.py @@ -19,7 +19,6 @@ boots_required_superbunny_mirror_locations = [ # Entrances that can't be superbunny-mirrored into. invalid_mirror_bunny_entrances = [ - "Skull Woods Final Section", "Hype Cave", "Bonk Fairy (Dark)", "Thieves Town", @@ -107,7 +106,7 @@ inverted_non_mandatory_exits = [ "Hyrule Castle Entrance (East)", ] + non_mandatory_exits -open_non_mandatory_exits_ = [ +open_non_mandatory_exits = [ "Dark Death Mountain Ledge (West)", "Dark Death Mountain Ledge (East)", "Mimic Cave", @@ -296,7 +295,12 @@ def overworld_glitches_rules(world, player): # This is doable even with bad enemies add_alternate_rule(world.get_location("Hobo", player), lambda state: state.can_boots_clip_lw(player)) - + + # Bunny pocket + if not inverted: + add_alternate_rule(world.get_entrance("Skull Woods Final Section", player), lambda state: state.can_bunny_pocket(player) and state.has("Fire Rod", player)) + add_alternate_rule(world.get_entrance("Dark World Shop", player), lambda state: state.can_bunny_pocket(player) and state.has("Hammer", player)) + def add_alternate_rule(entrance, rule): diff --git a/Rules.py b/Rules.py index f4de86c2..7e414424 100644 --- a/Rules.py +++ b/Rules.py @@ -1902,6 +1902,34 @@ def set_bunny_rules(world, player, inverted): return region.is_dark_world else: return region.is_light_world + + # Is it possible to do bunny pocket here + def can_bunny_pocket_skull_woods(world, player): + # return world.get_entrance( + # "Skull Woods Second Section Door (West)", player + # ).connected_region.type != RegionType.Dungeon and ( + # not world.state.can_reach_from("Skull Woods Forest (West)", "Light World", 1) + # or not world.state.can_reach_from("Light World", "Skull Woods Forest (West)", 1) + # ) + return world.get_entrance( + "Skull Woods Second Section Door (West)", player + ).connected_region.type == RegionType.Dungeon or ( + world.state.can_reach_from("Skull Woods Forest (West)", "Light World", 1) + and world.state.can_reach_from("Light World", "Skull Woods Forest (West)", 1) + ) + + def can_bunny_pocket_voo_shop(world, player): + # return world.get_entrance( + # "Dark World Shop", player + # ).connected_region.type != RegionType.Dungeon and ( + # not world.state.can_reach_from("West Dark World", "Light World", 1) + # or not world.state.can_reach_from("Light World", "West Dark World", 1) + # ) + return ( + world.state.can_reach_from("West Dark World", "Light World", 1) + and world.state.can_reach_from("Light World", "West Dark World", 1) + ) + def get_rule_to_add(region, location=None, connecting_entrance=None): # In OWG, a location can potentially be superbunny-mirror accessible or @@ -1940,6 +1968,10 @@ def set_bunny_rules(world, player, inverted): if region.type == RegionType.Dungeon and new_region.type != RegionType.Dungeon: if entrance.name in OverworldGlitchRules.invalid_mirror_bunny_entrances: continue + # Is this a bunny pocketable entrance? + if entrance.name == 'Skull Woods Final Section' and not can_bunny_pocket_skull_woods(world, player) or \ + entrance.name == 'Dark World Shop' and not can_bunny_pocket_voo_shop(world, player): + continue if entrance.name in drop_dungeon_entrances: lobby = entrance.connected_region else: @@ -1954,6 +1986,9 @@ def set_bunny_rules(world, player, inverted): elif region.type == RegionType.Cave and new_region.type != RegionType.Cave: if entrance.name in OverworldGlitchRules.invalid_mirror_bunny_entrances: continue + if entrance.name == 'Skull Woods Final Section' and not can_bunny_pocket_skull_woods(world, player) or \ + entrance.name == 'Dark World Shop' and not can_bunny_pocket_voo_shop(world, player): + continue if region.name in OverworldGlitchRules.sword_required_superbunny_mirror_regions: possible_options.append(path_to_access_rule(new_path + [lambda state: state.has_Mirror(player) and state.has_sword(player)], entrance)) elif region.name in OverworldGlitchRules.boots_required_superbunny_mirror_regions: