diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000000..537a05f68b67 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +worlds/blasphemous/region_data.py linguist-generated=true diff --git a/BaseClasses.py b/BaseClasses.py index 95f24af26548..1188e72261f6 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -541,9 +541,9 @@ def can_beat_game(self, starting_state: Optional[CollectionState] = None) -> boo return True state = starting_state.copy() else: - if self.has_beaten_game(self.state): - return True state = CollectionState(self) + if self.has_beaten_game(state): + return True prog_locations = {location for location in self.get_locations() if location.item and location.item.advancement and location not in state.locations_checked} @@ -616,8 +616,7 @@ def location_condition(location: Location) -> bool: def location_relevant(location: Location) -> bool: """Determine if this location is relevant to sweep.""" - return location.progress_type != LocationProgressType.EXCLUDED \ - and (location.player in players["full"] or location.advancement) + return location.player in players["full"] or location.advancement def all_done() -> bool: """Check if all access rules are fulfilled""" diff --git a/CommonClient.py b/CommonClient.py index 09937e4b9ab8..750bee80bd70 100644 --- a/CommonClient.py +++ b/CommonClient.py @@ -252,7 +252,7 @@ def update_game(self, game: str, name_to_id_lookup_table: typing.Dict[str, int]) starting_reconnect_delay: int = 5 current_reconnect_delay: int = starting_reconnect_delay command_processor: typing.Type[CommandProcessor] = ClientCommandProcessor - ui = None + ui: typing.Optional["kvui.GameManager"] = None ui_task: typing.Optional["asyncio.Task[None]"] = None input_task: typing.Optional["asyncio.Task[None]"] = None keep_alive_task: typing.Optional["asyncio.Task[None]"] = None diff --git a/KH1Client.py b/KH1Client.py new file mode 100644 index 000000000000..4c3ed501901b --- /dev/null +++ b/KH1Client.py @@ -0,0 +1,9 @@ +if __name__ == '__main__': + import ModuleUpdate + ModuleUpdate.update() + + import Utils + Utils.init_logging("KH1Client", exception_logger="Client") + + from worlds.kh1.Client import launch + launch() diff --git a/Main.py b/Main.py index edae5d7b19b1..c931e22145a5 100644 --- a/Main.py +++ b/Main.py @@ -101,7 +101,7 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No multiworld.early_items[player][item_name] = max(0, early-count) remaining_count = count-early if remaining_count > 0: - local_early = multiworld.early_local_items[player].get(item_name, 0) + local_early = multiworld.local_early_items[player].get(item_name, 0) if local_early: multiworld.early_items[player][item_name] = max(0, local_early - remaining_count) del local_early diff --git a/MultiServer.py b/MultiServer.py index f59855fca6a4..b7c0e0f74555 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -991,7 +991,7 @@ def collect_player(ctx: Context, team: int, slot: int, is_group: bool = False): collect_player(ctx, team, group, True) -def get_remaining(ctx: Context, team: int, slot: int) -> typing.List[int]: +def get_remaining(ctx: Context, team: int, slot: int) -> typing.List[typing.Tuple[int, int]]: return ctx.locations.get_remaining(ctx.location_checks, team, slot) @@ -1350,10 +1350,10 @@ def _cmd_collect(self) -> bool: def _cmd_remaining(self) -> bool: """List remaining items in your game, but not their location or recipient""" if self.ctx.remaining_mode == "enabled": - remaining_item_ids = get_remaining(self.ctx, self.client.team, self.client.slot) - if remaining_item_ids: - self.output("Remaining items: " + ", ".join(self.ctx.item_names[self.ctx.games[self.client.slot]][item_id] - for item_id in remaining_item_ids)) + rest_locations = get_remaining(self.ctx, self.client.team, self.client.slot) + if rest_locations: + self.output("Remaining items: " + ", ".join(self.ctx.item_names[self.ctx.games[slot]][item_id] + for slot, item_id in rest_locations)) else: self.output("No remaining items found.") return True @@ -1363,10 +1363,10 @@ def _cmd_remaining(self) -> bool: return False else: # is goal if self.ctx.client_game_state[self.client.team, self.client.slot] == ClientStatus.CLIENT_GOAL: - remaining_item_ids = get_remaining(self.ctx, self.client.team, self.client.slot) - if remaining_item_ids: - self.output("Remaining items: " + ", ".join(self.ctx.item_names[self.ctx.games[self.client.slot]][item_id] - for item_id in remaining_item_ids)) + rest_locations = get_remaining(self.ctx, self.client.team, self.client.slot) + if rest_locations: + self.output("Remaining items: " + ", ".join(self.ctx.item_names[self.ctx.games[slot]][item_id] + for slot, item_id in rest_locations)) else: self.output("No remaining items found.") return True diff --git a/NetUtils.py b/NetUtils.py index f8d698c74fcc..c451fa3f8460 100644 --- a/NetUtils.py +++ b/NetUtils.py @@ -79,6 +79,7 @@ class NetworkItem(typing.NamedTuple): item: int location: int player: int + """ Sending player, except in LocationInfo (from LocationScouts), where it is the receiving player. """ flags: int = 0 @@ -397,12 +398,12 @@ def get_missing(self, state: typing.Dict[typing.Tuple[int, int], typing.Set[int] location_id not in checked] def get_remaining(self, state: typing.Dict[typing.Tuple[int, int], typing.Set[int]], team: int, slot: int - ) -> typing.List[int]: + ) -> typing.List[typing.Tuple[int, int]]: checked = state[team, slot] player_locations = self[slot] - return sorted([player_locations[location_id][0] for - location_id in player_locations if - location_id not in checked]) + return sorted([(player_locations[location_id][1], player_locations[location_id][0]) for + location_id in player_locations if + location_id not in checked]) if typing.TYPE_CHECKING: # type-check with pure python implementation until we have a typing stub diff --git a/README.md b/README.md index 5b66e3db8782..0e57bce53b51 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,9 @@ Currently, the following games are supported: * Yu-Gi-Oh! Ultimate Masters: World Championship Tournament 2006 * A Hat in Time * Old School Runescape +* Kingdom Hearts 1 +* Mega Man 2 +* Yacht Dice For setup and instructions check out our [tutorials page](https://archipelago.gg/tutorial/). Downloads can be found at [Releases](https://github.com/ArchipelagoMW/Archipelago/releases), including compiled diff --git a/_speedups.pyx b/_speedups.pyx index 4b083c2f9aef..dc039e336500 100644 --- a/_speedups.pyx +++ b/_speedups.pyx @@ -287,15 +287,15 @@ cdef class LocationStore: entry in self.entries[start:start + count] if entry.location not in checked] - def get_remaining(self, state: State, team: int, slot: int) -> List[int]: + def get_remaining(self, state: State, team: int, slot: int) -> List[Tuple[int, int]]: cdef LocationEntry* entry cdef ap_player_t sender = slot cdef size_t start = self.sender_index[sender].start cdef size_t count = self.sender_index[sender].count cdef set checked = state[team, slot] - return sorted([entry.item for - entry in self.entries[start:start+count] if - entry.location not in checked]) + return sorted([(entry.receiver, entry.item) for + entry in self.entries[start:start+count] if + entry.location not in checked]) @cython.auto_pickle(False) diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS index 4f012c306be9..cd1e859af951 100644 --- a/docs/CODEOWNERS +++ b/docs/CODEOWNERS @@ -78,6 +78,9 @@ # Kirby's Dream Land 3 /worlds/kdl3/ @Silvris +# Kingdom Hearts +/worlds/kh1/ @gaithern + # Kingdom Hearts 2 /worlds/kh2/ @JaredWeakStrike @@ -103,6 +106,9 @@ # Minecraft /worlds/minecraft/ @KonoTyran @espeon65536 +# Mega Man 2 +/worlds/mm2/ @Silvris + # MegaMan Battle Network 3 /worlds/mmbn3/ @digiholic @@ -196,6 +202,9 @@ # The Witness /worlds/witness/ @NewSoupVi @blastron +# Yacht Dice +/worlds/yachtdice/ @spinerak + # Yoshi's Island /worlds/yoshisisland/ @PinkSwitch diff --git a/docs/network protocol.md b/docs/network protocol.md index da5c41431501..f8080fecc879 100644 --- a/docs/network protocol.md +++ b/docs/network protocol.md @@ -702,14 +702,18 @@ GameData is a **dict** but contains these keys and values. It's broken out into | checksum | str | A checksum hash of this game's data. | ### Tags -Tags are represented as a list of strings, the common Client tags follow: - -| Name | Notes | -|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| AP | Signifies that this client is a reference client, its usefulness is mostly in debugging to compare client behaviours more easily. | -| DeathLink | Client participates in the DeathLink mechanic, therefore will send and receive DeathLink bounce packets | -| Tracker | Tells the server that this client will not send locations and is actually a Tracker. When specified and used with empty or null `game` in [Connect](#connect), game and game's version validation will be skipped. | -| TextOnly | Tells the server that this client will not send locations and is intended for chat. When specified and used with empty or null `game` in [Connect](#connect), game and game's version validation will be skipped. | +Tags are represented as a list of strings, the common client tags follow: + +| Name | Notes | +|-----------|--------------------------------------------------------------------------------------------------------------------------------------| +| AP | Signifies that this client is a reference client, its usefulness is mostly in debugging to compare client behaviours more easily. | +| DeathLink | Client participates in the DeathLink mechanic, therefore will send and receive DeathLink bounce packets. | +| HintGame | Indicates the client is a hint game, made to send hints instead of locations. Special join/leave message,¹ `game` is optional.² | +| Tracker | Indicates the client is a tracker, made to track instead of sending locations. Special join/leave message,¹ `game` is optional.² | +| TextOnly | Indicates the client is a basic client, made to chat instead of sending locations. Special join/leave message,¹ `game` is optional.² | + +¹: When connecting or disconnecting, the chat message shows e.g. "tracking".\ +²: Allows `game` to be empty or null in [Connect](#connect). Game and version validation will then be skipped. ### DeathLink A special kind of Bounce packet that can be supported by any AP game. It targets the tag "DeathLink" and carries the following data: diff --git a/inno_setup.iss b/inno_setup.iss index f097500f7d7d..3bb76fc40abe 100644 --- a/inno_setup.iss +++ b/inno_setup.iss @@ -186,6 +186,11 @@ Root: HKCR; Subkey: "{#MyAppName}cv64patch"; ValueData: "Arc Root: HKCR; Subkey: "{#MyAppName}cv64patch\DefaultIcon"; ValueData: "{app}\ArchipelagoBizHawkClient.exe,0"; ValueType: string; ValueName: ""; Root: HKCR; Subkey: "{#MyAppName}cv64patch\shell\open\command"; ValueData: """{app}\ArchipelagoBizHawkClient.exe"" ""%1"""; ValueType: string; ValueName: ""; +Root: HKCR; Subkey: ".apmm2"; ValueData: "{#MyAppName}mm2patch"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; +Root: HKCR; Subkey: "{#MyAppName}mm2patch"; ValueData: "Archipelago Mega Man 2 Patch"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; +Root: HKCR; Subkey: "{#MyAppName}mm2patch\DefaultIcon"; ValueData: "{app}\ArchipelagoBizHawkClient.exe,0"; ValueType: string; ValueName: ""; +Root: HKCR; Subkey: "{#MyAppName}mm2patch\shell\open\command"; ValueData: """{app}\ArchipelagoBizHawkClient.exe"" ""%1"""; ValueType: string; ValueName: ""; + Root: HKCR; Subkey: ".apladx"; ValueData: "{#MyAppName}ladxpatch"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Root: HKCR; Subkey: "{#MyAppName}ladxpatch"; ValueData: "Archipelago Links Awakening DX Patch"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Root: HKCR; Subkey: "{#MyAppName}ladxpatch\DefaultIcon"; ValueData: "{app}\ArchipelagoLinksAwakeningClient.exe,0"; ValueType: string; ValueName: ""; diff --git a/test/bases.py b/test/bases.py index 9fb223af2ac1..83461b158f4f 100644 --- a/test/bases.py +++ b/test/bases.py @@ -293,13 +293,11 @@ def test_all_state_can_reach_everything(self): if not (self.run_default_tests and self.constructed): return with self.subTest("Game", game=self.game, seed=self.multiworld.seed): - excluded = self.multiworld.worlds[self.player].options.exclude_locations.value state = self.multiworld.get_all_state(False) for location in self.multiworld.get_locations(): - if location.name not in excluded: - with self.subTest("Location should be reached", location=location.name): - reachable = location.can_reach(state) - self.assertTrue(reachable, f"{location.name} unreachable") + with self.subTest("Location should be reached", location=location.name): + reachable = location.can_reach(state) + self.assertTrue(reachable, f"{location.name} unreachable") with self.subTest("Beatable"): self.multiworld.state = state self.assertBeatable(True) diff --git a/test/general/test_reachability.py b/test/general/test_reachability.py index 4b71762f77fe..fafa7023893c 100644 --- a/test/general/test_reachability.py +++ b/test/general/test_reachability.py @@ -14,6 +14,18 @@ class TestBase(unittest.TestCase): "Desert Northern Cliffs", # on top of mountain, only reachable via OWG "Dark Death Mountain Bunny Descent Area" # OWG Mountain descent }, + # These Blasphemous regions are not reachable with default options + "Blasphemous": { + "D01Z04S13[SE]", # difficulty must be hard + "D01Z05S25[E]", # difficulty must be hard + "D02Z02S05[W]", # difficulty must be hard and purified_hand must be true + "D04Z01S06[E]", # purified_hand must be true + "D04Z02S02[NE]", # difficulty must be hard and purified_hand must be true + "D05Z01S11[SW]", # difficulty must be hard + "D06Z01S08[N]", # difficulty must be hard and purified_hand must be true + "D20Z02S11[NW]", # difficulty must be hard + "D20Z02S11[E]", # difficulty must be hard + }, "Ocarina of Time": { "Prelude of Light Warp", # Prelude is not progression by default "Serenade of Water Warp", # Serenade is not progression by default @@ -37,12 +49,10 @@ def test_default_all_state_can_reach_everything(self): unreachable_regions = self.default_settings_unreachable_regions.get(game_name, set()) with self.subTest("Game", game=game_name): multiworld = setup_solo_multiworld(world_type) - excluded = multiworld.worlds[1].options.exclude_locations.value state = multiworld.get_all_state(False) for location in multiworld.get_locations(): - if location.name not in excluded: - with self.subTest("Location should be reached", location=location.name): - self.assertTrue(location.can_reach(state), f"{location.name} unreachable") + with self.subTest("Location should be reached", location=location.name): + self.assertTrue(location.can_reach(state), f"{location.name} unreachable") for region in multiworld.get_regions(): if region.name in unreachable_regions: diff --git a/test/netutils/test_location_store.py b/test/netutils/test_location_store.py index f3e83989bea4..1b984015844d 100644 --- a/test/netutils/test_location_store.py +++ b/test/netutils/test_location_store.py @@ -130,9 +130,9 @@ def test_get_missing(self) -> None: def test_get_remaining(self) -> None: self.assertEqual(self.store.get_remaining(full_state, 0, 1), []) - self.assertEqual(self.store.get_remaining(one_state, 0, 1), [13, 21]) - self.assertEqual(self.store.get_remaining(empty_state, 0, 1), [13, 21, 22]) - self.assertEqual(self.store.get_remaining(empty_state, 0, 3), [99]) + self.assertEqual(self.store.get_remaining(one_state, 0, 1), [(1, 13), (2, 21)]) + self.assertEqual(self.store.get_remaining(empty_state, 0, 1), [(1, 13), (2, 21), (2, 22)]) + self.assertEqual(self.store.get_remaining(empty_state, 0, 3), [(4, 99)]) def test_location_set_intersection(self) -> None: locations = {10, 11, 12} diff --git a/worlds/blasphemous/ExtractorConfig.json b/worlds/blasphemous/ExtractorConfig.json new file mode 100644 index 000000000000..4d565ccf4a7d --- /dev/null +++ b/worlds/blasphemous/ExtractorConfig.json @@ -0,0 +1,19 @@ +{ + "type": "WorldDefinition", + "configuration": "./output/StringWorldDefinition.json", + "emptyRegionsToKeep": [ + "D17Z01S01", + "D01Z02S01", + "D02Z03S09", + "D03Z03S11", + "D04Z03S01", + "D06Z01S09", + "D20Z02S09", + "D09Z01S09[Cell24]", + "D09Z01S08[Cell7]", + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell24]", + "D09BZ01S01[Cell17]", + "D09BZ01S01[Cell19]" + ] +} \ No newline at end of file diff --git a/worlds/blasphemous/Items.py b/worlds/blasphemous/Items.py index 23cad0f5c4dd..4843a99f2d12 100644 --- a/worlds/blasphemous/Items.py +++ b/worlds/blasphemous/Items.py @@ -637,52 +637,35 @@ class ItemDict(TypedDict): 'classification': ItemClassification.filler} ] -event_table: Dict[str, str] = { - "OpenedDCGateW": "D01Z05S24", - "OpenedDCGateE": "D01Z05S12", - "OpenedDCLadder": "D01Z05S20", - "OpenedWOTWCave": "D02Z01S06", - "RodeGOTPElevator": "D02Z02S11", - "OpenedConventLadder": "D02Z03S11", - "BrokeJondoBellW": "D03Z02S09", - "BrokeJondoBellE": "D03Z02S05", - "OpenedMOMLadder": "D04Z02S06", - "OpenedTSCGate": "D05Z02S11", - "OpenedARLadder": "D06Z01S23", - "BrokeBOTTCStatue": "D08Z01S02", - "OpenedWOTHPGate": "D09Z01S05", - "OpenedBOTSSLadder": "D17Z01S04" -} - group_table: Dict[str, Set[str]] = { - "wounds" : ["Holy Wound of Attrition", + "wounds" : {"Holy Wound of Attrition", "Holy Wound of Contrition", - "Holy Wound of Compunction"], + "Holy Wound of Compunction"}, - "masks" : ["Deformed Mask of Orestes", + "masks" : {"Deformed Mask of Orestes", "Mirrored Mask of Dolphos", - "Embossed Mask of Crescente"], + "Embossed Mask of Crescente"}, - "marks" : ["Mark of the First Refuge", + "marks" : {"Mark of the First Refuge", "Mark of the Second Refuge", - "Mark of the Third Refuge"], + "Mark of the Third Refuge"}, - "tirso" : ["Bouquet of Rosemary", + "tirso" : {"Bouquet of Rosemary", "Incense Garlic", "Olive Seeds", "Dried Clove", "Sooty Garlic", - "Bouquet of Thyme"], + "Bouquet of Thyme"}, - "tentudia": ["Tentudia's Carnal Remains", + "tentudia": {"Tentudia's Carnal Remains", "Remains of Tentudia's Hair", - "Tentudia's Skeletal Remains"], + "Tentudia's Skeletal Remains"}, - "egg" : ["Melted Golden Coins", + "egg" : {"Melted Golden Coins", "Torn Bridal Ribbon", - "Black Grieving Veil"], + "Black Grieving Veil"}, - "bones" : ["Parietal bone of Lasser, the Inquisitor", + "bones" : {"Parietal bone of Lasser, the Inquisitor", "Jaw of Ashgan, the Inquisitor", "Cervical vertebra of Zicher, the Brewmaster", "Clavicle of Dalhuisen, the Schoolchild", @@ -725,14 +708,14 @@ class ItemDict(TypedDict): "Scaphoid of Fierce, the Leper", "Anklebone of Weston, the Pilgrim", "Calcaneum of Persian, the Bandit", - "Navicular of Kahnnyhoo, the Murderer"], + "Navicular of Kahnnyhoo, the Murderer"}, - "power" : ["Life Upgrade", + "power" : {"Life Upgrade", "Fervour Upgrade", "Empty Bile Vessel", - "Quicksilver"], + "Quicksilver"}, - "prayer" : ["Seguiriya to your Eyes like Stars", + "prayer" : {"Seguiriya to your Eyes like Stars", "Debla of the Lights", "Saeta Dolorosa", "Campanillero to the Sons of the Aurora", @@ -746,10 +729,17 @@ class ItemDict(TypedDict): "Romance to the Crimson Mist", "Zambra to the Resplendent Crown", "Cantina of the Blue Rose", - "Mirabras of the Return to Port"] + "Mirabras of the Return to Port"}, + + "toe" : {"Little Toe made of Limestone", + "Big Toe made of Limestone", + "Fourth Toe made of Limestone"}, + + "eye" : {"Severed Right Eye of the Traitor", + "Broken Left Eye of the Traitor"} } -tears_set: Set[str] = [ +tears_list: List[str] = [ "Tears of Atonement (500)", "Tears of Atonement (625)", "Tears of Atonement (750)", @@ -772,16 +762,16 @@ class ItemDict(TypedDict): "Tears of Atonement (30000)" ] -reliquary_set: Set[str] = [ +reliquary_set: Set[str] = { "Reliquary of the Fervent Heart", "Reliquary of the Suffering Heart", "Reliquary of the Sorrowful Heart" -] +} -skill_set: Set[str] = [ +skill_set: Set[str] = { "Combo Skill", "Charged Skill", "Ranged Skill", "Dive Skill", "Lunge Skill" -] \ No newline at end of file +} diff --git a/worlds/blasphemous/Locations.py b/worlds/blasphemous/Locations.py index 6dd6e03180b3..6c2f71cd3799 100644 --- a/worlds/blasphemous/Locations.py +++ b/worlds/blasphemous/Locations.py @@ -1,986 +1,366 @@ -from typing import List, TypedDict +from typing import Dict -class LocationDict(TypedDict): - name: str - game_id: str - room: str - +location_names: Dict[str, str] = { + # The Holy Line + "PR14": "THL: Hanging skeleton", + "RB07": "THL: Across blood platforms", + "CO04": "THL: Underground ledge", + "QI55": "THL: Underground chest", + "RESCUED_CHERUB_07": "THL: Child of Moonlight", + "QI31": "THL: Deogracias' gift", -location_table: List[LocationDict] = [ # Albero - {'name': "Albero: Tirso's house, top floor", - 'game_id': "RB01", - 'room': "D01Z02S02"}, - {'name': "Albero: Outside Ossuary", - 'game_id': "CO43", - 'room': "D01Z02S04"}, - {'name': "Albero: Graveyard", - 'game_id': "CO16", - 'room': "D01Z02S05"}, - {'name': "Albero: Gate of Travel room", - 'game_id': "QI65", - 'room': "D01Z02S07"}, - {'name': "Albero: Child of Moonlight", - 'game_id': "RESCUED_CHERUB_08", - 'room': "D01Z02S03"}, - {'name': "Albero: Bless Linen Cloth", - 'game_id': "RE04", - 'room': "D01Z02S01"}, - {'name': "Albero: Bless Hatched Egg", - 'game_id': "RE10", - 'room': "D01Z02S01"}, - {'name': "Albero: Bless Severed Hand", - 'game_id': "RE02", - 'room': "D01Z02S01"}, - {'name': "Albero: First gift for Cleofas", - 'game_id': "QI01", - 'room': "D01Z02S03"}, - {'name': "Albero: Final gift for Cleofas", - 'game_id': "PR11", - 'room': "D01BZ04S01"}, - {'name': "Albero: Tirso's 1st reward", - 'game_id': "QI66", - 'room': "D01Z02S02"}, - {'name': "Albero: Tirso's 2nd reward", - 'game_id': "Tirso[500]", - 'room': "D01Z02S02"}, - {'name': "Albero: Tirso's 3rd reward", - 'game_id': "Tirso[1000]", - 'room': "D01Z02S02"}, - {'name': "Albero: Tirso's 4th reward", - 'game_id': "Tirso[2000]", - 'room': "D01Z02S02"}, - {'name': "Albero: Tirso's 5th reward", - 'game_id': "Tirso[5000]", - 'room': "D01Z02S02"}, - {'name': "Albero: Tirso's 6th reward", - 'game_id': "Tirso[10000]", - 'room': "D01Z02S02"}, - {'name': "Albero: Tirso's final reward", - 'game_id': "QI56", - 'room': "D01Z02S02"}, - {'name': "Albero: Lvdovico's 1st reward", - 'game_id': "Lvdovico[500]", - 'room': "D01Z02S03"}, - {'name': "Albero: Lvdovico's 2nd reward", - 'game_id': "Lvdovico[1000]", - 'room': "D01Z02S03"}, - {'name': "Albero: Lvdovico's 3rd reward", - 'game_id': "PR03", - 'room': "D01Z02S03"}, - {'name': "Ossuary: Isidora, Voice of the Dead", - 'game_id': "QI201", - 'room': "D01BZ08S01"}, - {'name': "Albero: Mea Culpa altar", - 'game_id': "Sword[D01Z02S06]", - 'room': "D01Z02S06"}, - {'name': "Albero: Donate 5000 Tears", - 'game_id': "RB104", - 'room': "D01BZ04S01"}, - {'name': "Albero: Donate 50000 Tears", - 'game_id': "RB105", - 'room': "D01BZ04S01"}, - {'name': "Ossuary: 1st reward", - 'game_id': "Undertaker[250]", - 'room': "D01BZ06S01"}, - {'name': "Ossuary: 2nd reward", - 'game_id': "Undertaker[500]", - 'room': "D01BZ06S01"}, - {'name': "Ossuary: 3rd reward", - 'game_id': "Undertaker[750]", - 'room': "D01BZ06S01"}, - {'name': "Ossuary: 4th reward", - 'game_id': "Undertaker[1000]", - 'room': "D01BZ06S01"}, - {'name': "Ossuary: 5th reward", - 'game_id': "Undertaker[1250]", - 'room': "D01BZ06S01"}, - {'name': "Ossuary: 6th reward", - 'game_id': "Undertaker[1500]", - 'room': "D01BZ06S01"}, - {'name': "Ossuary: 7th reward", - 'game_id': "Undertaker[1750]", - 'room': "D01BZ06S01"}, - {'name': "Ossuary: 8th reward", - 'game_id': "Undertaker[2000]", - 'room': "D01BZ06S01"}, - {'name': "Ossuary: 9th reward", - 'game_id': "Undertaker[2500]", - 'room': "D01BZ06S01"}, - {'name': "Ossuary: 10th reward", - 'game_id': "Undertaker[3000]", - 'room': "D01BZ06S01"}, - {'name': "Ossuary: 11th reward", - 'game_id': "Undertaker[5000]", - 'room': "D01BZ06S01"}, - - # All the Tears of the Sea - {'name': "AtTotS: Miriam's gift", - 'game_id': "PR201", - 'room': "D04Z04S01"}, + "RE02": "Albero: Bless Severed Hand", + "RE04": "Albero: Bless Linen Cloth", + "RE10": "Albero: Bless Hatched Egg", + "RB01": "Albero: Tirso's house, top floor", + "QI66": "Albero: Tirso's 1st reward", + "Tirso[500]": "Albero: Tirso's 2nd reward", + "Tirso[1000]": "Albero: Tirso's 3rd reward", + "Tirso[2000]": "Albero: Tirso's 4th reward", + "Tirso[5000]": "Albero: Tirso's 5th reward", + "Tirso[10000]": "Albero: Tirso's 6th reward", + "QI56": "Albero: Tirso's final reward", + "RESCUED_CHERUB_08": "Albero: Child of Moonlight", + "Lvdovico[500]": "Albero: Lvdovico's 1st reward", + "Lvdovico[1000]": "Albero: Lvdovico's 2nd reward", + "PR03": "Albero: Lvdovico's 3rd reward", + "QI01": "Albero: First gift for Cleofas", + "CO43": "Albero: Outside Ossuary", + "CO16": "Albero: Graveyard", + "Sword[D01Z02S06]": "Albero: Mea Culpa altar", + "QI65": "Albero: Gate of Travel room", + "RB104": "Albero: Donate 5000 Tears", + "RB105": "Albero: Donate 50000 Tears", + "PR11": "Albero: Final gift for Cleofas", + "Undertaker[250]": "Ossuary: 1st reward", + "Undertaker[500]": "Ossuary: 2nd reward", + "Undertaker[750]": "Ossuary: 3rd reward", + "Undertaker[1000]": "Ossuary: 4th reward", + "Undertaker[1250]": "Ossuary: 5th reward", + "Undertaker[1500]": "Ossuary: 6th reward", + "Undertaker[1750]": "Ossuary: 7th reward", + "Undertaker[2000]": "Ossuary: 8th reward", + "Undertaker[2500]": "Ossuary: 9th reward", + "Undertaker[3000]": "Ossuary: 10th reward", + "Undertaker[5000]": "Ossuary: 11th reward", + "QI201": "Ossuary: Isidora, Voice of the Dead", - # Archcathedral Rooftops - {'name': "AR: First soldier fight", - 'game_id': "QI02", - 'room': "D06Z01S03"}, - {'name': "AR: Second soldier fight", - 'game_id': "QI03", - 'room': "D06Z01S06"}, - {'name': "AR: Third soldier fight", - 'game_id': "QI04", - 'room': "D06Z01S21"}, - {'name': "AR: Upper west shaft ledge", - 'game_id': "CO06", - 'room': "D06Z01S12"}, - {'name': "AR: Upper west shaft Child of Moonlight", - 'game_id': "RESCUED_CHERUB_36", - 'room': "D06Z01S12"}, - {'name': "AR: Upper west shaft chest", - 'game_id': "PR12", - 'room': "D06Z01S12"}, - {'name': "AR: Statue near MoM", - 'game_id': "HE04", - 'room': "D06Z01S22"}, - {'name': "AR: Lady of the Six Sorrows", - 'game_id': "Lady[D06Z01S24]", - 'room': "D06Z01S24"}, - {'name': "AR: Upper east shaft ledge", - 'game_id': "CO40", - 'room': "D06Z01S15"}, - {'name': "AR: Mea Culpa altar", - 'game_id': "Sword[D06Z01S11]", - 'room': "D06Z01S11"}, - {'name': "AR: Crisanta of the Wrapped Agony", - 'game_id': "BS16", - 'room': "D06Z01S25"}, + # Wasteland of the Buried Churches + "RB04": "WotBC: Lower log path", + "CO14": "WotBC: Hidden alcove", + "CO36": "WotBC: Outside ledge", + "RESCUED_CHERUB_10": "WotBC: Outside Child of Moonlight", + "QI06": "WotBC: Under broken bridge", + "RB20": "WotBC: 3rd meeting with Redento", + "HE02": "WotBC: Cliffside statue", + "RESCUED_CHERUB_38": "WotBC: Cliffside Child of Moonlight", - # Bridge of the Three Cavalries - {'name': "BotTC: Esdras, of the Anointed Legion", - 'game_id': "BS12", - 'room': "D08Z01S01"}, - {'name': "BotTC: Esdras' gift", - 'game_id': "PR09", - 'room': "D08Z01S01"}, - {'name': "BotTC: Inside giant statue", - 'game_id': "HE101", - 'room': "D08Z01S02"}, + # Mercy Dreams + "CO30": "MD: First area hidden wall", + "CO03": "MD: Second area ledge", + "RESCUED_CHERUB_09": "MD: Second area Child of Moonlight", + "PR01": "MD: Second area trapped chest", + "RB17": "MD: First red candle", + "QI48": "MD: Third area hidden room", + "CO21": "MD: Behind gate to TSC", + "CO38": "MD: Sliding challenge", + "RESCUED_CHERUB_33": "MD: Cave Child of Moonlight", + "BS01": "MD: Ten Piedad", + "QI38": "MD: Visage of Attrition", + "QI58": "MD: Shop item 1", + "RB05": "MD: Shop item 2", + "RB09": "MD: Shop item 3", - # Brotherhood of the Silent Sorrow - {'name': "BotSS: Starting room Child of Moonlight", - 'game_id': "RESCUED_CHERUB_06", - 'room': "D17Z01S01"}, - {'name': "BotSS: Starting room ledge", - 'game_id': "RB204", - 'room': "D17Z01S01"}, - {'name': "BotSS: Chamber of the Eldest Brother", - 'game_id': "RE01", - 'room': "D17BZ01S01"}, - {'name': "BotSS: Mea Culpa altar", - 'game_id': "Sword[D17Z01S08]", - 'room': "D17Z01S08"}, - {'name': "BotSS: Platforming gauntlet", - 'game_id': "CO25", - 'room': "D17BZ02S01"}, - {'name': "BotSS: Outside church", - 'game_id': "PR203", - 'room': "D17Z01S14"}, - {'name': "BotSS: Esdras' final gift", - 'game_id': "QI204", - 'room': "D17Z01S15"}, - {'name': "BotSS: Crisanta's gift", - 'game_id': "QI301", - 'room': "D17Z01S15"}, - {'name': "BotSS: Warden of the Silent Sorrow", - 'game_id': "BS13", - 'room': "D17Z01S11"}, - - # Convent of Our Lady of the Charred Visage - {'name': "CoOLotCV: Snowy window ledge", - 'game_id': "CO05", - 'room': "D02Z03S03"}, - {'name': "CoOLotCV: Center enemy lineup", - 'game_id': "CO15", - 'room': "D02Z03S07"}, - {'name': "CoOLotCV: Center miasma room", - 'game_id': "RB08", - 'room': "D02Z03S05"}, - {'name': "CoOLotCV: Lower west statue", - 'game_id': "HE03", - 'room': "D02Z03S12"}, - {'name': "CoOLotCV: Lady of the Six Sorrows", - 'game_id': "Lady[D02Z03S15]", - 'room': "D02Z03S15"}, - {'name': "CoOLotCV: Mea Culpa altar", - 'game_id': "Sword[D02Z03S13]", - 'room': "D02Z03S13"}, - {'name': "CoOLotCV: First blue candle", - 'game_id': "RB24", - 'room': "D02Z03S17"}, - {'name': "CoOLotCV: Outside pathway", - 'game_id': "RB107", - 'room': "D02Z03S23"}, - {'name': "CoOLotCV: Fountain of burning oil", - 'game_id': "QI57", - 'room': "D02Z03S21"}, - {'name': "CoOLotCV: Our Lady of the Charred Visage", - 'game_id': "BS03", - 'room': "D02Z03S20"}, - {'name': "CoOLotCV: Visage of Compunction", - 'game_id': "QI40", - 'room': "D02Z03S21"}, - {'name': "CoOLotCV: Mask room", - 'game_id': "QI61", - 'room': "D02Z03S19"}, + # Desecrated Cistern + "CO09": "DC: Shortcut to WotBC", + "QI67": "DC: Hidden alcove near fountain", + "PR16": "DC: Upper east tunnel chest", + "RESCUED_CHERUB_13": "DC: Upper east Child of Moonlight", + "Oil[D01Z05S07]": "DC: Oil of the Pilgrims", + "QI12": "DC: Behind gate in miasma room", + "RESCUED_CHERUB_14": "DC: Child of Moonlight, miasma room", + "QI45": "DC: Lower east tunnel chest", + "RESCUED_CHERUB_12": "DC: Child of Moonlight, behind pillar", + "RESCUED_CHERUB_11": "DC: Child of Moonlight, above water", + "CO41": "DC: Behind sewage drips", + "CO32": "DC: High ledge near elevator shaft", + "RESCUED_CHERUB_15": "DC: Top of elevator Child of Moonlight", + "Lady[D01Z05S22]": "DC: Lady of the Six Sorrows, from MD", + "QI75": "DC: Chalice room", + "Sword[D01Z05S24]": "DC: Mea culpa altar", + "CO44": "DC: Elevator shaft ledge", + "RESCUED_CHERUB_22": "DC: Elevator shaft Child of Moonlight", + "Lady[D01Z05S26]": "DC: Lady of the Six Sorrows, elevator shaft", + "RB03": "DC: Shroud puzzle", - # Deambulatory of His Holiness - {'name': "DoHH: Viridiana's gift", - 'game_id': "PR08", - 'room': "D07Z01S01"}, + # Petrous + "QI101": "Petrous: Temple entrance", - # Desecrated Cistern - {'name': "DC: Lady of the Six Sorrows, from MD", - 'game_id': "Lady[D01Z05S22]", - 'room': "D01Z05S22"}, - {'name': "DC: Behind sewage drips", - 'game_id': "CO41", - 'room': "D01Z05S15"}, - {'name': "DC: Child of Moonlight, above water", - 'game_id': "RESCUED_CHERUB_11", - 'room': "D01Z05S14"}, - {'name': "DC: Lower east tunnel chest", - 'game_id': "QI45", - 'room': "D01Z05S11"}, - {'name': "DC: Upper east tunnel chest", - 'game_id': "PR16", - 'room': "D01Z05S06"}, - {'name': "DC: Upper east Child of Moonlight", - 'game_id': "RESCUED_CHERUB_13", - 'room': "D01Z05S06"}, - {'name': "DC: Hidden alcove near fountain", - 'game_id': "QI67", - 'room': "D01Z05S05"}, - {'name': "DC: Shortcut to WotBC", - 'game_id': "CO09", - 'room': "D01Z05S05"}, - {'name': "DC: Oil of the Pilgrims", - 'game_id': "Oil[D01Z05S07]", - 'room': "D01Z05S07"}, - {'name': "DC: Child of Moonlight, miasma room", - 'game_id': "RESCUED_CHERUB_14", - 'room': "D01Z05S08"}, - {'name': "DC: Behind gate in miasma room", - 'game_id': "QI12", - 'room': "D01Z05S08"}, - {'name': "DC: Child of Moonlight, behind pillar", - 'game_id': "RESCUED_CHERUB_12", - 'room': "D01Z05S13"}, - {'name': "DC: High ledge near elevator shaft", - 'game_id': "CO32", - 'room': "D01Z05S17"}, - {'name': "DC: Shroud puzzle", - 'game_id': "RB03", - 'room': "D01BZ05S01"}, - {'name': "DC: Chalice room", - 'game_id': "QI75", - 'room': "D01Z05S23"}, - {'name': "DC: Mea Culpa altar", - 'game_id': "Sword[D01Z05S24]", - 'room': "D01Z05S24"}, - {'name': "DC: Lady of the Six Sorrows, elevator shaft", - 'game_id': "Lady[D01Z05S26]", - 'room': "D01Z05S26"}, - {'name': "DC: Top of elevator Child of Moonlight", - 'game_id': "RESCUED_CHERUB_15", - 'room': "D01Z05S20"}, - {'name': "DC: Elevator shaft Child of Moonlight", - 'game_id': "RESCUED_CHERUB_22", - 'room': "D01Z05S25"}, - {'name': "DC: Elevator shaft ledge", - 'game_id': "CO44", - 'room': "D01Z05S25"}, + # Where Olive Trees Wither + "CO11": "WOTW: Below Prie Dieu", + "QI59": "WOTW: Gemino's gift", + "RB10": "WOTW: Gemino's reward", + "RESCUED_CHERUB_23": "WOTW: Upper east Child of Moonlight", + "QI20": "WOTW: Entrance to tomb", + "QI68": "WOTW: Gift for the tomb", + "QI07": "WOTW: Death run", + "CO19": "WOTW: Underground ledge", + "RESCUED_CHERUB_27": "WOTW: Underground Child of Moonlight", + "PR04": "WOTW: Underground tomb", + "HE05": "WOTW: Upper east statue", - # Echoes of Salt - {'name': "EoS: Lantern jump near MotED", - 'game_id': "RB108", - 'room': "D20Z01S02"}, - {'name': "EoS: Lantern jump near elevator", - 'game_id': "RB202", - 'room': "D20Z01S09"}, - # Graveyard of the Peaks - {'name': "GotP: Shop cave Child of Moonlight", - 'game_id': "RESCUED_CHERUB_31", - 'room': "D02Z02S08"}, - {'name': "GotP: Shop cave hidden hole", - 'game_id': "CO42", - 'room': "D02Z02S08"}, - {'name': "GotP: Shop item 1", - 'game_id': "QI11", - 'room': "D02BZ02S01"}, - {'name': "GotP: Shop item 2", - 'game_id': "RB37", - 'room': "D02BZ02S01"}, - {'name': "GotP: Shop item 3", - 'game_id': "RB02", - 'room': "D02BZ02S01"}, - {'name': "GotP: Confessor Dungeon room", - 'game_id': "RB38", - 'room': "D02Z02S06"}, - {'name': "GotP: Elevator shaft Child of Moonlight", - 'game_id': "RESCUED_CHERUB_26", - 'room': "D02Z02S11"}, - {'name': "GotP: Elevator shaft ledge", - 'game_id': "QI53", - 'room': "D02Z02S11"}, - {'name': "GotP: Lady of the Six Sorrows", - 'game_id': "Lady[D02Z02S12]", - 'room': "D02Z02S12"}, - {'name': "GotP: Self sacrifice statue", - 'game_id': "HE11", - 'room': "D02Z02S13"}, - {'name': "GotP: Lower east shaft", - 'game_id': "QI46", - 'room': "D02Z02S03"}, - {'name': "GotP: Center east shaft", - 'game_id': "CO29", - 'room': "D02Z02S03"}, - {'name': "GotP: Upper east shaft", - 'game_id': "QI08", - 'room': "D02Z02S03"}, - {'name': "GotP: East cliffside", - 'game_id': "RB106", - 'room': "D02Z02S14"}, - {'name': "GotP: West shaft Child of Moonlight", - 'game_id': "RESCUED_CHERUB_25", - 'room': "D02Z02S04"}, - {'name': "GotP: Lower west shaft", - 'game_id': "RB32", - 'room': "D02Z02S04"}, - {'name': "GotP: Upper west shaft", - 'game_id': "CO01", - 'room': "D02Z02S04"}, - {'name': "GotP: Center shaft Child of Moonlight", - 'game_id': "RESCUED_CHERUB_24", - 'room': "D02Z02S02"}, - {'name': "GotP: Center shaft ledge", - 'game_id': "RB15", - 'room': "D02Z02S05"}, - {'name': "GotP: Oil of the Pilgrims", - 'game_id': "Oil[D02Z02S10]", - 'room': "D02Z02S10"}, - {'name': "GotP: Amanecida of the Bejeweled Arrow", - 'game_id': "Amanecida[D02Z02S14]", - 'room': "D02Z02S14"}, - - # Grievance Ascends - {'name': "GA: Lower west ledge", - 'game_id': "QI44", - 'room': "D03Z03S02"}, - {'name': "GA: Miasma room treasure", - 'game_id': "RE07", - 'room': "D03Z03S06"}, - {'name': "GA: Miasma room Child of Moonlight", - 'game_id': "RESCUED_CHERUB_19", - 'room': "D03Z03S06"}, - {'name': "GA: Miasma room floor", - 'game_id': "CO12", - 'room': "D03Z03S06"}, - {'name': "GA: Oil of the Pilgrims", - 'game_id': "Oil[D03Z03S13]", - 'room': "D03Z03S13"}, - {'name': "GA: End of blood bridge", - 'game_id': "QI10", - 'room': "D03Z03S08"}, - {'name': "GA: Blood bridge Child of Moonlight", - 'game_id': "RESCUED_CHERUB_21", - 'room': "D03Z03S08"}, - {'name': "GA: Lower east Child of Moonlight", - 'game_id': "RESCUED_CHERUB_20", - 'room': "D03Z03S09"}, - {'name': "GA: Altasgracias' gift", - 'game_id': "QI13", - 'room': "D03Z03S10"}, - {'name': "GA: Empty giant egg", - 'game_id': "RB06", - 'room': "D03Z03S10"}, - {'name': "GA: Tres Angustias", - 'game_id': "BS04", - 'room': "D03Z03S15"}, - {'name': "GA: Visage of Contrition", - 'game_id': "QI39", - 'room': "D03Z03S16"}, - - # Hall of the Dawning - {'name': "HotD: Mirror room", - 'game_id': "QI105", - 'room': "D08Z03S01"}, - {'name': "HotD: Laudes, the First of the Amanecidas", - 'game_id': "LaudesBossTrigger[30000]", - 'room': "D08Z03S03"}, - + "RESCUED_CHERUB_24": "GotP: Center shaft Child of Moonlight", + "QI46": "GotP: Lower east shaft", + "CO29": "GotP: Center east shaft", + "QI08": "GotP: Upper east shaft", + "RB32": "GotP: Lower west shaft", + "CO01": "GotP: Upper west shaft", + "RESCUED_CHERUB_25": "GotP: West shaft Child of Moonlight", + "RB15": "GotP: Center shaft ledge", + "RB38": "GotP: Confessor Dungeon room", + "CO42": "GotP: Shop cave hidden hole", + "RESCUED_CHERUB_31": "GotP: Shop cave Child of Moonlight", + "Oil[D02Z02S10]": "GotP: Oil of the Pilgrims", + "QI53": "GotP: Elevator shaft ledge", + "RESCUED_CHERUB_26": "GotP: Elevator shaft Child of Moonlight", + "Lady[D02Z02S12]": "GotP: Lady of the Six Sorrows", + "HE11": "GotP: Self sacrifice statue", + "RB106": "GotP: East cliffside", + "Amanecida[D02Z02S14]": "GotP: Amanecida of the Bejeweled Arrow", + "QI11": "GotP: Shop item 1", + "RB37": "GotP: Shop item 2", + "RB02": "GotP: Shop item 3", + + # Convent of Our Lady of the Charred Visage + "CO05": "CoOLotCV: Snowy window ledge", + "RB08": "CoOLotCV: Center miasma room", + "CO15": "CoOLotCV: Center enemy lineup", + "HE03": "CoOLotCV: Lower west statue", + "Sword[D02Z03S13]": "CoOLotCV: Mea Culpa altar", + "Lady[D02Z03S15]": "CoOLotCV: Lady of the Six Sorrows", + "RB24": "CoOLotCV: First blue candle", + "QI61": "CoOLotCV: Mask room", + "BS03": "CoOLotCV: Our Lady of the Charred Visage", + "QI40": "CoOLotCV: Visage of Compunction", + "QI57": "CoOLotCV: Fountain of burning oil", + "RB107": "CoOLotCV: Outside pathway", + + # Mountains of the Endless Dusk + "CO13": "MotED: Under entrance to DC", + "QI47": "MotED: Platform above chasm", + "RB22": "MotED: 1st meeting with Redento", + "RESCUED_CHERUB_16": "MotED: Child of Moonlight, above chasm", + "Amanecida[D03Z01S03]": "MotED: Amanecida of the Golden Blades", + "QI63": "MotED: Blood platform alcove", + 'RB13': "MotED: Perpetva", + "QI14": "MotED: Egg hatching", + # Jondo - {'name': "Jondo: Upper east ledge", - 'game_id': "CO08", - 'room': "D03Z02S01"}, - {'name': "Jondo: Upper east chest", - 'game_id': "PR10", - 'room': "D03Z02S01"}, - {'name': "Jondo: Lower east under chargers", - 'game_id': "CO33", - 'room': "D03Z02S04"}, - {'name': "Jondo: Lower east bell trap", - 'game_id': "QI19", - 'room': "D03Z02S06"}, - {'name': "Jondo: Upper east Child of Moonlight", - 'game_id': "RESCUED_CHERUB_18", - 'room': "D03Z02S05"}, - {'name': "Jondo: Spike tunnel Child of Moonlight", - 'game_id': "RESCUED_CHERUB_37", - 'room': "D03Z02S11"}, - {'name': "Jondo: Spike tunnel statue", - 'game_id': "HE06", - 'room': "D03Z02S11"}, - {'name': "Jondo: Spike tunnel cave", - 'game_id': "QI103", - 'room': "D03Z02S15"}, - {'name': "Jondo: Lower west lift alcove", - 'game_id': "CO07", - 'room': "D03Z02S07"}, - {'name': "Jondo: Lower west bell alcove", - 'game_id': "QI41", - 'room': "D03Z02S08"}, - {'name': "Jondo: Upper west bell puzzle", - 'game_id': "QI52", - 'room': "D03Z02S12"}, - {'name': "Jondo: Upper west tree root", - 'game_id': "RB28", - 'room': "D03Z02S13"}, - {'name': "Jondo: Upper west Child of Moonlight", - 'game_id': "RESCUED_CHERUB_17", - 'room': "D03Z02S10"}, - - # Knot of the Three Words - {'name': "KotTW: Gift from the Traitor", - 'game_id': "HE201", - 'room': "D04Z03S02"}, - - # Library of the Negated Words - {'name': "LotNW: Platform room Child of Moonlight", - 'game_id': "RESCUED_CHERUB_01", - 'room': "D05Z01S04"}, - {'name': "LotNW: Platform room ledge", - 'game_id': "CO18", - 'room': "D05Z01S04"}, - {'name': "LotNW: Root ceiling platform", - 'game_id': "CO22", - 'room': "D05Z01S05"}, - {'name': "LotNW: Hidden floor", - 'game_id': "QI50", - 'room': "D05Z01S05"}, - {'name': "LotNW: Miasma hallway chest", - 'game_id': "RB31", - 'room': "D05Z01S06"}, - {'name': "LotNW: Lady of the Six Sorrows", - 'game_id': "Lady[D05Z01S14]", - 'room': "D05Z01S14"}, - {'name': "LotNW: Bone puzzle", - 'game_id': "PR15", - 'room': "D05Z01S18"}, - {'name': "LotNW: Lowest west upper ledge", - 'game_id': "CO28", - 'room': "D05Z01S11"}, - {'name': "LotNW: Platform puzzle chest", - 'game_id': "PR07", - 'room': "D05Z01S10"}, - {'name': "LotNW: Lowest west center ledge", - 'game_id': "RB30", - 'room': "D05Z01S11"}, - {'name': "LotNW: Lowest west Child of Moonlight", - 'game_id': "RESCUED_CHERUB_02", - 'room': "D05Z01S11"}, - {'name': "LotNW: Oil of the Pilgrims", - 'game_id': "Oil[D05Z01S19]", - 'room': "D05Z01S19"}, - {'name': "LotNW: Elevator Child of Moonlight", - 'game_id': "RESCUED_CHERUB_32", - 'room': "D05Z01S21"}, - {'name': "LotNW: Mask room", - 'game_id': "QI62", - 'room': "D05Z01S15"}, - {'name': "LotNW: Mea Culpa altar", - 'game_id': "Sword[D05Z01S13]", - 'room': "D05Z01S13"}, - {'name': "LotNW: Silence for Diosdado", - 'game_id': "RB203", - 'room': "D05Z01S11"}, - {'name': "LotNW: Twisted wood hidden wall", - 'game_id': "RB301", - 'room': "D05BZ01S01"}, + "CO08": "Jondo: Upper east ledge", + "PR10": "Jondo: Upper east chest", + "CO33": "Jondo: Lower east under chargers", + "RESCUED_CHERUB_18": "Jondo: Upper east Child of Moonlight", + "QI19": "Jondo: Lower east bell trap", + "CO07": "Jondo: Lower west lift alcove", + "QI41": "Jondo: Lower west bell alcove", + "RESCUED_CHERUB_17": "Jondo: Upper west Child of Moonlight", + "HE06": "Jondo: Spike tunnel statue", + "RESCUED_CHERUB_37": "Jondo: Spike tunnel Child of Moonlight", + "QI52": "Jondo: Upper west bell puzzle", + "RB28": "Jondo: Upper west tree root", + "QI103": "Jondo: Spike tunnel cave", - # Mercy Dreams - {'name': "MD: First area hidden wall", - 'game_id': "CO30", - 'room': "D01Z04S05"}, - {'name': "MD: Second area trapped chest", - 'game_id': "PR01", - 'room': "D01Z04S07"}, - {'name': "MD: Second area ledge", - 'game_id': "CO03", - 'room': "D01Z04S06"}, - {'name': "MD: Second area Child of Moonlight", - 'game_id': "RESCUED_CHERUB_09", - 'room': "D01Z04S06"}, - {'name': "MD: First red candle", - 'game_id': "RB17", - 'room': "D01Z04S08"}, - {'name': "MD: Shop item 1", - 'game_id': "QI58", - 'room': "D01BZ02S01"}, - {'name': "MD: Shop item 2", - 'game_id': "RB05", - 'room': "D01BZ02S01"}, - {'name': "MD: Shop item 3", - 'game_id': "RB09", - 'room': "D01BZ02S01"}, - {'name': "MD: Third area hidden room", - 'game_id': "QI48", - 'room': "D01Z04S11"}, - {'name': "MD: Sliding challenge", - 'game_id': "CO38", - 'room': "D01Z04S14"}, - {'name': "MD: Ten Piedad", - 'game_id': "BS01", - 'room': "D01Z04S18"}, - {'name': "MD: Visage of Attrition", - 'game_id': "QI38", - 'room': "D01Z04S19"}, - {'name': "MD: Cave Child of Moonlight", - 'game_id': "RESCUED_CHERUB_33", - 'room': "D01Z04S16"}, - {'name': "MD: Behind gate to TSC", - 'game_id': "CO21", - 'room': "D01Z04S13"}, + # Grievance Ascends + "QI44": "GA: Lower west ledge", + "CO12": "GA: Miasma room floor", + "RE07": "GA: Miasma room treasure", + "RESCUED_CHERUB_19": "GA: Miasma room Child of Moonlight", + "QI10": "GA: End of blood bridge", + "RESCUED_CHERUB_21": "GA: Blood bridge Child of Moonlight", + "RESCUED_CHERUB_20": "GA: Lower east Child of Moonlight", + "QI13": "GA: Altasgracias' gift", + "RB06": "GA: Empty giant egg", + "Oil[D03Z03S13]": "GA: Oil of the Pilgrims", + "BS04": "GA: Tres Angustias", + "QI39": "GA: Visage of Contrition", + + # Patio of the Silent Steps + "CO23": "PotSS: First area ledge", + "RESCUED_CHERUB_35": "PotSS: First area Child of Moonlight", + "RB14": "PotSS: Second area ledge", + "QI37": "PotSS: Third area lower ledge", + "CO39": "PotSS: Third area upper ledge", + "RESCUED_CHERUB_28": "PotSS: Third area Child of Moonlight", + "RB21": "PotSS: 4th meeting with Redento", + "Amanecida[D04Z01S04]": "PotSS: Amanecida of the Chiselled Steel", + "QI102": "PotSS: Climb to WotHP", # Mother of Mothers - {'name': "MoM: Oil of the Pilgrims", - 'game_id': "Oil[D04Z02S14]", - 'room': "D04Z02S14"}, - {'name': "MoM: Upper east ledge", - 'game_id': "RB33", - 'room': "D04Z02S07"}, - {'name': "MoM: East chandelier platform", - 'game_id': "CO35", - 'room': "D04Z02S07"}, - {'name': "MoM: Lower west Child of Moonlight", - 'game_id': "RESCUED_CHERUB_30", - 'room': "D04Z02S01"}, - {'name': "MoM: Upper west floor", - 'game_id': "CO17", - 'room': "D04Z02S02"}, - {'name': "MoM: Redento's treasure", - 'game_id': "RE03", - 'room': "D04BZ02S01"}, - {'name': "MoM: Final meeting with Redento", - 'game_id': "QI54", - 'room': "D04BZ02S01"}, - {'name': "MoM: Giant chandelier statue", - 'game_id': "HE01", - 'room': "D04Z02S16"}, - {'name': "MoM: Outside Cleofas' room", - 'game_id': "CO34", - 'room': "D04Z02S06"}, - {'name': "MoM: Upper center floor", - 'game_id': "CO20", - 'room': "D04Z02S11"}, - {'name': "MoM: Upper center Child of Moonlight", - 'game_id': "RESCUED_CHERUB_29", - 'room': "D04Z02S11"}, - {'name': "MoM: Mea Culpa altar", - 'game_id': "Sword[D04Z02S12]", - 'room': "D04Z02S12"}, - {'name': "MoM: Melquiades, The Exhumed Archbishop", - 'game_id': "BS05", - 'room': "D04Z02S22"}, - {'name': "MoM: Mask room", - 'game_id': "QI60", - 'room': "D04Z02S15"}, + "RE402": "MoM: Western room ledge", + "RESCUED_CHERUB_30": "MoM: Lower west Child of Moonlight", + "CO17": "MoM: Upper west floor", + "CO34": "MoM: Outside Cleofas' room", + "CO35": "MoM: East chandelier platform", + "RB33": "MoM: Upper east ledge", + "CO20": "MoM: Upper center floor", + "RESCUED_CHERUB_29": "MoM: Upper center Child of Moonlight", + "Sword[D04Z02S12]": "MoM: Mea Culpa altar", + "Oil[D04Z02S14]": "MoM: Oil of the Pilgrims", + "QI60": "MoM: Mask room", + "HE01": "MoM: Giant chandelier statue", + "BS05": "MoM: Melquiades, The Exhumed Archbishop", + "RE03": "MoM: Redento's treasure", + "QI54": "MoM: Final meeting with Redento", - # Mountains of the Endless Dusk - {'name': "MotED: Under entrance to DC", - 'game_id': "CO13", - 'room': "D03Z01S01"}, - {'name': "MotED: Perpetva", - 'game_id': "RB13", - 'room': "D03Z01S06"}, - {'name': "MotED: Child of Moonlight, above chasm", - 'game_id': "RESCUED_CHERUB_16", - 'room': "D03Z01S03"}, - {'name': "MotED: Platform above chasm", - 'game_id': "QI47", - 'room': "D03Z01S03"}, - {'name': "MotED: 1st meeting with Redento", - 'game_id': "RB22", - 'room': "D03Z01S03"}, - {'name': "MotED: Blood platform alcove", - 'game_id': "QI63", - 'room': "D03Z01S04"}, - {'name': "MotED: Egg hatching", - 'game_id': "QI14", - 'room': "D03Z01S06"}, - {'name': "MotED: Amanecida of the Golden Blades", - 'game_id': "Amanecida[D03Z01S03]", - 'room': "D03Z01S03"}, + # Knot of the Three Words + "HE201": "KotTW: Gift from the Traitor", - # Mourning and Havoc - {'name': "MaH: West chest", - 'game_id': "PR202", - 'room': "D20Z02S11"}, - {'name': "MaH: Upper east chest", - 'game_id': "RB201", - 'room': "D20Z02S02"}, - {'name': "MaH: Sierpes' eye", - 'game_id': "QI202", - 'room': "D20Z02S08"}, - {'name': "MaH: Sierpes", - 'game_id': "BossTrigger[5000]", - 'room': "D20Z02S08"}, - - # Patio of the Silent Steps - {'name': "PotSS: First area Child of Moonlight", - 'game_id': "RESCUED_CHERUB_35", - 'room': "D04Z01S01"}, - {'name': "PotSS: First area ledge", - 'game_id': "CO23", - 'room': "D04Z01S01"}, - {'name': "PotSS: Second area ledge", - 'game_id': "RB14", - 'room': "D04Z01S02"}, - {'name': "PotSS: Third area Child of Moonlight", - 'game_id': "RESCUED_CHERUB_28", - 'room': "D04Z01S03"}, - {'name': "PotSS: Third area lower ledge", - 'game_id': "QI37", - 'room': "D04Z01S03"}, - {'name': "PotSS: Third area upper ledge", - 'game_id': "CO39", - 'room': "D04Z01S03"}, - {'name': "PotSS: Climb to WotHP", - 'game_id': "QI102", - 'room': "D04Z01S06"}, - {'name': "PotSS: 4th meeting with Redento", - 'game_id': "RB21", - 'room': "D04Z01S04"}, - {'name': "PotSS: Amanecida of the Chiselled Steel", - 'game_id': "Amanecida[D04Z01S04]", - 'room': "D04Z01S04"}, + # All the Tears of the Sea + "PR201": "AtTotS: Miriam's gift", - # Petrous - {'name': "Petrous: Temple entrance", - 'game_id': "QI101", - 'room': "D01Z06S01"}, + # Library of the Negated Words + "CO18": "LotNW: Platform room ledge", + "RESCUED_CHERUB_01": "LotNW: Platform room Child of Moonlight", + "QI50": "LotNW: Hidden floor", + "CO22": "LotNW: Root ceiling platform", + "RB31": "LotNW: Miasma hallway chest", + "PR07": "LotNW: Platform puzzle chest", + "RB203": "LotNW: Silence for Diosdado", + "CO28": "LotNW: Lowest west upper ledge", + "RB30": "LotNW: Lowest west center ledge", + "RESCUED_CHERUB_02": "LotNW: Lowest west Child of Moonlight", + "Sword[D05Z01S13]": "LotNW: Mea Culpa altar", + "Lady[D05Z01S14]": "LotNW: Lady of the Six Sorrows", + "QI62": "LotNW: Mask room", + "PR15": "LotNW: Bone puzzle", + "Oil[D05Z01S19]": "LotNW: Oil of the Pilgrims", + "RESCUED_CHERUB_32": "LotNW: Elevator Child of Moonlight", + "RB301": "LotNW: Twisted wood hidden wall", - # The Resting Place of the Sister - {'name': "TRPotS: Perpetva's shrine", - 'game_id': "QI203", - 'room': "D20Z03S01"}, - # The Sleeping Canvases - {'name': "TSC: Painting ladder ledge", - 'game_id': "QI64", - 'room': "D05Z02S02"}, - {'name': "TSC: Candle wax puzzle", - 'game_id': "HE07", - 'room': "D05Z02S08"}, - {'name': "TSC: Shop item 1", - 'game_id': "RB12", - 'room': "D05BZ02S01"}, - {'name': "TSC: Shop item 2", - 'game_id': "QI49", - 'room': "D05BZ02S01"}, - {'name': "TSC: Shop item 3", - 'game_id': "QI71", - 'room': "D05BZ02S01"}, - {'name': "TSC: Swinging blade tunnel", - 'game_id': "QI104", - 'room': "D05Z02S15"}, - {'name': "TSC: Exposito, Scion of Abjuration", - 'game_id': "BS06", - 'room': "D05Z02S14"}, - {'name': "TSC: Under elevator shaft", - 'game_id': "CO31", - 'room': "D05Z02S11"}, - {'name': "TSC: Jocinero's 1st reward", - 'game_id': "RE05", - 'room': "D05Z02S10"}, - {'name': "TSC: Jocinero's final reward", - 'game_id': "PR05", - 'room': "D05Z02S10"}, + "QI64": "TSC: Painting ladder ledge", + "HE07": "TSC: Candle wax puzzle", + "RE05": "TSC: Jocinero's 1st reward", + "PR05": "TSC: Jocinero's final reward", + "CO31": "TSC: Under elevator shaft", + "BS06": "TSC: Exposito, Scion of Abjuration", + "QI104": "TSC: Swinging blade tunnel", + "RB12": "TSC: Shop item 1", + "QI49": "TSC: Shop item 2", + "QI71": "TSC: Shop item 3", - # The Holy Line - {'name': "THL: Deogracias' gift", - 'game_id': "QI31", - 'room': "D01Z01S07"}, - {'name': "THL: Hanging skeleton", - 'game_id': "PR14", - 'room': "D01Z01S02"}, - {'name': "THL: Across blood platforms", - 'game_id': "RB07", - 'room': "D01Z01S02"}, - {'name': "THL: Child of Moonlight", - 'game_id': "RESCUED_CHERUB_07", - 'room': "D01Z01S03"}, - {'name': "THL: Underground ledge", - 'game_id': "CO04", - 'room': "D01Z01S03"}, - {'name': "THL: Underground chest", - 'game_id': "QI55", - 'room': "D01Z01S03"}, + # Archcathedral Rooftops + "QI02": "AR: First soldier fight", + "QI03": "AR: Second soldier fight", + "QI04": "AR: Third soldier fight", + "Sword[D06Z01S11]": "AR: Mea Culpa altar", + "CO06": "AR: Upper west shaft ledge", + "PR12": "AR: Upper west shaft chest", + "RESCUED_CHERUB_36": "AR: Upper west shaft Child of Moonlight", + "CO40": "AR: Upper east shaft ledge", + "HE04": "AR: Statue near MoM", + "Lady[D06Z01S24]": "AR: Lady of the Six Sorrows", + "BS16": "AR: Crisanta of the Wrapped Agony", + + # Deambulatory of His Holiness + "PR08": "DoHH: Viridiana's gift", + + # Bridge of the Three Cavalries + "BS12": "BotTC: Esdras, of the Anointed Legion", + "PR09": "BotTC: Esdras' gift", + "HE101": "BotTC: Inside giant statue", + + # Hall of the Dawning + "QI105": "HotD: Mirror room", + "LaudesBossTrigger[30000]": "HotD: Laudes, the First of the Amanecidas", # Wall of the Holy Prohibitions - {'name': "WotHP: Upper east room, lift puzzle", - 'game_id': "RB11", - 'room': "D09Z01S02"}, - {'name': "WotHP: Upper east room, center cell ledge", - 'game_id': "CO10", - 'room': "D09BZ01S01"}, - {'name': "WotHP: Upper east room, center cell floor", - 'game_id': "QI69", - 'room': "D09BZ01S01"}, - {'name': "WotHP: Upper east room, top bronze cell", - 'game_id': "RESCUED_CHERUB_03", - 'room': "D09BZ01S01"}, - {'name': "WotHP: Upper east room, top silver cell", - 'game_id': "CO24", - 'room': "D09BZ01S01"}, - {'name': "WotHP: Upper east room, center gold cell", - 'game_id': "QI51", - 'room': "D09Z01S02"}, - {'name': "WotHP: Upper west room, center gold cell", - 'game_id': "CO26", - 'room': "D09BZ01S01"}, - {'name': "WotHP: Lower west room, bottom gold cell", - 'game_id': "CO02", - 'room': "D09BZ01S01"}, - {'name': "WotHP: Upper west room, top silver cell", - 'game_id': "RESCUED_CHERUB_34", - 'room': "D09BZ01S01"}, - {'name': "WotHP: Lower west room, top ledge", - 'game_id': "RB16", - 'room': "D09Z01S09"}, - {'name': "WotHP: Lower east room, hidden ledge", - 'game_id': "CO27", - 'room': "D09Z01S10"}, - {'name': "WotHP: Lower east room, bottom silver cell", - 'game_id': "RESCUED_CHERUB_04", - 'room': "D09BZ01S01"}, - {'name': "WotHP: Lower east room, top bronze cell", - 'game_id': "QI70", - 'room': "D09Z01S10"}, - {'name': "WotHP: Lower east room, top silver cell", - 'game_id': "CO37", - 'room': "D09BZ01S01"}, - {'name': "WotHP: Outside Child of Moonlight", - 'game_id': "RESCUED_CHERUB_05", - 'room': "D09Z01S06"}, - {'name': "WotHP: Oil of the Pilgrims", - 'game_id': "Oil[D09Z01S12]", - 'room': "D09Z01S12"}, - {'name': "WotHP: Quirce, Returned By The Flames", - 'game_id': "BS14", - 'room': "D09Z01S03"}, - {'name': "WotHP: Collapsing floor ledge", - 'game_id': "QI72", - 'room': "D09Z01S08"}, - {'name': "WotHP: Amanecida of the Molten Thorn", - 'game_id': "Amanecida[D09Z01S01]", - 'room': "D09Z01S01"}, + "Amanecida[D09Z01S01]": "WotHP: Amanecida of the Molten Thorn", + "QI51": "WotHP: Upper east room, center gold cell", + "RB11": "WotHP: Upper east room, lift puzzle", + "BS14": "WotHP: Quirce, Returned By The Flames", + "RESCUED_CHERUB_05": "WotHP: Outside Child of Moonlight", + "QI72": "WotHP: Collapsing floor ledge", + "RB16": "WotHP: Lower west room, top ledge", + "QI70": "WotHP: Lower east room, top bronze cell", + "CO27": "WotHP: Lower east room, hidden ledge", + "Oil[D09Z01S12]": "WotHP: Oil of the Pilgrims", + "CO10": "WotHP: Upper east room, center cell ledge", + "QI69": "WotHP: Upper east room, center cell floor", + "RESCUED_CHERUB_03": "WotHP: Upper east room, top bronze cell", + "CO24": "WotHP: Upper east room, top silver cell", + "RESCUED_CHERUB_34": "WotHP: Upper west room, top silver cell", + "CO26": "WotHP: Upper west room, center gold cell", + "CO02": "WotHP: Lower west room, bottom gold cell", + "CO37": "WotHP: Lower east room, top silver cell", + "RESCUED_CHERUB_04": "WotHP: Lower east room, bottom silver cell", - # Wasteland of the Buried Churches - {'name': "WotBC: Lower log path", - 'game_id': "RB04", - 'room': "D01Z03S01"}, - {'name': "WotBC: Hidden alcove", - 'game_id': "CO14", - 'room': "D01Z03S02"}, - {'name': "WotBC: Outside ledge", - 'game_id': "CO36", - 'room': "D01Z03S03"}, - {'name': "WotBC: Outside Child of Moonlight", - 'game_id': "RESCUED_CHERUB_10", - 'room': "D01Z03S03"}, - {'name': "WotBC: Under broken bridge", - 'game_id': "QI06", - 'room': "D01Z03S05"}, - {'name': "WotBC: Cliffside statue", - 'game_id': "HE02", - 'room': "D01Z03S07"}, - {'name': "WotBC: Cliffside Child of Moonlight", - 'game_id': "RESCUED_CHERUB_38", - 'room': "D01Z03S07"}, - {'name': "WotBC: 3rd meeting with Redento", - 'game_id': "RB20", - 'room': "D01Z03S06"}, - - # Where Olive Trees Wither - {'name': "WOTW: Below Prie Dieu", - 'game_id': "CO11", - 'room': "D02Z01S01"}, - {'name': "WOTW: Entrance to tomb", - 'game_id': "QI20", - 'room': "D02Z01S04"}, - {'name': "WOTW: Gift for the tomb", - 'game_id': "QI68", - 'room': "D02Z01S04"}, - {'name': "WOTW: Underground tomb", - 'game_id': "PR04", - 'room': "D02Z01S08"}, - {'name': "WOTW: Underground Child of Moonlight", - 'game_id': "RESCUED_CHERUB_27", - 'room': "D02Z01S06"}, - {'name': "WOTW: Underground ledge", - 'game_id': "CO19", - 'room': "D02Z01S06"}, - {'name': "WOTW: Upper east Child of Moonlight", - 'game_id': "RESCUED_CHERUB_23", - 'room': "D02Z01S02"}, - {'name': "WOTW: Upper east statue", - 'game_id': "HE05", - 'room': "D02Z01S09"}, - {'name': "WOTW: Death run", - 'game_id': "QI07", - 'room': "D02Z01S05"}, - {'name': "WOTW: Gemino's gift", - 'game_id': "QI59", - 'room': "D02Z01S01"}, - {'name': "WOTW: Gemino's reward", - 'game_id': "RB10", - 'room': "D02Z01S01"}, + # Brotherhood of the Silent Sorrow + "RB204": "BotSS: Starting room ledge", + "RESCUED_CHERUB_06": "BotSS: Starting room Child of Moonlight", + "RE401": "BotSS: 2nd meeting with Redento", + "Sword[D17Z01S08]": "BotSS: Mea Culpa altar", + "BS13": "BotSS: Warden of the Silent Sorrow", + "PR203": "BotSS: Outside church", + "QI204": "BotSS: Esdras' final gift", + "QI301": "BotSS: Crisanta's gift", + "RE01": "BotSS: Chamber of the Eldest Brother", + "CO25": "BotSS: Platforming gauntlet", + + # Echoes of Salt + "RB108": "EoS: Lantern jump near MotED", + "RB202": "EoS: Lantern jump near elevator", - # Various - {'name': "Beginning gift", - 'game_id': "QI106", - 'room': "Misc"}, - {'name': "Second red candle", - 'game_id': "RB18", - 'room': "Misc"}, - {'name': "Third red candle", - 'game_id': "RB19", - 'room': "Misc"}, - {'name': "Second blue candle", - 'game_id': "RB25", - 'room': "Misc"}, - {'name': "Third blue candle", - 'game_id': "RB26", - 'room': "Misc"}, - {'name': "Confessor Dungeon 1 extra", - 'game_id': "Arena_NailManager[1000]", - 'room': "Misc"}, - {'name': "Confessor Dungeon 1 main", - 'game_id': "QI32", - 'room': "Misc"}, - {'name': "Confessor Dungeon 2 extra", - 'game_id': "HE10", - 'room': "Misc"}, - {'name': "Confessor Dungeon 2 main", - 'game_id': "QI33", - 'room': "Misc"}, - {'name': "Confessor Dungeon 3 extra", - 'game_id': "Arena_NailManager[3000]", - 'room': "Misc"}, - {'name': "Confessor Dungeon 3 main", - 'game_id': "QI34", - 'room': "Misc"}, - {'name': "Confessor Dungeon 4 extra", - 'game_id': "RB34", - 'room': "Misc"}, - {'name': "Confessor Dungeon 4 main", - 'game_id': "QI35", - 'room': "Misc"}, - {'name': "Confessor Dungeon 5 extra", - 'game_id': "Arena_NailManager[5000]", - 'room': "Misc"}, - {'name': "Confessor Dungeon 5 main", - 'game_id': "QI79", - 'room': "Misc"}, - {'name': "Confessor Dungeon 6 extra", - 'game_id': "RB35", - 'room': "Misc"}, - {'name': "Confessor Dungeon 6 main", - 'game_id': "QI80", - 'room': "Misc"}, - {'name': "Confessor Dungeon 7 extra", - 'game_id': "RB36", - 'room': "Misc"}, - {'name': "Confessor Dungeon 7 main", - 'game_id': "QI81", - 'room': "Misc"}, - {'name': "Defeat 1 Amanecida", - 'game_id': "QI107", - 'room': "Misc"}, - {'name': "Defeat 2 Amanecidas", - 'game_id': "QI108", - 'room': "Misc"}, - {'name': "Defeat 3 Amanecidas", - 'game_id': "QI109", - 'room': "Misc"}, - {'name': "Defeat 4 Amanecidas", - 'game_id': "QI110", - 'room': "Misc"}, - {'name': "Defeat all Amanecidas", - 'game_id': "PR101", - 'room': "Misc"}, - {'name': "Skill 1, Tier 1", - 'game_id': "COMBO_1", - 'room': "Misc"}, - {'name': "Skill 1, Tier 2", - 'game_id': "COMBO_2", - 'room': "Misc"}, - {'name': "Skill 1, Tier 3", - 'game_id': "COMBO_3", - 'room': "Misc"}, - {'name': "Skill 2, Tier 1", - 'game_id': "CHARGED_1", - 'room': "Misc"}, - {'name': "Skill 2, Tier 2", - 'game_id': "CHARGED_2", - 'room': "Misc"}, - {'name': "Skill 2, Tier 3", - 'game_id': "CHARGED_3", - 'room': "Misc"}, - {'name': "Skill 3, Tier 1", - 'game_id': "RANGED_1", - 'room': "Misc"}, - {'name': "Skill 3, Tier 2", - 'game_id': "RANGED_2", - 'room': "Misc"}, - {'name': "Skill 3, Tier 3", - 'game_id': "RANGED_3", - 'room': "Misc"}, - {'name': "Skill 4, Tier 1", - 'game_id': "VERTICAL_1", - 'room': "Misc"}, - {'name': "Skill 4, Tier 2", - 'game_id': "VERTICAL_2", - 'room': "Misc"}, - {'name': "Skill 4, Tier 3", - 'game_id': "VERTICAL_3", - 'room': "Misc"}, - {'name': "Skill 5, Tier 1", - 'game_id': "LUNGE_1", - 'room': "Misc"}, - {'name': "Skill 5, Tier 2", - 'game_id': "LUNGE_2", - 'room': "Misc"}, - {'name': "Skill 5, Tier 3", - 'game_id': "LUNGE_3", - 'room': "Misc"}, + # Mourning and Havoc + "RB201": "MaH: Upper east chest", + "BossTrigger[5000]": "MaH: Sierpes", + "QI202": "MaH: Sierpes' eye", + "PR202": "MaH: West chest", + + # The Resting Place of the Sister + "QI203": "TRPotS: Perpetva's shrine", - # Custom Items - {'name': "BotSS: 2nd meeting with Redento", - 'game_id': "RE401", - 'room': "D17Z01S04"}, - {'name': "MoM: Western room ledge", - 'game_id': "RE402", - 'room': "D04Z02S01"} -] \ No newline at end of file + # Misc + "QI106": "Beginning gift", + "RB18": "Second red candle", + "RB19": "Third red candle", + "RB25": "Second blue candle", + "RB26": "Third blue candle", + "QI107": "Defeat 1 Amanecida", + "QI108": "Defeat 2 Amanecidas", + "QI109": "Defeat 3 Amanecidas", + "QI110": "Defeat 4 Amanecidas", + "PR101": "Defeat all Amanecidas", + "QI32": "Confessor Dungeon 1 main", + "QI33": "Confessor Dungeon 2 main", + "QI34": "Confessor Dungeon 3 main", + "QI35": "Confessor Dungeon 4 main", + "QI79": "Confessor Dungeon 5 main", + "QI80": "Confessor Dungeon 6 main", + "QI81": "Confessor Dungeon 7 main", + "Arena_NailManager[1000]": "Confessor Dungeon 1 extra", + "HE10": "Confessor Dungeon 2 extra", + "Arena_NailManager[3000]": "Confessor Dungeon 3 extra", + "RB34": "Confessor Dungeon 4 extra", + "Arena_NailManager[5000]": "Confessor Dungeon 5 extra", + "RB35": "Confessor Dungeon 6 extra", + "RB36": "Confessor Dungeon 7 extra", + "COMBO_1": "Skill 1, Tier 1", + "COMBO_2": "Skill 1, Tier 2", + "COMBO_3": "Skill 1, Tier 3", + "CHARGED_1": "Skill 2, Tier 1", + "CHARGED_2": "Skill 2, Tier 2", + "CHARGED_3": "Skill 2, Tier 3", + "RANGED_1": "Skill 3, Tier 1", + "RANGED_2": "Skill 3, Tier 2", + "RANGED_3": "Skill 3, Tier 3", + "VERTICAL_1": "Skill 4, Tier 1", + "VERTICAL_2": "Skill 4, Tier 2", + "VERTICAL_3": "Skill 4, Tier 3", + "LUNGE_1": "Skill 5, Tier 1", + "LUNGE_2": "Skill 5, Tier 2", + "LUNGE_3": "Skill 5, Tier 3" +} diff --git a/worlds/blasphemous/Options.py b/worlds/blasphemous/Options.py index 127a1dc77669..0bd08b13b260 100644 --- a/worlds/blasphemous/Options.py +++ b/worlds/blasphemous/Options.py @@ -1,4 +1,5 @@ -from Options import Choice, Toggle, DefaultOnToggle, DeathLink, StartInventoryPool +from dataclasses import dataclass +from Options import Choice, Toggle, DefaultOnToggle, DeathLink, PerGameCommonOptions, OptionGroup import random @@ -20,23 +21,30 @@ def from_text(cls, text: str) -> Choice: class PrieDieuWarp(DefaultOnToggle): - """Automatically unlocks the ability to warp between Prie Dieu shrines.""" + """ + Automatically unlocks the ability to warp between Prie Dieu shrines. + """ display_name = "Unlock Fast Travel" class SkipCutscenes(DefaultOnToggle): - """Automatically skips most cutscenes.""" + """ + Automatically skips most cutscenes. + """ display_name = "Auto Skip Cutscenes" class CorpseHints(DefaultOnToggle): - """Changes the 34 corpses in game to give various hints about item locations.""" + """ + Changes the 34 corpses in game to give various hints about item locations. + """ display_name = "Corpse Hints" class Difficulty(Choice): - """Adjusts the overall difficulty of the randomizer, including upgrades required to defeat bosses - and advanced movement tricks or glitches.""" + """ + Adjusts the overall difficulty of the randomizer, including upgrades required to defeat bosses and advanced movement tricks or glitches. + """ display_name = "Difficulty" option_easy = 0 option_normal = 1 @@ -45,15 +53,18 @@ class Difficulty(Choice): class Penitence(Toggle): - """Allows one of the three Penitences to be chosen at the beginning of the game.""" + """ + Allows one of the three Penitences to be chosen at the beginning of the game. + """ display_name = "Penitence" class StartingLocation(ChoiceIsRandom): - """Choose where to start the randomizer. Note that some starting locations cannot be chosen with certain - other options. - Specifically, Brotherhood and Mourning And Havoc cannot be chosen if Shuffle Dash is enabled, and Grievance Ascends - cannot be chosen if Shuffle Wall Climb is enabled.""" + """ + Choose where to start the randomizer. Note that some starting locations cannot be chosen with certain other options. + + Specifically, Brotherhood and Mourning And Havoc cannot be chosen if Shuffle Dash is enabled, and Grievance Ascends cannot be chosen if Shuffle Wall Climb is enabled. + """ display_name = "Starting Location" option_brotherhood = 0 option_albero = 1 @@ -66,10 +77,15 @@ class StartingLocation(ChoiceIsRandom): class Ending(Choice): - """Choose which ending is required to complete the game. + """ + Choose which ending is required to complete the game. + Talking to Tirso in Albero will tell you the selected ending for the current game. + Ending A: Collect all thorn upgrades. - Ending C: Collect all thorn upgrades and the Holy Wound of Abnegation.""" + + Ending C: Collect all thorn upgrades and the Holy Wound of Abnegation. + """ display_name = "Ending" option_any_ending = 0 option_ending_a = 1 @@ -78,14 +94,18 @@ class Ending(Choice): class SkipLongQuests(Toggle): - """Ensures that the rewards for long quests will be filler items. - Affected locations: \"Albero: Donate 50000 Tears\", \"Ossuary: 11th reward\", \"AtTotS: Miriam's gift\", - \"TSC: Jocinero's final reward\"""" + """ + Ensures that the rewards for long quests will be filler items. + + Affected locations: "Albero: Donate 50000 Tears", "Ossuary: 11th reward", "AtTotS: Miriam's gift", "TSC: Jocinero's final reward" + """ display_name = "Skip Long Quests" class ThornShuffle(Choice): - """Shuffles the Thorn given by Deogracias and all Thorn upgrades into the item pool.""" + """ + Shuffles the Thorn given by Deogracias and all Thorn upgrades into the item pool. + """ display_name = "Shuffle Thorn" option_anywhere = 0 option_local_only = 1 @@ -94,50 +114,68 @@ class ThornShuffle(Choice): class DashShuffle(Toggle): - """Turns the ability to dash into an item that must be found in the multiworld.""" + """ + Turns the ability to dash into an item that must be found in the multiworld. + """ display_name = "Shuffle Dash" class WallClimbShuffle(Toggle): - """Turns the ability to climb walls with your sword into an item that must be found in the multiworld.""" + """ + Turns the ability to climb walls with your sword into an item that must be found in the multiworld. + """ display_name = "Shuffle Wall Climb" class ReliquaryShuffle(DefaultOnToggle): - """Adds the True Torment exclusive Reliquary rosary beads into the item pool.""" + """ + Adds the True Torment exclusive Reliquary rosary beads into the item pool. + """ display_name = "Shuffle Penitence Rewards" class CustomItem1(Toggle): - """Adds the custom relic Boots of Pleading into the item pool, which grants the ability to fall onto spikes - and survive. - Must have the \"Blasphemous-Boots-of-Pleading\" mod installed to connect to a multiworld.""" + """ + Adds the custom relic Boots of Pleading into the item pool, which grants the ability to fall onto spikes and survive. + + Must have the "Boots of Pleading" mod installed to connect to a multiworld. + """ display_name = "Boots of Pleading" class CustomItem2(Toggle): - """Adds the custom relic Purified Hand of the Nun into the item pool, which grants the ability to jump - a second time in mid-air. - Must have the \"Blasphemous-Double-Jump\" mod installed to connect to a multiworld.""" + """ + Adds the custom relic Purified Hand of the Nun into the item pool, which grants the ability to jump a second time in mid-air. + + Must have the "Double Jump" mod installed to connect to a multiworld. + """ display_name = "Purified Hand of the Nun" class StartWheel(Toggle): - """Changes the beginning gift to The Young Mason's Wheel.""" + """ + Changes the beginning gift to The Young Mason's Wheel. + """ display_name = "Start with Wheel" class SkillRando(Toggle): - """Randomizes the abilities from the skill tree into the item pool.""" + """ + Randomizes the abilities from the skill tree into the item pool. + """ display_name = "Skill Randomizer" class EnemyRando(Choice): - """Randomizes the enemies that appear in each room. - Shuffled: Enemies will be shuffled amongst each other, but can only appear as many times as they do in - a standard game. + """ + Randomizes the enemies that appear in each room. + + Shuffled: Enemies will be shuffled amongst each other, but can only appear as many times as they do in a standard game. + Randomized: Every enemy is completely random, and can appear any number of times. - Some enemies will never be randomized.""" + + Some enemies will never be randomized. + """ display_name = "Enemy Randomizer" option_disabled = 0 option_shuffled = 1 @@ -146,43 +184,75 @@ class EnemyRando(Choice): class EnemyGroups(DefaultOnToggle): - """Randomized enemies will chosen from sets of specific groups. + """ + Randomized enemies will be chosen from sets of specific groups. + (Weak, normal, large, flying) - Has no effect if Enemy Randomizer is disabled.""" + + Has no effect if Enemy Randomizer is disabled. + """ display_name = "Enemy Groups" class EnemyScaling(DefaultOnToggle): - """Randomized enemies will have their stats increased or decreased depending on the area they appear in. - Has no effect if Enemy Randomizer is disabled.""" + """ + Randomized enemies will have their stats increased or decreased depending on the area they appear in. + + Has no effect if Enemy Randomizer is disabled. + """ display_name = "Enemy Scaling" class BlasphemousDeathLink(DeathLink): - """When you die, everyone dies. The reverse is also true. - Note that Guilt Fragments will not appear when killed by Death Link.""" - - -blasphemous_options = { - "prie_dieu_warp": PrieDieuWarp, - "skip_cutscenes": SkipCutscenes, - "corpse_hints": CorpseHints, - "difficulty": Difficulty, - "penitence": Penitence, - "starting_location": StartingLocation, - "ending": Ending, - "skip_long_quests": SkipLongQuests, - "thorn_shuffle" : ThornShuffle, - "dash_shuffle": DashShuffle, - "wall_climb_shuffle": WallClimbShuffle, - "reliquary_shuffle": ReliquaryShuffle, - "boots_of_pleading": CustomItem1, - "purified_hand": CustomItem2, - "start_wheel": StartWheel, - "skill_randomizer": SkillRando, - "enemy_randomizer": EnemyRando, - "enemy_groups": EnemyGroups, - "enemy_scaling": EnemyScaling, - "death_link": BlasphemousDeathLink, - "start_inventory": StartInventoryPool -} \ No newline at end of file + """ + When you die, everyone dies. The reverse is also true. + + Note that Guilt Fragments will not appear when killed by Death Link. + """ + + +@dataclass +class BlasphemousOptions(PerGameCommonOptions): + prie_dieu_warp: PrieDieuWarp + skip_cutscenes: SkipCutscenes + corpse_hints: CorpseHints + difficulty: Difficulty + penitence: Penitence + starting_location: StartingLocation + ending: Ending + skip_long_quests: SkipLongQuests + thorn_shuffle: ThornShuffle + dash_shuffle: DashShuffle + wall_climb_shuffle: WallClimbShuffle + reliquary_shuffle: ReliquaryShuffle + boots_of_pleading: CustomItem1 + purified_hand: CustomItem2 + start_wheel: StartWheel + skill_randomizer: SkillRando + enemy_randomizer: EnemyRando + enemy_groups: EnemyGroups + enemy_scaling: EnemyScaling + death_link: BlasphemousDeathLink + + +blas_option_groups = [ + OptionGroup("Quality of Life", [ + PrieDieuWarp, + SkipCutscenes, + CorpseHints, + SkipLongQuests, + StartWheel + ]), + OptionGroup("Moveset", [ + DashShuffle, + WallClimbShuffle, + SkillRando, + CustomItem1, + CustomItem2 + ]), + OptionGroup("Enemy Randomizer", [ + EnemyRando, + EnemyGroups, + EnemyScaling + ]) +] diff --git a/worlds/blasphemous/Preprocessor.py b/worlds/blasphemous/Preprocessor.py new file mode 100644 index 000000000000..dd845f26d5ab --- /dev/null +++ b/worlds/blasphemous/Preprocessor.py @@ -0,0 +1,582 @@ +# Preprocessor to convert Blasphemous Randomizer logic into a StringWorldDefinition for use with APHKLogicExtractor +# https://github.com/BrandenEK/Blasphemous.Randomizer +# https://github.com/ArchipelagoMW-HollowKnight/APHKLogicExtractor + + +import json, requests, argparse +from typing import List, Dict, Any + + +def load_resource_local(file: str) -> List[Dict[str, Any]]: + print(f"Reading from {file}") + loaded = [] + with open(file, encoding="utf-8") as f: + loaded = read_json(f.readlines()) + f.close() + + return loaded + + +def load_resource_from_web(url: str) -> List[Dict[str, Any]]: + req = requests.get(url, timeout=1) + print(f"Reading from {url}") + req.encoding = "utf-8" + lines: List[str] = [] + for line in req.text.splitlines(): + while "\t" in line: + line = line[1::] + if line != "": + lines.append(line) + return read_json(lines) + + +def read_json(lines: List[str]) -> List[Dict[str, Any]]: + loaded = [] + creating_object: bool = False + obj: str = "" + for line in lines: + stripped = line.strip() + if "{" in stripped: + creating_object = True + obj += stripped + continue + elif "}," in stripped or "}" in stripped and "]" in lines[lines.index(line)+1]: + creating_object = False + obj += "}" + #print(f"obj = {obj}") + loaded.append(json.loads(obj)) + obj = "" + continue + + if not creating_object: + continue + else: + try: + if "}," in lines[lines.index(line)+1] and stripped[-1] == ",": + obj += stripped[:-1] + else: + obj += stripped + except IndexError: + obj += stripped + + return loaded + + +def get_room_from_door(door: str) -> str: + return door[:door.find("[")] + + +def preprocess_logic(is_door: bool, id: str, logic: str) -> str: + if id in logic and not is_door: + index: int = logic.find(id) + logic = logic[:index] + logic[index+len(id)+4:] + + while ">=" in logic: + index: int = logic.find(">=") + logic = logic[:index-1] + logic[index+3:] + + while ">" in logic: + index: int = logic.find(">") + count = int(logic[index+2]) + count += 1 + logic = logic[:index-1] + str(count) + logic[index+3:] + + while "<=" in logic: + index: int = logic.find("<=") + logic = logic[:index-1] + logic[index+3:] + + while "<" in logic: + index: int = logic.find("<") + count = int(logic[index+2]) + count += 1 + logic = logic[:index-1] + str(count) + logic[index+3:] + + #print(logic) + return logic + + +def build_logic_conditions(logic: str) -> List[List[str]]: + all_conditions: List[List[str]] = [] + + parts = logic.split() + sub_part: str = "" + current_index: int = 0 + parens: int = -1 + current_condition: List[str] = [] + parens_conditions: List[List[List[str]]] = [] + + for index, part in enumerate(parts): + #print(current_index, index, parens, part) + + # skip parts that have already been handled + if index < current_index: + continue + + # break loop if reached final part + try: + parts[index+1] + except IndexError: + #print("INDEXERROR", part) + if parens < 0: + current_condition.append(part) + if len(parens_conditions) > 0: + for i in parens_conditions: + for j in i: + all_conditions.append(j + current_condition) + else: + all_conditions.append(current_condition) + break + + #print(current_condition, parens, sub_part) + + # prepare for subcondition + if "(" in part: + # keep track of nested parentheses + if parens == -1: + parens = 0 + for char in part: + if char == "(": + parens += 1 + + # add to sub part + if sub_part == "": + sub_part = part + else: + sub_part += f" {part}" + #if not ")" in part: + continue + + # end of subcondition + if ")" in part: + # read every character in case of multiple closing parentheses + for char in part: + if char == ")": + parens -= 1 + + sub_part += f" {part}" + + # if reached end of parentheses, handle subcondition + if parens == 0: + #print(current_condition, sub_part) + parens = -1 + + try: + parts[index+1] + except IndexError: + #print("END OF LOGIC") + if len(parens_conditions) > 0: + parens_conditions.append(build_logic_subconditions(current_condition, sub_part)) + #print("PARENS:", parens_conditions) + + temp_conditions: List[List[str]] = [] + + for i in parens_conditions[0]: + for j in parens_conditions[1]: + temp_conditions.append(i + j) + + parens_conditions.pop(0) + parens_conditions.pop(0) + + while len(parens_conditions) > 0: + temp_conditions2 = temp_conditions + temp_conditions = [] + for k in temp_conditions2: + for l in parens_conditions[0]: + temp_conditions.append(k + l) + + parens_conditions.pop(0) + + #print("TEMP:", remove_duplicates(temp_conditions)) + all_conditions += temp_conditions + else: + all_conditions += build_logic_subconditions(current_condition, sub_part) + else: + #print("NEXT PARTS:", parts[index+1], parts[index+2]) + if parts[index+1] == "&&": + parens_conditions.append(build_logic_subconditions(current_condition, sub_part)) + #print("PARENS:", parens_conditions) + else: + if len(parens_conditions) > 0: + parens_conditions.append(build_logic_subconditions(current_condition, sub_part)) + #print("PARENS:", parens_conditions) + + temp_conditions: List[List[str]] = [] + + for i in parens_conditions[0]: + for j in parens_conditions[1]: + temp_conditions.append(i + j) + + parens_conditions.pop(0) + parens_conditions.pop(0) + + while len(parens_conditions) > 0: + temp_conditions2 = temp_conditions + temp_conditions = [] + for k in temp_conditions2: + for l in parens_conditions[0]: + temp_conditions.append(k + l) + + parens_conditions.pop(0) + + #print("TEMP:", remove_duplicates(temp_conditions)) + all_conditions += temp_conditions + else: + all_conditions += build_logic_subconditions(current_condition, sub_part) + + current_index = index+2 + + current_condition = [] + sub_part = "" + + continue + + # collect all parts until reaching end of parentheses + if parens > 0: + sub_part += f" {part}" + continue + + current_condition.append(part) + + # continue with current condition + if parts[index+1] == "&&": + current_index = index+2 + continue + + # add condition to list and start new one + elif parts[index+1] == "||": + if len(parens_conditions) > 0: + for i in parens_conditions: + for j in i: + all_conditions.append(j + current_condition) + parens_conditions = [] + else: + all_conditions.append(current_condition) + current_condition = [] + current_index = index+2 + continue + + return remove_duplicates(all_conditions) + + +def build_logic_subconditions(current_condition: List[str], subcondition: str) -> List[List[str]]: + #print("STARTED SUBCONDITION", current_condition, subcondition) + subconditions = build_logic_conditions(subcondition[1:-1]) + final_conditions = [] + + for condition in subconditions: + final_condition = current_condition + condition + final_conditions.append(final_condition) + + #print("ENDED SUBCONDITION") + #print(final_conditions) + return final_conditions + + +def remove_duplicates(conditions: List[List[str]]) -> List[List[str]]: + final_conditions: List[List[str]] = [] + for condition in conditions: + final_conditions.append(list(dict.fromkeys(condition))) + + return final_conditions + + +def handle_door_visibility(door: Dict[str, Any]) -> Dict[str, Any]: + if door.get("visibilityFlags") == None: + return door + else: + flags: List[str] = str(door.get("visibilityFlags")).split(", ") + #print(flags) + temp_flags: List[str] = [] + this_door: bool = False + #required_doors: str = "" + + if "ThisDoor" in flags: + this_door = True + + #if "requiredDoors" in flags: + # required_doors: str = " || ".join(door.get("requiredDoors")) + + if "DoubleJump" in flags: + temp_flags.append("DoubleJump") + + if "NormalLogic" in flags: + temp_flags.append("NormalLogic") + + if "NormalLogicAndDoubleJump" in flags: + temp_flags.append("NormalLogicAndDoubleJump") + + if "HardLogic" in flags: + temp_flags.append("HardLogic") + + if "HardLogicAndDoubleJump" in flags: + temp_flags.append("HardLogicAndDoubleJump") + + if "EnemySkips" in flags: + temp_flags.append("EnemySkips") + + if "EnemySkipsAndDoubleJump" in flags: + temp_flags.append("EnemySkipsAndDoubleJump") + + # remove duplicates + temp_flags = list(dict.fromkeys(temp_flags)) + + original_logic: str = door.get("logic") + temp_logic: str = "" + + if this_door: + temp_logic = door.get("id") + + if temp_flags != []: + if temp_logic != "": + temp_logic += " || " + temp_logic += ' && '.join(temp_flags) + + if temp_logic != "" and original_logic != None: + if len(original_logic.split()) == 1: + if len(temp_logic.split()) == 1: + door["logic"] = f"{temp_logic} && {original_logic}" + else: + door["logic"] = f"({temp_logic}) && {original_logic}" + else: + if len(temp_logic.split()) == 1: + door["logic"] = f"{temp_logic} && ({original_logic})" + else: + door["logic"] = f"({temp_logic}) && ({original_logic})" + elif temp_logic != "" and original_logic == None: + door["logic"] = temp_logic + + return door + + +def get_state_provider_for_condition(condition: List[str]) -> str: + for item in condition: + if (item[0] == "D" and item[3] == "Z" and item[6] == "S")\ + or (item[0] == "D" and item[3] == "B" and item[4] == "Z" and item[7] == "S"): + return item + return None + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser() + parser.add_argument('-l', '--local', action="store_true", help="Use local files in the same directory instead of reading resource files from the BrandenEK/Blasphemous-Randomizer repository.") + args = parser.parse_args() + return args + + +def main(args: argparse.Namespace): + doors = [] + locations = [] + + if (args.local): + doors = load_resource_local("doors.json") + locations = load_resource_local("locations_items.json") + + else: + doors = load_resource_from_web("https://raw.githubusercontent.com/BrandenEK/Blasphemous-Randomizer/main/resources/data/Randomizer/doors.json") + locations = load_resource_from_web("https://raw.githubusercontent.com/BrandenEK/Blasphemous-Randomizer/main/resources/data/Randomizer/locations_items.json") + + original_connections: Dict[str, str] = {} + rooms: Dict[str, List[str]] = {} + output: Dict[str, Any] = {} + logic_objects: List[Dict[str, Any]] = [] + + for door in doors: + if door.get("originalDoor") != None: + if not door.get("id") in original_connections: + original_connections[door.get("id")] = door.get("originalDoor") + original_connections[door.get("originalDoor")] = door.get("id") + + room: str = get_room_from_door(door.get("originalDoor")) + if not room in rooms.keys(): + rooms[room] = [door.get("id")] + else: + rooms[room].append(door.get("id")) + + def flip_doors_in_condition(condition: List[str]) -> List[str]: + new_condition = [] + for item in condition: + if item in original_connections: + new_condition.append(original_connections[item]) + else: + new_condition.append(item) + + return new_condition + + for room in rooms.keys(): + obj = { + "Name": room, + "Logic": [], + "Handling": "Default" + } + + for door in rooms[room]: + logic = { + "StateProvider": door, + "Conditions": [], + "StateModifiers": [] + } + obj["Logic"].append(logic) + + logic_objects.append(obj) + + for door in doors: + if door.get("direction") == 5: + continue + + handling: str = "Transition" + if "Cell" in door.get("id"): + handling = "Default" + obj = { + "Name": door.get("id"), + "Logic": [], + "Handling": handling + } + + visibility_flags: List[str] = [] + if door.get("visibilityFlags") != None: + visibility_flags = str(door.get("visibilityFlags")).split(", ") + if "1" in visibility_flags: + visibility_flags.remove("1") + visibility_flags.append("ThisDoor") + + required_doors: List[str] = [] + if door.get("requiredDoors"): + required_doors = door.get("requiredDoors") + + if len(visibility_flags) > 0: + for flag in visibility_flags: + if flag == "RequiredDoors": + continue + + if flag == "ThisDoor": + flag = original_connections[door.get("id")] + + if door.get("logic") != None: + logic: str = door.get("logic") + logic = f"{flag} && ({logic})" + logic = preprocess_logic(True, door.get("id"), logic) + conditions = build_logic_conditions(logic) + for condition in conditions: + condition = flip_doors_in_condition(condition) + state_provider: str = get_room_from_door(door.get("id")) + + if get_state_provider_for_condition(condition) != None: + state_provider = get_state_provider_for_condition(condition) + condition.remove(state_provider) + + logic = { + "StateProvider": state_provider, + "Conditions": condition, + "StateModifiers": [] + } + obj["Logic"].append(logic) + else: + logic = { + "StateProvider": get_room_from_door(door.get("id")), + "Conditions": [flag], + "StateModifiers": [] + } + obj["Logic"].append(logic) + + if "RequiredDoors" in visibility_flags: + for d in required_doors: + flipped = original_connections[d] + if door.get("logic") != None: + logic: str = preprocess_logic(True, door.get("id"), door.get("logic")) + conditions = build_logic_conditions(logic) + for condition in conditions: + condition = flip_doors_in_condition(condition) + state_provider: str = flipped + + if flipped in condition: + condition.remove(flipped) + + logic = { + "StateProvider": state_provider, + "Conditions": condition, + "StateModifiers": [] + } + obj["Logic"].append(logic) + else: + logic = { + "StateProvider": flipped, + "Conditions": [], + "StateModifiers": [] + } + obj["Logic"].append(logic) + + else: + if door.get("logic") != None: + logic: str = preprocess_logic(True, door.get("id"), door.get("logic")) + conditions = build_logic_conditions(logic) + for condition in conditions: + condition = flip_doors_in_condition(condition) + stateProvider: str = get_room_from_door(door.get("id")) + + if get_state_provider_for_condition(condition) != None: + stateProvider = get_state_provider_for_condition(condition) + condition.remove(stateProvider) + + logic = { + "StateProvider": stateProvider, + "Conditions": condition, + "StateModifiers": [] + } + obj["Logic"].append(logic) + else: + logic = { + "StateProvider": get_room_from_door(door.get("id")), + "Conditions": [], + "StateModifiers": [] + } + obj["Logic"].append(logic) + + logic_objects.append(obj) + + for location in locations: + obj = { + "Name": location.get("id"), + "Logic": [], + "Handling": "Location" + } + + if location.get("logic") != None: + for condition in build_logic_conditions(preprocess_logic(False, location.get("id"), location.get("logic"))): + condition = flip_doors_in_condition(condition) + stateProvider: str = location.get("room") + + if get_state_provider_for_condition(condition) != None: + stateProvider = get_state_provider_for_condition(condition) + condition.remove(stateProvider) + + if stateProvider == "Initial": + stateProvider = None + + logic = { + "StateProvider": stateProvider, + "Conditions": condition, + "StateModifiers": [] + } + obj["Logic"].append(logic) + else: + stateProvider: str = location.get("room") + if stateProvider == "Initial": + stateProvider = None + logic = { + "StateProvider": stateProvider, + "Conditions": [], + "StateModifiers": [] + } + obj["Logic"].append(logic) + + logic_objects.append(obj) + + output["LogicObjects"] = logic_objects + + with open("StringWorldDefinition.json", "w") as file: + print("Writing to StringWorldDefinition.json") + file.write(json.dumps(output, indent=4)) + + +if __name__ == "__main__": + main(parse_args()) diff --git a/worlds/blasphemous/Rooms.py b/worlds/blasphemous/Rooms.py deleted file mode 100644 index 74f245adeff7..000000000000 --- a/worlds/blasphemous/Rooms.py +++ /dev/null @@ -1,5405 +0,0 @@ -from typing import List, TypedDict - - -room_table: List[str] = [ - "D01Z01S01", # THL - "D01Z01S02", # THL - "D01Z01S03", # THL - "D01Z01S07", # THL - "D01Z02S01", # Albero - "D01Z02S02", # Albero - "D01Z02S03", # Albero - "D01Z02S04", # Albero - "D01Z02S05", # Albero - "D01Z02S06", # Albero - "D01Z02S07", # Albero - "D01BZ04S01", # Albero Church - "D01BZ06S01", # Ossuary - "D01BZ08S01", # Ossuary - isidora's room? - "D01Z03S01", # WotBC - "D01Z03S02", # WotBC - "D01Z03S03", # WotBC - "D01Z03S04", # WotBC - "D01Z03S05", # WotBC - "D01Z03S06", # WotBC - "D01Z03S07", # WotBC - "D01Z04S01", # MD - "D01Z04S02", # MD - "D01Z04S03", # MD - "D01Z04S05", # MD - "D01Z04S06", # MD - "D01Z04S07", # MD - "D01Z04S08", # MD - "D01Z04S09", # MD - "D01Z04S10", # MD - "D01Z04S11", # MD - "D01Z04S12", # MD - "D01Z04S13", # MD - "D01Z04S14", # MD - "D01Z04S15", # MD - "D01Z04S16", # MD - "D01Z04S17", # MD - "D01Z04S18", # MD - "D01Z04S19", # MD - "D01BZ02S01", # MD - shop - "D01Z05S01", # DC - "D01Z05S02", # DC - "D01Z05S03", # DC - "D01Z05S04", # DC - "D01Z05S05", # DC - "D01Z05S06", # DC - "D01Z05S07", # DC - "D01Z05S08", # DC - "D01Z05S09", # DC - "D01Z05S10", # DC - "D01Z05S11", # DC - "D01Z05S12", # DC - "D01Z05S13", # DC - "D01Z05S14", # DC - "D01Z05S15", # DC - "D01Z05S16", # DC - "D01Z05S17", # DC - "D01Z05S18", # DC - "D01Z05S19", # DC - "D01Z05S20", # DC - "D01Z05S21", # DC - "D01Z05S22", # DC - "D01Z05S23", # DC - "D01Z05S24", # DC - "D01Z05S25", # DC - "D01Z05S26", # DC - "D01Z05S27", # DC - "D01BZ05S01", # DC - shroud of dreamt sins room? - "D01BZ09S01", # DC - arcade room - "D01Z06S01", # Petrous - "D01BZ07S01", # Petrous - Jibrael - "D02Z01S01", # WOTW - "D02Z01S02", # WOTW - "D02Z01S03", # WOTW - "D02Z01S04", # WOTW - "D02Z01S05", # WOTW - "D02Z01S06", # WOTW - "D02Z01S08", # WOTW - "D02Z01S09", # WOTW - "D02Z02S01", # GOTP - "D02Z02S02", # GOTP - "D02Z02S03", # GOTP - "D02Z02S04", # GOTP - "D02Z02S05", # GOTP - "D02Z02S06", # GOTP - "D02Z02S07", # GOTP - "D02Z02S08", # GOTP - "D02Z02S09", # GOTP - "D02Z02S10", # GOTP - "D02Z02S11", # GOTP - "D02Z02S12", # GOTP - "D02Z02S13", # GOTP - "D02Z02S14", # GOTP - "D02BZ02S01", # GOTP - shop - "D02Z03S01", # COOLOTCV - "D02Z03S02", # COOLOTCV - "D02Z03S03", # COOLOTCV - "D02Z03S05", # COOLOTCV - "D02Z03S06", # COOLOTCV - "D02Z03S07", # COOLOTCV - "D02Z03S08", # COOLOTCV - "D02Z03S09", # COOLOTCV - "D02Z03S10", # COOLOTCV - "D02Z03S11", # COOLOTCV - "D02Z03S12", # COOLOTCV - "D02Z03S13", # COOLOTCV - "D02Z03S14", # COOLOTCV - "D02Z03S15", # COOLOTCV - "D02Z03S16", # COOLOTCV - "D02Z03S17", # COOLOTCV - "D02Z03S18", # COOLOTCV - "D02Z03S19", # COOLOTCV - "D02Z03S20", # COOLOTCV - "D02Z03S21", # COOLOTCV - "D02Z03S22", # COOLOTCV - "D02Z03S23", # COOLOTCV - "D02Z03S24", # COOLOTCV - "D03Z01S01", # MOTED - "D03Z01S02", # MOTED - "D03Z01S03", # MOTED - "D03Z01S04", # MOTED - "D03Z01S05", # MOTED - "D03Z01S06", # MOTED - "D03Z02S01", # Jondo - "D03Z02S02", # Jondo - "D03Z02S03", # Jondo - "D03Z02S04", # Jondo - "D03Z02S05", # Jondo - "D03Z02S06", # Jondo - "D03Z02S07", # Jondo - "D03Z02S08", # Jondo - "D03Z02S09", # Jondo - "D03Z02S10", # Jondo - "D03Z02S11", # Jondo - "D03Z02S12", # Jondo - "D03Z02S13", # Jondo - "D03Z02S14", # Jondo - "D03Z02S15", # Jondo - "D03Z03S01", # GA - "D03Z03S02", # GA - "D03Z03S03", # GA - "D03Z03S04", # GA - "D03Z03S05", # GA - "D03Z03S06", # GA - "D03Z03S07", # GA - "D03Z03S08", # GA - "D03Z03S09", # GA - "D03Z03S10", # GA - "D03Z03S11", # GA - "D03Z03S12", # GA - "D03Z03S13", # GA - "D03Z03S14", # GA - "D03Z03S15", # GA - "D03Z03S16", # GA - "D03Z03S17", # GA - "D03Z03S18", # GA - "D03Z03S19", # GA - "D04Z01S01", # POTSS - "D04Z01S02", # POTSS - "D04Z01S03", # POTSS - "D04Z01S04", # POTSS - "D04Z01S05", # POTSS - "D04Z01S06", # POTSS - "D04Z02S01", # MOM - "D04Z02S02", # MOM - "D04Z02S03", # MOM - "D04Z02S04", # MOM - "D04Z02S05", # MOM - "D04Z02S06", # MOM - "D04Z02S07", # MOM - "D04Z02S08", # MOM - "D04Z02S09", # MOM - "D04Z02S10", # MOM - "D04Z02S11", # MOM - "D04Z02S12", # MOM - "D04Z02S13", # MOM - "D04Z02S14", # MOM - "D04Z02S15", # MOM - "D04Z02S16", # MOM - "D04Z02S17", # MOM - "D04Z02S19", # MOM - "D04Z02S20", # MOM - "D04Z02S21", # MOM - "D04Z02S22", # MOM - "D04Z02S23", # MOM - "D04Z02S24", # MOM - "D04Z02S25", # MOM - "D04BZ02S01", # MOM - Redento - "D04Z03S01", # KOTTW - "D04Z03S02", # KOTTW - "D04Z04S01", # ATTOTS - "D04Z04S02", # ATTOTS - "D05Z01S01", # LOTNW - "D05Z01S02", # LOTNW - "D05Z01S03", # LOTNW - "D05Z01S04", # LOTNW - "D05Z01S05", # LOTNW - "D05Z01S06", # LOTNW - "D05Z01S07", # LOTNW - "D05Z01S08", # LOTNW - "D05Z01S09", # LOTNW - "D05Z01S10", # LOTNW - "D05Z01S11", # LOTNW - "D05Z01S12", # LOTNW - "D05Z01S13", # LOTNW - "D05Z01S14", # LOTNW - "D05Z01S15", # LOTNW - "D05Z01S16", # LOTNW - "D05Z01S17", # LOTNW - "D05Z01S18", # LOTNW - "D05Z01S19", # LOTNW - "D05Z01S20", # LOTNW - "D05Z01S21", # LOTNW - "D05Z01S22", # LOTNW - "D05Z01S23", # LOTNW - "D05Z01S24", # LOTNW - "D05BZ01S01", # LOTNW - secret entrance to KOTTW? - "D05Z02S01", # TSC - "D05Z02S02", # TSC - "D05Z02S03", # TSC - "D05Z02S04", # TSC - "D05Z02S05", # TSC - "D05Z02S06", # TSC - "D05Z02S07", # TSC - "D05Z02S08", # TSC - "D05Z02S09", # TSC - "D05Z02S10", # TSC - "D05Z02S11", # TSC - "D05Z02S12", # TSC - "D05Z02S13", # TSC - "D05Z02S14", # TSC - "D05Z02S15", # TSC - "D05BZ02S01", # TSC - shop - "D06Z01S01", # AR - "D06Z01S02", # AR - "D06Z01S03", # AR - "D06Z01S04", # AR - "D06Z01S05", # AR - "D06Z01S06", # AR - "D06Z01S07", # AR - "D06Z01S08", # AR - "D06Z01S09", # AR - "D06Z01S10", # AR - "D06Z01S11", # AR - "D06Z01S12", # AR - "D06Z01S13", # AR - "D06Z01S14", # AR - "D06Z01S15", # AR - "D06Z01S16", # AR - "D06Z01S17", # AR - "D06Z01S18", # AR - "D06Z01S19", # AR - "D06Z01S20", # AR - "D06Z01S21", # AR - "D06Z01S22", # AR - "D06Z01S23", # AR - "D06Z01S24", # AR - "D06Z01S25", # AR - "D06Z01S26", # AR - "D07Z01S01", # DOHH? - "D07Z01S02", # DOHH? - "D07Z01S03", # DOHH? - "D08Z01S01", # BOTTC - "D08Z01S02", # BOTTC - "D08Z02S01", # FT - "D08Z02S02", # FT - "D08Z02S03", # FT - "D08Z03S01", # HOTD - "D08Z03S02", # HOTD - "D08Z03S03", # HOTD - "D09Z01S01", # WOTHP - "D09Z01S02", # WOTHP - "D09Z01S03", # WOTHP - "D09Z01S04", # WOTHP - "D09Z01S05", # WOTHP - "D09Z01S06", # WOTHP - "D09Z01S07", # WOTHP - "D09Z01S08", # WOTHP - "D09Z01S09", # WOTHP - "D09Z01S10", # WOTHP - "D09Z01S11", # WOTHP - "D09Z01S12", # WOTHP - "D09Z01S13", # WOTHP - "D09BZ01S01", # WOTHP - all cells - "D17Z01S01", # BOTSS - "D17Z01S02", # BOTSS - "D17Z01S03", # BOTSS - "D17Z01S04", # BOTSS - "D17Z01S05", # BOTSS - "D17Z01S06", # BOTSS - "D17Z01S07", # BOTSS - "D17Z01S08", # BOTSS - "D17Z01S09", # BOTSS - "D17Z01S10", # BOTSS - "D17Z01S11", # BOTSS - "D17Z01S12", # BOTSS - "D17Z01S13", # BOTSS - "D17Z01S14", # BOTSS - "D17Z01S15", # BOTSS - "D17BZ01S01", # BOTSS - chamber of the eldest brother - "D17BZ02S01", # BOTSS - platforming challenge - "D20Z01S01", # EOS - "D20Z01S02", # EOS - "D20Z01S03", # EOS - "D20Z01S04", # EOS - "D20Z01S05", # EOS - "D20Z01S06", # EOS - "D20Z01S07", # EOS - "D20Z01S08", # EOS - "D20Z01S09", # EOS - "D20Z01S10", # EOS - "D20Z01S11", # EOS - "D20Z01S12", # EOS - "D20Z01S13", # EOS - "D20Z01S14", # EOS - "D20Z02S01", # MAH - "D20Z02S02", # MAH - "D20Z02S03", # MAH - "D20Z02S04", # MAH - "D20Z02S05", # MAH - "D20Z02S06", # MAH - "D20Z02S07", # MAH - "D20Z02S08", # MAH - "D20Z02S09", # MAH - "D20Z02S10", # MAH - "D20Z02S11", # MAH - "D20Z02S12", # MAH - "D20Z03S01", # TRPOTS -] - - -class DoorDict(TypedDict, total=False): - Id: str - Direction: int - OriginalDoor: str - Type: int - Logic: str - VisibilityFlags: int - RequiredDoors: List[str] - - -door_table: List[DoorDict] = [ - { - "Id": "D01Z01S01[W]", - "Direction": 1, - "OriginalDoor": "D01Z01S07[E]" - }, - { - "Id": "D01Z01S01[E]", - "Direction": 2, - "OriginalDoor": "D01Z01S02[W]" - }, - { - "Id": "D01Z01S01[S]", - "Direction": 2, - "OriginalDoor": "D01Z06S01[N]", - "Type": 1, - "Logic": "D01Z01S01[S] || canBreakHoles || doubleJump" - }, - { - "Id": "D01Z01S02[W]", - "Direction": 1, - "OriginalDoor": "D01Z01S01[E]" - }, - { - "Id": "D01Z01S02[E]", - "Direction": 2, - "OriginalDoor": "D01Z01S03[W]" - }, - { - "Id": "D01Z01S03[W]", - "Direction": 1, - "OriginalDoor": "D01Z01S02[E]" - }, - { - "Id": "D01Z01S03[E]", - "Direction": 2, - "OriginalDoor": "D01Z02S01[W]", - "Type": 1 - }, - { - "Id": "D01Z01S07[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S03[E]", - "Type": 1 - }, - { - "Id": "D01Z01S07[E]", - "Direction": 2, - "OriginalDoor": "D01Z01S01[W]" - }, - - { - "Id": "D01Z02S01[W]", - "Direction": 1, - "OriginalDoor": "D01Z01S03[E]", - "Type": 1 - }, - { - "Id": "D01Z02S01[E]", - "Direction": 2, - "OriginalDoor": "D01Z02S02[W]" - }, - { - "Id": "D01Z02S02[SW]", - "Direction": 1, - "OriginalDoor": "D01Z02S06[E]" - }, - { - "Id": "D01Z02S02[SE]", - "Direction": 2, - "OriginalDoor": "D01Z02S04[W]" - }, - { - "Id": "D01Z02S02[W]", - "Direction": 1, - "OriginalDoor": "D01Z02S01[E]" - }, - { - "Id": "D01Z02S02[E]", - "Direction": 2, - "OriginalDoor": "D01Z02S03[W]" - }, - { - "Id": "D01Z02S02[NE]", - "Direction": 2, - "OriginalDoor": "D01Z02S03[NW]" - }, - { - "Id": "D01Z02S03[W]", - "Direction": 1, - "OriginalDoor": "D01Z02S02[E]" - }, - { - "Id": "D01Z02S03[NW]", - "Direction": 1, - "OriginalDoor": "D01Z02S02[NE]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D02Z02S11[NW]", "D02Z02S11[NE]", "D02Z02S11[W]", "D02Z02S11[E]", "D02Z02S11[SE]" ] - }, - { - "Id": "D01Z02S03[E]", - "Direction": 2, - "OriginalDoor": "D01Z02S05[W]" - }, - { - "Id": "D01Z02S03[church]", - "Direction": 4, - "OriginalDoor": "D01BZ04S01[church]", - "Logic": "canBeatMercyBoss || canBeatConventBoss || canBeatGrievanceBoss" - }, - { - "Id": "D01Z02S03[Cherubs]", - "Direction": 5 - }, - { - "Id": "D01Z02S04[W]", - "Direction": 1, - "OriginalDoor": "D01Z02S02[SE]" - }, - { - "Id": "D01Z02S04[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S01[N]", - "Type": 1 - }, - { - "Id": "D01Z02S04[Ossary]", - "Direction": 4, - "OriginalDoor": "D01BZ06S01[Ossary]" - }, - { - "Id": "D01Z02S05[W]", - "Direction": 1, - "OriginalDoor": "D01Z02S03[E]" - }, - { - "Id": "D01Z02S05[E]", - "Direction": 2, - "OriginalDoor": "D01Z03S01[W]", - "Type": 1 - }, - { - "Id": "D01Z02S06[W]", - "Direction": 1, - "OriginalDoor": "D01Z02S07[E]" - }, - { - "Id": "D01Z02S06[E]", - "Direction": 2, - "OriginalDoor": "D01Z02S02[SW]" - }, - { - "Id": "D01Z02S07[E]", - "Direction": 2, - "OriginalDoor": "D01Z02S06[W]" - }, - { - "Id": "D01BZ04S01[church]", - "Direction": 7, - "OriginalDoor": "D01Z02S03[church]" - }, - { - "Id": "D01BZ06S01[Ossary]", - "Direction": 7, - "OriginalDoor": "D01Z02S04[Ossary]" - }, - { - "Id": "D01BZ06S01[E]", - "Direction": 2, - "OriginalDoor": "D01BZ08S01[W]", - "Logic": "bones >= 30" - }, - { - "Id": "D01BZ08S01[W]", - "Direction": 1, - "OriginalDoor": "D01BZ06S01[E]" - }, - - { - "Id": "D01Z03S01[W]", - "Direction": 1, - "OriginalDoor": "D01Z02S05[E]", - "Type": 1 - }, - { - "Id": "D01Z03S01[E]", - "Direction": 2, - "OriginalDoor": "D01Z03S02[W]" - }, - { - "Id": "D01Z03S01[SE]", - "Direction": 2, - "OriginalDoor": "D01Z03S02[SW]", - "VisibilityFlags": 1 - }, - { - "Id": "D01Z03S02[W]", - "Direction": 1, - "OriginalDoor": "D01Z03S01[E]" - }, - { - "Id": "D01Z03S02[SW]", - "Direction": 1, - "OriginalDoor": "D01Z03S01[SE]" - }, - { - "Id": "D01Z03S02[E]", - "Direction": 2, - "OriginalDoor": "D01Z03S03[W]" - }, - { - "Id": "D01Z03S02[S]", - "Direction": 3, - "OriginalDoor": "D01Z05S05[N]", - "Type": 1, - "VisibilityFlags": 1 - }, - { - "Id": "D01Z03S03[W]", - "Direction": 1, - "OriginalDoor": "D01Z03S02[E]" - }, - { - "Id": "D01Z03S03[E]", - "Direction": 2, - "OriginalDoor": "D01Z03S04[SW]" - }, - { - "Id": "D01Z03S03[Cherubs]", - "Direction": 5 - }, - { - "Id": "D01Z03S03[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D01Z05S06[Cherubs]", - "Type": 1, - "Logic": "linen" - }, - { - "Id": "D01Z03S04[SW]", - "Direction": 1, - "OriginalDoor": "D01Z03S03[E]" - }, - { - "Id": "D01Z03S04[W]", - "Direction": 1, - "OriginalDoor": "D01Z03S07[E]" - }, - { - "Id": "D01Z03S04[NW]", - "Direction": 1, - "OriginalDoor": "D02Z01S01[SE]", - "Type": 1 - }, - { - "Id": "D01Z03S04[SE]", - "Direction": 2, - "OriginalDoor": "D01Z03S05[W]" - }, - { - "Id": "D01Z03S04[E]", - "Direction": 2, - "OriginalDoor": "D01Z03S06[W]" - }, - { - "Id": "D01Z03S05[W]", - "Direction": 1, - "OriginalDoor": "D01Z03S04[SE]" - }, - { - "Id": "D01Z03S05[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S01[NW]", - "Type": 1 - }, - { - "Id": "D01Z03S05[Cherubs]", - "Direction": 6, - "OriginalDoor": "D01Z05S11[Cherubs]", - "Type": 1, - "Logic": "linen" - }, - { - "Id": "D01Z03S06[W]", - "Direction": 1, - "OriginalDoor": "D01Z03S04[E]" - }, - { - "Id": "D01Z03S06[E]", - "Direction": 2, - "OriginalDoor": "D08Z01S01[W]", - "Type": 1 - }, - { - "Id": "D01Z03S07[E]", - "Direction": 2, - "OriginalDoor": "D01Z03S04[W]" - }, - { - "Id": "D01Z03S07[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D01Z03S03[Cherubs]", - "Logic": "linen" - }, - - { - "Id": "D01Z04S01[NW]", - "Direction": 1, - "OriginalDoor": "D01Z03S05[E]", - "Type": 1 - }, - { - "Id": "D01Z04S01[NE]", - "Direction": 2, - "OriginalDoor": "D01Z04S17[W]" - }, - { - "Id": "D01Z04S01[W]", - "Direction": 1, - "OriginalDoor": "D01Z04S03[E]" - }, - { - "Id": "D01Z04S01[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S05[NW]" - }, - { - "Id": "D01Z04S01[SE]", - "Direction": 2, - "OriginalDoor": "D01Z04S05[SW]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D01Z04S01[S]" ] - }, - { - "Id": "D01Z04S01[S]", - "Direction": 3, - "OriginalDoor": "D01Z04S15[N]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D01Z04S01[SE]" ] - }, - { - "Id": "D01Z04S02[W]", - "Direction": 1, - "OriginalDoor": "D01Z04S13[NE]" - }, - { - "Id": "D01Z04S03[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S01[W]" - }, - { - "Id": "D01Z04S05[NW]", - "Direction": 1, - "OriginalDoor": "D01Z04S01[E]" - }, - { - "Id": "D01Z04S05[SW]", - "Direction": 1, - "OriginalDoor": "D01Z04S01[SE]" - }, - { - "Id": "D01Z04S06[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S07[W]" - }, - { - "Id": "D01Z04S06[NW]", - "Direction": 1, - "OriginalDoor": "D01Z04S15[NE]" - }, - { - "Id": "D01Z04S06[SW]", - "Direction": 1, - "OriginalDoor": "D01Z04S15[E]" - }, - { - "Id": "D01Z04S07[W]", - "Direction": 1, - "OriginalDoor": "D01Z04S06[E]" - }, - { - "Id": "D01Z04S08[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S15[W]" - }, - { - "Id": "D01Z04S09[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S12[E]", - "Type": 1, - "Logic": "openedDCGateE" - }, - { - "Id": "D01Z04S09[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S15[SW]" - }, - { - "Id": "D01Z04S09[C]", - "Direction": 4, - "OriginalDoor": "D01BZ02S01[C]" - }, - { - "Id": "D01Z04S10[NW]", - "Direction": 1, - "OriginalDoor": "D01Z04S15[SE]" - }, - { - "Id": "D01Z04S10[SW]", - "Direction": 3, - "OriginalDoor": "D01Z04S11[NE]" - }, - { - "Id": "D01Z04S10[SE]", - "Direction": 3, - "OriginalDoor": "D01Z04S12[NW]" - }, - { - "Id": "D01Z04S11[NE]", - "Direction": 0, - "OriginalDoor": "D01Z04S10[SW]" - }, - { - "Id": "D01Z04S12[NW]", - "Direction": 0, - "OriginalDoor": "D01Z04S10[SE]" - }, - { - "Id": "D01Z04S12[W]", - "Direction": 1, - "OriginalDoor": "D01Z04S18[E]" - }, - { - "Id": "D01Z04S12[SE]", - "Direction": 2, - "OriginalDoor": "D01Z04S13[NW]" - }, - { - "Id": "D01Z04S13[NW]", - "Direction": 1, - "OriginalDoor": "D01Z04S12[SE]" - }, - { - "Id": "D01Z04S13[NE]", - "Direction": 2, - "OriginalDoor": "D01Z04S02[W]" - }, - { - "Id": "D01Z04S13[SW]", - "Direction": 1, - "OriginalDoor": "D01Z04S14[E]" - }, - { - "Id": "D01Z04S13[SE]", - "Direction": 2, - "OriginalDoor": "D01Z04S16[W]", - "VisibilityFlags": 5, - "Logic": "D01Z04S13[SE] || canDiveLaser && (canAirStall || wheel || doubleJump || canEnemyBounce)" - }, - { - "Id": "D01Z04S14[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S13[SW]" - }, - { - "Id": "D01Z04S15[N]", - "Direction": 0, - "OriginalDoor": "D01Z04S01[S]" - }, - { - "Id": "D01Z04S15[NE]", - "Direction": 2, - "OriginalDoor": "D01Z04S06[NW]" - }, - { - "Id": "D01Z04S15[W]", - "Direction": 1, - "OriginalDoor": "D01Z04S08[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D01Z04S15[E]", "D01Z04S15[SW]", "D01Z04S15[SE]" ] - }, - { - "Id": "D01Z04S15[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S06[SW]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D01Z04S15[W]", "D01Z04S15[SW]", "D01Z04S15[SE]" ] - }, - { - "Id": "D01Z04S15[SW]", - "Direction": 1, - "OriginalDoor": "D01Z04S09[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D01Z04S15[W]", "D01Z04S15[E]", "D01Z04S15[SE]" ] - }, - { - "Id": "D01Z04S15[SE]", - "Direction": 2, - "OriginalDoor": "D01Z04S10[NW]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D01Z04S15[W]", "D01Z04S15[E]", "D01Z04S15[SW]" ] - }, - { - "Id": "D01Z04S16[W]", - "Direction": 1, - "OriginalDoor": "D01Z04S13[SE]" - }, - { - "Id": "D01Z04S16[E]", - "Direction": 2, - "OriginalDoor": "D05Z02S12[W]", - "Type": 1 - }, - { - "Id": "D01Z04S17[W]", - "Direction": 1, - "OriginalDoor": "D01Z04S01[NE]" - }, - { - "Id": "D01Z04S18[W]", - "Direction": 1, - "OriginalDoor": "D01Z04S19[E]", - "Logic": "D01Z04S18[W] || canBeatMercyBoss" - }, - { - "Id": "D01Z04S18[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S12[W]", - "Logic": "D01Z04S18[E] || canBeatMercyBoss" - }, - { - "Id": "D01Z04S19[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S19[E]", - "Type": 1 - }, - { - "Id": "D01Z04S19[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S18[W]" - }, - { - "Id": "D01BZ02S01[C]", - "Direction": 7, - "OriginalDoor": "D01Z04S09[C]" - }, - - { - "Id": "D01Z05S01[N]", - "Direction": 1, - "OriginalDoor": "D01Z02S04[E]", - "Type": 1 - }, - { - "Id": "D01Z05S01[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S27[E]" - }, - { - "Id": "D01Z05S01[S]", - "Direction": 3, - "OriginalDoor": "D01Z05S02[N]" - }, - { - "Id": "D01Z05S02[N]", - "Direction": 0, - "OriginalDoor": "D01Z05S01[S]" - }, - { - "Id": "D01Z05S02[W]", - "Direction": 1, - "OriginalDoor": "D03Z01S01[NE]", - "Type": 1 - }, - { - "Id": "D01Z05S02[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S03[NW]", - "VisibilityFlags": 1 - }, - { - "Id": "D01Z05S02[S]", - "Direction": 3, - "OriginalDoor": "D01Z05S20[N]", - "Logic": "openedDCLadder" - }, - { - "Id": "D01Z05S03[NW]", - "Direction": 1, - "OriginalDoor": "D01Z05S02[E]" - }, - { - "Id": "D01Z05S03[NE]", - "Direction": 2, - "OriginalDoor": "D01Z05S04[W]" - }, - { - "Id": "D01Z05S03[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S07[E]" - }, - { - "Id": "D01Z05S03[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S08[W]" - }, - { - "Id": "D01Z05S03[S]", - "Direction": 3, - "OriginalDoor": "D01Z05S13[N]" - }, - { - "Id": "D01Z05S04[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S03[NE]" - }, - { - "Id": "D01Z05S04[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S05[NW]" - }, - { - "Id": "D01Z05S05[N]", - "Direction": 0, - "OriginalDoor": "D01Z03S02[S]", - "Type": 1 - }, - { - "Id": "D01Z05S05[NW]", - "Direction": 1, - "OriginalDoor": "D01Z05S04[E]" - }, - { - "Id": "D01Z05S05[NE]", - "Direction": 2, - "OriginalDoor": "D01Z05S06[W]" - }, - { - "Id": "D01Z05S05[SW]", - "Direction": 1, - "OriginalDoor": "D01Z05S18[E]" - }, - { - "Id": "D01Z05S05[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S09[NW]" - }, - { - "Id": "D01Z05S06[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S05[NE]" - }, - { - "Id": "D01Z05S06[Cherubs]", - "Direction": 5, - "Type": 1 - }, - { - "Id": "D01Z05S07[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S03[W]" - }, - { - "Id": "D01Z05S08[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S03[E]" - }, - { - "Id": "D01Z05S09[NW]", - "Direction": 1, - "OriginalDoor": "D01Z05S05[E]" - }, - { - "Id": "D01Z05S09[SE]", - "Direction": 2, - "OriginalDoor": "D01Z05S10[W]" - }, - { - "Id": "D01Z05S10[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S09[SE]" - }, - { - "Id": "D01Z05S10[NE]", - "Direction": 2, - "OriginalDoor": "D01Z05S11[W]" - }, - { - "Id": "D01Z05S10[SE]", - "Direction": 2, - "OriginalDoor": "D01Z05S12[W]" - }, - { - "Id": "D01Z05S10[S]", - "Direction": 3, - "OriginalDoor": "D01Z05S14[N]" - }, - { - "Id": "D01Z05S11[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S10[NE]" - }, - { - "Id": "D01Z05S11[Cherubs]", - "Direction": 5, - "Type": 1 - }, - { - "Id": "D01Z05S12[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S10[SE]" - }, - { - "Id": "D01Z05S12[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S09[W]", - "Type": 1 - }, - { - "Id": "D01Z05S13[SW]", - "Direction": 3, - "OriginalDoor": "D01Z05S16[N]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D01Z05S13[E]" ], - "Logic": "D01Z05S13[SW] || canSurvivePoison3 && canWaterJump" - }, - { - "Id": "D01Z05S13[N]", - "Direction": 0, - "OriginalDoor": "D01Z05S03[S]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D01Z05S13[E]" ], - "Logic": "D01Z05S13[N] || canSurvivePoison3 && canWaterJump" - }, - { - "Id": "D01Z05S13[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S14[W]", - "VisibilityFlags": 1 - }, - { - "Id": "D01Z05S14[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S13[E]" - }, - { - "Id": "D01Z05S14[N]", - "Direction": 0, - "OriginalDoor": "D01Z05S10[S]" - }, - { - "Id": "D01Z05S14[SE]", - "Direction": 2, - "OriginalDoor": "D01Z05S15[W]" - }, - { - "Id": "D01Z05S15[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S14[SE]" - }, - { - "Id": "D01Z05S15[SW]", - "Direction": 1, - "OriginalDoor": "D01Z05S22[E]" - }, - { - "Id": "D01Z05S15[SE]", - "Direction": 2, - "OriginalDoor": "D01Z05S19[W]" - }, - { - "Id": "D01Z05S16[N]", - "Direction": 0, - "OriginalDoor": "D01Z05S13[SW]" - }, - { - "Id": "D01Z05S16[SW]", - "Direction": 1, - "OriginalDoor": "D01Z05S21[E]" - }, - { - "Id": "D01Z05S16[SE]", - "Direction": 2, - "OriginalDoor": "D01Z05S17[W]" - }, - { - "Id": "D01Z05S17[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S16[SE]" - }, - { - "Id": "D01Z05S17[E]", - "Direction": 2, - "OriginalDoor": "D01BZ09S01[W]", - "Logic": "dash && (D01Z05S17[E] || canWaterJump || canCrossGap5)" - }, - { - "Id": "D01Z05S18[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S05[SW]" - }, - { - "Id": "D01Z05S19[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S15[SE]" - }, - { - "Id": "D01Z05S19[E]", - "Direction": 2, - "OriginalDoor": "D01Z04S19[W]", - "Type": 1 - }, - { - "Id": "D01Z05S20[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S25[NE]" - }, - { - "Id": "D01Z05S20[N]", - "Direction": 0, - "OriginalDoor": "D01Z05S02[S]" - }, - { - "Id": "D01Z05S21[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S25[E]" - }, - { - "Id": "D01Z05S21[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S16[SW]" - }, - { - "Id": "D01Z05S21[Reward]", - "Direction": 4, - "OriginalDoor": "D01BZ05S01[Reward]", - "Logic": "shroud" - }, - { - "Id": "D01Z05S22[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S15[SW]" - }, - { - "Id": "D01Z05S23[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S24[E]", - "Logic": "chalice && chaliceRooms >= 3" - }, - { - "Id": "D01Z05S23[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S25[W]" - }, - { - "Id": "D01Z05S24[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S04[E]", - "Type": 1 - }, - { - "Id": "D01Z05S24[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S23[W]" - }, - { - "Id": "D01Z05S25[NE]", - "Direction": 2, - "OriginalDoor": "D01Z05S20[W]", - "Logic": "D01Z05S25[SW] || D01Z05S25[SE] || D01Z05S25[NE] || linen" - }, - { - "Id": "D01Z05S25[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S23[E]", - "Logic": "D01Z05S25[W] || (linen && (canWalkOnRoot || doubleJump || canAirStall)) || (D01Z05S25[E] && (canWalkOnRoot || canCrossGap3))" - }, - { - "Id": "D01Z05S25[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S21[W]", - "VisibiliyFlags": 5, - "Logic": "D01Z05S25[E] || canBreakTirana && (linen || D01Z05S25[W] && (canWalkOnRoot || canCrossGap3))" - }, - { - "Id": "D01Z05S25[SW]", - "Direction": 1, - "OriginalDoor": "D03Z03S17[E]", - "Type": 1, - "Logic": "D01Z05S25[SW] || D01Z05S25[SE] || D01Z05S25[NE] || linen" - }, - { - "Id": "D01Z05S25[SE]", - "Direction": 2, - "OriginalDoor": "D01Z05S26[W]", - "Logic": "D01Z05S25[SW] || D01Z05S25[SE] || D01Z05S25[NE] || linen" - }, - { - "Id": "D01Z05S25[EchoesW]", - "Direction": 1, - "OriginalDoor": "D20Z01S09[E]", - "Type": 1, - "VisibilityFlags": 11, - "RequiredDoors": [ "D01Z05S25[EchoesE]" ], - "Logic": "D01Z05S25[EchoesW] || (D01Z05S25[EchoesE] && (blood || canCrossGap8)) || (linen && doubleJump)" - }, - { - "Id": "D01Z05S25[EchoesE]", - "Direction": 2, - "OriginalDoor": "D20Z01S10[W]", - "Type": 1, - "VisibilityFlags": 11, - "RequiredDoors": [ "D01Z05S25[EchoesW]" ], - "Logic": "D01Z05S25[EchoesE] || (D01Z05S25[EchoesW] && (blood || canCrossGap8)) || (linen && doubleJump)" - }, - { - "Id": "D01Z05S26[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S25[SE]" - }, - { - "Id": "D01Z05S27[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S01[W]" - }, - { - "Id": "D01BZ05S01[Reward]", - "Direction": 7, - "OriginalDoor": "D01Z05S21[Reward]" - }, - { - "Id": "D01BZ09S01[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S17[E]" - }, - - { - "Id": "D01Z06S01[N]", - "Direction": 1, - "OriginalDoor": "D01Z01S01[S]", - "Type": 1 - }, - { - "Id": "D01Z06S01[Santos]", - "Direction": 4, - "OriginalDoor": "D01BZ07S01[Santos]", - "Logic": "bell" - }, - { - "Id": "D01BZ07S01[Santos]", - "Direction": 7, - "OriginalDoor": "D01Z06S01[Santos]" - }, - - { - "Id": "D02Z01S01[SW]", - "Direction": 1, - "OriginalDoor": "D02Z01S06[E]", - "Logic": "openedWOTWCave && (D02Z01S01[W] || D02Z01S01[CherubsL] || D02Z01S01[SW] || D02Z01S01[CherubsR] || doubleJump || wallClimb)" - }, - { - "Id": "D02Z01S01[W]", - "Direction": 1, - "OriginalDoor": "D02Z01S02[E]", - "Logic": "D02Z01S01[W] || D02Z01S01[CherubsL] || wallClimb || doubleJump || ((D02Z01S01[SW] || D02Z01S01[CherubsR]) && canDawnJump)" - }, - { - "Id": "D02Z01S01[SE]", - "Direction": 2, - "OriginalDoor": "D01Z03S04[NW]", - "Type": 1 - }, - { - "Id": "D02Z01S01[CherubsL]", - "Direction": 5 - }, - { - "Id": "D02Z01S01[CherubsR]", - "Direction": 5 - }, - { - "Id": "D02Z01S02[W]", - "Direction": 1, - "OriginalDoor": "D02Z01S04[E]" - }, - { - "Id": "D02Z01S02[NW]", - "Direction": 1, - "OriginalDoor": "D02Z01S03[SE]", - "Logic": "D02Z01S02[NW] || wallClimb || doubleJump || (D02Z01S02[NE] && canWalkOnRoot && canCrossGap5)" - }, - { - "Id": "D02Z01S02[E]", - "Direction": 2, - "OriginalDoor": "D02Z01S01[W]" - }, - { - "Id": "D02Z01S02[NE]", - "Direction": 2, - "OriginalDoor": "D02Z01S09[W]", - "Logic": "D02Z01S02[NE] || (doubleJump && canEnemyBounce) || (D02Z01S02[NW] || wallClimb || doubleJump) && (canWalkOnRoot || canCrossGap10)" - }, - { - "Id": "D02Z01S02[]", - "Direction": 6, - "OriginalDoor": "D02Z01S06[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D02Z01S03[SW]", - "Direction": 1, - "OriginalDoor": "D02Z01S05[E]" - }, - { - "Id": "D02Z01S03[W]", - "Direction": 1, - "OriginalDoor": "D02Z02S01[E]", - "Type": 1, - "Logic": "D02Z01S03[W] || D02Z01S03[SE] || D02Z01S03[Cherubs] || wallClimb" - }, - { - "Id": "D02Z01S03[SE]", - "Direction": 2, - "OriginalDoor": "D02Z01S02[NW]", - "Logic": "D02Z01S03[W] || D02Z01S03[SE] || D02Z01S03[Cherubs] || wallClimb" - }, - { - "Id": "D02Z01S03[Cherubs]", - "Direction": 5 - }, - { - "Id": "D02Z01S04[E]", - "Direction": 2, - "OriginalDoor": "D02Z01S02[W]" - }, - { - "Id": "D02Z01S04[-N]", - "Direction": 6, - "OriginalDoor": "D02Z01S08[N]", - "Logic": "fullThimble && (D02Z01S01[W] || D02Z01S01[CherubsL] || wallClimb || doubleJump || ((D02Z01S01[SW] || D02Z01S01[CherubsR]) && canDawnJump))" - }, - { - "Id": "D02Z01S05[E]", - "Direction": 2, - "OriginalDoor": "D02Z01S03[SW]" - }, - { - "Id": "D02Z01S06[W]", - "Direction": 1, - "OriginalDoor": "D02Z01S08[E]", - "Logic": "D02Z01S06[W] || dash || wallClimb && doubleJump" - }, - { - "Id": "D02Z01S06[E]", - "Direction": 2, - "OriginalDoor": "D02Z01S01[SW]", - "Logic": "D02Z01S06[E] || wallClimb" - }, - { - "Id": "D02Z01S06[Cherubs]", - "Direction": 5 - }, - { - "Id": "D02Z01S08[E]", - "Direction": 2, - "OriginalDoor": "D02Z01S06[W]" - }, - { - "Id": "D02Z01S08[N]", - "Direction": 5 - }, - { - "Id": "D02Z01S09[W]", - "Direction": 1, - "OriginalDoor": "D02Z01S02[NE]" - }, - { - "Id": "D02Z01S09[-CherubsL]", - "Direction": 6, - "OriginalDoor": "D02Z01S01[CherubsL]", - "Logic": "linen" - }, - { - "Id": "D02Z01S09[-CherubsR]", - "Direction": 6, - "OriginalDoor": "D02Z01S01[CherubsR]", - "Logic": "linen && (canWalkOnRoot || canCrossGap2 || canEnemyBounce && canAirStall)" - }, - - { - "Id": "D02Z02S01[W]", - "Direction": 1, - "OriginalDoor": "D02Z02S08[E]", - "Logic": "D02Z02S01[W] || D02Z02S01[NW] || D02Z02S01[Cherubs] || dash" - }, - { - "Id": "D02Z02S01[NW]", - "Direction": 1, - "OriginalDoor": "D02Z02S02[SE]", - "Logic": "D02Z02S01[NW] || D02Z02S01[Cherubs] || wallClimb && (D02Z02S01[W] || dash)" - }, - { - "Id": "D02Z02S01[E]", - "Direction": 2, - "OriginalDoor": "D02Z01S03[W]", - "Type": 1, - "Logic": "D02Z02S01[E] || D02Z02S01[NW] || D02Z02S01[Cherubs] || wallClimb || dash" - }, - { - "Id": "D02Z02S01[Cherubs]", - "Direction": 5 - }, - { - "Id": "D02Z02S02[SE]", - "Direction": 2, - "OriginalDoor": "D02Z02S01[NW]" - }, - { - "Id": "D02Z02S02[NW]", - "Direction": 1, - "OriginalDoor": "D02Z02S04[SE]", - "Logic": "D02Z02S02[NW] || D02Z02S02[NE] || D02Z02S02[CherubsL] || D02Z02S02[CherubsR] || wallClimb" - }, - { - "Id": "D02Z02S02[NE]", - "Direction": 2, - "OriginalDoor": "D02Z02S03[SW]", - "Logic": "D02Z02S02[NW] || D02Z02S02[NE] || D02Z02S02[CherubsL] || D02Z02S02[CherubsR] || wallClimb" - }, - { - "Id": "D02Z02S02[-CherubsR]", - "Direction": 6, - "OriginalDoor": "D02Z02S08[CherubsR]", - "Logic": "linen" - }, - { - "Id": "D02Z02S02[CherubsL]", - "Direction": 5 - }, - { - "Id": "D02Z02S02[CherubsR]", - "Direction": 5 - }, - { - "Id": "D02Z02S03[SW]", - "Direction": 1, - "OriginalDoor": "D02Z02S02[NE]" - }, - { - "Id": "D02Z02S03[NW]", - "Direction": 1, - "OriginalDoor": "D02Z02S05[SE]", - "Logic": "D02Z02S03[NW] || doubleJump || wallClimb || D02Z02S03[NE] && canWalkOnRoot" - }, - { - "Id": "D02Z02S03[NE]", - "Direction": 2, - "OriginalDoor": "D02Z02S14[W]", - "Logic": "D02Z02S03[NE] || wallClimb && (canCrossGap11 || (blood && (canWalkOnRoot || canCrossGap7)) || (canWalkOnRoot && (doubleJump || canAirStall)))" - }, - { - "Id": "D02Z02S03[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D02Z02S01[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D02Z02S04[W]", - "Direction": 1, - "OriginalDoor": "D02Z02S09[E]", - "Logic": "D02Z02S04[NE] || D02Z02S04[W] || D02Z02S04[E] && dash || D02Z02S04[SE] && (wallClimb || doubleJump && canEnemyUpslash)" - }, - { - "Id": "D02Z02S04[SE]", - "Direction": 2, - "OriginalDoor": "D02Z02S02[NW]", - "Logic": "D02Z02S04[NE] || D02Z02S04[W] || D02Z02S04[SE] || dash" - }, - { - "Id": "D02Z02S04[E]", - "Direction": 2, - "OriginalDoor": "D02Z02S05[SW]", - "VisibilityFlags": 1 - }, - { - "Id": "D02Z02S04[NE]", - "Direction": 2, - "OriginalDoor": "D02Z02S05[W]", - "Logic": "D02Z02S04[NE] || ((D02Z02S04[W] || D02Z02S04[E] && dash) && (doubleJump || wallClimb)) || (D02Z02S04[SE] && (wallClimb || doubleJump && canEnemyUpslash))" - }, - { - "Id": "D02Z02S04[-CherubsL]", - "Direction": 6, - "OriginalDoor": "D02Z02S08[CherubsL]", - "Logic": "linen && (D02Z02S04[NE] || D02Z02S04[W] || D02Z02S04[SE] || dash)" - }, - { - "Id": "D02Z02S05[SW]", - "Direction": 1, - "OriginalDoor": "D02Z02S04[E]" - }, - { - "Id": "D02Z02S05[W]", - "Direction": 1, - "OriginalDoor": "D02Z02S04[NE]", - "VisibilityFlags": 65, - "Logic": "D02Z02S05[W] || doubleJump && canEnemyBounce" - }, - { - "Id": "D02Z02S05[SE]", - "Direction": 2, - "OriginalDoor": "D02Z02S03[NW]" - }, - { - "Id": "D02Z02S05[E]", - "Direction": 2, - "OriginalDoor": "D02Z02S10[W]", - "Logic": "D02Z02S05[NW] || D02Z02S05[E] || wallClimb" - }, - { - "Id": "D02Z02S05[NW]", - "Direction": 1, - "OriginalDoor": "D02Z02S07[E]", - "Logic": "D02Z02S05[NW] || wallClimb" - }, - { - "Id": "D02Z02S05[-CherubsL]", - "Direction": 6, - "OriginalDoor": "D02Z02S02[CherubsL]", - "Logic": "linen" - }, - { - "Id": "D02Z02S05[-CherubsR]", - "Direction": 6, - "OriginalDoor": "D02Z02S02[CherubsR]", - "Logic": "linen" - }, - { - "Id": "D02Z02S06[E]", - "Direction": 2, - "OriginalDoor": "D02Z02S11[W]" - }, - { - "Id": "D02Z02S07[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S01[E]", - "Type": 1 - }, - { - "Id": "D02Z02S07[E]", - "Direction": 2, - "OriginalDoor": "D02Z02S05[NW]" - }, - { - "Id": "D02Z02S07[Cherubs]", - "Direction": 5 - }, - { - "Id": "D02Z02S08[W]", - "Direction": 1, - "OriginalDoor": "D02Z02S11[SE]" - }, - { - "Id": "D02Z02S08[E]", - "Direction": 2, - "OriginalDoor": "D02Z02S01[W]" - }, - { - "Id": "D02Z02S08[C]", - "Direction": 4, - "OriginalDoor": "D02BZ02S01[C]" - }, - { - "Id": "D02Z02S08[CherubsL]", - "Direction": 5 - }, - { - "Id": "D02Z02S08[CherubsR]", - "Direction": 5 - }, - { - "Id": "D02Z02S09[E]", - "Direction": 2, - "OriginalDoor": "D02Z02S04[W]" - }, - { - "Id": "D02Z02S10[W]", - "Direction": 1, - "OriginalDoor": "D02Z02S05[E]" - }, - { - "Id": "D02Z02S11[W]", - "Direction": 1, - "OriginalDoor": "D02Z02S06[E]" - }, - { - "Id": "D02Z02S11[SE]", - "Direction": 2, - "OriginalDoor": "D02Z02S08[W]" - }, - { - "Id": "D02Z02S11[E]", - "Direction": 2, - "OriginalDoor": "D02Z02S12[W]", - "Logic": "D02Z02S11[E] || D02Z02S11[NW] || D02Z02S11[NE] || canCrossGap6" - }, - { - "Id": "D02Z02S11[NW]", - "Direction": 1, - "OriginalDoor": "D02Z03S14[E]", - "Type": 1, - "VisibilityFlags": 3, - "RequiredDoors": [ "D02Z02S11[NE]" ] - }, - { - "Id": "D02Z02S11[NE]", - "Direction": 2, - "OriginalDoor": "D02Z02S13[W]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D02Z02S11[NW]" ] - }, - { - "Id": "D02Z02S11[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D01Z02S03[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D02Z02S12[W]", - "Direction": 1, - "OriginalDoor": "D02Z02S11[E]" - }, - { - "Id": "D02Z02S13[W]", - "Direction": 1, - "OriginalDoor": "D02Z02S11[NE]" - }, - { - "Id": "D02Z02S14[W]", - "Direction": 1, - "OriginalDoor": "D02Z02S03[NE]" - }, - { - "Id": "D02Z02S14[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D02Z01S03[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D02BZ02S01[C]", - "Direction": 7, - "OriginalDoor": "D02Z02S08[C]" - }, - - { - "Id": "D02Z03S01[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S08[E]" - }, - { - "Id": "D02Z03S01[E]", - "Direction": 2, - "OriginalDoor": "D02Z02S07[W]", - "Type": 1 - }, - { - "Id": "D02Z03S02[S]", - "Direction": 3, - "OriginalDoor": "D02Z03S16[N]" - }, - { - "Id": "D02Z03S02[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S03[E]", - "Logic": "D02Z03S02[NW] || D02Z03S02[NE] || D02Z03S02[N] || D02Z03S02[W] || doubleJump || wallClimb" - }, - { - "Id": "D02Z03S02[NW]", - "Direction": 1, - "OriginalDoor": "D02Z03S21[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D02Z03S02[NE]", "D02Z03S02[N]" ] - }, - { - "Id": "D02Z03S02[NE]", - "Direction": 2, - "OriginalDoor": "D02Z03S13[W]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D02Z03S02[NW]", "D02Z03S02[N]" ] - }, - { - "Id": "D02Z03S02[N]", - "Direction": 0, - "OriginalDoor": "D02Z03S11[S]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D02Z03S02[NW]", "D02Z03S02[NE]" ], - "Logic": "openedConventLadder" - }, - { - "Id": "D02Z03S03[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S05[E]" - }, - { - "Id": "D02Z03S03[NW]", - "Direction": 1, - "OriginalDoor": "D02Z03S05[NE]", - "Logic": "D02Z03S03[NW] || blood || canCrossGap3" - }, - { - "Id": "D02Z03S03[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S02[W]" - }, - { - "Id": "D02Z03S05[S]", - "Direction": 3, - "OriginalDoor": "D02Z03S07[N]", - "Logic": "D02Z03S05[S] || D02Z03S05[NE] || wallClimb" - }, - { - "Id": "D02Z03S05[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S03[W]" - }, - { - "Id": "D02Z03S05[NE]", - "Direction": 2, - "OriginalDoor": "D02Z03S03[NW]", - "Logic": "D02Z03S05[S] || D02Z03S05[NE] || wallClimb || doubleJump" - }, - { - "Id": "D02Z03S06[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S18[SE]" - }, - { - "Id": "D02Z03S06[S]", - "Direction": 3, - "OriginalDoor": "D02Z03S07[NW]" - }, - { - "Id": "D02Z03S07[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S17[E]" - }, - { - "Id": "D02Z03S07[NWW]", - "Direction": 1, - "OriginalDoor": "D02Z03S24[E]" - }, - { - "Id": "D02Z03S07[NW]", - "Direction": 0, - "OriginalDoor": "D02Z03S06[S]" - }, - { - "Id": "D02Z03S07[N]", - "Direction": 0, - "OriginalDoor": "D02Z03S05[S]" - }, - { - "Id": "D02Z03S07[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S08[W]" - }, - { - "Id": "D02Z03S08[SW]", - "Direction": 1, - "OriginalDoor": "D02Z03S12[E]" - }, - { - "Id": "D02Z03S08[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S07[E]", - "VisibilityFlags": 1 - }, - { - "Id": "D02Z03S08[SE]", - "Direction": 2, - "OriginalDoor": "D02Z03S14[W]" - }, - { - "Id": "D02Z03S08[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S01[W]" - }, - { - "Id": "D02Z03S08[NE]", - "Direction": 2, - "OriginalDoor": "D02Z03S16[W]" - }, - { - "Id": "D02Z03S09[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S18[NE]" - }, - { - "Id": "D02Z03S09[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S20[W]" - }, - { - "Id": "D02Z03S10[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S11[E]" - }, - { - "Id": "D02Z03S10[-W]", - "Direction": 2, - "OriginalDoor": "D09Z01S06[-E]", - "Type": 1 - }, - { - "Id": "D02Z03S10[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D02Z02S07[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D02Z03S11[S]", - "Direction": 3, - "OriginalDoor": "D02Z03S02[N]" - }, - { - "Id": "D02Z03S11[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S15[E]" - }, - { - "Id": "D02Z03S11[NW]", - "Direction": 1, - "OriginalDoor": "D02Z03S19[E]" - }, - { - "Id": "D02Z03S11[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S10[W]" - }, - { - "Id": "D02Z03S11[NE]", - "Direction": 2, - "OriginalDoor": "D02Z03S22[W]" - }, - { - "Id": "D02Z03S12[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S08[SW]" - }, - { - "Id": "D02Z03S13[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S02[NE]" - }, - { - "Id": "D02Z03S14[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S08[SE]" - }, - { - "Id": "D02Z03S14[E]", - "Direction": 2, - "OriginalDoor": "D02Z02S11[NW]", - "Type": 1 - }, - { - "Id": "D02Z03S15[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S11[W]" - }, - { - "Id": "D02Z03S16[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S08[NE]" - }, - { - "Id": "D02Z03S16[N]", - "Direction": 0, - "OriginalDoor": "D02Z03S02[S]" - }, - { - "Id": "D02Z03S17[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S07[W]" - }, - { - "Id": "D02Z03S18[NW]", - "Direction": 1, - "OriginalDoor": "D02Z03S23[E]", - "Logic": "D02Z03S18[NW] || D02Z03S18[NE] || wallClimb" - }, - { - "Id": "D02Z03S18[SE]", - "Direction": 2, - "OriginalDoor": "D02Z03S06[W]" - }, - { - "Id": "D02Z03S18[NE]", - "Direction": 2, - "OriginalDoor": "D02Z03S09[W]", - "Logic": "D02Z03S18[NW] || D02Z03S18[NE] || wallClimb" - }, - { - "Id": "D02Z03S19[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S11[NW]" - }, - { - "Id": "D02Z03S20[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S09[E]", - "Logic": "D02Z03S20[W] || canBeatConventBoss" - }, - { - "Id": "D02Z03S20[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S21[W]", - "Logic": "D02Z03S20[E] || canBeatConventBoss" - }, - { - "Id": "D02Z03S21[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S20[E]" - }, - { - "Id": "D02Z03S21[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S02[NW]" - }, - { - "Id": "D02Z03S22[W]", - "Direction": 1, - "OriginalDoor": "D02Z03S11[NE]" - }, - { - "Id": "D02Z03S23[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S18[NW]" - }, - { - "Id": "D02Z03S24[E]", - "Direction": 2, - "OriginalDoor": "D02Z03S07[NWW]" - }, - - { - "Id": "D03Z01S01[W]", - "Direction": 1, - "OriginalDoor": "D03Z01S02[E]" - }, - { - "Id": "D03Z01S01[NE]", - "Direction": 2, - "OriginalDoor": "D01Z05S02[W]", - "Type": 1 - }, - { - "Id": "D03Z01S01[S]", - "Direction": 3, - "OriginalDoor": "D20Z01S03[N]", - "Type": 1, - "VisibilityFlags": 1 - }, - { - "Id": "D03Z01S01[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D20Z01S01[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D03Z01S02[W]", - "Direction": 1, - "OriginalDoor": "D03Z01S06[E]", - "Logic": "D03Z01S02[W] || wallClimb || canCrossGap3" - }, - { - "Id": "D03Z01S02[E]", - "Direction": 2, - "OriginalDoor": "D03Z01S01[W]", - "Logic": "D03Z01S02[E] || wallClimb || canCrossGap7" - }, - { - "Id": "D03Z01S03[W]", - "Direction": 1, - "OriginalDoor": "D03Z01S04[E]", - "Logic": "D03Z01S03[W] || wallClimb && (D03Z01S03[SW] || canCrossGap9)" - }, - { - "Id": "D03Z01S03[E]", - "Direction": 2, - "OriginalDoor": "D03Z01S06[W]", - "Logic": "D03Z01S03[E] || wallClimb" - }, - { - "Id": "D03Z01S03[SW]", - "Direction": 3, - "OriginalDoor": "D03Z02S10[N]", - "Type": 1, - "Logic": "D03Z01S03[W] || D03Z01S03[SW] || canCrossGap9" - }, - { - "Id": "D03Z01S03[SE]", - "Direction": 3, - "OriginalDoor": "D03Z02S01[N]", - "Type": 1 - }, - { - "Id": "D03Z01S03[-WestL]", - "Direction": 6, - "OriginalDoor": "D03Z02S10[Cherubs]", - "Type": 1, - "Logic": "linen && (D03Z01S03[W] || D03Z01S03[SW] || canCrossGap9)" - }, - { - "Id": "D03Z01S03[-WestR]", - "Direction": 6, - "OriginalDoor": "D03Z02S02[CherubsL]", - "Type": 1, - "Logic": "linen && (D03Z01S03[W] || D03Z01S03[SW] || canCrossGap9)" - }, - { - "Id": "D03Z01S03[-EastL]", - "Direction": 6, - "OriginalDoor": "D03Z02S02[CherubsR]", - "Type": 1, - "Logic": "linen && (D03Z01S03[W] || D03Z01S03[SW] || canCrossGap5)" - }, - { - "Id": "D03Z01S03[-EastR]", - "Direction": 6, - "OriginalDoor": "D03Z02S01[Cherubs]", - "Type": 1, - "Logic": "linen" - }, - { - "Id": "D03Z01S04[NW]", - "Direction": 1, - "OriginalDoor": "D03Z01S05[E]" - }, - { - "Id": "D03Z01S04[E]", - "Direction": 2, - "OriginalDoor": "D03Z01S03[W]" - }, - { - "Id": "D03Z01S05[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S07[SE]", - "Type": 1 - }, - { - "Id": "D03Z01S05[E]", - "Direction": 2, - "OriginalDoor": "D03Z01S04[NW]" - }, - { - "Id": "D03Z01S06[W]", - "Direction": 1, - "OriginalDoor": "D03Z01S03[E]", - "Logic": "D03Z01S06[W] || canBeatPerpetua" - }, - { - "Id": "D03Z01S06[E]", - "Direction": 2, - "OriginalDoor": "D03Z01S02[W]", - "Logic": "D03Z01S06[E] || canBeatPerpetua" - }, - - { - "Id": "D03Z02S01[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S02[E]", - "Logic": "D03Z02S01[W] || wallClimb || doubleJump && canEnemyBounce" - }, - { - "Id": "D03Z02S01[N]", - "Direction": 0, - "OriginalDoor": "D03Z01S03[SE]", - "Type": 1, - "Logic": "D03Z02S01[N] || wallClimb || doubleJump" - }, - { - "Id": "D03Z02S01[Cherubs]", - "Direction": 5, - "Type": 1 - }, - { - "Id": "D03Z02S02[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S10[E]", - "Logic": "D03Z02S02[W] || D03Z02S02[CherubsL] || doubleJump && (D03Z02S02[E] || D03Z02S02[CherubsR] || wallClimb || canEnemyBounce)" - }, - { - "Id": "D03Z02S02[E]", - "Direction": 2, - "OriginalDoor": "D03Z02S01[W]", - "Logic": "D03Z02S02[E] || wallClimb || doubleJump && canEnemyBounce" - }, - { - "Id": "D03Z02S02[S]", - "Direction": 3, - "OriginalDoor": "D03Z02S03[N]" - }, - { - "Id": "D03Z02S02[CherubsL]", - "Direction": 5, - "Type": 1 - }, - { - "Id": "D03Z02S02[CherubsR]", - "Direction": 5, - "Type": 1 - }, - { - "Id": "D03Z02S03[W]", - "Direction": 3, - "OriginalDoor": "D03Z02S07[N]", - "Logic": "D03Z02S03[W] || dash && (D03Z02S03[E] || D03Z02S03[N] || D03Z02S03[SE2])" - }, - { - "Id": "D03Z02S03[E]", - "Direction": 2, - "OriginalDoor": "D03Z02S05[W]", - "Logic": "D03Z02S03[E] || (canAirStall || doubleJump || boots) && (D03Z02S03[E] && dash || D03Z02S03[N] || D03Z02S03[SE2])" - }, - { - "Id": "D03Z02S03[N]", - "Direction": 0, - "OriginalDoor": "D03Z02S02[S]", - "Logic": "D03Z02S03[W] && dash || D03Z02S03[E] || D03Z02S03[N] || D03Z02S03[SE2]" - }, - { - "Id": "D03Z02S03[SE2]", - "Direction": 3, - "OriginalDoor": "D03Z02S04[NW]", - "Logic": "D03Z02S03[W] && dash || D03Z02S03[E] || D03Z02S03[N] || D03Z02S03[SE2]" - }, - { - "Id": "D03Z02S03[SW]", - "Direction": 1, - "OriginalDoor": "D03Z02S07[E]", - "Logic": "D03Z02S03[SW] || D03Z02S03[SE] || D03Z02S03[SSL] || D03Z02S03[SSR] || brokeJondoBellW && brokeJondoBellE && (D03Z02S03[W] && dash || D03Z02S03[E] || D03Z02S03[N] || D03Z02S03[SE2])" - }, - { - "Id": "D03Z02S03[SE]", - "Direction": 2, - "OriginalDoor": "D03Z02S06[W]", - "Logic": "D03Z02S03[SW] || D03Z02S03[SE] || D03Z02S03[SSL] || D03Z02S03[SSR] || brokeJondoBellW && brokeJondoBellE && (D03Z02S03[W] && dash || D03Z02S03[E] || D03Z02S03[N] || D03Z02S03[SE2])" - }, - { - "Id": "D03Z02S03[SSL]", - "Direction": 3, - "OriginalDoor": "D03Z03S01[NL]", - "Type": 1, - "Logic": "D03Z02S03[SW] || D03Z02S03[SE] || D03Z02S03[SSL] || D03Z02S03[SSR] || brokeJondoBellW && brokeJondoBellE && (D03Z02S03[W] && dash || D03Z02S03[E] || D03Z02S03[N] || D03Z02S03[SE2])" - }, - { - "Id": "D03Z02S03[SSC]", - "Direction": 6, - "OriginalDoor": "D03Z03S01[NC]", - "Type": 1, - "Logic": "D03Z02S03[SW] || D03Z02S03[SE] || D03Z02S03[SSL] || D03Z02S03[SSR] || brokeJondoBellW && brokeJondoBellE && (D03Z02S03[W] && dash || D03Z02S03[E] || D03Z02S03[N] || D03Z02S03[SE2])" - }, - { - "Id": "D03Z02S03[SSR]", - "Direction": 3, - "OriginalDoor": "D03Z03S01[NR]", - "Type": 1, - "Logic": "D03Z02S03[SW] || D03Z02S03[SE] || D03Z02S03[SSL] || D03Z02S03[SSR] || brokeJondoBellW && brokeJondoBellE && (D03Z02S03[W] && dash || D03Z02S03[E] || D03Z02S03[N] || D03Z02S03[SE2])" - }, - { - "Id": "D03Z02S04[NW]", - "Direction": 0, - "OriginalDoor": "D03Z02S03[SE2]", - "Logic": "D03Z02S04[NW] || wallClimb || doubleJump" - }, - { - "Id": "D03Z02S04[NE]", - "Direction": 0, - "OriginalDoor": "D03Z02S05[S]", - "Logic": "D03Z02S04[NE] || wallClimb || (D03Z02S04[S] && doubleJump)" - }, - { - "Id": "D03Z02S04[S]", - "Direction": 3, - "OriginalDoor": "D03Z02S06[N]", - "Logic": "D03Z02S04[NE] || D03Z02S04[S] || wallClimb" - }, - { - "Id": "D03Z02S05[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S03[E]" - }, - { - "Id": "D03Z02S05[E]", - "Direction": 2, - "OriginalDoor": "D03Z02S11[W]", - "Logic": "D03Z02S05[E] || D03Z02S05[S] || canCrossGap5 || (canEnemyBounce && canCrossGap3)" - }, - { - "Id": "D03Z02S05[S]", - "Direction": 3, - "OriginalDoor": "D03Z02S04[NE]", - "Logic": "D03Z02S05[E] || D03Z02S05[S] || canCrossGap5 || (canEnemyBounce && canCrossGap3)" - }, - { - "Id": "D03Z02S06[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S03[SE]", - "VisibilityFlags": 1 - }, - { - "Id": "D03Z02S06[N]", - "Direction": 0, - "OriginalDoor": "D03Z02S04[S]" - }, - { - "Id": "D03Z02S07[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S08[E]" - }, - { - "Id": "D03Z02S07[E]", - "Direction": 2, - "OriginalDoor": "D03Z02S03[SW]", - "VisibilityFlags": 1 - }, - { - "Id": "D03Z02S07[N]", - "Direction": 0, - "OriginalDoor": "D03Z02S03[W]" - }, - { - "Id": "D03Z02S08[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S14[E]", - "Logic": "D03Z02S08[N] || D03Z02S08[W] || wallClimb || doubleJump" - }, - { - "Id": "D03Z02S08[E]", - "Direction": 2, - "OriginalDoor": "D03Z02S07[W]" - }, - { - "Id": "D03Z02S08[N]", - "Direction": 0, - "OriginalDoor": "D03Z02S09[S]", - "Logic": "D03Z02S08[N] || D03Z02S08[W] || wallClimb || doubleJump" - }, - { - "Id": "D03Z02S09[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S12[E]", - "Logic": "D03Z02S09[W] || dash" - }, - { - "Id": "D03Z02S09[N]", - "Direction": 0, - "OriginalDoor": "D03Z02S10[S]", - "Logic": "D03Z02S09[N] || D03Z02S09[S] || D03Z02S09[Cherubs] || dash" - }, - { - "Id": "D03Z02S09[S]", - "Direction": 3, - "OriginalDoor": "D03Z02S08[N]", - "Logic": "D03Z02S09[N] || D03Z02S09[S] || D03Z02S09[Cherubs] || dash" - }, - { - "Id": "D03Z02S09[Cherubs]", - "Direction": 5 - }, - { - "Id": "D03Z02S10[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S13[E]" - }, - { - "Id": "D03Z02S10[N]", - "Direction": 0, - "OriginalDoor": "D03Z01S03[SW]", - "Type": 1 - }, - { - "Id": "D03Z02S10[S]", - "Direction": 3, - "OriginalDoor": "D03Z02S09[N]" - }, - { - "Id": "D03Z02S10[E]", - "Direction": 2, - "OriginalDoor": "D03Z02S02[W]" - }, - { - "Id": "D03Z02S10[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D03Z02S09[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D03Z02S10[Cherubs]", - "Direction": 5, - "Type": 1 - }, - { - "Id": "D03Z02S11[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S05[E]", - "Logic": "D03Z02S11[W] || dash && (doubleJump || wallClimb || canCrossGap2)" - }, - { - "Id": "D03Z02S11[E]", - "Direction": 2, - "OriginalDoor": "D03Z02S15[W]", - "Logic": "D03Z02S11[E] || dash && (wallClimb || doubleJump)" - }, - { - "Id": "D03Z02S12[E]", - "Direction": 2, - "OriginalDoor": "D03Z02S09[W]" - }, - { - "Id": "D03Z02S12[Cherubs]", - "Direction": 5 - }, - { - "Id": "D03Z02S13[E]", - "Direction": 2, - "OriginalDoor": "D03Z02S10[W]" - }, - { - "Id": "D03Z02S13[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D03Z02S12[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D03Z02S14[E]", - "Direction": 2, - "OriginalDoor": "D03Z02S08[W]" - }, - { - "Id": "D03Z02S15[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S11[E]" - }, - { - "Id": "D03Z02S15[E]", - "Direction": 2, - "OriginalDoor": "D20Z01S01[W]", - "Type": 1 - }, - - { - "Id": "D03Z03S01[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S18[E]" - }, - { - "Id": "D03Z03S01[S]", - "Direction": 2, - "OriginalDoor": "D03Z03S12[W]" - }, - { - "Id": "D03Z03S01[NL]", - "Direction": 0, - "OriginalDoor": "D03Z02S03[SSL]", - "Type": 1, - "Logic": "D03Z03S01[NL] || D03Z03S01[NR] || D03Z03S01[NC] || wallClimb || doubleJump" - }, - { - "Id": "D03Z03S01[NC]", - "Direction": 5, - "Type": 1 - }, - { - "Id": "D03Z03S01[NR]", - "Direction": 0, - "OriginalDoor": "D03Z02S03[SSR]", - "Type": 1, - "Logic": "D03Z03S01[NL] || D03Z03S01[NR] || D03Z03S01[NC] || wallClimb || doubleJump" - }, - { - "Id": "D03Z03S02[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S12[E]", - "Logic": "D03Z03S02[NE] || D03Z03S02[W] || wallClimb || doubleJump" - }, - { - "Id": "D03Z03S02[NE]", - "Direction": 2, - "OriginalDoor": "D03Z03S14[W]", - "Logic": "D03Z03S02[NE] || wallClimb || doubleJump" - }, - { - "Id": "D03Z03S02[E]", - "Direction": 2, - "OriginalDoor": "D03Z03S03[W]" - }, - { - "Id": "D03Z03S03[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S02[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D03Z03S03[NE]" ] - }, - { - "Id": "D03Z03S03[NE]", - "Direction": 2, - "OriginalDoor": "D03Z03S04[NW]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D03Z03S03[W]" ] - }, - { - "Id": "D03Z03S03[SE]", - "Direction": 2, - "OriginalDoor": "D03Z03S04[SW]", - "VisibilityFlags": 1 - }, - { - "Id": "D03Z03S04[NW]", - "Direction": 1, - "OriginalDoor": "D03Z03S03[NE]", - "Logic": "D03Z03S04[NW] || D03Z03S04[NE] || (wallClimb || doubleJump) && (D03Z03S04[E] || D03Z03S04[SW] || blood || canCrossGap10)" - }, - { - "Id": "D03Z03S04[NE]", - "Direction": 2, - "OriginalDoor": "D03Z03S05[NW]", - "Logic": "D03Z03S04[NE] || wallClimb && (D03Z03S04[NW] || D03Z03S04[E] || D03Z03S04[SW] || blood || canCrossGap10)" - }, - { - "Id": "D03Z03S04[E]", - "Direction": 2, - "OriginalDoor": "D03Z03S05[SW]", - "Logic": "D03Z03S04[NW] || D03Z03S04[NE] || D03Z03S04[E] || (wallClimb || doubleJump) && (D03Z03S04[SW] || blood || canCrossGap10)" - }, - { - "Id": "D03Z03S04[SW]", - "Direction": 1, - "OriginalDoor": "D03Z03S03[SE]", - "Logic": "D03Z03S04[NW] || D03Z03S04[NE] || D03Z03S04[E] || D03Z03S04[SW] || blood || canCrossGap10" - }, - { - "Id": "D03Z03S04[SE]", - "Direction": 2, - "OriginalDoor": "D03Z03S13[W]", - "Logic": "D03Z03S04[SE] || blood" - }, - { - "Id": "D03Z03S04[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D03Z03S10[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D03Z03S05[NW]", - "Direction": 1, - "OriginalDoor": "D03Z03S04[NE]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D03Z03S05[NE]" ] - }, - { - "Id": "D03Z03S05[NE]", - "Direction": 2, - "OriginalDoor": "D03Z03S06[W]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D03Z03S05[NW]" ] - }, - { - "Id": "D03Z03S05[SW]", - "Direction": 1, - "OriginalDoor": "D03Z03S04[E]", - "Logic": "D03Z03S05[SW] || D03Z03S05[SE] || linen" - }, - { - "Id": "D03Z03S05[SE]", - "Direction": 2, - "OriginalDoor": "D03Z03S07[SW]", - "Logic": "D03Z03S05[SW] || D03Z03S05[SE] || linen" - }, - { - "Id": "D03Z03S06[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S05[NE]" - }, - { - "Id": "D03Z03S07[NW]", - "Direction": 1, - "OriginalDoor": "D03Z03S19[E]", - "Logic": "D03Z03S07[NW] || D03Z03S07[NE] || wallClimb || doubleJump" - }, - { - "Id": "D03Z03S07[NE]", - "Direction": 2, - "OriginalDoor": "D03Z03S08[W]", - "Logic": "D03Z03S07[NW] || D03Z03S07[NE] || wallClimb || doubleJump" - }, - { - "Id": "D03Z03S07[SW]", - "Direction": 1, - "OriginalDoor": "D03Z03S05[SE]" - }, - { - "Id": "D03Z03S07[E]", - "Direction": 2, - "OriginalDoor": "D03Z03S11[W]" - }, - { - "Id": "D03Z03S07[S]", - "Direction": 3, - "OriginalDoor": "D03Z03S09[N]" - }, - { - "Id": "D03Z03S08[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S07[NE]" - }, - { - "Id": "D03Z03S08[-CherubsL]", - "Direction": 6, - "OriginalDoor": "D03Z03S11[CherubsL]", - "Logic": "linen" - }, - { - "Id": "D03Z03S08[-CherubsR]", - "Direction": 6, - "OriginalDoor": "D03Z03S11[CherubsR]", - "Logic": "linen" - }, - { - "Id": "D03Z03S09[SW]", - "Direction": 1, - "OriginalDoor": "D03Z03S10[E]" - }, - { - "Id": "D03Z03S09[N]", - "Direction": 0, - "OriginalDoor": "D03Z03S07[S]" - }, - { - "Id": "D03Z03S10[E]", - "Direction": 2, - "OriginalDoor": "D03Z03S09[SW]" - }, - { - "Id": "D03Z03S10[Cherubs]", - "Direction": 5 - }, - { - "Id": "D03Z03S11[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S07[E]" - }, - { - "Id": "D03Z03S11[E]", - "Direction": 2, - "OriginalDoor": "D03Z03S15[W]" - }, - { - "Id": "D03Z03S11[CherubsL]", - "Direction": 5 - }, - { - "Id": "D03Z03S11[CherubsR]", - "Direction": 5 - }, - { - "Id": "D03Z03S12[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S01[S]" - }, - { - "Id": "D03Z03S12[E]", - "Direction": 2, - "OriginalDoor": "D03Z03S02[W]" - }, - { - "Id": "D03Z03S13[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S04[SE]" - }, - { - "Id": "D03Z03S14[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S02[NE]" - }, - { - "Id": "D03Z03S15[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S11[E]", - "Logic": "canBeatGrievanceBoss" - }, - { - "Id": "D03Z03S15[E]", - "Direction": 2, - "OriginalDoor": "D03Z03S16[W]", - "Logic": "canBeatGrievanceBoss" - }, - { - "Id": "D03Z03S16[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S15[E]" - }, - { - "Id": "D03Z03S16[E]", - "Direction": 2, - "OriginalDoor": "D03Z03S17[W]" - }, - { - "Id": "D03Z03S17[W]", - "Direction": 1, - "OriginalDoor": "D03Z03S16[E]" - }, - { - "Id": "D03Z03S17[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S25[SW]", - "Type": 1 - }, - { - "Id": "D03Z03S18[E]", - "Direction": 2, - "OriginalDoor": "D03Z03S01[W]" - }, - { - "Id": "D03Z03S19[E]", - "Direction": 2, - "OriginalDoor": "D03Z03S07[NW]" - }, - - { - "Id": "D04Z01S01[W]", - "Direction": 1, - "OriginalDoor": "D08Z02S01[E]", - "Type": 1 - }, - { - "Id": "D04Z01S01[E]", - "Direction": 2, - "OriginalDoor": "D04Z01S02[W]" - }, - { - "Id": "D04Z01S01[NE]", - "Direction": 2, - "OriginalDoor": "D04Z01S02[NW]", - "Logic": "D04Z01S01[NE] || D04Z01S01[N] || canCrossGap3" - }, - { - "Id": "D04Z01S01[N]", - "Direction": 0, - "OriginalDoor": "D04Z01S05[S]", - "Logic": "D04Z01S01[NE] || D04Z01S01[N] || canCrossGap3" - }, - { - "Id": "D04Z01S01[Cherubs]", - "Direction": 5 - }, - { - "Id": "D04Z01S02[W]", - "Direction": 1, - "OriginalDoor": "D04Z01S01[E]" - }, - { - "Id": "D04Z01S02[NW]", - "Direction": 1, - "OriginalDoor": "D04Z01S01[NE]" - }, - { - "Id": "D04Z01S02[E]", - "Direction": 2, - "OriginalDoor": "D04Z01S03[W]" - }, - { - "Id": "D04Z01S03[W]", - "Direction": 1, - "OriginalDoor": "D04Z01S02[E]" - }, - { - "Id": "D04Z01S03[E]", - "Direction": 2, - "OriginalDoor": "D04Z01S04[W]" - }, - { - "Id": "D04Z01S03[S]", - "Direction": 3, - "OriginalDoor": "D05Z01S20[N]", - "Type": 1, - "VisibilityFlags": 1 - }, - { - "Id": "D04Z01S04[W]", - "Direction": 1, - "OriginalDoor": "D04Z01S03[E]" - }, - { - "Id": "D04Z01S04[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S01[W]", - "Type": 1 - }, - { - "Id": "D04Z01S04[Cherubs]", - "Direction": 5, - "Type": 1 - }, - { - "Id": "D04Z01S05[S]", - "Direction": 3, - "OriginalDoor": "D04Z01S01[N]" - }, - { - "Id": "D04Z01S05[N]", - "Direction": 0, - "OriginalDoor": "D04Z01S06[S]", - "Logic": "D04Z01S05[N] || (blood && canClimbOnRoot) || doubleJump && (blood || canClimbOnRoot)" - }, - { - "Id": "D04Z01S05[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D04Z01S01[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D04Z01S05[CherubsN]", - "Direction": 5 - }, - { - "Id": "D04Z01S06[S]", - "Direction": 3, - "OriginalDoor": "D04Z01S05[N]" - }, - { - "Id": "D04Z01S06[E]", - "Direction": 2, - "OriginalDoor": "D09Z01S09[SW]", - "Type": 1, - "VisibilityFlags": 9, - "Logic": "D04Z01S06[E] || doubleJump" - }, - { - "Id": "D04Z01S06[Cherubs]", - "Direction": 6, - "OriginalDoor": "D04Z01S05[CherubsN]", - "Logic": "linen" - }, - - { - "Id": "D04Z02S01[W]", - "Direction": 1, - "OriginalDoor": "D04Z01S04[E]", - "Type": 1 - }, - { - "Id": "D04Z02S01[N]", - "Direction": 0, - "OriginalDoor": "D04Z02S02[S]", - "Logic": "D04Z02S01[N] || D04Z02S01[NE] && dash && (doubleJump || wallClimb)" - }, - { - "Id": "D04Z02S01[E]", - "Direction": 2, - "OriginalDoor": "D04Z03S01[W]", - "Type": 1 - }, - { - "Id": "D04Z02S01[NE]", - "Direction": 2, - "OriginalDoor": "D04Z02S03[W]", - "Logic": "D04Z02S01[NE] || D04Z02S01[N] && dash && canCrossGap1" - }, - { - "Id": "D04Z02S02[S]", - "Direction": 3, - "OriginalDoor": "D04Z02S01[N]" - }, - { - "Id": "D04Z02S02[SE]", - "Direction": 2, - "OriginalDoor": "D04Z02S17[W]" - }, - { - "Id": "D04Z02S02[NE]", - "Direction": 2, - "OriginalDoor": "D04Z02S15[W]", - "VisibilityFlags": 49, - "Logic": "D04Z02S02[NE] || (doubleJump && upwarpSkipsAllowed) || (doubleJump && canEnemyUpslash) || (canEnemyUpslash && upwarpSkipsAllowed && (wallClimb || D04Z02S02[N]))" - }, - { - "Id": "D04Z02S02[N]", - "Direction": 0, - "OriginalDoor": "D06Z01S02[S]", - "Type": 1, - "Logic": "D04Z02S02[N] || D04Z02S02[NE] || wallClimb || doubleJump" - }, - { - "Id": "D04Z02S03[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S01[NE]" - }, - { - "Id": "D04Z02S03[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S04[NW]" - }, - { - "Id": "D04Z02S04[SW]", - "Direction": 1, - "OriginalDoor": "D04Z02S14[E]" - }, - { - "Id": "D04Z02S04[SE]", - "Direction": 2, - "OriginalDoor": "D05Z01S01[NW]", - "Type": 1 - }, - { - "Id": "D04Z02S04[W]", - "Direction": 1, - "OriginalDoor": "D04Z03S01[E]", - "Type": 1 - }, - { - "Id": "D04Z02S04[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S05[W]" - }, - { - "Id": "D04Z02S04[NW]", - "Direction": 1, - "OriginalDoor": "D04Z02S03[E]", - "Logic": "D04Z02S04[NW] || D04Z02S04[NE] || D04Z02S04[N] || D04Z02S04[Cherubs] || wallClimb && doubleJump" - }, - { - "Id": "D04Z02S04[NE]", - "Direction": 2, - "OriginalDoor": "D04Z02S19[W]", - "Logic": "D04Z02S04[NW] || D04Z02S04[NE] || D04Z02S04[N] || D04Z02S04[Cherubs] || wallClimb && doubleJump" - }, - { - "Id": "D04Z02S04[N]", - "Direction": 0, - "OriginalDoor": "D04Z02S06[S]", - "Logic": "(D04Z02S04[NW] || D04Z02S04[NE] || D04Z02S04[N] || D04Z02S04[Cherubs] || wallClimb && doubleJump) && openedMoMLadder" - }, - { - "Id": "D04Z02S04[Cherubs]", - "Direction": 5 - }, - { - "Id": "D04Z02S05[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S04[E]" - }, - { - "Id": "D04Z02S05[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S07[SW]" - }, - { - "Id": "D04Z02S06[S]", - "Direction": 3, - "OriginalDoor": "D04Z02S04[N]" - }, - { - "Id": "D04Z02S06[NW]", - "Direction": 1, - "OriginalDoor": "D04Z02S11[E]", - "Logic": "D04Z02S06[NW] || D04Z02S06[N] || D04Z02S06[NE] || wallClimb" - }, - { - "Id": "D04Z02S06[N]", - "Direction": 0, - "OriginalDoor": "D06Z01S23[S]", - "Type": 1, - "Logic": "(D04Z02S06[NW] || D04Z02S06[N] || D04Z02S06[NE] || wallClimb) && openedARLadder" - }, - { - "Id": "D04Z02S06[NE]", - "Direction": 2, - "OriginalDoor": "D04Z02S09[W]", - "Logic": "D04Z02S06[NW] || D04Z02S06[N] || D04Z02S06[NE] || wallClimb" - }, - { - "Id": "D04Z02S06[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S10[W]" - }, - { - "Id": "D04Z02S06[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D04Z02S04[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D04Z02S07[SW]", - "Direction": 1, - "OriginalDoor": "D04Z02S05[E]" - }, - { - "Id": "D04Z02S07[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S19[E]" - }, - { - "Id": "D04Z02S07[N]", - "Direction": 0, - "OriginalDoor": "D04Z02S08[S]" - }, - { - "Id": "D04Z02S07[NE]", - "Direction": 2, - "OriginalDoor": "D04Z02S13[W]" - }, - { - "Id": "D04Z02S07[SE]", - "Direction": 2, - "OriginalDoor": "D04Z02S23[W]" - }, - { - "Id": "D04Z02S08[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S09[E]" - }, - { - "Id": "D04Z02S08[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S20[W]" - }, - { - "Id": "D04Z02S08[S]", - "Direction": 3, - "OriginalDoor": "D04Z02S07[N]" - }, - { - "Id": "D04Z02S08[Cherubs]", - "Direction": 5 - }, - { - "Id": "D04Z02S09[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S06[NE]" - }, - { - "Id": "D04Z02S09[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S08[W]" - }, - { - "Id": "D04Z02S09[NE]", - "Direction": 2, - "OriginalDoor": "D04Z02S16[W]", - "Logic": "D04Z02S09[NE] || blood" - }, - { - "Id": "D04Z02S10[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S06[E]" - }, - { - "Id": "D04Z02S11[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S21[SE]" - }, - { - "Id": "D04Z02S11[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S06[NW]" - }, - { - "Id": "D04Z02S12[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S21[NE]" - }, - { - "Id": "D04Z02S13[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S07[NE]" - }, - { - "Id": "D04Z02S14[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S04[SW]" - }, - { - "Id": "D04Z02S15[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S02[NE]" - }, - { - "Id": "D04Z02S15[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S22[W]" - }, - { - "Id": "D04Z02S16[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S09[NE]" - }, - { - "Id": "D04Z02S16[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D04Z02S08[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D04Z02S17[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S02[SE]" - }, - { - "Id": "D04Z02S19[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S04[NE]" - }, - { - "Id": "D04Z02S19[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S07[W]" - }, - { - "Id": "D04Z02S20[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S08[E]" - }, - { - "Id": "D04Z02S20[Redento]", - "Direction": 4, - "OriginalDoor": "D04BZ02S01[Redento]", - "Logic": "redentoRooms >= 5" - }, - { - "Id": "D04Z02S21[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S22[E]", - "Logic": "D04Z02S21[NE] || D04Z02S21[W] || wallClimb || doubleJump" - }, - { - "Id": "D04Z02S21[SE]", - "Direction": 2, - "OriginalDoor": "D04Z02S11[W]" - }, - { - "Id": "D04Z02S21[NE]", - "Direction": 2, - "OriginalDoor": "D04Z02S12[W]", - "Logic": "D04Z02S21[NE] || wallClimb || doubleJump" - }, - { - "Id": "D04Z02S22[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S15[E]", - "Logic": "D04Z02S22[W] || canBeatMothersBoss" - }, - { - "Id": "D04Z02S22[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S21[W]", - "Logic": "D04Z02S22[E] || canBeatMothersBoss" - }, - { - "Id": "D04Z02S23[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S07[SE]" - }, - { - "Id": "D04Z02S23[SE]", - "Direction": 2, - "OriginalDoor": "D04Z02S24[NW]" - }, - { - "Id": "D04Z02S23[NE]", - "Direction": 2, - "OriginalDoor": "D04Z04S01[W]", - "Type": 1 - }, - { - "Id": "D04Z02S24[NW]", - "Direction": 1, - "OriginalDoor": "D04Z02S23[SE]" - }, - { - "Id": "D04Z02S24[SW]", - "Direction": 1, - "OriginalDoor": "D20Z02S01[E]", - "Type": 1 - }, - { - "Id": "D04Z02S24[SE]", - "Direction": 2, - "OriginalDoor": "D04Z02S25[W]" - }, - { - "Id": "D04Z02S25[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S24[SE]" - }, - { - "Id": "D04BZ02S01[Redento]", - "Direction": 7, - "OriginalDoor": "D04Z02S20[Redento]" - }, - - { - "Id": "D04Z03S01[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S01[E]", - "Type": 1 - }, - { - "Id": "D04Z03S01[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S04[W]", - "Type": 1 - }, - { - "Id": "D04Z03S02[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S22[E]", - "Type": 1 - }, - - { - "Id": "D04Z04S01[W]", - "Direction": 1, - "OriginalDoor": "D04Z02S23[NE]", - "Type": 1 - }, - { - "Id": "D04Z04S01[E]", - "Direction": 2, - "OriginalDoor": "D04Z04S02[W]", - "Type": 9 - }, - { - "Id": "D04Z04S02[W]", - "Direction": 1, - "OriginalDoor": "D04Z04S01[E]", - "Type": 9 - }, - - { - "Id": "D05Z01S01[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S02[E]" - }, - { - "Id": "D05Z01S01[NW]", - "Direction": 1, - "OriginalDoor": "D04Z02S04[SE]", - "Type": 1 - }, - { - "Id": "D05Z01S01[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S16[W]" - }, - { - "Id": "D05Z01S02[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S15[E]", - "VisibilityFlags": 1 - }, - { - "Id": "D05Z01S02[NW]", - "Direction": 1, - "OriginalDoor": "D05Z01S03[E]" - }, - { - "Id": "D05Z01S02[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S01[W]" - }, - { - "Id": "D05Z01S03[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S04[E]" - }, - { - "Id": "D05Z01S03[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S02[NW]" - }, - { - "Id": "D05Z01S03[Frontal]", - "Direction": 4, - "OriginalDoor": "D05BZ01S01[FrontalS]", - "Logic": "woodKey && D05Z01S23[E] && (D05Z01S11[NW] || D05Z01S11[NE])" - }, - { - "Id": "D05Z01S04[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S05[E]" - }, - { - "Id": "D05Z01S04[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S03[W]" - }, - { - "Id": "D05Z01S05[SW]", - "Direction": 1, - "OriginalDoor": "D05Z01S07[E]" - }, - { - "Id": "D05Z01S05[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S04[W]" - }, - { - "Id": "D05Z01S05[NE]", - "Direction": 2, - "OriginalDoor": "D05Z01S17[W]", - "Logic": "D05Z01S05[NE] || blood" - }, - { - "Id": "D05Z01S06[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S24[E]", - "Logic": "D05Z01S06[W] || canSurvivePoison3" - }, - { - "Id": "D05Z01S06[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S20[W]", - "Logic": "D05Z01S06[E] || canSurvivePoison3" - }, - { - "Id": "D05Z01S07[SW]", - "Direction": 1, - "OriginalDoor": "D05Z01S08[NE]" - }, - { - "Id": "D05Z01S07[NW]", - "Direction": 1, - "OriginalDoor": "D05Z01S20[E]", - "Logic": "D05Z01S07[NW] || blood && (canClimbOnRoot || doubleJump) || (canClimbOnRoot && canCrossGap3) || canCrossGap7" - }, - { - "Id": "D05Z01S07[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S05[SW]" - }, - { - "Id": "D05Z01S08[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S10[E]" - }, - { - "Id": "D05Z01S08[NW]", - "Direction": 1, - "OriginalDoor": "D05Z01S12[E]" - }, - { - "Id": "D05Z01S08[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S09[W]" - }, - { - "Id": "D05Z01S08[Health]", - "Direction": 2, - "OriginalDoor": "D05Z01S14[W]" - }, - { - "Id": "D05Z01S08[NE]", - "Direction": 2, - "OriginalDoor": "D05Z01S07[SW]" - }, - { - "Id": "D05Z01S09[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S08[E]" - }, - { - "Id": "D05Z01S09[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S18[W]" - }, - { - "Id": "D05Z01S10[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S11[E]" - }, - { - "Id": "D05Z01S10[NW]", - "Direction": 1, - "OriginalDoor": "D05Z01S11[NE]" - }, - { - "Id": "D05Z01S10[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S08[W]" - }, - { - "Id": "D05Z01S11[SW]", - "Direction": 1, - "OriginalDoor": "D05Z01S19[E]", - "VisibilityFlags": 5, - "Logic": "canBreakTirana" - }, - { - "Id": "D05Z01S11[NW]", - "Direction": 1, - "OriginalDoor": "D05Z01S23[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D05Z01S11[NE]" ] - }, - { - "Id": "D05Z01S11[NE]", - "Direction": 2, - "OriginalDoor": "D05Z01S10[NW]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D05Z01S11[NW]" ] - }, - { - "Id": "D05Z01S11[SE]", - "Direction": 2, - "OriginalDoor": "D05Z02S01[W]", - "Type": 1 - }, - { - "Id": "D05Z01S11[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S10[W]" - }, - { - "Id": "D05Z01S12[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S08[NW]" - }, - { - "Id": "D05Z01S13[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S21[NW]" - }, - { - "Id": "D05Z01S14[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S08[Health]" - }, - { - "Id": "D05Z01S15[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S21[NE]" - }, - { - "Id": "D05Z01S15[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S02[W]" - }, - { - "Id": "D05Z01S16[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S01[E]" - }, - { - "Id": "D05Z01S17[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S05[NE]" - }, - { - "Id": "D05Z01S18[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S09[E]" - }, - { - "Id": "D05Z01S19[W]", - "Direction": 1, - "OriginalDoor": "D05Z02S15[E]", - "Type": 1 - }, - { - "Id": "D05Z01S19[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S11[SW]" - }, - { - "Id": "D05Z01S20[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S06[E]" - }, - { - "Id": "D05Z01S20[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S07[NW]" - }, - { - "Id": "D05Z01S20[N]", - "Direction": 0, - "OriginalDoor": "D04Z01S03[S]", - "Type": 1 - }, - { - "Id": "D05Z01S21[SW]", - "Direction": 1, - "OriginalDoor": "D05Z02S14[E]", - "Type": 1 - }, - { - "Id": "D05Z01S21[NW]", - "Direction": 1, - "OriginalDoor": "D05Z01S13[E]" - }, - { - "Id": "D05Z01S21[NE]", - "Direction": 2, - "OriginalDoor": "D05Z01S15[W]" - }, - { - "Id": "D05Z01S21[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D05Z02S11[Cherubs]", - "Type": 1, - "Logic": "linen" - }, - { - "Id": "D05Z01S22[FrontalN]", - "Direction": 4, - "OriginalDoor": "D05BZ01S01[FrontalN]" - }, - { - "Id": "D05Z01S22[E]", - "Direction": 2, - "OriginalDoor": "D04Z03S02[W]", - "Type": 1 - }, - { - "Id": "D05Z01S23[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S11[NW]" - }, - { - "Id": "D05Z01S24[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S06[W]" - }, - { - "Id": "D05BZ01S01[FrontalS]", - "Direction": 7, - "OriginalDoor": "D05Z01S03[Frontal]" - }, - { - "Id": "D05BZ01S01[FrontalN]", - "Direction": 7, - "OriginalDoor": "D05Z01S22[FrontalN]" - }, - - { - "Id": "D05Z02S01[W]", - "Direction": 1, - "OriginalDoor": "D05Z01S11[SE]", - "Type": 1 - }, - { - "Id": "D05Z02S01[E]", - "Direction": 2, - "OriginalDoor": "D05Z02S02[NW]" - }, - { - "Id": "D05Z02S02[SW]", - "Direction": 1, - "OriginalDoor": "D05Z02S03[E]" - }, - { - "Id": "D05Z02S02[NW]", - "Direction": 1, - "OriginalDoor": "D05Z02S01[E]" - }, - { - "Id": "D05Z02S02[SE]", - "Direction": 2, - "OriginalDoor": "D05Z02S09[W]" - }, - { - "Id": "D05Z02S02[NE]", - "Direction": 2, - "OriginalDoor": "D05Z02S05[W]" - }, - { - "Id": "D05Z02S03[W]", - "Direction": 1, - "OriginalDoor": "D05Z02S04[E]" - }, - { - "Id": "D05Z02S03[E]", - "Direction": 2, - "OriginalDoor": "D05Z02S02[SW]" - }, - { - "Id": "D05Z02S04[W]", - "Direction": 1, - "OriginalDoor": "D05Z02S12[E]" - }, - { - "Id": "D05Z02S04[E]", - "Direction": 2, - "OriginalDoor": "D05Z02S03[W]" - }, - { - "Id": "D05Z02S04[C]", - "Direction": 4, - "OriginalDoor": "D05BZ02S01[C]" - }, - { - "Id": "D05Z02S05[W]", - "Direction": 1, - "OriginalDoor": "D05Z02S02[NE]" - }, - { - "Id": "D05Z02S05[E]", - "Direction": 2, - "OriginalDoor": "D05Z02S06[SW]" - }, - { - "Id": "D05Z02S06[SW]", - "Direction": 1, - "OriginalDoor": "D05Z02S05[E]" - }, - { - "Id": "D05Z02S06[NW]", - "Direction": 1, - "OriginalDoor": "D05Z02S07[E]" - }, - { - "Id": "D05Z02S06[SE]", - "Direction": 2, - "OriginalDoor": "D05Z02S11[W]", - "Logic": "openedTSCGate" - }, - { - "Id": "D05Z02S06[NE]", - "Direction": 2, - "OriginalDoor": "D05Z02S14[W]" - }, - { - "Id": "D05Z02S07[W]", - "Direction": 1, - "OriginalDoor": "D05Z02S10[E]" - }, - { - "Id": "D05Z02S07[E]", - "Direction": 2, - "OriginalDoor": "D05Z02S06[NW]" - }, - { - "Id": "D05Z02S08[W]", - "Direction": 1, - "OriginalDoor": "D05Z02S09[E]" - }, - { - "Id": "D05Z02S09[W]", - "Direction": 1, - "OriginalDoor": "D05Z02S02[SE]" - }, - { - "Id": "D05Z02S09[E]", - "Direction": 2, - "OriginalDoor": "D05Z02S08[W]", - "Logic": "redWax >= 3 && blueWax >= 3" - }, - { - "Id": "D05Z02S10[W]", - "Direction": 1, - "OriginalDoor": "D05Z02S13[E]", - "Logic": "dash" - }, - { - "Id": "D05Z02S10[E]", - "Direction": 2, - "OriginalDoor": "D05Z02S07[W]" - }, - { - "Id": "D05Z02S11[W]", - "Direction": 1, - "OriginalDoor": "D05Z02S06[SE]" - }, - { - "Id": "D05Z02S11[Cherubs]", - "Direction": 5, - "Type": 1 - }, - { - "Id": "D05Z02S12[W]", - "Direction": 1, - "OriginalDoor": "D01Z04S16[E]", - "Type": 1 - }, - { - "Id": "D05Z02S12[E]", - "Direction": 2, - "OriginalDoor": "D05Z02S04[W]" - }, - { - "Id": "D05Z02S12[N]", - "Direction": 0, - "OriginalDoor": "D05Z02S15[S]" - }, - { - "Id": "D05Z02S13[E]", - "Direction": 2, - "OriginalDoor": "D05Z02S10[W]", - "Logic": "dash" - }, - { - "Id": "D05Z02S14[W]", - "Direction": 1, - "OriginalDoor": "D05Z02S06[NE]", - "Logic": "D05Z02S14[W] || canBeatCanvasesBoss" - }, - { - "Id": "D05Z02S14[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S21[SW]", - "Type": 1, - "Logic": "D05Z02S14[E] || canBeatCanvasesBoss" - }, - { - "Id": "D05Z02S15[S]", - "Direction": 3, - "OriginalDoor": "D05Z02S12[N]" - }, - { - "Id": "D05Z02S15[E]", - "Direction": 2, - "OriginalDoor": "D05Z01S19[W]", - "Type": 1 - }, - { - "Id": "D05BZ02S01[C]", - "Direction": 7, - "OriginalDoor": "D05Z02S04[C]" - }, - - { - "Id": "D06Z01S01[SW]", - "Direction": 1, - "OriginalDoor": "D06Z01S14[E]", - "Logic": "(D06Z01S01[SW] || D06Z01S01[SE] || D06Z01S01[W] || D06Z01S01[E] || D06Z01S01[NNW] || D06Z01S01[NNE] || D06Z01S01[N]) || linen && (D06Z01S01[NW] || D06Z01S01[NE])" - }, - { - "Id": "D06Z01S01[SE]", - "Direction": 2, - "OriginalDoor": "D06Z01S03[W]", - "Logic": "(D06Z01S01[SW] || D06Z01S01[SE] || D06Z01S01[W] || D06Z01S01[E] || D06Z01S01[NNW] || D06Z01S01[NNE] || D06Z01S01[N]) || linen && (D06Z01S01[NW] || D06Z01S01[NE])" - }, - { - "Id": "D06Z01S01[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S07[E]", - "Logic": "(D06Z01S01[W] || D06Z01S01[E] || D06Z01S01[NNW] || D06Z01S01[NNE] || D06Z01S01[N]) || masks >= 1 && (D06Z01S01[SW] || D06Z01S01[SE]) || linen && (D06Z01S01[NW] || D06Z01S01[NE] && (canWalkOnRoot || canCrossGap1))" - }, - { - "Id": "D06Z01S01[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S06[WW]", - "Logic": "(D06Z01S01[W] || D06Z01S01[E] || D06Z01S01[NNW] || D06Z01S01[NNE] || D06Z01S01[N]) || masks >= 1 && (D06Z01S01[SW] || D06Z01S01[SE]) || linen && (D06Z01S01[NE] || D06Z01S01[NW] && (canWalkOnRoot || canCrossGap1))" - }, - { - "Id": "D06Z01S01[NW]", - "Direction": 1, - "OriginalDoor": "D06Z01S16[E]", - "Logic": "D06Z01S01[NW] || D06Z01S01[NE] && (canWalkOnRoot || canCrossGap8) || linen && (D06Z01S01[NNW] || D06Z01S01[NNE] && (canWalkOnRoot || canCrossGap3))" - }, - { - "Id": "D06Z01S01[NE]", - "Direction": 2, - "OriginalDoor": "D06Z01S17[W]", - "Logic": "D06Z01S01[NE] || D06Z01S01[NW] && (canWalkOnRoot || canCrossGap8) || linen && (D06Z01S01[NNE] || D06Z01S01[NNW] && (canWalkOnRoot || canCrossGap3))" - }, - { - "Id": "D06Z01S01[NNW]", - "Direction": 1, - "OriginalDoor": "D06Z01S09[E]", - "Logic": "(D06Z01S01[NNW] || D06Z01S01[NNE] || D06Z01S01[N]) || masks >= 2 && (D06Z01S01[SW] || D06Z01S01[SE] || D06Z01S01[W] || D06Z01S01[E] || linen && (D06Z01S01[NW] || D06Z01S01[NE]))" - }, - { - "Id": "D06Z01S01[NNE]", - "Direction": 2, - "OriginalDoor": "D06Z01S10[W]", - "Logic": "(D06Z01S01[NNW] || D06Z01S01[NNE] || D06Z01S01[N]) || masks >= 2 && (D06Z01S01[SW] || D06Z01S01[SE] || D06Z01S01[W] || D06Z01S01[E] || linen && (D06Z01S01[NW] || D06Z01S01[NE]))" - }, - { - "Id": "D06Z01S01[N]", - "Direction": 0, - "OriginalDoor": "D06Z01S19[S]", - "Logic": "masks >= 3 && (D06Z01S01[SW] || D06Z01S01[SE] || D06Z01S01[W] || D06Z01S01[E] || D06Z01S01[NNW] || D06Z01S01[NNE] || D06Z01S01[N] || linen && (D06Z01S01[NW] || D06Z01S01[NE]))", - "Type": 9 - }, - { - "Id": "D06Z01S01[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D06Z01S23[Cherubs]", - "Logic": "linen && (D06Z01S01[SW] || D06Z01S01[SE] || D06Z01S01[W] || D06Z01S01[E] || D06Z01S01[NW] || D06Z01S01[NE] || D06Z01S01[NNW] || D06Z01S01[NNE])" - }, - { - "Id": "D06Z01S02[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S18[E]" - }, - { - "Id": "D06Z01S02[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S08[W]" - }, - { - "Id": "D06Z01S02[S]", - "Direction": 3, - "OriginalDoor": "D04Z02S02[N]", - "Type": 1 - }, - { - "Id": "D06Z01S03[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S01[SE]", - "Logic": "D06Z01S03[W] || canBeatLegionary" - }, - { - "Id": "D06Z01S03[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S04[W]", - "Logic": "D06Z01S03[E] || canBeatLegionary" - }, - { - "Id": "D06Z01S04[SW]", - "Direction": 1, - "OriginalDoor": "D06Z01S20[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S04[W]", "D06Z01S04[Health]" ] - }, - { - "Id": "D06Z01S04[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S03[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S04[SW]", "D06Z01S04[Health]" ] - }, - { - "Id": "D06Z01S04[Health]", - "Direction": 2, - "OriginalDoor": "D06Z01S24[W]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S04[SW]", "D06Z01S04[W]" ], - "Logic": "D06Z01S04[Health] || (wallClimb && canSurvivePoison2 && (doubleJump || blood && canClimbOnRoot))" - }, - { - "Id": "D06Z01S04[NW]", - "Direction": 1, - "OriginalDoor": "D06Z01S06[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S04[NE]", "D06Z01S04[Cherubs]" ], - "Logic": "D06Z01S04[NW] || D06Z01S04[Cherubs] || (D06Z01S04[SW] || D06Z01S04[W] || D06Z01S04[Health]) && wallClimb && canSurvivePoison2 && (dash || doubleJump && (canDawnJump || canClimbOnRoot))" - }, - { - "Id": "D06Z01S04[NE]", - "Direction": 2, - "OriginalDoor": "D06Z01S06[W]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S04[NW]", "D06Z01S04[Cherubs]" ], - "Logic": "D06Z01S04[NE] || (D06Z01S04[SW] || D06Z01S04[W] || D06Z01S04[Health]) && wallClimb && canSurvivePoison2 && (dash || doubleJump && (canDawnJump || canClimbOnRoot))" - }, - { - "Id": "D06Z01S04[Cherubs]", - "Direction": 5 - }, - { - "Id": "D06Z01S05[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S12[NW]" - }, - { - "Id": "D06Z01S06[WW]", - "Direction": 1, - "OriginalDoor": "D06Z01S01[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S06[E]" ], - "Logic": "D06Z01S06[WW] || canBeatLegionary" - }, - { - "Id": "D06Z01S06[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S04[NW]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S06[WW]" ], - "Logic": "D06Z01S06[E] || canBeatLegionary" - }, - { - "Id": "D06Z01S06[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S04[NE]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S06[EE]" ] - }, - { - "Id": "D06Z01S06[EE]", - "Direction": 2, - "OriginalDoor": "D06Z01S15[SW]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S06[W]" ] - }, - { - "Id": "D06Z01S07[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S12[E]" - }, - { - "Id": "D06Z01S07[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S01[W]" - }, - { - "Id": "D06Z01S07[CherubsL]", - "Direction": 5 - }, - { - "Id": "D06Z01S07[CherubsR]", - "Direction": 5 - }, - { - "Id": "D06Z01S08[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S02[E]" - }, - { - "Id": "D06Z01S08[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S14[W]", - "Logic": "D06Z01S08[N] || D06Z01S08[E] || wallClimb" - }, - { - "Id": "D06Z01S08[N]", - "Direction": 0, - "OriginalDoor": "D06Z01S13[S]", - "VisibilityFlags": 1 - }, - { - "Id": "D06Z01S09[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S12[NE]" - }, - { - "Id": "D06Z01S09[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S01[NNW]" - }, - { - "Id": "D06Z01S09[-CherubsL]", - "Direction": 6, - "OriginalDoor": "D06Z01S16[CherubsL]", - "Logic": "linen" - }, - { - "Id": "D06Z01S09[-CherubsR]", - "Direction": 6, - "OriginalDoor": "D06Z01S16[CherubsR]", - "Logic": "linen" - }, - { - "Id": "D06Z01S10[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S01[NNE]" - }, - { - "Id": "D06Z01S10[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S21[W]" - }, - { - "Id": "D06Z01S10[-CherubsL]", - "Direction": 6, - "OriginalDoor": "D06Z01S17[CherubsL]", - "Logic": "linen" - }, - { - "Id": "D06Z01S10[-CherubsR]", - "Direction": 6, - "OriginalDoor": "D06Z01S17[CherubsR]", - "Logic": "linen" - }, - { - "Id": "D06Z01S11[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S15[NE]" - }, - { - "Id": "D06Z01S12[S]", - "Direction": 3, - "OriginalDoor": "D06Z01S14[N]" - }, - { - "Id": "D06Z01S12[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S13[E]", - "Logic": "D06Z01S12[NW] || D06Z01S12[NE] || D06Z01S12[NE2] || D06Z01S12[W] || D06Z01S12[E] || wallClimb && doubleJump" - }, - { - "Id": "D06Z01S12[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S07[W]", - "Logic": "D06Z01S12[NW] || D06Z01S12[NE] || D06Z01S12[NE2] || D06Z01S12[W] || D06Z01S12[E] || wallClimb && doubleJump" - }, - { - "Id": "D06Z01S12[NW]", - "Direction": 1, - "OriginalDoor": "D06Z01S05[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S12[NE]", "D06Z01S12[NE2]" ], - "Logic": "D06Z01S12[NW] || D06Z01S12[NE] || wallClimb || doubleJump" - }, - { - "Id": "D06Z01S12[NE]", - "Direction": 2, - "OriginalDoor": "D06Z01S09[W]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S12[NW]", "D06Z01S12[NE2]" ], - "Logic": "D06Z01S12[NW] || D06Z01S12[NE] || wallClimb || doubleJump" - }, - { - "Id": "D06Z01S12[NE2]", - "Direction": 2, - "OriginalDoor": "D06Z01S16[W]", - "VisibilityFlags": 1 - }, - { - "Id": "D06Z01S13[W]", - "Direction": 1, - "OriginalDoor": "D09Z01S01[E]", - "Type": 1 - }, - { - "Id": "D06Z01S13[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S12[W]" - }, - { - "Id": "D06Z01S13[S]", - "Direction": 3, - "OriginalDoor": "D06Z01S08[N]" - }, - { - "Id": "D06Z01S14[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S08[E]" - }, - { - "Id": "D06Z01S14[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S01[SW]" - }, - { - "Id": "D06Z01S14[N]", - "Direction": 0, - "OriginalDoor": "D06Z01S12[S]" - }, - { - "Id": "D06Z01S15[SW]", - "Direction": 1, - "OriginalDoor": "D06Z01S06[EE]", - "VisibilityFlags": 1 - }, - { - "Id": "D06Z01S15[NW]", - "Direction": 1, - "OriginalDoor": "D06Z01S21[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S15[NE]" ], - "Logic": "D06Z01S15[NW] || D06Z01S15[SW] && wallClimb" - }, - { - "Id": "D06Z01S15[NE]", - "Direction": 2, - "OriginalDoor": "D06Z01S11[W]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D06Z01S15[NW]" ], - "Logic": "D06Z01S15[NE] || D06Z01S15[SW] && wallClimb" - }, - { - "Id": "D06Z01S16[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S12[NE2]", - "Logic": "D06Z01S16[W] || (D06Z01S16[CherubsL] && (doubleJump || wallClimb && (canWalkOnRoot || canAirStall))) || (D06Z01S16[CherubsR] && (doubleJump || canAirStall && (canWalkOnRoot || wheel) && (wallClimb || canDawnJump))) || (D06Z01S16[E] && (canWalkOnRoot || canCrossGap7) && (wallClimb || canCrossGap5))" - }, - { - "Id": "D06Z01S16[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S01[NW]", - "Logic": "D06Z01S16[E] || ((D06Z01S16[W] || D06Z01S16[CherubsL]) && (canWalkOnRoot || canCrossGap5)) || (D06Z01S16[CherubsR] && (doubleJump || canAirStall && (canWalkOnRoot || wheel)))" - }, - { - "Id": "D06Z01S16[-CherubsL]", - "Direction": 6, - "OriginalDoor": "D06Z01S07[CherubsL]", - "Logic": "linen && (D06Z01S16[W] || D06Z01S16[CherubsL] || (D06Z01S16[CherubsR] && (doubleJump || canAirStall && (canWalkOnRoot || wheel))) || (D06Z01S16[E] && (canWalkOnRoot || canCrossGap7)))" - }, - { - "Id": "D06Z01S16[-CherubsR]", - "Direction": 6, - "OriginalDoor": "D06Z01S07[CherubsR]", - "Logic": "linen && (D06Z01S16[E] || D06Z01S16[CherubsR] || (D06Z01S16[CherubsL] && (canAirStall || canWalkOnRoot || doubleJump)) || (D06Z01S16[W] && (canWalkOnRoot || canCrossGap1)))" - }, - { - "Id": "D06Z01S16[CherubsL]", - "Direction": 5 - }, - { - "Id": "D06Z01S16[CherubsR]", - "Direction": 5 - }, - { - "Id": "D06Z01S17[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S01[NE]", - "Logic": "D06Z01S17[W] || (D06Z01S17[E] || D06Z01S17[CherubsR]) && blood || D06Z01S17[CherubsL] && doubleJump" - }, - { - "Id": "D06Z01S17[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S26[W]", - "Logic": "D06Z01S17[E] || D06Z01S17[CherubsR] || blood && (D06Z01S17[W] || D06Z01S17[CherubsL] && doubleJump)" - }, - { - "Id": "D06Z01S17[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D06Z01S04[Cherubs]", - "Logic": "linen" - }, - { - "Id": "D06Z01S17[CherubsL]", - "Direction": 5 - }, - { - "Id": "D06Z01S17[CherubsR]", - "Direction": 5 - }, - { - "Id": "D06Z01S18[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S02[W]" - }, - { - "Id": "D06Z01S18[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D04Z01S04[Cherubs]", - "Type": 1, - "Logic": "linen" - }, - { - "Id": "D06Z01S19[S]", - "Direction": 3, - "OriginalDoor": "D06Z01S01[N]", - "Type": 9 - }, - { - "Id": "D06Z01S19[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S25[W]", - "Type": 9 - }, - { - "Id": "D06Z01S20[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S23[E]" - }, - { - "Id": "D06Z01S20[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S04[SW]" - }, - { - "Id": "D06Z01S21[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S10[E]", - "Logic": "D06Z01S21[W] || canBeatLegionary" - }, - { - "Id": "D06Z01S21[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S15[NW]", - "Logic": "D06Z01S21[E] || canBeatLegionary" - }, - { - "Id": "D06Z01S22[Sword]", - "Direction": 2, - "OriginalDoor": "D06Z01S23[Sword]" - }, - { - "Id": "D06Z01S23[Sword]", - "Direction": 1, - "OriginalDoor": "D06Z01S22[Sword]" - }, - { - "Id": "D06Z01S23[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S20[W]" - }, - { - "Id": "D06Z01S23[S]", - "Direction": 3, - "OriginalDoor": "D04Z02S06[N]", - "Type": 1 - }, - { - "Id": "D06Z01S23[Cherubs]", - "Direction": 5 - }, - { - "Id": "D06Z01S24[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S04[Health]" - }, - { - "Id": "D06Z01S25[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S19[E]", - "Logic": "D06Z01S25[W] || canBeatRooftopsBoss", - "Type": 9 - }, - { - "Id": "D06Z01S25[E]", - "Direction": 2, - "OriginalDoor": "D07Z01S01[W]", - "Logic": "D06Z01S25[E] || canBeatRooftopsBoss", - "Type": 9 - }, - { - "Id": "D06Z01S26[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S17[E]" - }, - - { - "Id": "D07Z01S01[W]", - "Direction": 1, - "OriginalDoor": "D06Z01S25[E]", - "Type": 9 - }, - { - "Id": "D07Z01S01[E]", - "Direction": 2, - "OriginalDoor": "D07Z01S02[W]", - "Type": 9 - }, - { - "Id": "D07Z01S02[W]", - "Direction": 1, - "OriginalDoor": "D07Z01S01[E]", - "Type": 9 - }, - { - "Id": "D07Z01S02[E]", - "Direction": 2, - "OriginalDoor": "D07Z01S03[W]", - "Type": 9 - }, - { - "Id": "D07Z01S03[W]", - "Direction": 1, - "OriginalDoor": "D07Z01S02[E]", - "Type": 9 - }, - - { - "Id": "D08Z01S01[W]", - "Direction": 1, - "OriginalDoor": "D01Z03S06[E]", - "Type": 1, - "Logic": "D08Z01S01[W] || canBeatBridgeBoss" - }, - { - "Id": "D08Z01S01[E]", - "Direction": 2, - "OriginalDoor": "D08Z02S01[W]", - "Type": 1, - "Logic": "holyWounds >= 3 && (D08Z01S01[E] || D08Z01S01[Cherubs] || canBeatBridgeBoss)" - }, - { - "Id": "D08Z01S01[Cherubs]", - "Direction": 5 - }, - { - "Id": "D08Z01S02[NE]", - "Direction": 2, - "OriginalDoor": "D08Z03S03[W]", - "Type": 1, - "VisibilityFlags": 1 - }, - { - "Id": "D08Z01S02[SE]", - "Direction": 2, - "OriginalDoor": "D08Z02S03[W]", - "Type": 1 - }, - { - "Id": "D08Z01S02[-Cherubs]", - "Direction": 6, - "OriginalDoor": "D08Z01S01[Cherubs]", - "Logic": "linen" - }, - - { - "Id": "D08Z02S01[W]", - "Direction": 1, - "OriginalDoor": "D08Z01S01[E]", - "Type": 1 - }, - { - "Id": "D08Z02S01[SE]", - "Direction": 2, - "OriginalDoor": "D08Z02S02[W]" - }, - { - "Id": "D08Z02S01[E]", - "Direction": 2, - "OriginalDoor": "D04Z01S01[W]", - "Type": 1 - }, - { - "Id": "D08Z02S01[N]", - "Direction": 0, - "OriginalDoor": "D08Z02S03[S]" - }, - { - "Id": "D08Z02S02[W]", - "Direction": 1, - "OriginalDoor": "D08Z02S01[SE]" - }, - { - "Id": "D08Z02S03[W]", - "Direction": 1, - "OriginalDoor": "D08Z01S02[SE]", - "Type": 1, - "Logic": "brokeBotTCStatue" - }, - { - "Id": "D08Z02S03[E]", - "Direction": 2, - "OriginalDoor": "D08Z03S01[W]", - "Type": 1 - }, - { - "Id": "D08Z02S03[S]", - "Direction": 3, - "OriginalDoor": "D08Z02S01[N]" - }, - - { - "Id": "D08Z03S01[W]", - "Direction": 1, - "OriginalDoor": "D08Z02S03[E]", - "Type": 1 - }, - { - "Id": "D08Z03S01[E]", - "Direction": 2, - "OriginalDoor": "D08Z03S02[SW]", - "Logic": "verses >= 4" - }, - { - "Id": "D08Z03S02[SW]", - "Direction": 1, - "OriginalDoor": "D08Z03S01[E]" - }, - { - "Id": "D08Z03S02[NW]", - "Direction": 1, - "OriginalDoor": "D08Z03S03[E]", - "Logic": "D08Z03S02[NW] || wallClimb" - }, - { - "Id": "D08Z03S03[W]", - "Direction": 1, - "OriginalDoor": "D08Z01S02[NE]", - "Type": 1, - "Logic": "D08Z03S03[W] || canBeatHallBoss" - }, - { - "Id": "D08Z03S03[E]", - "Direction": 2, - "OriginalDoor": "D08Z03S02[NW]", - "Logic": "D08Z03S03[E] || canBeatHallBoss" - }, - - { - "Id": "D09Z01S01[W]", - "Direction": 1, - "OriginalDoor": "D09Z01S11[E]" - }, - { - "Id": "D09Z01S01[E]", - "Direction": 2, - "OriginalDoor": "D06Z01S13[W]", - "Type": 1 - }, - { - "Id": "D09Z01S02[SW]", - "Direction": 1, - "OriginalDoor": "D09Z01S07[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S02[Cell2]" ] - }, - { - "Id": "D09Z01S02[NW]", - "Direction": 1, - "OriginalDoor": "D09Z01S07[NE]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S02[NW]", "D09Z01S02[N]", "D09Z01S02[Cell1]", "D09Z01S02[Cell6]", "D09Z01S02[Cell4]", "D09Z01S02[Cell3]", "D09Z01S02[Cell22]", "D09Z01S02[Cell23]" ] - }, - { - "Id": "D09Z01S02[N]", - "Direction": 0, - "OriginalDoor": "D09Z01S11[S]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S02[NW]", "D09Z01S02[N]", "D09Z01S02[Cell1]", "D09Z01S02[Cell6]", "D09Z01S02[Cell4]", "D09Z01S02[Cell3]", "D09Z01S02[Cell22]", "D09Z01S02[Cell23]" ] - }, - { - "Id": "D09Z01S02[Cell1]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell1]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S02[NW]", "D09Z01S02[N]", "D09Z01S02[Cell1]", "D09Z01S02[Cell6]", "D09Z01S02[Cell4]", "D09Z01S02[Cell3]", "D09Z01S02[Cell22]", "D09Z01S02[Cell23]" ], - "Logic": "bronzeKey" - }, - { - "Id": "D09Z01S02[Cell6]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell6]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S02[NW]", "D09Z01S02[N]", "D09Z01S02[Cell1]", "D09Z01S02[Cell6]", "D09Z01S02[Cell4]", "D09Z01S02[Cell3]", "D09Z01S02[Cell22]", "D09Z01S02[Cell23]" ], - "Logic": "silverKey" - }, - { - "Id": "D09Z01S02[Cell5]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell5]", - "VisibilityFlags": 1 - }, - { - "Id": "D09Z01S02[Cell4]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell4]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S02[NW]", "D09Z01S02[N]", "D09Z01S02[Cell1]", "D09Z01S02[Cell6]", "D09Z01S02[Cell4]", "D09Z01S02[Cell3]", "D09Z01S02[Cell22]", "D09Z01S02[Cell23]" ], - "Logic": "goldKey" - }, - { - "Id": "D09Z01S02[Cell2]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell2]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S02[SW]" ] - }, - { - "Id": "D09Z01S02[Cell3]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell3]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S02[NW]", "D09Z01S02[N]", "D09Z01S02[Cell1]", "D09Z01S02[Cell6]", "D09Z01S02[Cell4]", "D09Z01S02[Cell3]", "D09Z01S02[Cell22]", "D09Z01S02[Cell23]" ], - "Logic": "bronzeKey" - }, - { - "Id": "D09Z01S02[Cell22]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell22]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S02[NW]", "D09Z01S02[N]", "D09Z01S02[Cell1]", "D09Z01S02[Cell6]", "D09Z01S02[Cell4]", "D09Z01S02[Cell3]", "D09Z01S02[Cell22]", "D09Z01S02[Cell23]" ] - }, - { - "Id": "D09Z01S02[Cell23]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell23]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S02[NW]", "D09Z01S02[N]", "D09Z01S02[Cell1]", "D09Z01S02[Cell6]", "D09Z01S02[Cell4]", "D09Z01S02[Cell3]", "D09Z01S02[Cell22]", "D09Z01S02[Cell23]" ], - "Logic": "bronzeKey" - }, - { - "Id": "D09Z01S03[W]", - "Direction": 1, - "OriginalDoor": "D09Z01S05[SE]", - "Logic": "D09Z01S03[N] && canBeatPrisonBoss" - }, - { - "Id": "D09Z01S03[N]", - "Direction": 5 - }, - { - "Id": "D09Z01S04[W]", - "Direction": 1, - "OriginalDoor": "D09Z01S06[E]" - }, - { - "Id": "D09Z01S04[E]", - "Direction": 2, - "OriginalDoor": "D09Z01S11[W]" - }, - { - "Id": "D09Z01S04[S]", - "Direction": 3, - "OriginalDoor": "D09Z01S07[N]" - }, - { - "Id": "D09Z01S05[W]", - "Direction": 1, - "OriginalDoor": "D09Z01S13[E]" - }, - { - "Id": "D09Z01S05[SE]", - "Direction": 2, - "OriginalDoor": "D09Z01S03[W]" - }, - { - "Id": "D09Z01S05[NE]", - "Direction": 2, - "OriginalDoor": "D09Z01S08[W]" - }, - { - "Id": "D09Z01S06[-E]", - "Direction": 1, - "OriginalDoor": "D02Z03S10[-W]", - "Type": 1, - "Logic": "peaksKey" - }, - { - "Id": "D09Z01S06[E]", - "Direction": 2, - "OriginalDoor": "D09Z01S04[W]" - }, - { - "Id": "D09Z01S07[SW]", - "Direction": 1, - "OriginalDoor": "D09Z01S09[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S07[SW]", "D09Z01S07[SE]", "D09Z01S07[W]", "D09Z01S07[E]" ] - }, - { - "Id": "D09Z01S07[SE]", - "Direction": 2, - "OriginalDoor": "D09Z01S10[W]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S07[SW]", "D09Z01S07[SE]", "D09Z01S07[W]", "D09Z01S07[E]" ] - }, - { - "Id": "D09Z01S07[W]", - "Direction": 1, - "OriginalDoor": "D09Z01S08[SE]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S07[SW]", "D09Z01S07[SE]", "D09Z01S07[W]", "D09Z01S07[E]" ] - }, - { - "Id": "D09Z01S07[E]", - "Direction": 2, - "OriginalDoor": "D09Z01S02[SW]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S07[SW]", "D09Z01S07[SE]", "D09Z01S07[W]", "D09Z01S07[E]" ] - }, - { - "Id": "D09Z01S07[NW]", - "Direction": 1, - "OriginalDoor": "D09Z01S08[NE]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S07[N]" ] - }, - { - "Id": "D09Z01S07[N]", - "Direction": 0, - "OriginalDoor": "D09Z01S04[S]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S07[NW]" ] - }, - { - "Id": "D09Z01S07[NE]", - "Direction": 2, - "OriginalDoor": "D09Z01S02[NW]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S07[SW]", "D09Z01S07[SE]", "D09Z01S07[W]", "D09Z01S07[E]" ], - "Logic": "D09Z01S07[NE] || blood" - }, - { - "Id": "D09Z01S08[W]", - "Direction": 1, - "OriginalDoor": "D09Z01S05[NE]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S08[Cell14]" ], - "Logic": "openedWotHPGate" - }, - { - "Id": "D09Z01S08[S]", - "Direction": 6, - "OriginalDoor": "D09Z01S03[N]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S08[W]", "D09Z01S08[Cell14]" ] - }, - { - "Id": "D09Z01S08[SE]", - "Direction": 2, - "OriginalDoor": "D09Z01S07[W]", - "Logic": "D09Z01S08[SE] || D09Z01S08[Cell15] || D09Z01S08[Cell16] || D09Z01S08[Cell18] || D09Z01S08[Cell17] && dash" - }, - { - "Id": "D09Z01S08[NE]", - "Direction": 2, - "OriginalDoor": "D09Z01S07[NW]", - "Logic": "D09Z01S08[NE] || D09Z01S08[Cell7] || D09Z01S08[Cell17] && dash" - }, - { - "Id": "D09Z01S08[Cell14]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell14]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S08[W]" ] - }, - { - "Id": "D09Z01S08[Cell15]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell15]", - "Logic": "silverKey && (D09Z01S08[SE] || D09Z01S08[Cell15] || D09Z01S08[Cell16] || D09Z01S08[Cell18] || D09Z01S08[Cell17] && dash)" - }, - { - "Id": "D09Z01S08[Cell7]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell7]", - "Logic": "goldKey && (D09Z01S08[NE] || D09Z01S08[Cell7] || D09Z01S08[Cell17] && dash)" - }, - { - "Id": "D09Z01S08[Cell16]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell16]", - "Logic": "goldKey && (D09Z01S08[SE] || D09Z01S08[Cell15] || D09Z01S08[Cell16] || D09Z01S08[Cell18] || D09Z01S08[Cell17] && dash)" - }, - { - "Id": "D09Z01S08[Cell18]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell18]", - "Logic": "silverKey && (D09Z01S08[SE] || D09Z01S08[Cell15] || D09Z01S08[Cell16] || D09Z01S08[Cell18] || D09Z01S08[Cell17] && dash)" - }, - { - "Id": "D09Z01S08[Cell17]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell17]", - "VisibilityFlags": 1 - }, - { - "Id": "D09Z01S09[SW]", - "Direction": 1, - "OriginalDoor": "D04Z01S06[E]", - "Type": 1, - "Logic": "D09Z01S09[Cell21] || D09Z01S09[Cell20] || D09Z01S09[SW] || D09Z01S09[E] || dash" - }, - { - "Id": "D09Z01S09[NW]", - "Direction": 1, - "OriginalDoor": "D09Z01S12[E]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S09[Cell19]", "D09Z01S09[Cell24]" ], - "Logic": "D09Z01S09[NW] || D09Z01S09[Cell19] || dash" - }, - { - "Id": "D09Z01S09[E]", - "Direction": 2, - "OriginalDoor": "D09Z01S07[SW]", - "Logic": "D09Z01S09[Cell21] || D09Z01S09[Cell20] || D09Z01S09[SW] || D09Z01S09[E] || dash" - }, - { - "Id": "D09Z01S09[Cell24]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell24]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S09[NW]", "D09Z01S09[Cell19]" ], - "Logic": "D09Z01S09[Cell24] || dash" - }, - { - "Id": "D09Z01S09[Cell19]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell19]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S09[NW]", "D09Z01S09[Cell24]" ], - "Logic": "D09Z01S09[NW] || D09Z01S09[Cell19] || dash" - }, - { - "Id": "D09Z01S09[Cell20]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell20]", - "Logic": "silverKey && (D09Z01S09[Cell21] || D09Z01S09[Cell20] || D09Z01S09[SW] || D09Z01S09[E] || dash)" - }, - { - "Id": "D09Z01S09[Cell21]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell21]", - "Logic": "goldKey && (D09Z01S09[Cell21] || D09Z01S09[Cell20] || D09Z01S09[SW] || D09Z01S09[E] || dash)" - }, - { - "Id": "D09Z01S10[W]", - "Direction": 1, - "OriginalDoor": "D09Z01S07[SE]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S10[Cell12]", "D09Z01S10[Cell10]", "D09Z01S10[Cell11]" ] - }, - { - "Id": "D09Z01S10[Cell13]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell13]", - "VisibilityFlags": 1 - }, - { - "Id": "D09Z01S10[Cell12]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell12]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S10[W]", "D09Z01S10[Cell10]", "D09Z01S10[Cell11]" ], - "Logic": "bronzeKey" - }, - { - "Id": "D09Z01S10[Cell10]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell10]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S10[W]", "D09Z01S10[Cell12]", "D09Z01S10[Cell11]" ], - "Logic": "silverKey" - }, - { - "Id": "D09Z01S10[Cell11]", - "Direction": 4, - "OriginalDoor": "D09BZ01S01[Cell11]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09Z01S10[W]", "D09Z01S10[Cell12]", "D09Z01S10[Cell10]" ], - "Logic": "silverKey" - }, - { - "Id": "D09Z01S11[W]", - "Direction": 1, - "OriginalDoor": "D09Z01S04[E]", - "VisibilityFlags": 1 - }, - { - "Id": "D09Z01S11[E]", - "Direction": 2, - "OriginalDoor": "D09Z01S01[W]" - }, - { - "Id": "D09Z01S11[S]", - "Direction": 3, - "OriginalDoor": "D09Z01S02[N]" - }, - { - "Id": "D09Z01S12[E]", - "Direction": 2, - "OriginalDoor": "D09Z01S09[NW]" - }, - { - "Id": "D09Z01S13[E]", - "Direction": 2, - "OriginalDoor": "D09Z01S05[W]" - }, - { - "Id": "D09BZ01S01[Cell1]", - "Direction": 7, - "OriginalDoor": "D09Z01S02[Cell1]", - "VisibilityFlags": 1 - }, - { - "Id": "D09BZ01S01[Cell2]", - "Direction": 7, - "OriginalDoor": "D09Z01S02[Cell2]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell3]" ] - }, - { - "Id": "D09BZ01S01[Cell3]", - "Direction": 7, - "OriginalDoor": "D09Z01S02[Cell3]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell2]" ] - }, - { - "Id": "D09BZ01S01[Cell4]", - "Direction": 7, - "OriginalDoor": "D09Z01S02[Cell4]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell5]" ] - }, - { - "Id": "D09BZ01S01[Cell5]", - "Direction": 7, - "OriginalDoor": "D09Z01S02[Cell5]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell4]" ] - }, - { - "Id": "D09BZ01S01[Cell6]", - "Direction": 7, - "OriginalDoor": "D09Z01S02[Cell6]", - "VisibilityFlags": 1 - }, - { - "Id": "D09BZ01S01[Cell7]", - "Direction": 7, - "OriginalDoor": "D09Z01S08[Cell7]", - "VisibilityFlags": 1 - }, - { - "Id": "D09BZ01S01[Cell10]", - "Direction": 7, - "OriginalDoor": "D09Z01S10[Cell10]", - "VisibilityFlags": 1 - }, - { - "Id": "D09BZ01S01[Cell11]", - "Direction": 7, - "OriginalDoor": "D09Z01S10[Cell11]", - "VisibilityFlags": 1 - }, - { - "Id": "D09BZ01S01[Cell12]", - "Direction": 7, - "OriginalDoor": "D09Z01S10[Cell12]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell13]" ] - }, - { - "Id": "D09BZ01S01[Cell13]", - "Direction": 7, - "OriginalDoor": "D09Z01S10[Cell13]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell12]" ] - }, - { - "Id": "D09BZ01S01[Cell14]", - "Direction": 7, - "OriginalDoor": "D09Z01S08[Cell14]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell15]" ] - }, - { - "Id": "D09BZ01S01[Cell15]", - "Direction": 7, - "OriginalDoor": "D09Z01S08[Cell15]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell14]" ] - }, - { - "Id": "D09BZ01S01[Cell16]", - "Direction": 7, - "OriginalDoor": "D09Z01S08[Cell16]", - "VisibilityFlags": 1 - }, - { - "Id": "D09BZ01S01[Cell17]", - "Direction": 7, - "OriginalDoor": "D09Z01S08[Cell17]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell18]" ] - }, - { - "Id": "D09BZ01S01[Cell18]", - "Direction": 7, - "OriginalDoor": "D09Z01S08[Cell18]", - "VisibilityFlags": 1 - }, - { - "Id": "D09BZ01S01[Cell19]", - "Direction": 7, - "OriginalDoor": "D09Z01S09[Cell19]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell20]" ] - }, - { - "Id": "D09BZ01S01[Cell20]", - "Direction": 7, - "OriginalDoor": "D09Z01S09[Cell20]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell19]" ] - }, - { - "Id": "D09BZ01S01[Cell21]", - "Direction": 7, - "OriginalDoor": "D09Z01S09[Cell21]", - "VisibilityFlags": 1 - }, - { - "Id": "D09BZ01S01[Cell22]", - "Direction": 7, - "OriginalDoor": "D09Z01S02[Cell22]", - "VisibilityFlags": 1 - }, - { - "Id": "D09BZ01S01[Cell23]", - "Direction": 7, - "OriginalDoor": "D09Z01S02[Cell23]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D09BZ01S01[Cell22]" ], - "Logic": "bronzeKey" - }, - { - "Id": "D09BZ01S01[Cell24]", - "Direction": 7, - "OriginalDoor": "D09Z01S09[Cell24]", - "VisibilityFlags": 1 - }, - - { - "Id": "D17Z01S01[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S02[W]" - }, - { - "Id": "D17Z01S01[Cherubs1]", - "Direction": 5 - }, - { - "Id": "D17Z01S01[Cherubs2]", - "Direction": 5 - }, - { - "Id": "D17Z01S01[Cherubs3]", - "Direction": 5 - }, - { - "Id": "D17Z01S02[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S01[E]", - "Logic": "D17Z01S02[W] || dash" - }, - { - "Id": "D17Z01S02[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S05[W]", - "Logic": "D17Z01S02[N] || D17Z01S02[E] || dash" - }, - { - "Id": "D17Z01S02[N]", - "Direction": 0, - "OriginalDoor": "D17Z01S10[S]", - "Logic": "D17Z01S02[N] || blood && (D17Z01S02[E] || D17Z01S02[W] && dash)" - }, - { - "Id": "D17Z01S03[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S11[E]" - }, - { - "Id": "D17Z01S03[E]", - "Direction": 2, - "OriginalDoor": "D01Z01S07[W]", - "Type": 1 - }, - { - "Id": "D17Z01S03[relic]", - "Direction": 4, - "OriginalDoor": "D17BZ01S01[relic]", - "Logic": "elderKey" - }, - { - "Id": "D17Z01S04[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S12[E]" - }, - { - "Id": "D17Z01S04[S]", - "Direction": 3, - "OriginalDoor": "D17Z01S07[N]" - }, - { - "Id": "D17Z01S04[FrontL]", - "Direction": 4, - "OriginalDoor": "D17BZ02S01[FrontL]" - }, - { - "Id": "D17Z01S04[N]", - "Direction": 0, - "OriginalDoor": "D17Z01S05[S]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D17Z01S04[FrontR]" ] - }, - { - "Id": "D17Z01S04[FrontR]", - "Direction": 4, - "OriginalDoor": "D17BZ02S01[FrontR]", - "VisibilityFlags": 3, - "RequiredDoors": [ "D17Z01S04[N]" ] - }, - { - "Id": "D17Z01S05[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S02[E]" - }, - { - "Id": "D17Z01S05[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S11[W]" - }, - { - "Id": "D17Z01S05[S]", - "Direction": 3, - "OriginalDoor": "D17Z01S04[N]", - "Logic": "openedBotSSLadder" - }, - { - "Id": "D17Z01S06[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S07[W]" - }, - { - "Id": "D17Z01S07[SW]", - "Direction": 1, - "OriginalDoor": "D17Z01S08[E]" - }, - { - "Id": "D17Z01S07[SE]", - "Direction": 2, - "OriginalDoor": "D03Z01S05[W]", - "Type": 1 - }, - { - "Id": "D17Z01S07[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S06[E]" - }, - { - "Id": "D17Z01S07[NW]", - "Direction": 1, - "OriginalDoor": "D17Z01S09[E]" - }, - { - "Id": "D17Z01S07[N]", - "Direction": 0, - "OriginalDoor": "D17Z01S04[S]" - }, - { - "Id": "D17Z01S08[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S07[SW]" - }, - { - "Id": "D17Z01S09[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S07[NW]" - }, - { - "Id": "D17Z01S10[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S13[E]", - "Logic": "D17Z01S10[W] || blood || doubleJump" - }, - { - "Id": "D17Z01S10[S]", - "Direction": 3, - "OriginalDoor": "D17Z01S02[N]" - }, - { - "Id": "D17Z01S11[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S05[E]", - "Logic": "D17Z01S11[W] || canBeatBrotherhoodBoss" - }, - { - "Id": "D17Z01S11[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S03[W]", - "Logic": "D17Z01S11[E] || canBeatBrotherhoodBoss" - }, - { - "Id": "D17Z01S12[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S04[W]" - }, - { - "Id": "D17Z01S13[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S14[E]" - }, - { - "Id": "D17Z01S13[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S10[W]" - }, - { - "Id": "D17Z01S14[W]", - "Direction": 1, - "OriginalDoor": "D17Z01S15[E]", - "Logic": "scapular && (D17Z01S14[W] || blood)" - }, - { - "Id": "D17Z01S14[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S13[W]", - "Logic": "D17Z01S14[E] || blood" - }, - { - "Id": "D17Z01S14[-Cherubs1]", - "Direction": 6, - "OriginalDoor": "D17Z01S01[Cherubs1]", - "Logic": "linen && (D17Z01S14[W] || blood || canCrossGap11)" - }, - { - "Id": "D17Z01S14[-Cherubs2]", - "Direction": 6, - "OriginalDoor": "D17Z01S01[Cherubs2]", - "Logic": "linen && (D17Z01S14[E] && canCrossGap8 || D17Z01S14[W] && canCrossGap10 || blood)" - }, - { - "Id": "D17Z01S14[-Cherubs3]", - "Direction": 6, - "OriginalDoor": "D17Z01S01[Cherubs3]", - "Logic": "linen && (D17Z01S14[E] || blood)" - }, - { - "Id": "D17Z01S15[E]", - "Direction": 2, - "OriginalDoor": "D17Z01S14[W]" - }, - { - "Id": "D17BZ01S01[relic]", - "Direction": 7, - "OriginalDoor": "D17Z01S03[relic]" - }, - { - "Id": "D17BZ02S01[FrontL]", - "Direction": 7, - "OriginalDoor": "D17Z01S04[FrontL]", - "VisibilityFlags": 1 - }, - { - "Id": "D17BZ02S01[FrontR]", - "Direction": 7, - "OriginalDoor": "D17Z01S04[FrontR]", - "Logic": "D17BZ02S01[FrontR] || dash && wallClimb" - }, - - { - "Id": "D20Z01S01[W]", - "Direction": 1, - "OriginalDoor": "D03Z02S15[E]", - "Type": 1 - }, - { - "Id": "D20Z01S01[E]", - "Direction": 2, - "OriginalDoor": "D20Z01S02[W]" - }, - { - "Id": "D20Z01S01[S]", - "Direction": 3, - "OriginalDoor": "D20Z01S04[N]" - }, - { - "Id": "D20Z01S01[Cherubs]", - "Direction": 5 - }, - { - "Id": "D20Z01S02[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S01[E]" - }, - { - "Id": "D20Z01S02[E]", - "Direction": 2, - "OriginalDoor": "D20Z01S03[W]" - }, - { - "Id": "D20Z01S03[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S02[E]" - }, - { - "Id": "D20Z01S03[N]", - "Direction": 0, - "OriginalDoor": "D03Z01S01[S]", - "Type": 1 - }, - { - "Id": "D20Z01S04[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S05[E]" - }, - { - "Id": "D20Z01S04[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S24[W]", - "Type": 1, - "Logic": "openedDCGateW" - }, - { - "Id": "D20Z01S04[N]", - "Direction": 0, - "OriginalDoor": "D20Z01S01[S]" - }, - { - "Id": "D20Z01S05[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S06[NE]" - }, - { - "Id": "D20Z01S05[E]", - "Direction": 2, - "OriginalDoor": "D20Z01S04[W]" - }, - { - "Id": "D20Z01S06[NE]", - "Direction": 2, - "OriginalDoor": "D20Z01S05[W]" - }, - { - "Id": "D20Z01S06[SE]", - "Direction": 2, - "OriginalDoor": "D20Z01S07[NW]" - }, - { - "Id": "D20Z01S07[NW]", - "Direction": 1, - "OriginalDoor": "D20Z01S06[SE]" - }, - { - "Id": "D20Z01S07[NE]", - "Direction": 2, - "OriginalDoor": "D20Z01S08[W]" - }, - { - "Id": "D20Z01S07[SE]", - "Direction": 2, - "OriginalDoor": "D20Z01S09[W]" - }, - { - "Id": "D20Z01S08[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S07[NE]" - }, - { - "Id": "D20Z01S09[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S07[SE]", - "Logic": "D20Z01S09[W] || dash" - }, - { - "Id": "D20Z01S09[E]", - "Direction": 2, - "OriginalDoor": "D01Z05S25[EchoesW]", - "Type": 1, - "Logic": "D20Z01S09[E] || blood && dash" - }, - { - "Id": "D20Z01S10[W]", - "Direction": 1, - "OriginalDoor": "D01Z05S25[EchoesE]", - "Type": 1, - "Logic": "D20Z01S10[W] || blood && dash" - }, - { - "Id": "D20Z01S10[E]", - "Direction": 2, - "OriginalDoor": "D20Z01S11[W]", - "Logic": "D20Z01S10[E] || blood && dash" - }, - { - "Id": "D20Z01S11[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S10[E]" - }, - { - "Id": "D20Z01S11[NW]", - "Direction": 1, - "OriginalDoor": "D20Z01S12[E]" - }, - { - "Id": "D20Z01S11[NE]", - "Direction": 2, - "OriginalDoor": "D20Z01S13[W]" - }, - { - "Id": "D20Z01S11[SE]", - "Direction": 2, - "OriginalDoor": "D20Z02S12[W]", - "Type": 1 - }, - { - "Id": "D20Z01S12[E]", - "Direction": 2, - "OriginalDoor": "D20Z01S11[NW]" - }, - { - "Id": "D20Z01S13[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S11[NE]" - }, - { - "Id": "D20Z01S13[E]", - "Direction": 2, - "OriginalDoor": "D20Z02S11[NW]", - "Type": 1 - }, - { - "Id": "D20Z01S13[N]", - "Direction": 0, - "OriginalDoor": "D20Z01S14[S]" - }, - { - "Id": "D20Z01S14[S]", - "Direction": 3, - "OriginalDoor": "D20Z01S13[N]" - }, - { - "Id": "D20Z01S14[E]", - "Direction": 2, - "OriginalDoor": "D20Z03S01[W]", - "Type": 1 - }, - - { - "Id": "D20Z02S01[W]", - "Direction": 1, - "OriginalDoor": "D20Z02S03[SE]" - }, - { - "Id": "D20Z02S01[E]", - "Direction": 2, - "OriginalDoor": "D04Z02S24[SW]", - "Type": 1 - }, - { - "Id": "D20Z02S02[W]", - "Direction": 1, - "OriginalDoor": "D20Z02S03[NE]" - }, - { - "Id": "D20Z02S03[W]", - "Direction": 1, - "OriginalDoor": "D20Z02S04[E]" - }, - { - "Id": "D20Z02S03[NE]", - "Direction": 2, - "OriginalDoor": "D20Z02S02[W]", - "Logic": "D20Z02S03[NE] || canWalkOnRoot || canCrossGap5" - }, - { - "Id": "D20Z02S03[SE]", - "Direction": 2, - "OriginalDoor": "D20Z02S01[W]" - }, - { - "Id": "D20Z02S04[W]", - "Direction": 1, - "OriginalDoor": "D20Z02S05[E]", - "Logic": "D20Z02S04[W] || dash" - }, - { - "Id": "D20Z02S04[E]", - "Direction": 2, - "OriginalDoor": "D20Z02S03[W]", - "Logic": "D20Z02S04[E] || dash" - }, - { - "Id": "D20Z02S05[SW]", - "Direction": 1, - "OriginalDoor": "D20Z02S06[SE]" - }, - { - "Id": "D20Z02S05[NW]", - "Direction": 1, - "OriginalDoor": "D20Z02S06[NE]", - "Logic": "D20Z02S05[NW] || nail || canCrossGap3" - }, - { - "Id": "D20Z02S05[E]", - "Direction": 2, - "OriginalDoor": "D20Z02S04[W]" - }, - { - "Id": "D20Z02S06[SW]", - "Direction": 1, - "OriginalDoor": "D20Z02S09[E]" - }, - { - "Id": "D20Z02S06[SE]", - "Direction": 2, - "OriginalDoor": "D20Z02S05[SW]" - }, - { - "Id": "D20Z02S06[NW]", - "Direction": 1, - "OriginalDoor": "D20Z02S07[E]", - "Logic": "D20Z02S06[NW] || D20Z02S06[NE] || doubleJump || canClimbOnRoot || canDiveLaser" - }, - { - "Id": "D20Z02S06[NE]", - "Direction": 2, - "OriginalDoor": "D20Z02S05[NW]", - "Logic": "D20Z02S06[NW] || D20Z02S06[NE] || doubleJump || canClimbOnRoot || canDiveLaser" - }, - { - "Id": "D20Z02S07[W]", - "Direction": 1, - "OriginalDoor": "D20Z02S08[E]" - }, - { - "Id": "D20Z02S07[E]", - "Direction": 2, - "OriginalDoor": "D20Z02S06[NW]" - }, - { - "Id": "D20Z02S08[E]", - "Direction": 2, - "OriginalDoor": "D20Z02S07[W]" - }, - { - "Id": "D20Z02S09[W]", - "Direction": 1, - "OriginalDoor": "D20Z02S10[E]" - }, - { - "Id": "D20Z02S09[E]", - "Direction": 2, - "OriginalDoor": "D20Z02S06[SW]" - }, - { - "Id": "D20Z02S10[W]", - "Direction": 1, - "OriginalDoor": "D20Z02S11[E]" - }, - { - "Id": "D20Z02S10[E]", - "Direction": 2, - "OriginalDoor": "D20Z02S09[W]" - }, - { - "Id": "D20Z02S11[SW]", - "Direction": 1, - "OriginalDoor": "D20Z02S12[E]" - }, - { - "Id": "D20Z02S11[NW]", - "Direction": 1, - "OriginalDoor": "D20Z01S13[E]", - "Type": 1, - "VisibilityFlags": 5, - "RequiredDoors": [ "D20Z02S11[E]" ], - "Logic": "D20Z02S11[NW] || mourningSkipAllowed && (doubleJump || canBreakTirana || D20Z02S11[E])" - }, - { - "Id": "D20Z02S11[E]", - "Direction": 2, - "OriginalDoor": "D20Z02S10[W]", - "VisibilityFlags": 5, - "Logic": "D20Z02S11[E] || mourningSkipAllowed && (doubleJump || canBreakTirana || D20Z02S11[NW] && canCrossGap5)" - }, - { - "Id": "D20Z02S12[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S11[SE]", - "Type": 1 - }, - { - "Id": "D20Z02S12[E]", - "Direction": 2, - "OriginalDoor": "D20Z02S11[SW]" - }, - - { - "Id": "D20Z03S01[W]", - "Direction": 1, - "OriginalDoor": "D20Z01S14[E]", - "Type": 1 - }, -] \ No newline at end of file diff --git a/worlds/blasphemous/Rules.py b/worlds/blasphemous/Rules.py index 5d8829213163..119e618dc22f 100644 --- a/worlds/blasphemous/Rules.py +++ b/worlds/blasphemous/Rules.py @@ -1,4458 +1,1388 @@ -from typing import Dict, List, Set -from worlds.generic.Rules import set_rule, add_rule +from typing import Dict, List, Tuple, Any, Callable, TYPE_CHECKING from BaseClasses import CollectionState +if TYPE_CHECKING: + from . import BlasphemousWorld +else: + BlasphemousWorld = object + + +class BlasRules: + player: int + world: BlasphemousWorld + string_rules: Dict[str, Callable[[CollectionState], bool]] + + def __init__(self, world: "BlasphemousWorld") -> None: + self.player = world.player + self.world = world + self.multiworld = world.multiworld + self.indirect_conditions: List[Tuple[str, str]] = [] + + # BrandenEK/Blasphemous.Randomizer/ItemRando/BlasphemousInventory.cs + self.string_rules = { + # Visibility flags + "DoubleJump": lambda state: bool(self.world.options.purified_hand), + "NormalLogic": lambda state: self.world.options.difficulty >= 1, + "NormalLogicAndDoubleJump": lambda state: self.world.options.difficulty >= 1 \ + and bool(self.world.options.purified_hand), + "HardLogic": lambda state: self.world.options.difficulty >= 2, + "HardLogicAndDoubleJump": lambda state: self.world.options.difficulty >= 2 \ + and bool(self.world.options.purified_hand), + "EnemySkips": self.enemy_skips_allowed, + "EnemySkipsAndDoubleJump": lambda state: self.enemy_skips_allowed(state) \ + and bool(self.world.options.purified_hand), + + # Relics + "blood": self.blood, + # skip "root" + "linen": self.linen, + "nail": self.nail, + "shroud": self.shroud, + # skip "lung" + + # Keys + "bronzeKey": self.bronze_key, + "silverKey": self.silver_key, + "goldKey": self.gold_key, + "peaksKey": self.peaks_key, + "elderKey": self.elder_key, + "woodKey": self.wood_key, + + # Collections + "cherubs20": lambda state: self.cherubs(state) >= 20, + "cherubs38": lambda state: self.cherubs(state) >= 38, + + "bones4": lambda state: self.bones(state) >= 4, + "bones8": lambda state: self.bones(state) >= 8, + "bones12": lambda state: self.bones(state) >= 12, + "bones16": lambda state: self.bones(state) >= 16, + "bones20": lambda state: self.bones(state) >= 20, + "bones24": lambda state: self.bones(state) >= 24, + "bones28": lambda state: self.bones(state) >= 28, + "bones30": lambda state: self.bones(state) >= 30, + "bones32": lambda state: self.bones(state) >= 32, + "bones36": lambda state: self.bones(state) >= 36, + "bones40": lambda state: self.bones(state) >= 40, + "bones44": lambda state: self.bones(state) >= 44, + + "tears0": lambda state: True, + + # Special items + "dash": self.dash, + "wallClimb": self.wall_climb, + # skip "airImpulse" + "boots": self.boots, + "doubleJump": self.double_jump, + + # Speed boosts + "wheel": self.wheel, + # skip "dawnHeart" + + # Health boosts + # skip "flasks" + # skip "quicksilver" + + # Puzzles + "redWax1": lambda state: self.red_wax(state) >= 1, + "redWax3": lambda state: self.red_wax(state) >= 3, + "blueWax1": lambda state: self.blue_wax(state) >= 1, + "blueWax3": lambda state: self.blue_wax(state) >= 3, + "chalice": self.chalice, + + # Cherubs + "debla": self.debla, + "lorquiana": self.lorquiana, + "zarabanda": self.zarabanda, + "taranto": self.taranto, + "verdiales": self.verdiales, + "cante": self.cante, + "cantina": self.cantina, + + "aubade": self.aubade, + "tirana": self.tirana, + + "ruby": self.ruby, + "tiento": self.tiento, + # skip "anyPrayer" + "pillar": self.pillar, + + # Stats + # skip "healthLevel" + # skip "fervourLevel" + # skip "swordLevel" + + # Skills + # skip "combo" + # skip "charged" + # skip "ranged" + # skip "dive" + # skip "lunge" + "chargeBeam": self.charge_beam, + "rangedAttack": lambda state: self.ranged(state) > 0, + + # Main quest + "holyWounds3": lambda state: self.holy_wounds(state) >= 3, + "masks1": lambda state: self.masks(state) >= 1, + "masks2": lambda state: self.masks(state) >= 2, + "masks3": lambda state: self.masks(state) >= 3, + "guiltBead": self.guilt_bead, + + # LOTL quest + "cloth": self.cloth, + "hand": self.hand, + "hatchedEgg": self.hatched_egg, + + # Tirso quest + "herbs1": lambda state: self.herbs(state) >= 1, + "herbs2": lambda state: self.herbs(state) >= 2, + "herbs3": lambda state: self.herbs(state) >= 3, + "herbs4": lambda state: self.herbs(state) >= 4, + "herbs5": lambda state: self.herbs(state) >= 5, + "herbs6": lambda state: self.herbs(state) >= 6, + + # Tentudia quest + "tentudiaRemains1": lambda state: self.tentudia_remains(state) >= 1, + "tentudiaRemains2": lambda state: self.tentudia_remains(state) >= 2, + "tentudiaRemains3": lambda state: self.tentudia_remains(state) >= 3, + + # Gemino quest + "emptyThimble": self.empty_thimble, + "fullThimble": self.full_thimble, + "driedFlowers": self.dried_flowers, + + # Altasgracias quest + "ceremonyItems3": lambda state: self.ceremony_items(state) >= 3, + "egg": self.egg, + + # Redento quest + # skip "limestones", not actually used + # skip "knots", not actually used + + # Cleofas quest + "marksOfRefuge3": lambda state: self.marks_of_refuge(state) >= 3, + "cord": self.cord, + + # Crisanta quest + "scapular": self.scapular, + "trueHeart": self.true_heart, + "traitorEyes2": lambda state: self.traitor_eyes(state) >= 2, + + # Jibrael quest + "bell": self.bell, + "verses4": lambda state: self.verses(state) >= 4, + + # Movement tech + "canAirStall": self.can_air_stall, + "canDawnJump": self.can_dawn_jump, + "canWaterJump": self.can_water_jump, + + # Breakable tech + "canBreakHoles": self.can_break_holes, + "canDiveLaser": self.can_dive_laser, + + # Root tech + "canWalkOnRoot": self.can_walk_on_root, + "canClimbOnRoot": self.can_climb_on_root, + + # Lung tech + "canSurvivePoison1": self.can_survive_poison_1, + "canSurvivePoison2": self.can_survive_poison_2, + "canSurvivePoison3": self.can_survive_poison_3, + + # Enemy tech + "canEnemyBounce": self.can_enemy_bounce, + "canEnemyUpslash": self.can_enemy_upslash, + + # Reaching rooms + "guiltRooms1": lambda state: self.guilt_rooms(state) >= 1, + "guiltRooms2": lambda state: self.guilt_rooms(state) >= 2, + "guiltRooms3": lambda state: self.guilt_rooms(state) >= 3, + "guiltRooms4": lambda state: self.guilt_rooms(state) >= 4, + "guiltRooms5": lambda state: self.guilt_rooms(state) >= 5, + "guiltRooms6": lambda state: self.guilt_rooms(state) >= 6, + "guiltRooms7": lambda state: self.guilt_rooms(state) >= 7, + + "swordRooms1": lambda state: self.sword_rooms(state) >= 1, + "swordRooms2": lambda state: self.sword_rooms(state) >= 2, + "swordRooms3": lambda state: self.sword_rooms(state) >= 3, + "swordRooms4": lambda state: self.sword_rooms(state) >= 4, + "swordRooms5": lambda state: self.sword_rooms(state) >= 5, + "swordRooms6": lambda state: self.sword_rooms(state) >= 6, + "swordRooms7": lambda state: self.sword_rooms(state) >= 7, + + "redentoRooms2": lambda state: self.redento_rooms(state) >= 2, + "redentoRooms3": lambda state: self.redento_rooms(state) >= 3, + "redentoRooms4": lambda state: self.redento_rooms(state) >= 4, + "redentoRooms5": lambda state: self.redento_rooms(state) >= 5, + + "miriamRooms5": lambda state: self.miriam_rooms(state) >= 5, + + "amanecidaRooms1": lambda state: self.amanecida_rooms(state) >= 1, + "amanecidaRooms2": lambda state: self.amanecida_rooms(state) >= 2, + "amanecidaRooms3": lambda state: self.amanecida_rooms(state) >= 3, + "amanecidaRooms4": lambda state: self.amanecida_rooms(state) >= 4, + + "chaliceRooms3": lambda state: self.chalice_rooms(state) >= 3, + + # Crossing gaps + "canCrossGap1": self.can_cross_gap_1, + "canCrossGap2": self.can_cross_gap_2, + "canCrossGap3": self.can_cross_gap_3, + "canCrossGap4": self.can_cross_gap_4, + "canCrossGap5": self.can_cross_gap_5, + "canCrossGap6": self.can_cross_gap_6, + "canCrossGap7": self.can_cross_gap_7, + "canCrossGap8": self.can_cross_gap_8, + "canCrossGap9": self.can_cross_gap_9, + "canCrossGap10": self.can_cross_gap_10, + "canCrossGap11": self.can_cross_gap_11, + + # Events in different scenes + "openedDCGateW": self.opened_dc_gate_w, + "openedDCGateE": self.opened_dc_gate_e, + "openedDCLadder": self.opened_dc_ladder, + "openedWOTWCave": self.opened_wotw_cave, + "rodeGotPElevator": self.rode_gotp_elevator, + "openedConventLadder": self.opened_convent_ladder, + "brokeJondoBellW": self.broke_jondo_bell_w, + "brokeJondoBellE": self.broke_jondo_bell_e, + "openedMoMLadder": self.opened_mom_ladder, + "openedTSCGate": self.opened_tsc_gate, + "openedARLadder": self.opened_ar_ladder, + "brokeBotTCStatue": self.broke_bottc_statue, + "openedWotHPGate": self.opened_wothp_gate, + "openedBotSSLadder": self.opened_botss_ladder, + + # Special skips + "upwarpSkipsAllowed": self.upwarp_skips_allowed, + "mourningSkipAllowed": self.mourning_skip_allowed, + "enemySkipsAllowed": self.enemy_skips_allowed, + "obscureSkipsAllowed": self.obscure_skips_allowed, + "preciseSkipsAllowed": self.precise_skips_allowed, + + # Bosses + "canBeatBrotherhoodBoss": self.can_beat_brotherhood_boss, + "canBeatMercyBoss": self.can_beat_mercy_boss, + "canBeatConventBoss": self.can_beat_convent_boss, + "canBeatGrievanceBoss": self.can_beat_grievance_boss, + "canBeatBridgeBoss": self.can_beat_bridge_boss, + "canBeatMothersBoss": self.can_beat_mothers_boss, + "canBeatCanvasesBoss": self.can_beat_canvases_boss, + "canBeatPrisonBoss": self.can_beat_prison_boss, + "canBeatRooftopsBoss": self.can_beat_rooftops_boss, + "canBeatOssuaryBoss": self.can_beat_ossuary_boss, + "canBeatMourningBoss": self.can_beat_mourning_boss, + "canBeatGraveyardBoss": self.can_beat_graveyard_boss, + "canBeatJondoBoss": self.can_beat_jondo_boss, + "canBeatPatioBoss": self.can_beat_patio_boss, + "canBeatWallBoss": self.can_beat_wall_boss, + "canBeatHallBoss": self.can_beat_hall_boss, + "canBeatPerpetua": self.can_beat_perpetua, + "canBeatLegionary": self.can_beat_legionary + } -def total_fervour(state: CollectionState, player: int) -> int: - totalFervour: int = 60 + (20 * state.count("Fervour Upgrade", player)) + (10 * state.count("Bead of Blue Wax", player)) - - return totalFervour - - -def aubade(state: CollectionState, player: int) -> bool: - return state.has("Aubade of the Nameless Guardian", player) if total_fervour(state, player) >= 90 else False - - -def tirana(state: CollectionState, player: int) -> bool: - return state.has("Tirana of the Celestial Bastion", player) if total_fervour(state, player) >= 90 else False - - -def pillar(state: CollectionState, player: int) -> bool: - return state.has_any({"Debla of the Lights", "Taranto to my Sister", "Cloistered Ruby"}, player) + boss_strength_indirect_regions: List[str] = [ + # flasks + "D01Z05S05[SW]", + "D02Z02S04[W]", + "D03Z02S08[W]", + "D03Z03S04[SW]", + "D04Z02S13[W]", + "D05Z01S08[NW]", + "D20Z01S07[NE]", + # quicksilver + "D01Z05S01[W]" + ] + + guilt_indirect_regions: List[str] = [ + "D01Z04S01[NE]", + "D02Z02S11[W]", + "D03Z03S02[NE]", + "D04Z02S02[SE]", + "D05Z01S05[NE]", + "D09Z01S05[W]", + "D17Z01S04[W]" + ] + + sword_indirect_regions: List[str] = [ + "D01Z02S07[E]", + "D01Z02S02[SW]", + "D20Z01S04[E]", + "D01Z05S23[W]", + "D02Z03S02[NE]", + "D04Z02S21[NE]", + "D05Z01S21[NW]", + "D06Z01S15[NE]", + "D17Z01S07[SW]" + ] + + redento_indirect_regions: List[str] = [ + "D03Z01S04[E]", + "D03Z02S10[N]", + "D17Z01S05[S]", + "D17BZ02S01[FrontR]", + "D01Z03S04[E]", + "D08Z01S01[W]", + "D04Z01S03[E]", + "D04Z02S01[W]", + "D06Z01S18[-Cherubs]", + "D04Z02S08[E]", + "D04BZ02S01[Redento]", + "D17Z01S07[NW]" + ] + + miriam_indirect_regions: List[str] = [ + "D02Z03S07[NWW]", + "D03Z03S07[NW]", + "D04Z04S01[E]", + "D05Z01S06[W]", + "D06Z01S17[E]" + ] + + chalice_indirect_regions: List[str] = [ + "D03Z01S02[E]", + "D01Z05S02[W]", + "D20Z01S03[N]", + "D05Z01S11[SE]", + "D05Z02S02[NW]", + "D09Z01S09[E]", + "D09Z01S10[W]", + "D09Z01S08[SE]", + "D09Z01S02[SW]" + ] + + self.indirect_regions: Dict[str, List[str]] = { + "openedDCGateW": ["D20Z01S04[E]", + "D01Z05S23[W]"], + "openedDCGateE": ["D01Z05S10[SE]", + "D01Z04S09[W]"], + "openedDCLadder": ["D01Z05S25[NE]", + "D01Z05S02[S]"], + "openedWOTWCave": ["D02Z01S01[SW]", + "D02Z01S08[E]", + "D02Z01S02[]"], + "rodeGotPElevator": ["D02Z03S14[E]", + "D02Z02S13[W]", + "D02Z02S06[E]", + "D02Z02S12[W]", + "D02Z02S08[W]"], + "openedConventLadder": ["D02Z03S02[N]", + "D02Z03S15[E]", + "D02Z03S19[E]", + "D02Z03S10[W]", + "D02Z03S22[W]"], + "brokeJondoBellW": ["D03Z02S08[N]", + "D03Z02S12[E]", + "D03Z02S10[S]", + "D03Z02S10[-Cherubs]"], + "brokeJondoBellE": ["D03Z02S04[NE]", + "D03Z02S11[W]", + "D03Z02S03[E]"], + "openedMoMLadder": ["D04Z02S11[E]", + "D04Z02S09[W]", + "D06Z01S23[S]", + "D04Z02S04[N]"], + "openedTSCGate": ["D05Z02S06[SE]", + "D05Z01S21[-Cherubs]"], + "openedARLadder": ["D06Z01S22[Sword]", + "D06Z01S20[W]", + "D04Z02S06[N]", + "D06Z01S01[-Cherubs]"], + "brokeBotTCStatue": ["D08Z03S03[W]", + "D08Z02S03[W]"], + "openedWotHPGate": ["D09Z01S13[E]", + "D09Z01S03[W]", + "D09Z01S08[W]"], + "openedBotSSLadder": ["D17Z01S05[S]", + "D17BZ02S01[FrontR]"], + "canBeatBrotherhoodBoss": [*boss_strength_indirect_regions, + "D17Z01S05[E]", + "D17Z01S03[W]"], + "canBeatMercyBoss": [*boss_strength_indirect_regions, + "D01Z04S19[E]", + "D01Z04S12[W]"], + "canBeatConventBoss": [*boss_strength_indirect_regions, + "D02Z03S09[E]", + "D02Z03S21[W]"], + "canBeatGrievanceBoss": [*boss_strength_indirect_regions, + "D03Z03S11[E]", + "D03Z03S16[W]"], + "canBeatBridgeBoss": [*boss_strength_indirect_regions, + "D01Z03S06[E]", + "D08Z02S01[W]"], + "canBeatMothersBoss": [*boss_strength_indirect_regions, + "D04Z02S15[E]", + "D04Z02S21[W]"], + "canBeatCanvasesBoss": [*boss_strength_indirect_regions, + "D05Z02S06[NE]", + "D05Z01S21[SW]"], + "canBeatPrisonBoss": [*boss_strength_indirect_regions, + "D09Z01S05[SE]", + "D09Z01S08[S]"], + "canBeatRooftopsBoss": [*boss_strength_indirect_regions, + "D06Z01S19[E]", + "D07Z01S01[W]"], + "canBeatOssuaryBoss": [*boss_strength_indirect_regions, + "D01BZ06S01[E]"], + "canBeatMourningBoss": [*boss_strength_indirect_regions, + "D20Z02S07[W]"], + "canBeatGraveyardBoss": [*boss_strength_indirect_regions, + "D01Z06S01[Santos]", + "D02Z03S18[NW]", + "D02Z02S03[NE]"], + "canBeatJondoBoss": [*boss_strength_indirect_regions, + "D01Z06S01[Santos]", + "D20Z01S06[NE]", + "D20Z01S04[W]", + "D03Z01S04[E]", + "D03Z02S10[N]"], + "canBeatPatioBoss": [*boss_strength_indirect_regions, + "D01Z06S01[Santos]", + "D06Z01S02[W]", + "D04Z01S03[E]", + "D04Z01S01[W]", + "D06Z01S18[-Cherubs]"], + "canBeatWallBoss": [*boss_strength_indirect_regions, + "D01Z06S01[Santos]", + "D09Z01S09[Cell24]", + "D09Z01S11[E]", + "D06Z01S13[W]"], + "canBeatHallBoss": [*boss_strength_indirect_regions, + "D08Z01S02[NE]", + "D08Z03S02[NW]"], + "canBeatPerpetua": boss_strength_indirect_regions, + "canBeatLegionary": boss_strength_indirect_regions, + "guiltRooms1": guilt_indirect_regions, + "guiltRooms2": guilt_indirect_regions, + "guiltRooms3": guilt_indirect_regions, + "guiltRooms4": guilt_indirect_regions, + "guiltRooms5": guilt_indirect_regions, + "guiltRooms6": guilt_indirect_regions, + "guiltRooms7": guilt_indirect_regions, + "swordRooms1": sword_indirect_regions, + "swordRooms2": sword_indirect_regions, + "swordRooms3": sword_indirect_regions, + "swordRooms4": sword_indirect_regions, + "swordRooms5": sword_indirect_regions, + "swordRooms6": sword_indirect_regions, + "swordRooms7": sword_indirect_regions, + "redentoRooms2": redento_indirect_regions, + "redentoRooms3": redento_indirect_regions, + "redentoRooms4": redento_indirect_regions, + "redentoRooms5": redento_indirect_regions, + "miriamRooms5": miriam_indirect_regions, + "chaliceRooms3": chalice_indirect_regions + } + self.indirect_regions["amanecidaRooms1"] = [*self.indirect_regions["canBeatGraveyardBoss"], + *self.indirect_regions["canBeatJondoBoss"], + *self.indirect_regions["canBeatPatioBoss"], + *self.indirect_regions["canBeatWallBoss"]] + self.indirect_regions["amanecidaRooms2"] = [*self.indirect_regions["canBeatGraveyardBoss"], + *self.indirect_regions["canBeatJondoBoss"], + *self.indirect_regions["canBeatPatioBoss"], + *self.indirect_regions["canBeatWallBoss"]] + self.indirect_regions["amanecidaRooms3"] = [*self.indirect_regions["canBeatGraveyardBoss"], + *self.indirect_regions["canBeatJondoBoss"], + *self.indirect_regions["canBeatPatioBoss"], + *self.indirect_regions["canBeatWallBoss"]] + self.indirect_regions["amanecidaRooms4"] = [*self.indirect_regions["canBeatGraveyardBoss"], + *self.indirect_regions["canBeatJondoBoss"], + *self.indirect_regions["canBeatPatioBoss"], + *self.indirect_regions["canBeatWallBoss"]] + + + def req_is_region(self, string: str) -> bool: + return (string[0] == "D" and string[3] == "Z" and string[6] == "S")\ + or (string[0] == "D" and string[3] == "B" and string[4] == "Z" and string[7] == "S") + + def load_rule(self, obj_is_region: bool, name: str, obj: Dict[str, Any]) -> Callable[[CollectionState], bool]: + clauses = [] + for clause in obj["logic"]: + reqs = [] + for req in clause["item_requirements"]: + if self.req_is_region(req): + if obj_is_region: + # add to indirect conditions if object and requirement are doors + self.indirect_conditions.append((req, f"{name} -> {obj['target']}")) + reqs.append(lambda state, req=req: state.can_reach_region(req, self.player)) + else: + if obj_is_region and req in self.indirect_regions: + # add to indirect conditions if object is door and requirement has list of regions + for region in self.indirect_regions[req]: + self.indirect_conditions.append((region, f"{name} -> {obj['target']}")) + reqs.append(self.string_rules[req]) + if len(reqs) == 1: + clauses.append(reqs[0]) + else: + clauses.append(lambda state, reqs=reqs: all(req(state) for req in reqs)) + if not clauses: + return lambda state: True + elif len(clauses) == 1: + return clauses[0] + else: + return lambda state: any(clause(state) for clause in clauses) -def charge_beam(state: CollectionState, player: int) -> bool: - return state.has("Charged Skill", player, 3) + # Relics + def blood(self, state: CollectionState) -> bool: + return state.has("Blood Perpetuated in Sand", self.player) + + def root(self, state: CollectionState) -> bool: + return state.has("Three Gnarled Tongues", self.player) + def linen(self, state: CollectionState) -> bool: + return state.has("Linen of Golden Thread", self.player) + + def nail(self, state: CollectionState) -> bool: + return state.has("Nail Uprooted from Dirt", self.player) + + def shroud(self, state: CollectionState) -> bool: + return state.has("Shroud of Dreamt Sins", self.player) -def can_air_stall(state: CollectionState, logic: int, player: int) -> bool: - return state.has("Ranged Skill", player) if logic >= 1 else False + def lung(self, state: CollectionState) -> bool: + return state.has("Silvered Lung of Dolphos", self.player) + + # Keys + def bronze_key(self, state: CollectionState) -> bool: + return state.has("Key of the Secular", self.player) + + def silver_key(self, state: CollectionState) -> bool: + return state.has("Key of the Scribe", self.player) + + def gold_key(self, state: CollectionState) -> bool: + return state.has("Key of the Inquisitor", self.player) + def peaks_key(self, state: CollectionState) -> bool: + return state.has("Key of the High Peaks", self.player) + + def elder_key(self, state: CollectionState) -> bool: + return state.has("Key to the Chamber of the Eldest Brother", self.player) + + def wood_key(self, state: CollectionState) -> bool: + return state.has("Key Grown from Twisted Wood", self.player) + + # Collections + def cherubs(self, state: CollectionState) -> int: + return state.count("Child of Moonlight", self.player) + + def bones(self, state: CollectionState) -> int: + return state.count_group_unique("bones", self.player) + + # def tears(): -def can_dawn_jump(state: CollectionState, logic: int, player: int) -> bool: - return state.has_all({"Brilliant Heart of Dawn", "Dash Ability"}, player) if logic >= 1 else False + # Special items + def dash(self, state: CollectionState) -> bool: + return state.has("Dash Ability", self.player) + def wall_climb(self, state: CollectionState) -> bool: + return state.has("Wall Climb Ability", self.player) + + #def air_impulse(): -def can_water_jump(state: CollectionState, player: int) -> bool: - return state.has_any({"Nail Uprooted from Dirt", "Purified Hand of the Nun"}, player) + def boots(self, state: CollectionState) -> bool: + return state.has("Boots of Pleading", self.player) + + def double_jump(self, state: CollectionState) -> bool: + return state.has("Purified Hand of the Nun", self.player) + + # Speed boosts + def wheel(self, state: CollectionState) -> bool: + return state.has("The Young Mason's Wheel", self.player) + + def dawn_heart(self, state: CollectionState) -> bool: + return state.has("Brilliant Heart of Dawn", self.player) + + # Health boosts + def flasks(self, state: CollectionState) -> int: + doors = { + "D01Z05S05[SW]", + "D02Z02S04[W]", + "D03Z02S08[W]", + "D03Z03S04[SW]", + "D04Z02S13[W]", + "D05Z01S08[NW]", + "D20Z01S07[NE]" + } + return state.count("Empty Bile Vessel", self.player) \ + if sum(state.can_reach_region(door, self.player) for door in doors) >= 1 else 0 + + def quicksilver(self, state: CollectionState) -> int: + return state.count("Quicksilver", self.player) if state.can_reach_region("D01Z05S01[W]", self.player) else 0 + + # Puzzles + def red_wax(self, state: CollectionState) -> int: + return state.count("Bead of Red Wax", self.player) + + def blue_wax(self, state: CollectionState) -> int: + return state.count("Bead of Blue Wax", self.player) + + def chalice(self, state: CollectionState) -> bool: + return state.has("Chalice of Inverted Verses", self.player) + + # Cherubs + def debla(self, state: CollectionState) -> bool: + return state.has("Debla of the Lights", self.player) + + def lorquiana(self, state: CollectionState) -> bool: + return state.has("Lorquiana", self.player) + + def zarabanda(self, state: CollectionState) -> bool: + return state.has("Zarabanda of the Safe Haven", self.player) + + def taranto(self, state: CollectionState) -> bool: + return state.has("Taranto to my Sister", self.player) + + def verdiales(self, state: CollectionState) -> bool: + return state.has("Verdiales of the Forsaken Hamlet", self.player) + + def cante(self, state: CollectionState) -> bool: + return state.has("Cante Jondo of the Three Sisters", self.player) + + def cantina(self, state: CollectionState) -> bool: + return state.has("Cantina of the Blue Rose", self.player) -def can_break_holes(state: CollectionState, player: int) -> bool: - return ( - state.has_any({"Charged Skill", "Dive Skill"}, player) - or ( - state.has("Lunge Skill", player, 3) - and state.has("Dash Ability", player) + def aubade(self, state: CollectionState) -> bool: + return ( + state.has("Aubade of the Nameless Guardian", self.player) + and self.total_fervour(state) >= 90 + ) + + def tirana(self, state: CollectionState) -> bool: + return ( + state.has("Tirana of the Celestial Bastion", self.player) + and self.total_fervour(state) >= 90 ) - or state.has_group("prayer", player) - or aubade(state, player) - or tirana(state, player) - ) - - -def can_break_tirana(state: CollectionState, logic: int, player: int) -> bool: - return tirana(state, player) if logic >= 2 else False - - -def can_dive_laser(state: CollectionState, logic: int, player: int) -> bool: - return state.has("Dive Skill", player, 3) if logic >= 2 else False - - -def can_walk_on_root(state: CollectionState, player: int) -> bool: - return state.has("Three Gnarled Tongues", player) - - -def can_climb_on_root(state: CollectionState, player: int) -> bool: - return state.has_all({"Three Gnarled Tongues", "Wall Climb Ability"}, player) - - -def can_survive_poison(state: CollectionState, logic: int, player: int, number: int) -> bool: - if number == 1: - if logic >= 2: - return True - elif logic == 1: - return state.has_any({"Silvered Lung of Dolphos", "Tiento to your Thorned Hairs"}, player) - elif logic == 0: - return state.has("Silvered Lung of Dolphos", player) - elif number == 2: - if logic >= 1: - return state.has_any({"Silvered Lung of Dolphos", "Tiento to your Thorned Hairs"}, player) - else: - return state.has("Silvered Lung of Dolphos", player) - elif number == 3: - if logic >= 2 and total_fervour(state, player) >= 120: - return state.has_any({"Silvered Lung of Dolphos", "Tiento to your Thorned Hairs"}, player) - else: - return state.has("Silvered Lung of Dolphos", player) + def ruby(self, state: CollectionState) -> bool: + return state.has("Cloistered Ruby", self.player) + + def tiento(self, state: CollectionState) -> bool: + return state.has("Tiento to my Sister", self.player) + + def any_small_prayer(self, state: CollectionState) -> bool: + return ( + self.debla(state) + or self.lorquiana(state) + or self.zarabanda(state) + or self.taranto(state) + or self.verdiales(state) + or self.cante(state) + or self.cantina(state) + or self.tiento(state) + or state.has_any({ + "Campanillero to the Sons of the Aurora", + "Mirabras of the Return to Port", + "Romance to the Crimson Mist", + "Saeta Dolorosa", + "Seguiriya to your Eyes like Stars", + "Verdiales of the Forsaken Hamlet", + "Zambra to the Resplendent Crown" + }, self.player) + ) + + def pillar(self, state: CollectionState) -> bool: + return ( + self.debla(state) + or self.taranto(state) + or self.ruby(state) + ) + + def can_use_any_prayer(self, state: CollectionState) -> bool: + return ( + self.any_small_prayer(state) + or self.tirana(state) + or self.aubade(state) + ) -def can_enemy_bounce(logic: int, enemy: int) -> bool: # TODO - return enemy_skips_allowed(logic, enemy) + # Stats + def total_fervour(self, state: CollectionState) -> int: + return ( + 60 + + (20 * min(6, state.count("Fervour Upgrade", self.player))) + + (10 * min(3, state.count("Bead of Blue Wax", self.player))) + ) + # Skills + def combo(self, state: CollectionState) -> int: + return state.count("Combo Skill", self.player) -def can_enemy_upslash(state: CollectionState, logic: int, enemy: int, player: int) -> bool: - return state.has("Combo Skill", player, 2) and \ - enemy_skips_allowed(logic, enemy) + def charged(self, state: CollectionState) -> int: + return state.count("Charged Skill", self.player) + def ranged(self, state: CollectionState) -> int: + return state.count("Ranged Skill", self.player) + + def dive(self, state: CollectionState) -> int: + return state.count("Dive Skill", self.player) + + def lunge(self, state: CollectionState) -> int: + return state.count("Lunge Skill", self.player) + + def charge_beam(self, state: CollectionState) -> bool: + return self.charged(state) >= 3 + + # Main quest + def holy_wounds(self, state: CollectionState) -> int: + return state.count_group_unique("wounds", self.player) + + def masks(self, state: CollectionState) -> int: + return state.count_group_unique("masks", self.player) + + def guilt_bead(self, state: CollectionState) -> bool: + return state.has("Weight of True Guilt", self.player) + + # LOTL quest + def cloth(self, state: CollectionState) -> bool: + return state.has("Linen Cloth", self.player) + + def hand(self, state: CollectionState) -> bool: + return state.has("Severed Hand", self.player) -def can_cross_gap(state: CollectionState, logic: int, player: int, number: int) -> bool: - if number == 1: + def hatched_egg(self, state: CollectionState) -> bool: + return state.has("Hatched Egg of Deformity", self.player) + + # Tirso quest + def herbs(self, state: CollectionState) -> int: + return state.count_group_unique("tirso", self.player) + + # Tentudia quest + def tentudia_remains(self, state: CollectionState) -> int: + return state.count_group_unique("tentudia", self.player) + + # Gemino quest + def empty_thimble(self, state: CollectionState) -> bool: + return state.has("Empty Golden Thimble", self.player) + + def full_thimble(self, state: CollectionState) -> bool: + return state.has("Golden Thimble Filled with Burning Oil", self.player) + + def dried_flowers(self, state: CollectionState) -> bool: + return state.has("Dried Flowers bathed in Tears", self.player) + + # Altasgracias quest + def ceremony_items(self, state: CollectionState) -> int: + return state.count_group_unique("egg", self.player) + + def egg(self, state: CollectionState) -> bool: + return state.has("Egg of Deformity", self.player) + + # Redento quest + def limestones(self, state: CollectionState) -> int: + return state.count_group_unique("toe", self.player) + + def knots(self, state: CollectionState) -> int: + return state.count("Knot of Rosary Rope", self.player) if state.can_reach_region("D17Z01S07[NW]", self.player)\ + else 0 + + # Cleofas quest + def marks_of_refuge(self, state: CollectionState) -> int: + return state.count_group_unique("marks", self.player) + + def cord(self, state: CollectionState) -> bool: + return state.has("Cord of the True Burying", self.player) + + # Crisanta quest + def scapular(self, state: CollectionState) -> bool: + return state.has("Incomplete Scapular", self.player) + + def true_heart(self, state: CollectionState) -> bool: + return state.has("Apodictic Heart of Mea Culpa", self.player) + + def traitor_eyes(self, state: CollectionState) -> int: + return state.count_group_unique("eye", self.player) + + # Jibrael quest + def bell(self, state: CollectionState) -> bool: + return state.has("Petrified Bell", self.player) + + def verses(self, state: CollectionState) -> int: + return state.count("Verses Spun from Gold", self.player) + + # Movement tech + def can_air_stall(self, state: CollectionState) -> bool: return ( - state.has_any({"Purified Hand of the Nun", "The Young Mason's Wheel"}, player) - or can_dawn_jump(state, logic, player) - or can_air_stall(state, logic, player) + self.ranged(state) > 0 + and self.world.options.difficulty >= 1 ) - elif number == 2: + + def can_dawn_jump(self, state: CollectionState) -> bool: return ( - state.has_any({"Purified Hand of the Nun", "The Young Mason's Wheel"}, player) - or can_dawn_jump(state, logic, player) + self.dawn_heart(state) + and self.dash(state) + and self.world.options.difficulty >= 1 ) - elif number == 3: + + def can_water_jump(self, state: CollectionState) -> bool: return ( - state.has("Purified Hand of the Nun", player) - or can_dawn_jump(state, logic, player) - or ( - state.has("The Young Mason's Wheel", player) - and can_air_stall(state, logic, player) - ) + self.nail(state) + or self.double_jump(state) + ) + + # Breakable tech + def can_break_holes(self, state: CollectionState) -> bool: + return ( + self.charged(state) > 0 + or self.dive(state) > 0 + or self.lunge(state) >= 3 and self.dash(state) + or self.can_use_any_prayer(state) + ) + + def can_dive_laser(self, state: CollectionState) -> bool: + return ( + self.dive(state) >= 3 + and self.world.options.difficulty >= 2 + ) + + # Root tech + def can_walk_on_root(self, state: CollectionState) -> bool: + return self.root(state) + + def can_climb_on_root(self, state: CollectionState) -> bool: + return ( + self.root(state) + and self.wall_climb(state) + ) + + # Lung tech + def can_survive_poison_1(self, state: CollectionState) -> bool: + return ( + self.lung(state) + or self.world.options.difficulty >= 1 + and self.tiento(state) + or self.world.options.difficulty >= 2 + ) + + def can_survive_poison_2(self, state: CollectionState) -> bool: + return ( + self.lung(state) + or self.world.options.difficulty >= 1 + and self.tiento(state) + ) + + def can_survive_poison_3(self, state: CollectionState) -> bool: + return ( + self.lung(state) + or self.world.options.difficulty >= 2 + and self.tiento(state) + and self.total_fervour(state) >= 120 + ) + + # Enemy tech + def can_enemy_bounce(self, state: CollectionState) -> bool: + return self.enemy_skips_allowed(state) + + def can_enemy_upslash(self, state: CollectionState) -> bool: + return ( + self.combo(state) >= 2 + and self.enemy_skips_allowed(state) + ) + + # Crossing gaps + def can_cross_gap_1(self, state: CollectionState) -> bool: + return ( + self.double_jump(state) + or self.can_dawn_jump(state) + or self.wheel(state) + or self.can_air_stall(state) + ) + + def can_cross_gap_2(self, state: CollectionState) -> bool: + return ( + self.double_jump(state) + or self.can_dawn_jump(state) + or self.wheel(state) ) - elif number == 4: + + def can_cross_gap_3(self, state: CollectionState) -> bool: + return ( + self.double_jump(state) + or self.can_dawn_jump(state) + or self.wheel(state) + and self.can_air_stall(state) + ) + + def can_cross_gap_4(self, state: CollectionState) -> bool: return ( - state.has("Purified Hand of the Nun", player) - or can_dawn_jump(state, logic, player) + self.double_jump(state) + or self.can_dawn_jump(state) ) - elif number == 5: + + def can_cross_gap_5(self, state: CollectionState) -> bool: return ( - state.has("Purified Hand of the Nun", player) - or ( - can_dawn_jump(state, logic, player) - and can_air_stall(state, logic, player)) + self.double_jump(state) + or self.can_dawn_jump(state) + and self.can_air_stall(state) ) - elif number == 6: - return state.has("Purified Hand of the Nun", player) - elif number == 7: + + def can_cross_gap_6(self, state: CollectionState) -> bool: + return self.double_jump(state) + + def can_cross_gap_7(self, state: CollectionState) -> bool: return ( - state.has("Purified Hand of the Nun", player) + self.double_jump(state) and ( - can_dawn_jump(state, logic, player) - or state.has("The Young Mason's Wheel", player) - or can_air_stall(state, logic, player) + self.can_dawn_jump(state) + or self.wheel(state) + or self.can_air_stall(state) ) ) - elif number == 8: + + def can_cross_gap_8(self, state: CollectionState) -> bool: return ( - state.has("Purified Hand of the Nun", player) + self.double_jump(state) and ( - can_dawn_jump(state, logic, player) - or state.has("The Young Mason's Wheel", player) + self.can_dawn_jump(state) + or self.wheel(state) ) ) - elif number == 9: + + def can_cross_gap_9(self, state: CollectionState) -> bool: return ( - state.has("Purified Hand of the Nun", player) + self.double_jump(state) and ( - can_dawn_jump(state, logic, player) - or state.has("The Young Mason's Wheel", player) - and can_air_stall(state, logic, player) + self.can_dawn_jump(state) + or self.wheel(state) + and self.can_air_stall(state) ) ) - elif number == 10: + + def can_cross_gap_10(self, state: CollectionState) -> bool: return ( - state.has("Purified Hand of the Nun", player) - and can_dawn_jump(state, logic, player) + self.double_jump(state) + and self.can_dawn_jump(state) ) - elif number == 11: + + def can_cross_gap_11(self, state: CollectionState) -> bool: return ( - state.has("Purified Hand of the Nun", player) - and can_dawn_jump(state, logic, player) - and can_air_stall(state, logic, player) + self.double_jump(state) + and self.can_dawn_jump(state) + and self.can_air_stall(state) ) - -def can_ride_albero_elevator(state: CollectionState, player: int) -> bool: - return state.has_any({"D02Z02S11[NW]", "D02Z02S11[NE]", "D02Z02S11[W]", "D02Z02S11[E]", \ - "D02Z02S11[SE]"}, player) - - -def opened_dc_gate_w(state: CollectionState, player: int) -> bool: - return state.has_any({"D01Z05S24[W]", "D01Z05S24[E]"}, player) - - -def opened_dc_gate_e(state: CollectionState, player: int) -> bool: - return state.has_any({"D01Z05S12[W]", "D01Z05S12[E]"}, player) - - -def opened_dc_ladder(state: CollectionState, player: int) -> bool: - return state.has_any({"D01Z05S20[W]", "D01Z05S20[N]"}, player) - - -def opened_wotw_cave(state: CollectionState, player: int) -> bool: - return ( - state.has("D02Z01S06[E]", player) - or state.has("Wall Climb Ability", player) - and ( - state.has("D02Z01S06[W]", player) - or state.has("D02Z01S06[Cherubs]", player) + # Events that trigger in different scenes + def opened_dc_gate_w(self, state: CollectionState) -> bool: + return ( + state.can_reach_region("D20Z01S04[E]", self.player) + or state.can_reach_region("D01Z05S23[W]", self.player) ) - ) - - -def rode_gotp_elevator(state: CollectionState, player: int) -> bool: - return state.has_any({"D02Z02S11[NW]", "D02Z02S11[NE]", "D02Z02S11[W]", "D02Z02S11[E]", \ - "D02Z02S11[SE]"}, player) - - -def opened_convent_ladder(state: CollectionState, player: int) -> bool: - return state.has_any({"D02Z03S11[S]", "D02Z03S11[W]", "D02Z03S11[NW]", "D02Z03S11[E]", \ - "D02Z03S11[NE]"}, player) - - -def broke_jondo_bell_w(state: CollectionState, player: int) -> bool: - return ( - state.has("D03Z02S09[S]", player) - or state.has("D03Z02S09[W]", player) - and state.has("Dash Ability", player) - or state.has("D03Z02S09[N]", player) - or state.has("D03Z02S09[Cherubs]", player) - ) - - -def broke_jondo_bell_e(state: CollectionState, logic: int, enemy: int, player: int) -> bool: - return ( - state.has("D03Z02S05[S]", player) - or state.has("D03Z02S05[E]", player) - or state.has("D03Z02S05[W]", player) - and ( - can_cross_gap(state, logic, player, 5) - or can_enemy_bounce(logic, enemy) - and can_cross_gap(state, logic, player, 3) + + def opened_dc_gate_e(self, state: CollectionState) -> bool: + return ( + state.can_reach_region("D01Z05S10[SE]", self.player) + or state.can_reach_region("D01Z04S09[W]", self.player) ) - ) - - -def opened_mom_ladder(state: CollectionState, player: int) -> bool: - return state.has_any({"D04Z02S06[NW]", "D04Z02S06[NE]", "D04Z02S06[N]", "D04Z02S06[S]"}, player) - - -def opened_tsc_gate(state: CollectionState, player: int) -> bool: - return state.has_any({"D05Z02S11[W]", "D05Z02S11[Cherubs]"}, player) - - -def opened_ar_ladder(state: CollectionState, player: int) -> bool: - return state.has_any({"D06Z01S23[Sword]", "D06Z01S23[E]", "D06Z01S23[S]", "D06Z01S23[Cherubs]"}, player) - - -def broke_bottc_statue(state: CollectionState, player: int) -> bool: - return state.has_any({"D08Z01S02[NE]", "D08Z01S02[SE]"}, player) - - -def opened_wothp_gate(state: CollectionState, player: int) -> bool: - return state.has_any({"D09Z01S05[W]", "D09Z01S05[SE]", "D09Z01S05[NE]"}, player) - - -def opened_botss_ladder(state: CollectionState, player: int) -> bool: - return state.has_any({"D17Z01S04[N]", "D17Z01S04[FrontR]"}, player) - - -def upwarp_skips_allowed(logic: int) -> bool: - return logic >= 2 - - -def mourning_skips_allowed(logic: int) -> bool: - return logic >= 2 - - -def enemy_skips_allowed(logic: int, enemy: int) -> bool: - return logic >= 2 and enemy == 0 - - -def obscure_skips_allowed(logic): - return logic >= 2 - - -def precise_skips_allowed(logic): - return logic >= 2 - - -def can_beat_boss(state: CollectionState, boss: str, logic: int, player: int) -> bool: - def has_boss_strength(name: str) -> bool: - silver: int = state.count("Quicksilver", player) if state.has("D01Z05S27[E]", player) else 0 - flasks: int = state.count("Empty Bile Flask", player) if \ - state.has_any({"D01Z05S18[E]", "D02Z02S09[E]", "D03Z02S14[E]", "D03Z03S03[SE]", "D04Z02S13[W]", \ - "D05Z01S12[E]", "D20Z01S08[W]"}, player) else 0 - - - playerStrength: float = state.count("Life Upgrade", player) * 0.25 / 6 + \ - state.count("Mea Culpa Upgrade", player) * 0.25 / 7 + state.count("Fervour Upgrade", player) * 0.20 \ - / 6 + flasks * 0.15 / 8 + silver * 0.15 / 5 - - bosses: Dict[str, int] = { - "warden": -0.10, - "ten-piedad": 0.05, - "charred-visage": 0.20, - "tres-angustias": 0.15, - "esdras": 0.25, - "melquiades": 0.25, - "exposito": 0.30, - "quirce": 0.35, - "crisanta": 0.50, - "isidora": 0.70, - "sierpes": 0.70, - "amanecida": 0.60, - "laudes": 0.60, - "perpetua": -0.05, - "legionary": 0.20 - } - - bossStrength: int = bosses[name] - - return playerStrength >= (bossStrength - 0.10 if logic >= 2 else (bossStrength if logic >= 1 else bossStrength + 0.10)) - if boss == "Brotherhood": + def opened_dc_ladder(self, state: CollectionState) -> bool: return ( - has_boss_strength("warden") - and state.has_any({"D17Z01S11[W]", "D17Z01S11[E]"}, player) + state.can_reach_region("D01Z05S25[NE]", self.player) + or state.can_reach_region("D01Z05S02[S]", self.player) ) - elif boss == "Mercy": + + def opened_wotw_cave(self, state: CollectionState) -> bool: return ( - has_boss_strength("ten-piedad") - and state.has_any({"D01Z04S18[W]", "D01Z04S18[E]"}, player) + state.can_reach_region("D02Z01S01[SW]", self.player) + or self.wall_climb(state) + and state.can_reach_region("D02Z01S08[E]", self.player) + or state.can_reach_region("D02Z01S02[]", self.player) ) - elif boss == "Convent": + + def rode_gotp_elevator(self, state: CollectionState) -> bool: return ( - has_boss_strength("charred-visage") - and state.has_any({"D02Z03S20[W]", "D02Z03S20[E]"}, player) + state.can_reach_region("D02Z03S14[E]", self.player) + or state.can_reach_region("D02Z02S13[W]", self.player) + or state.can_reach_region("D02Z02S06[E]", self.player) + or state.can_reach_region("D02Z02S12[W]", self.player) + or state.can_reach_region("D02Z02S08[W]", self.player) ) - elif boss == "Grievance": + + def opened_convent_ladder(self, state: CollectionState) -> bool: return ( - has_boss_strength("tres-angustias") - and state.has_any({"Wall Climb Ability", "Purified Hand of the Nun"}, player) - and state.has_any({"D03Z03S15[W]", "D03Z03S15[E]"}, player) + state.can_reach_region("D02Z03S02[N]", self.player) + or state.can_reach_region("D02Z03S15[E]", self.player) + or state.can_reach_region("D02Z03S19[E]", self.player) + or state.can_reach_region("D02Z03S10[W]", self.player) + or state.can_reach_region("D02Z03S22[W]", self.player) ) - elif boss == "Bridge": + + def broke_jondo_bell_w(self, state: CollectionState) -> bool: return ( - has_boss_strength("esdras") - and state.has_any({"D08Z01S01[W]", "D08Z01S01[E]"}, player) + state.can_reach_region("D03Z02S08[N]", self.player) + or state.can_reach_region("D03Z02S12[E]", self.player) + and self.dash(state) + or state.can_reach_region("D03Z02S10[S]", self.player) + or state.can_reach_region("D03Z02S10[-Cherubs]", self.player) ) - elif boss == "Mothers": + + def broke_jondo_bell_e(self, state: CollectionState) -> bool: return ( - has_boss_strength("melquiades") - and state.has_any({"D04Z02S22[W]", "D04Z02S22[E]"}, player) + state.can_reach_region("D03Z02S04[NE]", self.player) + or state.can_reach_region("D03Z02S11[W]", self.player) + or state.can_reach_region("D03Z02S03[E]", self.player) + and ( + self.can_cross_gap_5(state) + or self.can_enemy_bounce(state) + and self.can_cross_gap_3(state) + ) ) - elif boss == "Canvases": + + def opened_mom_ladder(self, state: CollectionState) -> bool: return ( - has_boss_strength("exposito") - and state.has_any({"D05Z02S14[W]", "D05Z02S14[E]"}, player) + state.can_reach_region("D04Z02S11[E]", self.player) + or state.can_reach_region("D04Z02S09[W]", self.player) + or state.can_reach_region("D06Z01S23[S]", self.player) + or state.can_reach_region("D04Z02S04[N]", self.player) ) - elif boss == "Prison": + + def opened_tsc_gate(self, state: CollectionState) -> bool: return ( - has_boss_strength("quirce") - and state.has_any({"D09Z01S03[W]", "D09Z01S03[N]"}, player) + state.can_reach_region("D05Z02S06[SE]", self.player) + or state.can_reach_region("D05Z01S21[-Cherubs]", self.player) ) - elif boss == "Rooftops": + + def opened_ar_ladder(self, state: CollectionState) -> bool: return ( - has_boss_strength("crisanta") - and state.has_any({"D06Z01S25[W]", "D06Z01S25[E]"}, player) + state.can_reach_region("D06Z01S22[Sword]", self.player) + or state.can_reach_region("D06Z01S20[W]", self.player) + or state.can_reach_region("D04Z02S06[N]", self.player) + or state.can_reach_region("D06Z01S01[-Cherubs]", self.player) ) - elif boss == "Ossuary": + + def broke_bottc_statue(self, state: CollectionState) -> bool: return ( - has_boss_strength("isidora") - and state.has("D01BZ08S01[W]", player) + state.can_reach_region("D08Z03S03[W]", self.player) + or state.can_reach_region("D08Z02S03[W]", self.player) ) - elif boss == "Mourning": + + def opened_wothp_gate(self, state: CollectionState) -> bool: return ( - has_boss_strength("sierpes") - and state.has("D20Z02S08[E]", player) + state.can_reach_region("D09Z01S13[E]", self.player) + or state.can_reach_region("D09Z01S03[W]", self.player) + or state.can_reach_region("D09Z01S08[W]", self.player) ) - elif boss == "Graveyard": + + def opened_botss_ladder(self, state: CollectionState) -> bool: return ( - has_boss_strength("amanecida") - and state.has_all({"D01Z06S01[Santos]", "D02Z03S23[E]", "D02Z02S14[W]", "Wall Climb Ability"}, player) + state.can_reach_region("D17Z01S05[S]", self.player) + or state.can_reach_region("D17BZ02S01[FrontR]", self.player) ) - elif boss == "Jondo": + + # Special skips + def upwarp_skips_allowed(self, state: CollectionState) -> bool: + return self.world.options.difficulty >= 2 + + def mourning_skip_allowed(self, state: CollectionState) -> bool: + return self.world.options.difficulty >= 2 + + def enemy_skips_allowed(self, state: CollectionState) -> bool: return ( - has_boss_strength("amanecida") - and state.has("D01Z06S01[Santos]", player) - and state.has_any({"D20Z01S05[W]", "D20Z01S05[E]"}, player) - and state.has_any({"D03Z01S03[W]", "D03Z01S03[SW]"}, player) + self.world.options.difficulty >= 2 + and not self.world.options.enemy_randomizer ) - elif boss == "Patio": + + def obscure_skips_allowed(self, state: CollectionState) -> bool: + return self.world.options.difficulty >= 2 + + def precise_skips_allowed(self, state: CollectionState) -> bool: + return self.world.options.difficulty >= 2 + + # Bosses + def can_beat_brotherhood_boss(self, state: CollectionState) -> bool: return ( - has_boss_strength("amanecida") - and state.has_all({"D01Z06S01[Santos]", "D06Z01S18[E]"}, player) - and state.has_any({"D04Z01S04[W]", "D04Z01S04[E]", "D04Z01S04[Cherubs]"}, player) + self.has_boss_strength(state, "warden") + and ( + state.can_reach_region("D17Z01S05[E]", self.player) + or state.can_reach_region("D17Z01S03[W]", self.player) + ) ) - elif boss == "Wall": + + def can_beat_mercy_boss(self, state: CollectionState) -> bool: return ( - has_boss_strength("amanecida") - and state.has_all({"D01Z06S01[Santos]", "D09BZ01S01[Cell24]"}, player) - and state.has_any({"D09Z01S01[W]", "D09Z01S01[E]"}, player) + self.has_boss_strength(state, "ten-piedad") + and ( + state.can_reach_region("D01Z04S19[E]", self.player) + or state.can_reach_region("D01Z04S12[W]", self.player) + ) ) - elif boss == "Hall": + + def can_beat_convent_boss(self, state: CollectionState) -> bool: return ( - has_boss_strength("laudes") - and state.has_any({"D08Z03S03[W]", "D08Z03S03[E]"}, player) + self.has_boss_strength(state, "charred-visage") + and ( + state.can_reach_region("D02Z03S09[E]", self.player) + or state.can_reach_region("D02Z03S21[W]", self.player) + ) ) - elif boss == "Perpetua": - return has_boss_strength("perpetua") - elif boss == "Legionary": - return has_boss_strength("legionary") - - -def guilt_rooms(state: CollectionState, player: int, number: int) -> bool: - doors: List[str] = [ - "D01Z04S17[W]", - "D02Z02S06[E]", - "D03Z03S14[W]", - "D04Z02S17[W]", - "D05Z01S17[W]", - "D09Z01S13[E]", - "D17Z01S12[E]" - ] - - total: int = sum(state.has(item, player) for item in doors) - - return total >= number - - -def sword_rooms(state: CollectionState, player: int, number: int) -> bool: - doors: List[Set[str]] = [ - {"D01Z02S06[W]", "D01Z02S06[E]"}, - {"D01Z05S24[W]", "D01Z05S24[E]"}, - {"D02Z03S13[W]"}, - {"D04Z02S12[W]"}, - {"D05Z01S13[E]"}, - {"D06Z01S11[W]"}, - {"D17Z01S08[E]"} - ] - - total: int = sum(state.has_any(items, player) for items in doors) - - return total >= number - - -def redento(state: CollectionState, world, player: int, number: int) -> bool: - if number == 1: - return state.has_any({"D03Z01S03[W]", "D03Z01S03[SW]"}, player) - elif number == 2: + + def can_beat_grievance_boss(self, state: CollectionState) -> bool: return ( - state.has_any({"D03Z01S03[W]", "D03Z01S03[SW]"}, player) - and state.has("OpenedBOTSSLadder", player) + self.has_boss_strength(state, "tres-angustias") + and ( + self.wall_climb(state) + or self.double_jump(state) + ) and ( + state.can_reach_region("D03Z03S11[E]", self.player) + or state.can_reach_region("D03Z03S16[W]", self.player) + ) ) - elif number == 3: + + def can_beat_bridge_boss(self, state: CollectionState) -> bool: return ( - state.has_any({"D03Z01S03[W]", "D03Z01S03[SW]"}, player) - and state.has("OpenedBOTSSLadder", player) - and state.can_reach(world.multiworld.get_region("D01Z03S06", player)) + self.has_boss_strength(state, "esdras") + and ( + state.can_reach_region("D01Z03S06[E]", self.player) + or state.can_reach_region("D08Z02S01[W]", self.player) + ) ) - elif number == 4: + + def can_beat_mothers_boss(self, state: CollectionState) -> bool: return ( - state.has_any({"D03Z01S03[W]", "D03Z01S03[SW]"}, player) - and state.has("OpenedBOTSSLadder", player) - and state.can_reach(world.multiworld.get_region("D01Z03S06", player)) - and state.can_reach(world.multiworld.get_region("D04Z01S04", player)) + self.has_boss_strength(state, "melquiades") + and ( + state.can_reach_region("D04Z02S15[E]", self.player) + or state.can_reach_region("D04Z02S21[W]", self.player) + ) ) - elif number == 5: + + def can_beat_canvases_boss(self, state: CollectionState) -> bool: return ( - state.has_any({"D03Z01S03[W]", "D03Z01S03[SW]"}, player) - and state.has("OpenedBOTSSLadder", player) - and state.can_reach(world.multiworld.get_region("D01Z03S06", player)) - and state.can_reach(world.multiworld.get_region("D04Z01S04", player)) - and state.can_reach(world.multiworld.get_region("D04Z02S20", player)) - and state.has_all({"Little Toe made of Limestone", "Big Toe made of Limestone", \ - "Fourth Toe made of Limestone", "D17Z01S09[E]"}, player) - and state.has("Knot of Rosary Rope", player) + self.has_boss_strength(state, "exposito") + and ( + state.can_reach_region("D05Z02S06[NE]", self.player) + or state.can_reach_region("D05Z01S21[SW]", self.player) + ) ) - - -def miriam(state: CollectionState, player: int) -> bool: - return state.has_all({"D02Z03S24[E]", "D03Z03S19[E]", "D04Z04S02[W]", "D05Z01S24[E]", "D06Z01S26[W]"}, player) - - -def amanecida_rooms(state: CollectionState, logic: int, player: int, number: int) -> bool: - bosses: List[str] = [ - "Graveyard", - "Jondo", - "Patio", - "Wall" - ] - - total = sum(can_beat_boss(state, boss, logic, player) for boss in bosses) - - return total >= number - - -def chalice_rooms(state: CollectionState, player: int, number: int) -> bool: - doors: List[Set[str]] = [ - {"D03Z01S01[W]", "D03Z01S01[NE]", "D03Z01S01[S]"}, - {"D05Z02S01[W]", "D05Z02S01[E]"}, - {"D09Z01S07[SW]", "D09Z01S07[SE]", "D09Z01S07[W]", "D09Z01S07[E]"} - ] - - total: int = sum(state.has_any(items, player) for items in doors) - - return total >= number - - -def rules(blasphemousworld): - world = blasphemousworld.multiworld - player = blasphemousworld.player - logic = world.difficulty[player].value - enemy = world.enemy_randomizer[player].value - - - # D01Z01S01 (The Holy Line) - # No items - # Doors - set_rule(world.get_entrance("D01Z01S01[S]", player), - lambda state: ( - can_break_holes(state, player) - or state.has("Purified Hand of the Nun", player) - )) - - - # D01Z01S02 (The Holy Line) - # Items - set_rule(world.get_location("THL: Across blood platforms", player), - lambda state: ( - state.has_any({"Blood Perpetuated in Sand", "Purified Hand of the Nun"}, player) - )) - # No doors - - - # D01Z01S03 (The Holy Line) - # Items - set_rule(world.get_location("THL: Underground chest", player), - lambda state: ( - state.has_all({"Blood Perpetuated in Sand", "Dash Ability"}, player) - and can_water_jump(state, player) - )) - # No doors - - - # D01Z02S01 (Albero) - # Items - set_rule(world.get_location("Albero: Bless Linen Cloth", player), - lambda state: state.has("Linen Cloth", player)) - set_rule(world.get_location("Albero: Bless Hatched Egg", player), - lambda state: state.has("Hatched Egg of Deformity", player)) - set_rule(world.get_location("Albero: Bless Severed Hand", player), - lambda state: state.has("Severed Hand", player)) - # No doors - - - # D01Z02S02 (Albero) - # Items - set_rule(world.get_location("Albero: Tirso's 1st reward", player), - lambda state: state.has_group("tirso", player, 1)) - set_rule(world.get_location("Albero: Tirso's 2nd reward", player), - lambda state: state.has_group("tirso", player, 2)) - set_rule(world.get_location("Albero: Tirso's 3rd reward", player), - lambda state: state.has_group("tirso", player, 3)) - set_rule(world.get_location("Albero: Tirso's 4th reward", player), - lambda state: state.has_group("tirso", player, 4)) - set_rule(world.get_location("Albero: Tirso's 5th reward", player), - lambda state: state.has_group("tirso", player, 5)) - set_rule(world.get_location("Albero: Tirso's 6th reward", player), - lambda state: state.has_group("tirso", player, 6)) - set_rule(world.get_location("Albero: Tirso's final reward", player), - lambda state: ( - state.has_group("tirso", player, 6) - and can_beat_boss(state, "Mercy", logic, player) - and can_beat_boss(state, "Convent", logic, player) - and can_beat_boss(state, "Grievance", logic, player) - and can_beat_boss(state, "Mothers", logic, player) - and can_beat_boss(state, "Canvases", logic, player) - and can_beat_boss(state, "Prison", logic, player) - )) - # No doors - - - # D01Z02S03 (Albero) - # Items - set_rule(world.get_location("Albero: Child of Moonlight", player), - lambda state: ( - state.has("RodeGOTPElevator", player) - or pillar(state, player) - or state.has("Cante Jondo of the Three Sisters", player) - or state.has("Purified Hand of the Nun", player) - or state.has("D01Z02S03[NW]", player) - and ( - can_cross_gap(state, logic, player, 2) - or state.has("Lorquiana", player) - or aubade(state, player) - or state.has("Cantina of the Blue Rose", player) - or charge_beam(state, player) - or state.has("Ranged Skill", player) - ) - )) - set_rule(world.get_location("Albero: Lvdovico's 1st reward", player), - lambda state: state.has_group("tentudia", player, 1)) - set_rule(world.get_location("Albero: Lvdovico's 2nd reward", player), - lambda state: state.has_group("tentudia", player, 2)) - set_rule(world.get_location("Albero: Lvdovico's 3rd reward", player), - lambda state: state.has_group("tentudia", player, 3)) - set_rule(world.get_location("Albero: First gift for Cleofas", player), - lambda state: state.has("D04Z02S10[W]", player)) - # Doors - set_rule(world.get_entrance("D01Z02S03[NW]", player), - lambda state: ( - state.has("D02Z02S11[NW]", player) - or state.has("D02Z02S11[NE]", player) - or state.has("D02Z02S11[W]", player) - or state.has("D02Z02S11[E]", player) - or state.has("D02Z02S11[SE]", player) - )) - set_rule(world.get_entrance("D01Z02S03[church]", player), - lambda state: ( - can_beat_boss(state, "Mercy", logic, player) - or can_beat_boss(state, "Convent", logic, player) - or can_beat_boss(state, "Grievance", logic, player) - )) - - - # D01BZ04S01 (Albero: Inside church) - # Items - set_rule(world.get_location("Albero: Final gift for Cleofas", player), - lambda state: ( - state.has_group("marks", player, 3) - and state.has("Cord of the True Burying", player) - and state.has("D04Z02S10[W]", player) - and state.has("D06Z01S18[E]", player) - )) - # No doors - - - # D01BZ06S01 (Ossuary) - # Items - set_rule(world.get_location("Ossuary: 1st reward", player), - lambda state: state.has_group("bones", player, 4)) - set_rule(world.get_location("Ossuary: 2nd reward", player), - lambda state: state.has_group("bones", player, 8)) - set_rule(world.get_location("Ossuary: 3rd reward", player), - lambda state: state.has_group("bones", player, 12)) - set_rule(world.get_location("Ossuary: 4th reward", player), - lambda state: state.has_group("bones", player, 16)) - set_rule(world.get_location("Ossuary: 5th reward", player), - lambda state: state.has_group("bones", player, 20)) - set_rule(world.get_location("Ossuary: 6th reward", player), - lambda state: state.has_group("bones", player, 24)) - set_rule(world.get_location("Ossuary: 7th reward", player), - lambda state: state.has_group("bones", player, 28)) - set_rule(world.get_location("Ossuary: 8th reward", player), - lambda state: state.has_group("bones", player, 32)) - set_rule(world.get_location("Ossuary: 9th reward", player), - lambda state: state.has_group("bones", player, 36)) - set_rule(world.get_location("Ossuary: 10th reward", player), - lambda state: state.has_group("bones", player, 40)) - set_rule(world.get_location("Ossuary: 11th reward", player), - lambda state: state.has_group("bones", player, 44)) - # Doors - set_rule(world.get_entrance("D01BZ06S01[E]", player), - lambda state: state.has_group("bones", player, 30)) - - - # D01BZ08S01 (Isidora) - # Items - set_rule(world.get_location("Ossuary: Isidora, Voice of the Dead", player), - lambda state: can_beat_boss(state, "Ossuary", logic, player)) - # No doors - - - # D01Z03S01 (Wasteland of the Buried Churches) - # Items - set_rule(world.get_location("WotBC: Lower log path", player), - lambda state: state.has("D01Z03S01[SE]", player)) - # No doors - - - # D01Z03S02 (Wasteland of the Buried Churches) - # Items - set_rule(world.get_location("WotBC: Hidden alcove", player), - lambda state: state.has("Dash Ability", player)) - # No doors - - - # D01Z03S03 (Wasteland of the Buried Churches) - # No items - # Doors - set_rule(world.get_entrance("D01Z03S03[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D01Z03S05 (Wasteland of the Buried Churches) - # Items - set_rule(world.get_location("WotBC: Under broken bridge", player), - lambda state: ( - state.has_any({"Blood Perpetuated in Sand", "Boots of Pleading"}, player) - or can_cross_gap(state, logic, player, 3) - )) - # Doors - set_rule(world.get_entrance("D01Z03S05[Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D01Z03S06 (Wasteland of the Buried Churches) - # Items - set_rule(world.get_location("WotBC: 3rd meeting with Redento", player), - lambda state: redento(state, blasphemousworld, player, 3)) - # No doors - - - # D01Z03S07 (Wasteland of the Buried Churches) - # Items - set_rule(world.get_location("WotBC: Cliffside Child of Moonlight", player), - lambda state: ( - can_cross_gap(state, logic, player, 2) - or aubade(state, player) - or charge_beam(state, player) - or state.has_any({"Lorquiana", "Cante Jondo of the Three Sisters", "Cantina of the Blue Rose", \ - "Cloistered Ruby", "Ranged Skill"}, player) - or precise_skips_allowed(logic) - )) - # Doors - set_rule(world.get_entrance("D01Z03S07[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D01Z04S01 (Mercy Dreams) - # No items - # Doors - set_rule(world.get_entrance("D01Z04S01[SE]", player), - lambda state: state.has("D01Z04S01[S]", player)) - set_rule(world.get_entrance("D01Z04S01[S]", player), - lambda state: state.has("D01Z04S01[SE]", player)) - - - # D01Z04S09 (Mercy Dreams) - # No items - # Doors - set_rule(world.get_entrance("D01Z04S09[W]", player), - lambda state: state.has("OpenedDCGateE", player)) - - - # D01Z04S13 (Mercy Dreams) - # Items - set_rule(world.get_location("MD: Behind gate to TSC", player), - lambda state: ( - state.has("D01Z04S13[SE]", player) - or can_dive_laser(state, logic, player) and ( - can_air_stall(state, logic, player) - or state.has_any({"The Young Mason's Wheel", "Purified Hand of the Nun"}, player) - or can_enemy_bounce(logic, enemy) - ) - )) - # Doors - set_rule(world.get_entrance("D01Z04S13[SE]", player), - lambda state: ( - can_dive_laser(state, logic, player) and ( - can_air_stall(state, logic, player) - or state.has_any({"The Young Mason's Wheel", "Purified Hand of the Nun"}, player) - or can_enemy_bounce(logic, enemy) - ) - )) - - - # D01Z04S14 (Mercy Dreams) - # Items - set_rule(world.get_location("MD: Sliding challenge", player), - lambda state: state.has("Dash Ability", player)) - # No doors - - - # D01Z04S15 (Mercy Dreams) - # No items - # Doors - set_rule(world.get_entrance("D01Z04S15[W]", player), - lambda state: ( - state.has("D01Z04S15[E]", player) - or state.has("D01Z04S15[SW]", player) - or state.has("D01Z04S15[SE]", player) - )) - set_rule(world.get_entrance("D01Z04S15[E]", player), - lambda state: ( - state.has("D01Z04S15[W]", player) - or state.has("D01Z04S15[SW]", player) - or state.has("D01Z04S15[SE]", player) - )) - set_rule(world.get_entrance("D01Z04S15[SW]", player), - lambda state: ( - state.has("D01Z04S15[W]", player) - or state.has("D01Z04S15[E]", player) - or state.has("D01Z04S15[SE]", player) - )) - set_rule(world.get_entrance("D01Z04S15[SE]", player), - lambda state: ( - state.has("D01Z04S15[W]", player) - or state.has("D01Z04S15[E]", player) - or state.has("D01Z04S15[SW]", player) - )) - - - # D01Z04S16 (Mercy Dreams) - # Items - set_rule(world.get_location("MD: Cave Child of Moonlight", player), - lambda state: ( - state.has_any({"Purified Hand of the Nun", "Cante Jondo of the Three Sisters"}, player) - or pillar(state, player) - or tirana(state, player) - )) - # No doors - - - # D01Z04S18 (Ten Piedad) - # Items - set_rule(world.get_location("MD: Ten Piedad", player), - lambda state: can_beat_boss(state, "Mercy", logic, player)) - # Doors - set_rule(world.get_entrance("D01Z04S18[W]", player), - lambda state: can_beat_boss(state, "Mercy", logic, player)) - set_rule(world.get_entrance("D01Z04S18[E]", player), - lambda state: can_beat_boss(state, "Mercy", logic, player)) - - - # D01Z05S02 (Desecrated Cistern) - # No items - # Doors - set_rule(world.get_entrance("D01Z05S02[S]", player), - lambda state: state.has("OpenedDCLadder", player)) - - - # D01Z05S05 (Desecrated Cistern) - # Items - set_rule(world.get_location("DC: Hidden alcove near fountain", player), - lambda state: ( - state.has("Dash Ability", player) - and can_water_jump(state, player) - )) - # No doors - - - # D01Z05S06 (Desecrated Cistern) - # Items - set_rule(world.get_location("DC: Upper east tunnel chest", player), - lambda state: ( - state.has("D01Z05S06[Cherubs]", player) - or can_water_jump(state, player) - )) - set_rule(world.get_location("DC: Upper east Child of Moonlight", player), - lambda state: ( - state.has("D01Z05S06[Cherubs]", player) - or can_water_jump(state, player) - or pillar(state, player) - or state.has("Cante Jondo of the Three Sisters", player) - or aubade(state, player) - or tirana(state, player) - or can_air_stall(state, logic, player) - )) - # No doors - - - # D01Z05S12 (Desecrated Cistern) - # Event - set_rule(world.get_location("OpenedDCGateE", player), - lambda state: opened_dc_gate_e(state, player)) - - - # D01Z05S13 (Desecrated Cistern) - # Items - set_rule(world.get_location("DC: Child of Moonlight, behind pillar", player), - lambda state: ( - state.has("D01Z05S13[SW]", player) - or state.has("D01Z05S13[E]", player) - and can_survive_poison(state, logic, player, 3) - and can_water_jump(state, player) - )) - # Doors - set_rule(world.get_entrance("D01Z05S13[SW]", player), - lambda state: state.has("D01Z05S13[E]", player)) - add_rule(world.get_entrance("D01Z05S13[SW]", player), - lambda state: ( - can_survive_poison(state, logic, player, 3) - and can_water_jump(state, player) - )) - set_rule(world.get_entrance("D01Z05S13[N]", player), - lambda state: state.has("D01Z05S13[E]", player)) - add_rule(world.get_entrance("D01Z05S13[N]", player), - lambda state: ( - can_survive_poison(state, logic, player, 3) - and can_water_jump(state, player) - )) - - - # D01Z05S17 (Desecrated Cistern) - # Items - set_rule(world.get_location("DC: High ledge near elevator shaft", player), - lambda state: ( - state.has("D01Z05S17[E]", player) - or can_water_jump(state, player) - or can_cross_gap(state, logic, player, 5) - )) - # Doors - set_rule(world.get_entrance("D01Z05S17[E]", player), - lambda state: ( - state.has("Dash Ability", player) and ( - can_water_jump(state, player) - or can_cross_gap(state, logic, player, 5) - ) - )) - - - # D01Z05S20 (Desecrated Cistern) - # Event - set_rule(world.get_location("OpenedDCLadder", player), - lambda state: opened_dc_ladder(state, player)) - - - # D01Z05S21 (Desecrated Cistern) - # No items - # Doors - set_rule(world.get_entrance("D01Z05S21[Reward]", player), - lambda state: state.has("Shroud of Dreamt Sins", player)) - - - # D01Z05S23 (Desecrated Cistern) - # No items - # Doors - set_rule(world.get_entrance("D01Z05S23[W]", player), - lambda state: ( - chalice_rooms(state, player, 3) - and state.has("Chalice of Inverted Verses", player) - )) - - - # D01Z05S24 (Desecrated Cistern) - # Event - set_rule(world.get_location("OpenedDCGateW", player), - lambda state: opened_dc_gate_w(state, player)) - - - # D01Z05S25 (Desecrated Cistern) - # Items - set_rule(world.get_location("DC: Elevator shaft ledge", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - or ( - state.has("Purified Hand of the Nun", player) - and state.has_any({"D01Z05S25[SW]", "D01Z05S25[SE]", "D01Z05S25[NE]"}, player) - ) - )) - set_rule(world.get_location("DC: Elevator shaft Child of Moonlight", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - or ( - obscure_skips_allowed(logic) - and state.has_any({"D01Z05S25[SW]", "D01Z05S25[SE]", "D01Z05S25[NE]"}, player) - and ( - aubade(state, player) - or state.has("Cantina of the Blue Rose", player) - ) - ) - or ( - pillar(state, player) - and ( - state.has("D01Z05S25[E]", player) - or state.has("D01Z05S25[W]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 3) - ) - ) - ) - )) - # Doors - set_rule(world.get_entrance("D01Z05S25[NE]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - or state.has("D01Z05S25[SW]", player) - or state.has("D01Z05S25[SE]", player) - )) - set_rule(world.get_entrance("D01Z05S25[W]", player), - lambda state: ( - ( - state.has("Linen of Golden Thread", player) - and ( - can_walk_on_root(state, player) - or state.has("Purified Hand of the Nun", player) - or can_air_stall(state, logic, player) - ) - ) - or ( - state.has("D01Z05S25[E]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 3) - ) - ) - )) - set_rule(world.get_entrance("D01Z05S25[E]", player), - lambda state: ( - can_break_tirana(state, logic, player) - and ( - state.has("Linen of Golden Thread", player) - or state.has("D01Z05S25[W]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 3) - ) - ) - )) - set_rule(world.get_entrance("D01Z05S25[SW]", player), - lambda state: ( - state.has("D01Z05S25[SE]", player) - or state.has("D01Z05S25[NE]", player) - or state.has("Linen of Golden Thread", player) - )) - set_rule(world.get_entrance("D01Z05S25[SE]", player), - lambda state: ( - state.has("D01Z05S25[SW]", player) - or state.has("D01Z05S25[NE]", player) - or state.has("Linen of Golden Thread", player) - )) - set_rule(world.get_entrance("D01Z05S25[EchoesW]", player), - lambda state: state.has("D01Z05S25[EchoesE]", player)) - add_rule(world.get_entrance("D01Z05S25[EchoesW]", player), - lambda state: ( - state.has("D01Z05S25[EchoesE]", player) - and ( - state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 8) - ) - or state.has("Linen of Golden Thread", player) - and ( - can_cross_gap(state, logic, player, 5) - or can_air_stall(state, logic, player) - and state.has("Blood Perpetuated in Sand", player) - ) - )) - set_rule(world.get_entrance("D01Z05S25[EchoesE]", player), - lambda state: state.has("D01Z05S25[EchoesW]", player)) - add_rule(world.get_entrance("D01Z05S25[EchoesE]", player), - lambda state: ( - state.has("D01Z05S25[EchoesW]", player) - and ( - state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 8) - ) - or state.has("Linen of Golden Thread", player) - and ( - can_cross_gap(state, logic, player, 5) - or can_air_stall(state, logic, player) - and state.has("Blood Perpetuated in Sand", player) - ) - )) - - - # D01Z06S01 (Petrous) - # No items - # Doors - set_rule(world.get_entrance("D01Z06S01[Santos]", player), - lambda state: state.has("Petrified Bell", player)) - - - # D02Z01S01 (Where Olive Trees Wither) - # Items - set_rule(world.get_location("WOTW: Below Prie Dieu", player), - lambda state: ( - state.has("D02Z01S01[W]", player) - or state.has("D02Z01S01[CherubsL]", player) - or state.has("D02Z01S01[SW]", player) - or state.has("D02Z01S01[CherubsR]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_location("WOTW: Gemino's gift", player), - lambda state: ( - state.has("D02Z01S01[W]", player) - or state.has("D02Z01S01[CherubsL]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - or ( - ( - state.has("D02Z01S01[SW]", player) - or state.has("D02Z01S01[CherubsR]", player) - ) - and can_dawn_jump(state, logic, player) - ) - )) - set_rule(world.get_location("WOTW: Gemino's reward", player), - lambda state: ( - state.has("Golden Thimble Filled with Burning Oil", player) - and ( - state.has("D02Z01S01[W]", player) - or state.has("D02Z01S01[CherubsL]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - or ( - ( - state.has("D02Z01S01[SW]", player) - or state.has("D02Z01S01[CherubsR]", player) - ) - and can_dawn_jump(state, logic, player) - ) - ) - )) - # Doors - set_rule(world.get_entrance("D02Z01S01[SW]", player), - lambda state: ( - state.has("OpenedWOTWCave", player) - and ( - state.has("D02Z01S01[W]", player) - or state.has("D02Z01S01[CherubsL]", player) - or state.has("D02Z01S01[CherubsR]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - ) - )) - set_rule(world.get_entrance("D02Z01S01[W]", player), - lambda state: ( - state.has("D02Z01S01[CherubsL]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - or ( - ( - state.has("D02Z01S01[SW]", player) - or state.has("D02Z01S01[CherubsR]", player) - ) - and can_dawn_jump(state, logic, player) - ) - )) - - - # D02Z01S02 (Where Olive Trees Wither) - # Items - set_rule(world.get_location("WOTW: Upper east Child of Moonlight", player), - lambda state: ( - state.has("D02Z01S02[NE]", player) - or ( - state.has("D02Z01S02[NW]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - ) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 4) - or pillar(state, player) - ) - )) - # Doors - set_rule(world.get_entrance("D02Z01S02[NW]", player), - lambda state: ( - state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - or ( - state.has("D02Z01S02[NE]", player) - and can_walk_on_root(state, player) - and can_cross_gap(state, logic, player, 5) - ) - )) - set_rule(world.get_entrance("D02Z01S02[NE]", player), - lambda state: ( - ( - state.has("Purified Hand of the Nun", player) - and can_enemy_bounce(logic, enemy) - ) - or ( - state.has("D02Z01S02[NW]", player) - or state.has("Wall Climb Ability", player) - or state.has("Purified Hand of the Nun", player) - ) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 10) - ) - )) - set_rule(world.get_entrance("D02Z01S02[]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D02Z01S03 (Where Olive Trees Wither) - # No items - # Doors - set_rule(world.get_entrance("D02Z01S03[W]", player), - lambda state: ( - state.has("D02Z01S03[SE]", player) - or state.has("D02Z01S03[Cherubs]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_entrance("D02Z01S03[SE]", player), - lambda state: ( - state.has("D02Z01S03[W]", player) - or state.has("D02Z01S03[Cherubs]", player) - or state.has("Wall Climb Ability", player) - )) - - - # D02Z01S04 (Where Olive Trees Wither) - # Items - set_rule(world.get_location("WOTW: Gift for the tomb", player), - lambda state: ( - state.has("Golden Thimble Filled with Burning Oil", player) - and ( - state.has("D02Z01S01[W]", player) - or state.has("D02Z01S01[CherubsL]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - or ( - ( - state.has("D02Z01S01[SW]", player) - or state.has("D02Z01S01[CherubsR]", player) - ) - and can_dawn_jump(state, logic, player) - ) - ) - )) - # Doors - set_rule(world.get_entrance("D02Z01S04[-N]", player), - lambda state: ( - state.has("Golden Thimble Filled with Burning Oil", player) - and ( - state.has("D02Z01S01[W]", player) - or state.has("D02Z01S01[CherubsL]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - or ( - ( - state.has("D02Z01S01[SW]", player) - or state.has("D02Z01S01[CherubsR]", player) - ) - and can_dawn_jump(state, logic, player) - ) - ) - )) - - - # D02Z01S06 (Where Olive Trees Wither) - # Items - set_rule(world.get_location("WOTW: Underground ledge", player), - lambda state: ( - state.has("Wall Climb Ability", player) - and ( - state.has("Purified Hand of the Nun", player) - or state.has("Blood Perpetuated in Sand", player) - and ( - state.has("Dash Ability", player) - or state.has("D02Z01S06[Cherubs]", player) - ) - ) - )) - set_rule(world.get_location("WOTW: Underground Child of Moonlight", player), - lambda state: ( - ( - state.has("D02Z01S06[W]", player) - or state.has("Dash Ability", player) - or state.has("Purified Hand of the Nun", player) - and state.has("Wall Climb Ability", player) - ) - and ( - pillar(state, player) - or state.has("Cante Jondo of the Three Sisters", player) - or can_dive_laser(state, logic, player) - ) - or ( - state.has("Wall Climb Ability", player) - and ( - state.has("D02Z01S06[W]", player) - or state.has("Purified Hand of the Nun", player) - or state.has("Dash Ability", player) - ) - ) - and ( - state.has("Lorquiana", player) - or aubade(state, player) - or state.has("Cantina of the Blue Rose", player) - or can_air_stall(state, logic, player) - ) - )) - # Doors - set_rule(world.get_entrance("D02Z01S06[W]", player), - lambda state: ( - state.has("Dash Ability", player) - or state.has_all({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_entrance("D02Z01S06[E]", player), - lambda state: state.has("Wall Climb Ability", player)) - # Event - set_rule(world.get_location("OpenedWOTWCave", player), - lambda state: opened_wotw_cave(state, player)) - - - # D02Z01S08 (Where Olive Trees Wither) - # Items - set_rule(world.get_location("WOTW: Underground tomb", player), - lambda state: state.has("Dried Flowers bathed in Tears", player)) - # No doors - - - # D02Z01S09 (Where Olive Trees Wither) - # Items - set_rule(world.get_location("WOTW: Upper east statue", player), - lambda state: ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 11) - or state.has("Purified Hand of the Nun", player) - and can_enemy_bounce(logic, enemy) - )) - # Doors - set_rule(world.get_entrance("D02Z01S09[-CherubsL]", player), - lambda state: state.has("Linen of Golden Thread", player)) - set_rule(world.get_entrance("D02Z01S09[-CherubsR]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 2) - or can_enemy_bounce(logic, enemy) - and can_air_stall(state, logic, player) - ) - )) - - - # D02Z02S01 (Graveyard of the Peaks) - # No items - # Doors - set_rule(world.get_entrance("D02Z02S01[W]", player), - lambda state: ( - state.has("D02Z02S01[NW]", player) - or state.has("D02Z02S01[Cherubs]", player) - or state.has("Dash Ability", player) - )) - set_rule(world.get_entrance("D02Z02S01[NW]", player), - lambda state: ( - state.has("D02Z02S01[Cherubs]", player) - or state.has("Wall Climb Ability", player) - and ( - state.has("D02Z02S01[W]", player) - or state.has("Dash Ability", player) - ) - )) - set_rule(world.get_entrance("D02Z02S01[E]", player), - lambda state: ( - state.has("D02Z02S01[NW]", player) - or state.has("D02Z02S01[Cherubs]", player) - or state.has_any({"Wall Climb Ability", "Dash Ability"}, player) - )) - - - # D02Z02S02 (Graveyard of the Peaks) - # Items - set_rule(world.get_location("GotP: Center shaft Child of Moonlight", player), - lambda state: ( - state.has("D02Z02S02[CherubsL]", player) - or state.has("D02Z02S02[CherubsR]", player) - or ( - ( - state.has("D02Z02S02[NW]", player) - or state.has("D02Z02S02[NE]", player) - or state.has("Wall Climb Ability", player) - ) - and ( - state.has_any({"Purified Hand of the Nun", "Cante Jondo of the Three Sisters"}, player) - or pillar(state, player) - or tirana(state, player) - or can_dive_laser(state, logic, player) - ) - ) - )) - # Doors - set_rule(world.get_entrance("D02Z02S02[NW]", player), - lambda state: ( - state.has("D02Z02S02[NE]", player) - or state.has("D02Z02S02[CherubsL]", player) - or state.has("D02Z02S02[CherubsR]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_entrance("D02Z02S02[NE]", player), - lambda state: ( - state.has("D02Z02S02[NW]", player) - or state.has("D02Z02S02[CherubsL]", player) - or state.has("D02Z02S02[CherubsR]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_entrance("D02Z02S02[-CherubsR]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D02Z02S03 (Graveyard of the Peaks) - # Items - set_rule(world.get_location("GotP: Lower east shaft", player), - lambda state: ( - state.has("D02Z02S03[NW]", player) - or state.has("D02Z02S03[NE]", player) - or state.has("Wall Climb Ability", player) - or can_cross_gap(state, logic, player, 2) - )) - set_rule(world.get_location("GotP: Center east shaft", player), - lambda state: ( - state.has("D02Z02S03[NW]", player) - or state.has("D02Z02S03[NE]", player) - or state.has_any({"Wall Climb Ability", "Purified Hand of the Nun"}, player) - )) - set_rule(world.get_location("GotP: Upper east shaft", player), - lambda state: ( - can_climb_on_root(state, player) - and ( - state.has("D02Z02S03[NE]", player) - or state.has("Purified Hand of the Nun", player) - or state.has("Blood Perpetuated in Sand", player) - ) - or state.has_all({"Blood Perpetuated in Sand", "Purified Hand of the Nun"}, player) - )) - # Doors - set_rule(world.get_entrance("D02Z02S03[NW]", player), - lambda state: ( - state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - or state.has("D02Z02S03[NE]", player) - and can_walk_on_root(state, player) - )) - set_rule(world.get_entrance("D02Z02S03[NE]", player), - lambda state: ( - state.has("Wall Climb Ability", player) - and ( - can_cross_gap(state, logic, player, 11) - or ( - state.has("Blood Perpetuated in Sand", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 7) - ) - ) - or ( - can_walk_on_root(state, player) - and ( - state.has("Purified Hand of the Nun", player) - or can_air_stall(state, logic, player) - ) - ) - ) - )) - set_rule(world.get_entrance("D02Z02S03[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D02Z02S04 (Graveyard of the Peaks) - # Items - set_rule(world.get_location("GotP: Lower west shaft", player), - lambda state: state.has("D02Z02S04[E]", player)) - set_rule(world.get_location("GotP: Upper west shaft", player), - lambda state: - ( - state.has("D02Z02S04[NE]", player) - or ( - ( - state.has("D02Z02S04[W]", player) - or state.has("D02Z02S04[E]", player) - and state.has("Dash Ability", player) - ) - and ( - state.has("Purified Hand of the Nun", player) - or state.has("Wall Climb Ability", player) - ) - ) - or ( - state.has("D02Z02S04[SE]", player) - and ( - state.has("Wall Climb Ability", player) - or state.has("Purified Hand of the Nun", player) - and can_enemy_upslash(state, logic, enemy, player) - ) - ) - )) - set_rule(world.get_location("GotP: West shaft Child of Moonlight", player), - lambda state: - ( - ( - state.has("D02Z02S04[NE]", player) - or state.has("D02Z02S04[W]", player) - or state.has("D02Z02S04[E]", player) - and state.has("Dash Ability", player) - or state.has("D02Z02S04[SE]", player) - and ( - state.has("Wall Climb Ability", player) - or state.has("Purified Hand of the Nun", player) - and can_enemy_upslash(state, logic, enemy, player) - ) - ) - and ( - state.has("Blood Perpetuated in Sand", player) - and state.has("Dash Ability", player) - or state.has("Purified Hand of the Nun", player) - and can_enemy_bounce(logic, enemy) - or state.has_any({"Lorquiana", "Cante Jondo of the Three Sisters", "Verdiales of the Forsaken Hamlet", "Cantina of the Blue Rose"}, player) - or aubade(state, player) - ) - or ( - state.has("D02Z02S04[NE]", player) - or state.has("D02Z02S04[W]", player) - or state.has("D02Z02S04[E]", player) - and state.has("Dash Ability", player) - or state.has("D02Z02S04[SE]", player) - ) - and pillar(state, player) - )) - # Doors - set_rule(world.get_entrance("D02Z02S04[W]", player), - lambda state: ( - state.has("D02Z02S04[NE]", player) - or state.has("D02Z02S04[E]", player) - and state.has("Dash Ability", player) - or state.has("D02Z02S04[SE]", player) - and ( - state.has("Wall Climb Ability", player) - or state.has("Purified Hand of the Nun", player) - and can_enemy_upslash(state, logic, enemy, player) - ) - )) - set_rule(world.get_entrance("D02Z02S04[SE]", player), - lambda state: ( - state.has("D02Z02S04[NE]", player) - or state.has("D02Z02S04[W]", player) - or state.has("Dash Ability", player) - )) - set_rule(world.get_entrance("D02Z02S04[NE]", player), - lambda state: ( - ( - ( - state.has("D02Z02S04[W]", player) - or state.has("D02Z02S04[E]", player) - and state.has("Dash Ability", player) - ) - and state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - ) - or ( - state.has("D02Z02S04[SE]", player) - and ( - state.has("Wall Climb Ability", player) - or state.has("Purified Hand of the Nun", player) - and can_enemy_upslash(state, logic, enemy, player) - ) - ) - )) - set_rule(world.get_entrance("D02Z02S04[-CherubsL]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - and ( - state.has("D02Z02S04[NE]", player) - or state.has("D02Z02S04[W]", player) - or state.has("D02Z02S04[SE]", player) - or state.has("Dash Ability", player) - ) - )) - - - # D02Z02S05 (Graveyard of the Peaks) - # Items - set_rule(world.get_location("GotP: Center shaft ledge", player), - lambda state: ( - state.has("D02Z02S05[NW]", player) - or state.has("Wall Climb Ability", player) - )) - # Doors - set_rule(world.get_entrance("D02Z02S05[W]", player), - lambda state: ( - state.has("Purified Hand of the Nun", player) - and can_enemy_bounce(logic, enemy) - )) - set_rule(world.get_entrance("D02Z02S05[E]", player), - lambda state: ( - state.has("D02Z02S05[NW]", player) - or state.has("D02Z02S05[E]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_entrance("D02Z02S05[NW]", player), - lambda state: ( - state.has("D02Z02S05[NW]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_entrance("D02Z02S05[-CherubsL]", player), - lambda state: state.has("Linen of Golden Thread", player)) - set_rule(world.get_entrance("D02Z02S05[-CherubsR]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D02Z02S08 (Graveyard of the Peaks) - # Items - set_rule(world.get_location("GotP: Shop cave hidden hole", player), - lambda state: ( - state.has("D02Z02S08[CherubsR]", player) - or state.has("Blood Perpetuated in Sand", player) - or can_break_holes(state, player) - or can_cross_gap(state, logic, player, 8) - )) - set_rule(world.get_location("GotP: Shop cave Child of Moonlight", player), - lambda state: ( - state.has("D02Z02S08[CherubsR]", player) - or can_dive_laser(state, logic, player) - or state.has("Blood Perpetuated in Sand", player) - or pillar(state, player) - or can_cross_gap(state, logic, player, 8) - )) - # No doors - - - # D02Z02S11 (Graveyard of the Peaks) - # No items - # Doors - set_rule(world.get_entrance("D02Z02S11[E]", player), - lambda state: ( - state.has("D02Z02S11[NW]", player) - or state.has("D02Z02S11[NE]", player) - or can_cross_gap(state, logic, player, 6) - )) - set_rule(world.get_entrance("D02Z02S11[NW]", player), - lambda state: state.has("D02Z02S11[NE]", player)) - set_rule(world.get_entrance("D02Z02S11[NE]", player), - lambda state: state.has("D02Z02S11[NW]", player)) - set_rule(world.get_entrance("D02Z02S11[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D02Z02S14 (Graveyard of the Peaks) - # Items - set_rule(world.get_location("GotP: Amanecida of the Bejeweled Arrow", player), - lambda state: can_beat_boss(state, "Graveyard", logic, player)) - # Doors - set_rule(world.get_entrance("D02Z02S14[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D02Z03S02 (Convent of Our Lady of the Charred Visage) - # No items - # Doors - set_rule(world.get_entrance("D02Z03S02[W]", player), - lambda state: ( - state.has("D02Z03S02[NW]", player) - or state.has("D02Z03S02[NE]", player) - or state.has("D02Z03S02[N]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_entrance("D02Z03S02[NW]", player), - lambda state: ( - state.has("D02Z03S02[NE]", player) - or state.has("D02Z03S02[N]", player) - )) - set_rule(world.get_entrance("D02Z03S02[NE]", player), - lambda state: ( - state.has("D02Z03S02[NW]", player) - or state.has("D02Z03S02[N]", player) - )) - set_rule(world.get_entrance("D02Z03S02[N]", player), - lambda state: ( - state.has("D02Z03S02[NW]", player) - or state.has("D02Z03S02[NE]", player) - )) - add_rule(world.get_entrance("D02Z03S02[N]", player), - lambda state: state.has("OpenedConventLadder", player)) - - - # D02Z03S03 (Convent of Our Lady of the Charred Visage) - # Items - set_rule(world.get_location("CoOLotCV: Snowy window ledge", player), - lambda state: ( - state.has("D02Z03S03[NW]", player) - or state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 3) - )) - # Doors - set_rule(world.get_entrance("D02Z03S03[NW]", player), - lambda state: ( - state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 3) - )) - - - # D02Z03S05 (Convent of Our Lady of the Charred Visage) - # Items - set_rule(world.get_location("CoOLotCV: Center miasma room", player), - lambda state: ( - state.has("Dash Ability", player) - and ( - state.has("D02Z03S05[S]", player) - or state.has("D02Z03S05[NE]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - ) - )) - # Doors - set_rule(world.get_entrance("D02Z03S05[S]", player), - lambda state: ( - state.has("D02Z03S05[NE]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_entrance("D02Z03S05[NE]", player), - lambda state: ( - state.has("D02Z03S05[S]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - - - # D02Z03S10 (Convent of Our Lady of the Charred Visage) - # No items - # Doors - set_rule(world.get_entrance("D02Z03S10[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D02Z03S11 (Convent of Our Lady of the Charred Visage) - # Event - set_rule(world.get_location("OpenedConventLadder", player), - lambda state: opened_convent_ladder(state, player)) - - - # D02Z03S12 (Convent of Our Lady of the Charred Visage) - # Items - set_rule(world.get_location("CoOLotCV: Lower west statue", player), - lambda state: ( - can_survive_poison(state, logic, player, 1) - and state.has("Dash Ability", player) - )) - # No doors - - - # D02Z03S18 (Convent of Our Lady of the Charred Visage) - # No items - # Doors - set_rule(world.get_entrance("D02Z03S18[NW]", player), - lambda state: ( - state.has("D02Z03S18[NE]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_entrance("D02Z03S18[NE]", player), - lambda state: ( - state.has("D02Z03S18[NW]", player) - or state.has("Wall Climb Ability", player) - )) - - - # D02Z03S20 (Convent of Our Lady of the Charred Visage) - # Items - set_rule(world.get_location("CoOLotCV: Our Lady of the Charred Visage", player), - lambda state: can_beat_boss(state, "Convent", logic, player)) - # Doors - set_rule(world.get_entrance("D02Z03S20[W]", player), - lambda state: can_beat_boss(state, "Convent", logic, player)) - set_rule(world.get_entrance("D02Z03S20[E]", player), - lambda state: can_beat_boss(state, "Convent", logic, player)) - - - # D02Z03S21 (Convent of Our Lady of the Charred Visage) - # Items - set_rule(world.get_location("CoOLotCV: Fountain of burning oil", player), - lambda state: state.has("Empty Golden Thimble", player)) - # No doors - - - # D03Z01S01 (Mountains of the Endless Dusk) - # No items - # Doors - set_rule(world.get_entrance("D03Z01S01[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D03Z01S02 (Mountains of the Endless Dusk) - # No items - # Doors - set_rule(world.get_entrance("D03Z01S02[W]", player), - lambda state: ( - state.has("Wall Climb Ability", player) - or can_cross_gap(state, logic, player, 3) - )) - set_rule(world.get_entrance("D03Z01S02[E]", player), - lambda state: ( - state.has("Wall Climb Ability", player) - or can_cross_gap(state, logic, player, 7) - )) - - - # D03Z01S03 (Mountains of the Endless Dusk) - # Items - set_rule(world.get_location("MotED: Platform above chasm", player), - lambda state: ( - state.has_any({"Blood Perpetuated in Sand", "Purified Hand of the Nun"}, player) - and ( - state.has("D03Z01S03[W]", player) - or state.has("D03Z01S03[SW]", player) - or can_cross_gap(state, logic, player, 9) - ) - )) - set_rule(world.get_location("MotED: 1st meeting with Redento", player), - lambda state: ( - state.has("D03Z01S03[W]", player) - or state.has("D03Z01S03[SW]", player) - or can_cross_gap(state, logic, player, 9) - )) - set_rule(world.get_location("MotED: Child of Moonlight, above chasm", player), - lambda state: ( - state.has("D03Z01S03[W]", player) - or state.has("D03Z01S03[SW]", player) - or can_cross_gap(state, logic, player, 9) - )) - set_rule(world.get_location("MotED: Amanecida of the Golden Blades", player), - lambda state: ( - can_beat_boss(state, "Jondo", logic, player) - and ( - state.has("D03Z01S03[W]", player) - or state.has("D03Z01S03[SW]", player) - or can_cross_gap(state, logic, player, 9) - ) - )) - # Doors - set_rule(world.get_entrance("D03Z01S03[W]", player), - lambda state: ( - state.has("Wall Climb Ability", player) - and ( - state.has("D03Z01S03[SW]", player) - or can_cross_gap(state, logic, player, 9) - ) - )) - set_rule(world.get_entrance("D03Z01S03[E]", player), - lambda state: state.has("Wall Climb Ability", player)) - set_rule(world.get_entrance("D03Z01S03[SW]", player), - lambda state: ( - state.has("D03Z01S03[W]", player) - or can_cross_gap(state, logic, player, 9) - )) - set_rule(world.get_entrance("D03Z01S03[-WestL]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - and ( - state.has("D03Z01S03[W]", player) - or state.has("D03Z01S03[SW]", player) - or can_cross_gap(state, logic, player, 9) - ) - )) - set_rule(world.get_entrance("D03Z01S03[-WestR]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - and ( - state.has("D03Z01S03[W]", player) - or state.has("D03Z01S03[SW]", player) - or can_cross_gap(state, logic, player, 9) - ) - )) - set_rule(world.get_entrance("D03Z01S03[-EastL]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - and ( - state.has("D03Z01S03[W]", player) - or state.has("D03Z01S03[SW]", player) - or can_cross_gap(state, logic, player, 5) - ) - )) - set_rule(world.get_entrance("D03Z01S03[-EastR]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D03Z01S04 (Mountains of the Endless Dusk) - # Items - set_rule(world.get_location("MotED: Blood platform alcove", player), - lambda state: ( - state.has_any({"Blood Perpetuated in Sand", "Purified Hand of the Nun"}, player) - or upwarp_skips_allowed(logic) - )) - # No doors - - - # D03Z01S06 (Mountains of the Endless Dusk) - # Items - set_rule(world.get_location("MotED: Perpetva", player), - lambda state: can_beat_boss(state, "Perpetua", logic, player)) - set_rule(world.get_location("MotED: Egg hatching", player), - lambda state: can_beat_boss(state, "Perpetua", logic, player) and \ - state.has("Egg of Deformity", player)) - # Doors - set_rule(world.get_entrance("D03Z01S06[W]", player), - lambda state: can_beat_boss(state, "Perpetua", logic, player)) - set_rule(world.get_entrance("D03Z01S06[E]", player), - lambda state: can_beat_boss(state, "Perpetua", logic, player)) - - - # D03Z02S01 (Jondo) - # Items - set_rule(world.get_location("Jondo: Upper east chest", player), - lambda state: ( - state.has("D03Z02S01[Cherubs]", player) - or can_climb_on_root(state, player) - or can_cross_gap(state, logic, player, 8) - or state.has("Purified Hand of the Nun", player) - and can_enemy_bounce(logic, enemy) - )) - # Doors - set_rule(world.get_entrance("D03Z02S01[W]", player), - lambda state: ( - state.has("Wall Climb Ability", player) - or state.has("Purified Hand of the Nun", player) - and can_enemy_bounce(logic, enemy) - )) - set_rule(world.get_entrance("D03Z02S01[N]", player), - lambda state: ( - state.has("Wall Climb Ability", player) - or state.has("Purified Hand of the Nun", player) - )) - - - # D03Z02S02 (Jondo) - # No items - # Doors - set_rule(world.get_entrance("D03Z02S02[W]", player), - lambda state: ( - state.has("D03Z02S02[CherubsL]", player) - or state.has("Purified Hand of the Nun", player) - and ( - state.has("D03Z02S02[E]", player) - or state.has("D03Z02S02[CherubsR]", player) - or state.has("Wall Climb Ability", player) - or can_enemy_bounce(logic, enemy) - ) - )) - set_rule(world.get_entrance("D03Z02S02[E]", player), - lambda state: ( - state.has("Wall Climb Ability", player) - or state.has("Purified Hand of the Nun", player) - and can_enemy_bounce(logic, enemy) - )) - - # D03Z02S03 (Jondo) - # No items - # Doors - set_rule(world.get_entrance("D03Z02S03[W]", player), - lambda state: ( - state.has("Dash Ability", player) - and ( - state.has("D03Z02S03[E]", player) - or state.has("D03Z02S03[N]", player) - or state.has("D03Z02S03[SE2]", player) - ) - )) - set_rule(world.get_entrance("D03Z02S03[E]", player), - lambda state: ( - ( - can_air_stall(state, logic, player) - or state.has_any({"Purified Hand of the Nun", "Boots of Pleading"}, player) - ) - and ( - state.has("Dash Ability", player) - or state.has("D03Z02S03[N]", player) - or state.has("D03Z02S03[SE2]", player) - ) - )) - set_rule(world.get_entrance("D03Z02S03[N]", player), - lambda state: ( - state.has("D03Z02S03[W]", player) - and state.has("Dash Ability", player) - or state.has("D03Z02S03[E]", player) - or state.has("D03Z02S03[SE2]", player) - )) - set_rule(world.get_entrance("D03Z02S03[SE2]", player), - lambda state: ( - state.has("D03Z02S03[W]", player) - and state.has("Dash Ability", player) - or state.has("D03Z02S03[E]", player) - or state.has("D03Z02S03[N]", player) - )) - set_rule(world.get_entrance("D03Z02S03[SW]", player), - lambda state: ( - state.has("D03Z02S03[SE]", player) - or state.has("D03Z02S03[SSL]", player) - or state.has("D03Z02S03[SSR]", player) - or state.has("BrokeJondoBellW", player) - and state.has("BrokeJondoBellE", player) - and ( - state.has("D03Z02S03[W]", player) - and state.has("Dash Ability", player) - or state.has("D03Z02S03[E]", player) - or state.has("D03Z02S03[N]", player) - or state.has("D03Z02S03[SE2]", player) - ) - )) - set_rule(world.get_entrance("D03Z02S03[SE]", player), - lambda state: ( - state.has("D03Z02S03[SW]", player) - or state.has("D03Z02S03[SSL]", player) - or state.has("D03Z02S03[SSR]", player) - or state.has("BrokeJondoBellW", player) - and state.has("BrokeJondoBellE", player) - and ( - state.has("D03Z02S03[W]", player) - and state.has("Dash Ability", player) - or state.has("D03Z02S03[E]", player) - or state.has("D03Z02S03[N]", player) - or state.has("D03Z02S03[SE2]", player) - ) - )) - set_rule(world.get_entrance("D03Z02S03[SSL]", player), - lambda state: ( - state.has("D03Z02S03[SW]", player) - or state.has("D03Z02S03[SE]", player) - or state.has("D03Z02S03[SSR]", player) - or state.has("BrokeJondoBellW", player) - and state.has("BrokeJondoBellE", player) - and ( - state.has("D03Z02S03[W]", player) - and state.has("Dash Ability", player) - or state.has("D03Z02S03[E]", player) - or state.has("D03Z02S03[N]", player) - or state.has("D03Z02S03[SE2]", player) - ) - )) - set_rule(world.get_entrance("D03Z02S03[SSC]", player), - lambda state: ( - state.has("D03Z02S03[SW]", player) - or state.has("D03Z02S03[SE]", player) - or state.has("D03Z02S03[SSL]", player) - or state.has("D03Z02S03[SSR]", player) - or state.has("BrokeJondoBellW", player) - and state.has("BrokeJondoBellE", player) - and ( - state.has("D03Z02S03[W]", player) - and state.has("Dash Ability", player) - or state.has("D03Z02S03[E]", player) - or state.has("D03Z02S03[N]", player) - or state.has("D03Z02S03[SE2]", player) - ) - )) - set_rule(world.get_entrance("D03Z02S03[SSR]", player), - lambda state: ( - state.has("D03Z02S03[SW]", player) - or state.has("D03Z02S03[SE]", player) - or state.has("D03Z02S03[SSL]", player) - or state.has("BrokeJondoBellW", player) - and state.has("BrokeJondoBellE", player) - and ( - state.has("D03Z02S03[W]", player) - and state.has("Dash Ability", player) - or state.has("D03Z02S03[E]", player) - or state.has("D03Z02S03[N]", player) - or state.has("D03Z02S03[SE2]", player) - ) - )) - - - # D03Z02S04 (Jondo) - # Items - set_rule(world.get_location("Jondo: Lower east under chargers", player), - lambda state: ( - state.has("D03Z02S04[NE]", player) - or state.has("D03Z02S04[S]", player) - or state.has("Wall Climb Ability", player) - )) - # Doors - set_rule(world.get_entrance("D03Z02S04[NW]", player), - lambda state: state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player)) - set_rule(world.get_entrance("D03Z02S04[NE]", player), - lambda state: ( - state.has("Wall Climb Ability", player) - or ( - state.has("D03Z02S04[S]", player) - and state.has("Purified Hand of the Nun", player) - ) - )) - set_rule(world.get_entrance("D03Z02S04[S]", player), - lambda state: ( - state.has("D03Z02S04[NE]", player) - or state.has("Wall Climb Ability", player) - )) - - - # D03Z02S05 (Jondo) - # Items - set_rule(world.get_location("Jondo: Upper east Child of Moonlight", player), - lambda state: ( - state.has("D03Z02S05[E]", player) - or state.has("D03Z02S05[S]", player) - or can_cross_gap(state, logic, player, 5) - or ( - can_enemy_bounce(logic, enemy) - and can_cross_gap(state, logic, player, 3) - ) - )) - # Doors - set_rule(world.get_entrance("D03Z02S05[E]", player), - lambda state: ( - state.has("D03Z02S05[S]", player) - or can_cross_gap(state, logic, player, 5) - or ( - can_enemy_bounce(logic, enemy) - and can_cross_gap(state, logic, player, 3) - ) - )) - set_rule(world.get_entrance("D03Z02S05[S]", player), - lambda state: ( - state.has("D03Z02S05[E]", player) - or can_cross_gap(state, logic, player, 5) - or ( - can_enemy_bounce(logic, enemy) - and can_cross_gap(state, logic, player, 3) - ) - )) - # Event - set_rule(world.get_location("BrokeJondoBellE", player), - lambda state: broke_jondo_bell_e(state, logic, enemy, player)) - - - # D03Z02S08 (Jondo) - # Items - set_rule(world.get_location("Jondo: Lower west bell alcove", player), - lambda state: ( - state.has("D03Z02S08[N]", player) - or state.has("D03Z02S08[W]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - # Doors - set_rule(world.get_entrance("D03Z02S08[W]", player), - lambda state: ( - state.has("D03Z02S08[N]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_entrance("D03Z02S08[N]", player), - lambda state: ( - state.has("D03Z02S08[W]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - - - # D03Z02S09 (Jondo) - # No items - # Doors - set_rule(world.get_entrance("D03Z02S09[W]", player), - lambda state: state.has("Dash Ability", player)) - set_rule(world.get_entrance("D03Z02S09[N]", player), - lambda state: ( - state.has("D03Z02S09[S]", player) - or state.has("D03Z02S09[Cherubs]", player) - or state.has("Dash Ability", player) - )) - set_rule(world.get_entrance("D03Z02S09[S]", player), - lambda state: ( - state.has("D03Z02S09[N]", player) - or state.has("D03Z02S09[Cherubs]", player) - or state.has("Dash Ability", player) - )) - # Event - set_rule(world.get_location("BrokeJondoBellW", player), - lambda state: broke_jondo_bell_w(state, player)) - - - # D03Z02S10 (Jondo) - # No items - # Doors - set_rule(world.get_entrance("D03Z02S10[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D03Z02S11 (Jondo) - # Items - set_rule(world.get_location("Jondo: Spike tunnel statue", player), - lambda state: ( - state.has("D03Z02S11[W]", player) - and state.has("Purified Hand of the Nun", player) - or state.has("D03Z02S11[E]", player) - and state.has("Dash Ability", player) - and ( - state.has("Wall Climb Ability", player) - or can_cross_gap(state, logic, player, 2) - or precise_skips_allowed(logic) - and can_cross_gap(state, logic, player, 1) - ) - )) - set_rule(world.get_location("Jondo: Spike tunnel Child of Moonlight", player), - lambda state: ( - state.has("D03Z02S11[W]", player) - and ( - state.has("Purified Hand of the Nun", player) - or state.has("Dash Ability", player) - and ( - state.has("Wall Climb Ability", player) - or can_cross_gap(state, logic, player, 2) - and can_enemy_bounce(logic, enemy) - or can_cross_gap(state, logic, player, 3) - ) - ) - or state.has("D03Z02S11[E]", player) - and state.has("Dash Ability", player) - and ( - can_cross_gap(state, logic, player, 1) - or state.has("Wall Climb Ability", player) - or can_enemy_bounce(logic, enemy) - ) - )) - # Doors - set_rule(world.get_entrance("D03Z02S11[W]", player), - lambda state: ( - state.has("Dash Ability", player) - and ( - state.has("Wall Climb Ability", player) - or can_cross_gap(state, logic, player, 2) - or precise_skips_allowed(logic) - and can_cross_gap(state, logic, player, 1) - ) - )) - set_rule(world.get_entrance("D03Z02S11[E]", player), - lambda state: ( - state.has("Dash Ability", player) - and ( - state.has("Wall Climb Ability", player) - or state.has("Purified Hand of the Nun", player) - or can_cross_gap(state, logic, player, 2) - and can_enemy_bounce(logic, enemy) - ) - )) - - # D03Z02S13 (Jondo) - # Items - set_rule(world.get_location("Jondo: Upper west tree root", player), - lambda state: ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 3) - )) - # Doors - set_rule(world.get_entrance("D03Z02S13[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D03Z03S01 (Grievance Ascends) - # No items - # Doors - set_rule(world.get_entrance("D03Z03S01[NL]", player), - lambda state: ( - state.has("D03Z03S01[NR]", player) - or state.has("D03Z03S01[NC]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_entrance("D03Z03S01[NR]", player), - lambda state: ( - state.has("D03Z03S01[NL]", player) - or state.has("D03Z03S01[NC]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - - - # D03Z03S02 (Grievance Ascends) - # Items - set_rule(world.get_location("GA: Lower west ledge", player), - lambda state: can_survive_poison(state, logic, player, 1)) - # Doors - set_rule(world.get_entrance("D03Z03S02[W]", player), - lambda state: ( - state.has("D03Z03S02[NE]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_entrance("D03Z03S02[NE]", player), - lambda state: state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player)) - - - # D03Z03S03 (Grievance Ascends) - # No items - # Doors - set_rule(world.get_entrance("D03Z03S03[W]", player), - lambda state: state.has("D03Z03S03[NE]", player)) - set_rule(world.get_entrance("D03Z03S03[NE]", player), - lambda state: state.has("D03Z03S03[W]", player)) - - - # D03Z03S04 (Grievance Ascends) - # No items - # Doors - set_rule(world.get_entrance("D03Z03S04[NW]", player), - lambda state: ( - state.has("D03Z03S04[NE]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - and ( - state.has("D03Z03S04[E]", player) - or state.has("D03Z03S04[SW]", player) - or state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 10) - ) - )) - set_rule(world.get_entrance("D03Z03S04[NE]", player), - lambda state: ( - ( - state.has("Wall Climb Ability", player) - or state.has("Purified Hand of the Nun", player) - and can_enemy_bounce(logic, enemy) - ) - and ( - state.has("D03Z03S04[NW]", player) - or state.has("D03Z03S04[E]", player) - or state.has("D03Z03S04[SW]", player) - or state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 10) - ) - )) - set_rule(world.get_entrance("D03Z03S04[E]", player), - lambda state: ( - state.has("D03Z03S04[NW]", player) - or state.has("D03Z03S04[NE]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - and ( - state.has("D03Z03S04[SW]", player) - or state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 10) - ) - )) - set_rule(world.get_entrance("D03Z03S04[SW]", player), - lambda state: ( - state.has("D03Z03S04[NW]", player) - or state.has("D03Z03S04[NE]", player) - or state.has("D03Z03S04[E]", player) - or state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 10) - )) - set_rule(world.get_entrance("D03Z03S04[SE]", player), - lambda state: state.has("Blood Perpetuated in Sand", player)) - set_rule(world.get_entrance("D03Z03S04[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D03Z03S05 (Grievance Ascends) - # No items - # Doors - set_rule(world.get_entrance("D03Z03S05[NW]", player), - lambda state: state.has("D03Z03S05[NE]", player)) - set_rule(world.get_entrance("D03Z03S05[NE]", player), - lambda state: state.has("D03Z03S05[NW]", player)) - set_rule(world.get_entrance("D03Z03S05[SW]", player), - lambda state: state.has("D03Z03S05[SE]", player) or \ - state.has("Linen of Golden Thread", player)) - set_rule(world.get_entrance("D03Z03S05[SE]", player), - lambda state: state.has("D03Z03S05[SW]", player) or \ - state.has("Linen of Golden Thread", player)) - - - # D03Z03S06 (Grievance Ascends) - # Items - set_rule(world.get_location("GA: Miasma room floor", player), - lambda state: can_survive_poison(state, logic, player, 1)) - set_rule(world.get_location("GA: Miasma room treasure", player), - lambda state: state.has("Wall Climb Ability", player)) - set_rule(world.get_location("GA: Miasma room Child of Moonlight", player), - lambda state: ( - state.has("Wall Climb Ability", player) - or can_cross_gap(state, logic, player, 11) - and state.has("Taranto to my Sister", player) - and obscure_skips_allowed(logic) - )) - # No doors - - - # D03Z03S07 (Grievance Ascends) - # No items - # Doors - set_rule(world.get_entrance("D03Z03S07[NW]", player), - lambda state: ( - state.has("D03Z03S07[NE]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_entrance("D03Z03S07[NE]", player), - lambda state: ( - state.has("D03Z03S07[NE]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - - - # D03Z03S08 (Grievance Ascends) - # Items - set_rule(world.get_location("GA: End of blood bridge", player), - lambda state: ( - state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 11) - )) - set_rule(world.get_location("GA: Blood bridge Child of Moonlight", player), - lambda state: ( - ( - state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 11) - ) - and ( - state.has_any({"Purified Hand of the Nun", "Cante Jondo of the Three Sisters", "Verdiales of the Forsaken Hamlet"}, player) - or pillar(state, player) - or tirana(state, player) - or aubade(state, player) - and can_air_stall(state, logic, player) - ) - )) - # Doors - set_rule(world.get_entrance("D03Z03S08[-CherubsL]", player), - lambda state: state.has("Linen of Golden Thread", player)) - set_rule(world.get_entrance("D03Z03S08[-CherubsR]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D03Z03S09 (Grievance Ascends) - # Items - set_rule(world.get_location("GA: Lower east Child of Moonlight", player), - lambda state: ( - can_climb_on_root(state, player) - or state.has_any({"Purified Hand of the Nun", "Lorquiana", "Zarabanda of the Safe Haven", "Cante Jondo of the Three Sisters"}, player) - or pillar(state, player) - or aubade(state, player) - or tirana(state, player) - )) - # No doors - - - # D03Z03S10 (Grievance Ascends) - # Items - set_rule(world.get_location("GA: Altasgracias' gift", player), - lambda state: state.has_group("egg", player, 3)) - set_rule(world.get_location("GA: Empty giant egg", player), - lambda state: ( - state.has_group("egg", player, 3) - and state.has("Hatched Egg of Deformity", player) - and ( - state.has("D01Z02S01[W]", player) - or state.has("D01Z02S01[E]", player) - ) - )) - # No doors - - - # D03Z03S15 (Grievance Ascends) - # Items - set_rule(world.get_location("GA: Tres Angustias", player), - lambda state: can_beat_boss(state, "Grievance", logic, player)) - # Doors - set_rule(world.get_entrance("D03Z03S15[W]", player), - lambda state: can_beat_boss(state, "Grievance", logic, player)) - set_rule(world.get_entrance("D03Z03S15[E]", player), - lambda state: can_beat_boss(state, "Grievance", logic, player)) - - - # D04Z01S01 (Patio of the Silent Steps) - # Items - set_rule(world.get_location("PotSS: First area ledge", player), - lambda state: ( - state.has("D04Z01S01[NE]", player) - or state.has("D04Z01S01[N]", player) - or can_cross_gap(state, logic, player, 3) - )) - # Doors - set_rule(world.get_entrance("D04Z01S01[NE]", player), - lambda state: ( - state.has("D04Z01S01[N]", player) - or can_cross_gap(state, logic, player, 3) - )) - set_rule(world.get_entrance("D04Z01S01[N]", player), - lambda state: ( - state.has("D04Z01S01[NE]", player) - or can_cross_gap(state, logic, player, 3) - )) - - - # D04Z01S02 (Patio of the Silent Steps) - # Items - set_rule(world.get_location("PotSS: Second area ledge", player), - lambda state: ( - can_climb_on_root(state, player) - or can_cross_gap(state, logic, player, 3) - )) - # No doors - - - # D04Z01S03 (Patio of the Silent Steps) - # Items - set_rule(world.get_location("PotSS: Third area upper ledge", player), - lambda state: ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 3) - )) - # No doors - - - # D04Z01S04 (Patio of the Silent Steps) - # Items - set_rule(world.get_location("PotSS: 4th meeting with Redento", player), - lambda state: redento(state, blasphemousworld, player, 4)) - set_rule(world.get_location("PotSS: Amanecida of the Chiselled Steel", player), - lambda state: can_beat_boss(state, "Patio", logic, player)) - # No doors - - - # D04Z01S05 (Patio of the Silent Steps) - # No items - # Doors - set_rule(world.get_entrance("D04Z01S05[N]", player), - lambda state: ( - ( - state.has("Blood Perpetuated in Sand", player) - and can_climb_on_root(state, player) - ) - or state.has("Purified Hand of the Nun", player) - and ( - state.has("Blood Perpetuated in Sand", player) - or can_climb_on_root(state, player) - ) - )) - set_rule(world.get_entrance("D04Z01S05[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D04Z01S06 (Patio of the Silent Steps) - # No items - # Doors - set_rule(world.get_entrance("D04Z01S06[E]", player), - lambda state: state.has("Purified Hand of the Nun", player)) - set_rule(world.get_entrance("D04Z01S06[Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D04Z02S01 (Mother of Mothers) - # Items - if world.purified_hand[player]: - set_rule(world.get_location("MoM: Western room ledge", player), - lambda state: ( - state.has("D04Z02S01[N]", player) - or state.has("D04Z02S01[NE]", player) - and state.has("Dash Ability", player) - and state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_location("MoM: Lower west Child of Moonlight", player), - lambda state: ( - state.has("D04Z02S01[N]", player) - or pillar(state, player) - or state.has("D04Z02S01[NE]", player) - and state.has("Dash Ability", player) - and ( - state.has("Wall Climb Ability", player) - or can_cross_gap(state, logic, player, 1) - ) - )) - # Doors - set_rule(world.get_entrance("D04Z02S01[N]", player), - lambda state: ( - state.has("D04Z02S04[NE]", player) - and state.has("Dash Ability", player) - and state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_entrance("D04Z02S01[NE]", player), - lambda state: ( - state.has("D04Z02S01[N]", player) - or state.has("Dash Ability", player) - and can_cross_gap(state, logic, player, 1) - )) - - - # D04Z02S02 (Mother of Mothers) - # No items - # Doors - set_rule(world.get_entrance("D04Z02S02[NE]", player), - lambda state: ( - ( - state.has("Purified Hand of the Nun", player) - and upwarp_skips_allowed(logic) - ) - or ( - state.has("Purified Hand of the Nun", player) - and can_enemy_upslash(state, logic, enemy, player) - ) - or ( - can_enemy_upslash(state, logic, enemy, player) - and upwarp_skips_allowed(logic) - and ( - state.has("Wall Climb Ability", player) - or state.has("D04Z02S02[N]", player) - ) - ) - )) - set_rule(world.get_entrance("D04Z02S02[N]", player), - lambda state: ( - state.has("D04Z02S02[NE]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - - - # D04Z02S04 (Mother of Mothers) - # No items - # Doors - set_rule(world.get_entrance("D04Z02S04[NW]", player), - lambda state: ( - state.has("D04Z02S04[NE]", player) - or state.has("D04Z02S04[N]", player) - or state.has("D04Z02S04[Cherubs]", player) - or state.has_all({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_entrance("D04Z02S04[NE]", player), - lambda state: ( - state.has("D04Z02S04[NW]", player) - or state.has("D04Z02S04[N]", player) - or state.has("D04Z02S04[Cherubs]", player) - or state.has_all({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_entrance("D04Z02S04[N]", player), - lambda state: ( - ( - state.has("D04Z02S04[NW]", player) - or state.has("D04Z02S04[NE]", player) - or state.has("D04Z02S04[Cherubs]", player) - or state.has_all({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - ) - and state.has("OpenedMOMLadder", player) - )) - - - # D04Z02S06 (Mother of Mothers) - # Items - set_rule(world.get_location("MoM: Outside Cleofas' room", player), - lambda state: ( - state.has("D04Z02S06[NW]", player) - or state.has("D04Z02S06[N]", player) - or state.has("D04Z02S06[NE]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - # Doors - set_rule(world.get_entrance("D04Z02S06[NW]", player), - lambda state: ( - state.has("D04Z02S06[N]", player) - or state.has("D04Z02S06[NE]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_entrance("D04Z02S06[N]", player), - lambda state: ( - ( - state.has("D04Z02S06[NW]", player) - or state.has("D04Z02S06[NE]", player) - or state.has("Wall Climb Ability", player) - ) - and state.has("OpenedARLadder", player) - )) - set_rule(world.get_entrance("D04Z02S06[NE]", player), - lambda state: ( - state.has("D04Z02S06[NW]", player) - or state.has("D04Z02S06[N]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_entrance("D04Z02S06[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - # Event - set_rule(world.get_location("OpenedMOMLadder", player), - lambda state: opened_mom_ladder(state, player)) - - - # D04Z02S07 (Mother of Mothers) - # Items - set_rule(world.get_location("MoM: East chandelier platform", player), - lambda state: ( - state.has("Dash Ability", player) - and ( - state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 3) - ) - )) - # No doors - - - # D04Z02S09 (Mother of Mothers) - # No items - # Doors - set_rule(world.get_entrance("D04Z02S09[NE]", player), - lambda state: state.has("Blood Perpetuated in Sand", player)) - - - # D04Z02S16 (Mother of Mothers) - # Items - set_rule(world.get_location("MoM: Giant chandelier statue", player), - lambda state: ( - state.has("Wall Climb Ability", player) - and state.has_any({"Blood Perpetuated in Sand", "Purified Hand of the Nun"}, player) - )) - # Doors - set_rule(world.get_entrance("D04Z02S16[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D04Z02S20 (Mother of Mothers) - # No items - # Doors - set_rule(world.get_entrance("D04Z02S20[Redento]", player), - lambda state: redento(state, blasphemousworld, player, 5)) - - - # D04Z02S21 (Mother of Mothers) - # No items - # Doors - set_rule(world.get_entrance("D04Z02S21[W]", player), - lambda state: ( - state.has("D04Z02S21[NE]", player) - or state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player) - )) - set_rule(world.get_entrance("D04Z02S21[NE]", player), - lambda state: state.has_any({"Purified Hand of the Nun", "Wall Climb Ability"}, player)) - - - # D04Z02S22 (Mother of Mothers) - # Items - set_rule(world.get_location("MoM: Melquiades, The Exhumed Archbishop", player), - lambda state: can_beat_boss(state, "Mothers", logic, player)) - # Doors - set_rule(world.get_entrance("D04Z02S22[W]", player), - lambda state: can_beat_boss(state, "Mothers", logic, player)) - set_rule(world.get_entrance("D04Z02S22[E]", player), - lambda state: can_beat_boss(state, "Mothers", logic, player)) - - - # D04BZ02S01 (Mother of Mothers - Redento) - # Items - set_rule(world.get_location("MoM: Final meeting with Redento", player), - lambda state: redento(state, blasphemousworld, player, 5)) - # No doors - - - # D04Z03S02 (Knot of the Three Words) - # Items - set_rule(world.get_location("KotTW: Gift from the Traitor", player), - lambda state: state.has_all({"Severed Right Eye of the Traitor", "Broken Left Eye of the Traitor"}, player)) - # No doors - - - # D04Z04S01 (All the Tears of the Sea) - # Items - set_rule(world.get_location("AtTotS: Miriam's gift", player), - lambda state: ( - miriam(state, player) - and state.has("Dash Ability", player) - and state.has("Wall Climb Ability", player) - )) - # No doors - - - # D05Z01S03 (Library of the Negated Words) - # No items - # Doors - set_rule(world.get_entrance("D05Z01S03[Frontal]", player), - lambda state: ( - state.has("Key Grown from Twisted Wood", player) - and state.has("D05Z01S23[E]", player) - and ( - state.has("D05Z01S11[NW]", player) - or state.has("D05Z01S11[NE]", player) - ) - )) - - - # D05Z01S05 (Library of the Negated Words) - # Items - set_rule(world.get_location("LotNW: Hidden floor", player), - lambda state: can_break_holes(state, player)) - set_rule(world.get_location("LotNW: Root ceiling platform", player), - lambda state: ( - ( - can_climb_on_root(state, player) - or state.has("Purified Hand of the Nun", player) - ) - and ( - state.has("D05Z01S05[NE]", player) - or state.has("Blood Perpetuated in Sand", player) - ) - )) - # Doors - set_rule(world.get_entrance("D05Z01S05[NE]", player), - lambda state: state.has("Blood Perpetuated in Sand", player)) - - - # D05Z01S06 (Library of the Negated Words) - # Items - set_rule(world.get_location("LotNW: Miasma hallway chest", player), - lambda state: ( - state.has("D05Z01S06[W]", player) - or can_survive_poison(state, logic, player, 3) - )) - # Doors - set_rule(world.get_entrance("D05Z01S06[W]", player), - lambda state: can_survive_poison(state, logic, player, 3)) - set_rule(world.get_entrance("D05Z01S06[E]", player), - lambda state: can_survive_poison(state, logic, player, 3)) - - - # D05Z01S07 (Library of the Negated Words) - # No items - # Doors - set_rule(world.get_entrance("D05Z01S07[NW]", player), - lambda state: ( - state.has("Blood Perpetuated in Sand", player) - and ( - can_climb_on_root(state, player) - or state.has("Purified Hand of the Nun", player) - ) - or ( - can_climb_on_root(state, player) - and can_cross_gap(state, logic, player, 3) - ) - or can_cross_gap(state, logic, player, 7) - )) - - - # D05Z01S10 (Library of the Negated Words) - # Items - set_rule(world.get_location("LotNW: Platform puzzle chest", player), - lambda state: ( - state.has_any({"Blood Perpetuated in Sand", "Purified Hand of the Nun"}, player) - or can_enemy_bounce(logic, enemy) - and can_cross_gap(state, logic, player, 2) - )) - # No doors - - - # D05Z01S11 (Library of the Negated Words) - # Items - set_rule(world.get_location("LotNW: Silence for Diosdado", player), - lambda state: ( - ( - state.has("D05Z01S11[NW]", player) - or state.has("D05Z01S11[NE]", player) - ) - and state.has("D05Z01S23[E]", player) - )) - set_rule(world.get_location("LotNW: Lowest west upper ledge", player), - lambda state: ( - state.has("D05Z01S11[NW]", player) - or state.has("D05Z01S11[NE]", player) - )) - # Doors - set_rule(world.get_entrance("D05Z01S11[SW]", player), - lambda state: can_break_tirana(state, logic, player)) - set_rule(world.get_entrance("D05Z01S11[NW]", player), - lambda state: state.has("D05Z01S11[NE]", player)) - set_rule(world.get_entrance("D05Z01S11[NE]", player), - lambda state: state.has("D05Z01S11[NW]", player)) - - - # D05Z01S21 (Library of the Negated Words) - # Items - set_rule(world.get_location("LotNW: Elevator Child of Moonlight", player), - lambda state: ( - state.has("Blood Perpetuated in Sand", player) - and ( - can_walk_on_root(state, player) - or state.has("Purified Hand of the Nun", player) - or can_cross_gap(state, logic, player, 5) - and pillar(state, player) - ) - or obscure_skips_allowed(logic) - and ( - state.has("Zarabanda of the Safe Haven", player) - or aubade(state, player) - or state.has("Cantina of the Blue Rose", player) - ) - )) - # Doors - set_rule(world.get_entrance("D05Z01S21[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D05Z02S06 (The Sleeping Canvases) - # No items - # Doors - set_rule(world.get_entrance("D05Z02S06[SE]", player), - lambda state: state.has("OpenedTSCGate", player)) - - - # D05Z02S09 (The Sleeping Canvases) - # No items - # Doors - set_rule(world.get_entrance("D05Z02S09[E]", player), - lambda state: ( - state.has("Bead of Red Wax", player, 3) - and state.has("Bead of Blue Wax", player, 3) - )) - - - # D05Z02S10 (The Sleeping Canvases) - # Items - set_rule(world.get_location("TSC: Jocinero's 1st reward", player), - lambda state: state.has("Child of Moonlight", player, 20)) - set_rule(world.get_location("TSC: Jocinero's final reward", player), - lambda state: state.has("Child of Moonlight", player, 38)) - # Doors - set_rule(world.get_entrance("D05Z02S10[W]", player), - lambda state: state.has("Dash Ability", player)) - - # D05Z02S11 (The Sleeping Canvases) - # Event - set_rule(world.get_location("OpenedTSCGate", player), - lambda state: opened_tsc_gate(state, player)) - - - # D05Z02S13 (The Sleeping Canvases) - # No items - # Doors - set_rule(world.get_entrance("D05Z02S13[E]", player), - lambda state: state.has("Dash Ability", player)) - - - # D05Z02S14 (The Sleeping Canvases) - # Items - set_rule(world.get_location("TSC: Exposito, Scion of Abjuration", player), - lambda state: can_beat_boss(state, "Canvases", logic, player)) - # Doors - set_rule(world.get_entrance("D05Z02S14[W]", player), - lambda state: can_beat_boss(state, "Canvases", logic, player)) - set_rule(world.get_entrance("D05Z02S14[E]", player), - lambda state: can_beat_boss(state, "Canvases", logic, player)) - - - # D05Z02S15 (The Sleeping Canvases) - # Items - set_rule(world.get_location("TSC: Swinging blade tunnel", player), - lambda state: state.has("Dash Ability", player)) - # No doors - - - # D06Z01S01 (Archcathedral Rooftops) - # No items - # Doors - set_rule(world.get_entrance("D06Z01S01[SW]", player), - lambda state: ( - ( - state.has("D06Z01S01[SE]", player) - or state.has("D06Z01S01[W]", player) - or state.has("D06Z01S01[E]", player) - or state.has("D06Z01S01[NNW]", player) - or state.has("D06Z01S01[NNE]", player) - or state.has("D06Z01S01[N]", player) - ) - or state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S01[NW]", player) - or state.has("D06Z01S01[NE]", player) - ) - )) - set_rule(world.get_entrance("D06Z01S01[SE]", player), - lambda state: ( - ( - state.has("D06Z01S01[SW]", player) - or state.has("D06Z01S01[W]", player) - or state.has("D06Z01S01[E]", player) - or state.has("D06Z01S01[NNW]", player) - or state.has("D06Z01S01[NNE]", player) - or state.has("D06Z01S01[N]", player) - ) - or state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S01[NW]", player) - or state.has("D06Z01S01[NE]", player) - ) - )) - set_rule(world.get_entrance("D06Z01S01[W]", player), - lambda state: ( - ( - state.has("D06Z01S01[E]", player) - or state.has("D06Z01S01[NNW]", player) - or state.has("D06Z01S01[NNE]", player) - or state.has("D06Z01S01[N]", player) - ) - or state.has_group("masks", player, 1) - and ( - state.has("D06Z01S01[SW]", player) - or state.has("D06Z01S01[SE]", player) - ) - or state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S01[NW]", player) - or state.has("D06Z01S01[NE]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 1) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S01[E]", player), - lambda state: ( - ( - state.has("D06Z01S01[W]", player) - or state.has("D06Z01S01[NNW]", player) - or state.has("D06Z01S01[NNE]", player) - or state.has("D06Z01S01[N]", player) - ) - or state.has_group("masks", player, 1) - and ( - state.has("D06Z01S01[SW]", player) - or state.has("D06Z01S01[SE]", player) - ) - or state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S01[NW]", player) - or state.has("D06Z01S01[NE]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 1) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S01[NW]", player), - lambda state: ( - state.has("D06Z01S01[NE]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 8) - ) - or state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S01[NNW]", player) - or state.has("D06Z01S01[NNE]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 3) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S01[NE]", player), - lambda state: ( - state.has("D06Z01S01[NW]", player) - or ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 8) - ) - or state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S01[NNW]", player) - or state.has("D06Z01S01[NNE]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 3) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S01[NNW]", player), - lambda state: ( - ( - state.has("D06Z01S01[NNE]", player) - or state.has("D06Z01S01[N]", player) - ) - or state.has_group("masks", player, 2) - and ( - state.has("D06Z01S01[SW]", player) - or state.has("D06Z01S01[SE]", player) - or state.has("D06Z01S01[W]", player) - or state.has("D06Z01S01[E]", player) - or state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S01[NW]", player) - or state.has("D06Z01S01[NE]", player) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S01[NNE]", player), - lambda state: ( - ( - state.has("D06Z01S01[NNW]", player) - or state.has("D06Z01S01[N]", player) - ) - or state.has_group("masks", player, 2) - and ( - state.has("D06Z01S01[SW]", player) - or state.has("D06Z01S01[SE]", player) - or state.has("D06Z01S01[W]", player) - or state.has("D06Z01S01[E]", player) - or state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S01[NW]", player) - or state.has("D06Z01S01[NE]", player) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S01[N]", player), - lambda state: ( - state.has_group("masks", player, 3) - and ( - state.has("D06Z01S01[SW]", player) - or state.has("D06Z01S01[SE]", player) - or state.has("D06Z01S01[W]", player) - or state.has("D06Z01S01[E]", player) - or state.has("D06Z01S01[NNW]", player) - or state.has("D06Z01S01[NNE]", player) - or state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S01[NW]", player) - or state.has("D06Z01S01[NE]", player) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S01[-Cherubs]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S01[SW]", player) - or state.has("D06Z01S01[SE]", player) - or state.has("D06Z01S01[W]", player) - or state.has("D06Z01S01[E]", player) - or state.has("D06Z01S01[NW]", player) - or state.has("D06Z01S01[NE]", player) - or state.has("D06Z01S01[NNW]", player) - or state.has("D06Z01S01[NNE]", player)) - )) - - - # D06Z01S03 (Archcathedral Rooftops) - # Items - set_rule(world.get_location("AR: First soldier fight", player), - lambda state: can_beat_boss(state, "Legionary", logic, player)) - # Doors - set_rule(world.get_entrance("D06Z01S03[W]", player), - lambda state: can_beat_boss(state, "Legionary", logic, player)) - set_rule(world.get_entrance("D06Z01S03[E]", player), - lambda state: can_beat_boss(state, "Legionary", logic, player)) - - - # D06Z01S04 (Archcathedral Rooftops) - # No items - # Doors - set_rule(world.get_entrance("D06Z01S04[SW]", player), - lambda state: ( - state.has("D06Z01S04[W]", player) - or state.has("D06Z01S04[Health]", player) - )) - set_rule(world.get_entrance("D06Z01S04[W]", player), - lambda state: ( - state.has("D06Z01S04[SW]", player) - or state.has("D06Z01S04[Health]", player) - )) - set_rule(world.get_entrance("D06Z01S04[Health]", player), - lambda state: ( - state.has("D06Z01S04[SW]", player) - or state.has("D06Z01S04[W]", player) - )) - add_rule(world.get_entrance("D06Z01S04[Health]", player), - lambda state: ( - ( - state.has("Wall Climb Ability", player) - and can_survive_poison(state, logic, player, 2) - and ( - state.has("Purified Hand of the Nun", player) - or ( - state.has("Blood Perpetuated in Sand", player) - and can_climb_on_root(state, player) - ) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S04[NW]", player), - lambda state: ( - state.has("D06Z01S04[NE]", player) - or state.has("D06Z01S04[Cherubs]", player) - )) - add_rule(world.get_entrance("D06Z01S04[NW]", player), - lambda state: ( - state.has("D06Z01S04[Cherubs]", player) - or ( - state.has("D06Z01S04[SW]", player) - or state.has("D06Z01S04[W]", player) - or state.has("D06Z01S04[Health]", player) - ) - and state.has("Wall Climb Ability", player) - and can_survive_poison(state, logic, player, 2) - and ( - state.has_any({"Dash Ability", "Purified Hand of the Nun"}, player) - and ( - can_dawn_jump(state, logic, player) - or can_climb_on_root(state, player) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S04[NE]", player), - lambda state: ( - state.has("D06Z01S04[NW]", player) - or state.has("D06Z01S04[Cherubs]", player) - )) - add_rule(world.get_entrance("D06Z01S04[NE]", player), - lambda state: ( - ( - state.has("D06Z01S04[SW]", player) - or state.has("D06Z01S04[W]", player) - or state.has("D06Z01S04[Health]", player) - ) - and state.has("Wall Climb Ability", player) - and can_survive_poison(state, logic, player, 2) - and ( - state.has_any({"Dash Ability", "Purified Hand of the Nun"}, player) - and ( - can_dawn_jump(state, logic, player) - or can_climb_on_root(state, player) - ) - ) - )) - - - # D06Z01S06 (Archcathedral Rooftops) - # Items - set_rule(world.get_location("AR: Second soldier fight", player), - lambda state: ( - can_beat_boss(state, "Legionary", logic, player) - and ( - state.has("D06Z01S06[WW]", player) - or state.has("D06Z01S06[E]", player) - ) - )) - # Doors - set_rule(world.get_entrance("D06Z01S06[WW]", player), - lambda state: state.has("D06Z01S06[E]", player)) - add_rule(world.get_entrance("D06Z01S06[WW]", player), - lambda state: can_beat_boss(state, "Legionary", logic, player)) - set_rule(world.get_entrance("D06Z01S06[E]", player), - lambda state: state.has("D06Z01S06[WW]", player)) - add_rule(world.get_entrance("D06Z01S06[E]", player), - lambda state: can_beat_boss(state, "Legionary", logic, player)) - set_rule(world.get_entrance("D06Z01S06[W]", player), - lambda state: state.has("D06Z01S06[EE]", player)) - set_rule(world.get_entrance("D06Z01S06[EE]", player), - lambda state: state.has("D06Z01S06[W]", player)) - - - # D06Z01S08 (Archcathedral Rooftops) - # No items - # Doors - set_rule(world.get_entrance("D06Z01S08[E]", player), - lambda state: state.has("D06Z01S08[N]", player) or \ - state.has("Wall Climb Ability", player)) - - - # D06Z01S09 (Archcathedral Rooftops) - # No items - # Doors - set_rule(world.get_entrance("D06Z01S09[-CherubsL]", player), - lambda state: state.has("Linen of Golden Thread", player)) - set_rule(world.get_entrance("D06Z01S09[-CherubsR]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D06Z01S10 (Archcathedral Rooftops) - # No items - # Doors - set_rule(world.get_entrance("D06Z01S10[-CherubsL]", player), - lambda state: state.has("Linen of Golden Thread", player)) - set_rule(world.get_entrance("D06Z01S10[-CherubsR]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D06Z01S12 (Archcathedral Rooftops) - # Items - set_rule(world.get_location("AR: Upper west shaft ledge", player), - lambda state: ( - state.has("D06Z01S12[NW]", player) - or state.has("D06Z01S12[NE]", player) - or state.has("D06Z01S12[NE2]", player) - or state.has("D06Z01S12[W]", player) - or state.has("D06Z01S12[E]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_location("AR: Upper west shaft chest", player), - lambda state: ( - state.has("D06Z01S12[NE2]", player) - or ( - state.has("D06Z01S12[NW]", player) - or state.has("D06Z01S12[NE]", player) - ) - and state.has("Purified Hand of the Nun", player) - )) - set_rule(world.get_location("AR: Upper west shaft Child of Moonlight", player), - lambda state: ( - state.has("D06Z01S12[W]", player) - or state.has("D06Z01S12[E]", player) - or state.has("D06Z01S12[NW]", player) - or state.has("D06Z01S12[NE]", player) - or state.has("D06Z01S12[NE2]", player) - or state.has("Wall Climb Ability", player) - and state.has_any({"Purified Hand of the Nun", "Taranto to my Sister"}, player) - )) - # Doors - set_rule(world.get_entrance("D06Z01S12[W]", player), - lambda state: ( - state.has("D06Z01S12[NW]", player) - or state.has("D06Z01S12[NE]", player) - or state.has("D06Z01S12[NE2]", player) - or state.has("D06Z01S12[E]", player) - or state.has_all({"Wall Climb Ability", "Purified Hand of the Nun"}, player) - )) - set_rule(world.get_entrance("D06Z01S12[E]", player), - lambda state: ( - state.has("D06Z01S12[NW]", player) - or state.has("D06Z01S12[NE]", player) - or state.has("D06Z01S12[NE2]", player) - or state.has("D06Z01S12[W]", player) - or state.has_all({"Wall Climb Ability", "Purified Hand of the Nun"}, player) - )) - set_rule(world.get_entrance("D06Z01S12[NW]", player), - lambda state: ( - state.has("D06Z01S12[NE]", player) - or state.has("D06Z01S12[NE2]", player) - )) - add_rule(world.get_entrance("D06Z01S12[NW]", player), - lambda state: ( - state.has("D06Z01S12[NE]", player) - or state.has_any({"Wall Climb Ability", "Purified Hand of the Nun"}, player) - )) - set_rule(world.get_entrance("D06Z01S12[NE]", player), - lambda state: ( - state.has("D06Z01S12[NW]", player) - or state.has("D06Z01S12[NE2]", player) - )) - add_rule(world.get_entrance("D06Z01S12[NE]", player), - lambda state: ( - state.has("D06Z01S12[NW]", player) - or state.has_any({"Wall Climb Ability", "Purified Hand of the Nun"}, player) - )) - - - # D06Z01S15 (Archcathedral Rooftops) - # Items - set_rule(world.get_location("AR: Upper east shaft ledge", player), - lambda state: ( - state.has("D06Z01S15[SW]", player) - and state.has("Wall Climb Ability", player) - and ( - can_cross_gap(state, logic, player, 10) - or can_climb_on_root(state, player) - and ( - state.has("Blood Perpetuated in Sand", player) - or state.has("Purified Hand of the Nun", player) - and can_air_stall(state, logic, player) - ) - ) - )) - # Doors - set_rule(world.get_entrance("D06Z01S15[NW]", player), - lambda state: state.has("D06Z01S15[NE]", player)) - add_rule(world.get_entrance("D06Z01S15[NW]", player), - lambda state: ( - state.has("D06Z01S15[SW]", player) - or state.has("Wall Climb Ability", player) - )) - set_rule(world.get_entrance("D06Z01S15[NE]", player), - lambda state: state.has("D06Z01S15[NW]", player)) - add_rule(world.get_entrance("D06Z01S15[NE]", player), - lambda state: ( - state.has("D06Z01S15[SW]", player) - or state.has("Wall Climb Ability", player) - )) - - - # D06Z01S16 (Archcathedral Rooftops) - # No items - # Doors - set_rule(world.get_entrance("D06Z01S16[W]", player), - lambda state: ( - ( - state.has("D06Z01S16[CherubsL]", player) - and ( - state.has("Purified Hand of the Nun", player) - or state.has("Wall Climb Ability", player) - and ( - can_walk_on_root(state, player) - or can_air_stall(state, logic, player) - ) - ) - ) - or ( - state.has("D06Z01S16[CherubsR]", player) - and ( - state.has("Purified Hand of the Nun", player) - or can_air_stall(state, logic, player) - and ( - can_walk_on_root(state, player) - or state.has("The Young Mason's Wheel", player) - ) - and ( - state.has("Wall Climb Ability", player) - or can_dawn_jump(state, logic, player) - ) - ) - ) - or ( - state.has("D06Z01S16[E]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 7) - ) - and ( - state.has("Wall Climb Ability", player) or - can_cross_gap(state, logic, player, 5) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S16[E]", player), - lambda state: ( - ( - ( - state.has("D06Z01S16[W]", player) - or state.has("D06Z01S16[CherubsL]", player) - ) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 5) - ) - ) - or ( - state.has("D06Z01S16[CherubsR]", player) - and ( - state.has("Purified Hand of the Nun", player) - or can_air_stall(state, logic, player) - and ( - can_walk_on_root(state, player) - and state.has("The Young Mason's Wheel", player) - ) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S16[-CherubsL]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S16[W]", player) - or ( - state.has("D06Z01S16[CherubsR]", player) - and ( - state.has("Purified Hand of the Nun", player) - or can_air_stall(state, logic, player) - and ( - can_walk_on_root(state, player) - or state.has("The Young Mason's Wheel", player) - ) - ) - ) - or ( - state.has("D06Z01S16[E]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 7) - ) - ) - ) - )) - set_rule(world.get_entrance("D06Z01S16[-CherubsR]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) - and ( - state.has("D06Z01S16[E]", player) - or ( - state.has("D06Z01S16[CherubsL]", player) - and ( - can_air_stall(state, logic, player) - or can_walk_on_root(state, player) - or state.has("Purified Hand of the Nun", player) - ) - ) - or ( - state.has("D06Z01S16[W]", player) - and ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 1) - ) - ) - ) - )) - - - # D06Z01S17 (Archcathedral Rooftops) - # No items - # Doors - set_rule(world.get_entrance("D06Z01S17[W]", player), - lambda state: ( - ( - state.has("D06Z01S17[E]", player) - or state.has("D06Z01S17[CherubsR]", player) - ) - and state.has("Blood Perpetuated in Sand", player) - or state.has("D06Z01S17[CherubsL]", player) - and state.has("Purified Hand of the Nun", player) - )) - set_rule(world.get_entrance("D06Z01S17[E]", player), - lambda state: ( - state.has("D06Z01S17[CherubsR]", player) - or state.has("Blood Perpetuated in Sand", player) + def can_beat_prison_boss(self, state: CollectionState) -> bool: + return ( + self.has_boss_strength(state, "quirce") and ( - state.has("D06Z01S17[W]", player) - or state.has("D06Z01S17[CherubsL]", player) - and state.has("Purified Hand of the Nun", player) + state.can_reach_region("D09Z01S05[SE]", self.player) + or state.can_reach_region("D09Z01S08[S]", self.player) ) - )) - set_rule(world.get_entrance("D06Z01S17[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - - # D06Z01S18 (Archcathedral Rooftops) - # No items - # Doors - set_rule(world.get_entrance("D06Z01S18[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - - # D06Z01S21 (Archcathedral Rooftops) - # Items - set_rule(world.get_location("AR: Third soldier fight", player), - lambda state: can_beat_boss(state, "Legionary", logic, player)) - # Doors - set_rule(world.get_entrance("D06Z01S21[W]", player), - lambda state: can_beat_boss(state, "Legionary", logic, player)) - set_rule(world.get_entrance("D06Z01S21[E]", player), - lambda state: can_beat_boss(state, "Legionary", logic, player)) + ) - - # D06Z01S23 (Archcathedral Rooftops) - # Event - set_rule(world.get_location("OpenedARLadder", player), - lambda state: opened_ar_ladder(state, player)) - - - # D06Z01S25 (Archcathedral Rooftops) - # Items - set_rule(world.get_location("AR: Crisanta of the Wrapped Agony", player), - lambda state: can_beat_boss(state, "Rooftops", logic, player)) - # Doors - set_rule(world.get_entrance("D06Z01S25[W]", player), - lambda state: can_beat_boss(state, "Rooftops", logic, player)) - set_rule(world.get_entrance("D06Z01S25[E]", player), - lambda state: can_beat_boss(state, "Rooftops", logic, player)) - - - # D08Z01S01 (Bridge of the Three Cavalries) - # Items - set_rule(world.get_location("BotTC: Esdras, of the Anointed Legion", player), - lambda state: ( - state.has_group("wounds", player, 3) - and can_beat_boss(state, "Bridge", logic, player) - )) - set_rule(world.get_location("BotTC: Esdras' gift", player), - lambda state: ( - state.has_group("wounds", player, 3) - and can_beat_boss(state, "Bridge", logic, player) - )) - # Doors - set_rule(world.get_entrance("D08Z01S01[W]", player), - lambda state: can_beat_boss(state, "Bridge", logic, player)) - set_rule(world.get_entrance("D08Z01S01[E]", player), - lambda state: ( - state.has_group("wounds", player, 3) + def can_beat_rooftops_boss(self, state: CollectionState) -> bool: + return ( + self.has_boss_strength(state, "crisanta") and ( - state.has("D08Z01S01[Cherubs]", player) - or can_beat_boss(state, "Bridge", logic, player) + state.can_reach_region("D06Z01S19[E]", self.player) + or state.can_reach_region("D07Z01S01[W]", self.player) ) - )) - - - # D08Z01S02 (Bridge of the Three Cavalries) - # No items - # Items - set_rule(world.get_entrance("D08Z01S02[-Cherubs]", player), - lambda state: state.has("Linen of Golden Thread", player)) - # Event - set_rule(world.get_location("BrokeBOTTCStatue", player), - lambda state: broke_bottc_statue(state, player)) - - - # D08Z02S03 (Ferrous Tree) - # No items - # Doors - set_rule(world.get_entrance("D08Z02S03[W]", player), - lambda state: state.has("OpenedBOTTCStatue", player)) - - - # D08Z03S01 (Hall of the Dawning) - # No items - # Doors - set_rule(world.get_entrance("D08Z03S01[E]", player), - lambda state: state.has("Verses Spun from Gold", player, 4)) - - - # D08Z03S02 (Hall of the Dawning) - # No items - # Doors - set_rule(world.get_entrance("D08Z03S02[NW]", player), - lambda state: state.has("Wall Climb Ability", player)) - - - # D08Z03S03 (Hall of the Dawning) - # Items - set_rule(world.get_location("HotD: Laudes, the First of the Amanecidas", player), - lambda state: can_beat_boss(state, "Hall", logic, player)) - # Doors - set_rule(world.get_entrance("D08Z03S03[W]", player), - lambda state: can_beat_boss(state, "Hall", logic, player)) - set_rule(world.get_entrance("D08Z03S03[E]", player), - lambda state: can_beat_boss(state, "Hall", logic, player)) - - - # D09Z01S01 (Wall of the Holy Prohibitions) - # Items - set_rule(world.get_location("WotHP: Amanecida of the Molten Thorn", player), - lambda state: can_beat_boss(state, "Wall", logic, player)) - # No doors - - - # D09Z01S02 (Wall of the Holy Prohibitions) - # Items - set_rule(world.get_location("WotHP: Upper east room, center gold cell", player), - lambda state: state.has("D09Z01S02[Cell5]", player)) - set_rule(world.get_location("WotHP: Upper east room, lift puzzle", player), - lambda state: ( - state.has("D09Z01S02[NW]", player) - or state.has("D09Z01S02[N]", player) - or state.has("D09Z01S02[Cell1]", player) - or state.has("D09Z01S02[Cell6]", player) - or state.has("D09Z01S02[Cell4]", player) - or state.has("D09Z01S02[Cell3]", player) - or state.has("D09Z01S02[Cell22]", player) - or state.has("D09Z01S02[Cell23]", player) - )) - # Doors - set_rule(world.get_entrance("D09Z01S02[SW]", player), - lambda state: state.has("D09Z01S02[Cell2]", player)) - set_rule(world.get_entrance("D09Z01S02[NW]", player), - lambda state: ( - state.has("D09Z01S02[N]", player) - or state.has("D09Z01S02[Cell1]", player) - or state.has("D09Z01S02[Cell6]", player) - or state.has("D09Z01S02[Cell4]", player) - or state.has("D09Z01S02[Cell3]", player) - or state.has("D09Z01S02[Cell22]", player) - or state.has("D09Z01S02[Cell23]", player) - )) - set_rule(world.get_entrance("D09Z01S02[N]", player), - lambda state: ( - state.has("D09Z01S02[NW]", player) - or state.has("D09Z01S02[Cell1]", player) - or state.has("D09Z01S02[Cell6]", player) - or state.has("D09Z01S02[Cell4]", player) - or state.has("D09Z01S02[Cell3]", player) - or state.has("D09Z01S02[Cell22]", player) - or state.has("D09Z01S02[Cell23]", player) - )) - set_rule(world.get_entrance("D09Z01S02[Cell1]", player), - lambda state: ( - state.has("D09Z01S02[NW]", player) - or state.has("D09Z01S02[N]", player) - or state.has("D09Z01S02[Cell6]", player) - or state.has("D09Z01S02[Cell4]", player) - or state.has("D09Z01S02[Cell3]", player) - or state.has("D09Z01S02[Cell22]", player) - or state.has("D09Z01S02[Cell23]", player) - )) - add_rule(world.get_entrance("D09Z01S02[Cell1]", player), - lambda state: state.has("Key of the Secular", player)) - set_rule(world.get_entrance("D09Z01S02[Cell6]", player), - lambda state: ( - state.has("D09Z01S02[NW]", player) - or state.has("D09Z01S02[N]", player) - or state.has("D09Z01S02[Cell1]", player) - or state.has("D09Z01S02[Cell4]", player) - or state.has("D09Z01S02[Cell3]", player) - or state.has("D09Z01S02[Cell22]", player) - or state.has("D09Z01S02[Cell23]", player) - )) - add_rule(world.get_entrance("D09Z01S02[Cell6]", player), - lambda state: state.has("Key of the Scribe", player)) - set_rule(world.get_entrance("D09Z01S02[Cell4]", player), - lambda state: ( - state.has("D09Z01S02[NW]", player) - or state.has("D09Z01S02[N]", player) - or state.has("D09Z01S02[Cell1]", player) - or state.has("D09Z01S02[Cell6]", player) - or state.has("D09Z01S02[Cell3]", player) - or state.has("D09Z01S02[Cell22]", player) - or state.has("D09Z01S02[Cell23]", player) - )) - add_rule(world.get_entrance("D09Z01S02[Cell4]", player), - lambda state: state.has("Key of the Inquisitor", player)) - set_rule(world.get_entrance("D09Z01S02[Cell2]", player), - lambda state: state.has("D09Z01S02[SW]", player)) - set_rule(world.get_entrance("D09Z01S02[Cell3]", player), - lambda state: ( - state.has("D09Z01S02[NW]", player) - or state.has("D09Z01S02[N]", player) - or state.has("D09Z01S02[Cell1]", player) - or state.has("D09Z01S02[Cell6]", player) - or state.has("D09Z01S02[Cell4]", player) - or state.has("D09Z01S02[Cell22]", player) - or state.has("D09Z01S02[Cell23]", player) - )) - add_rule(world.get_entrance("D09Z01S02[Cell3]", player), - lambda state: state.has("Key of the Secular", player)) - set_rule(world.get_entrance("D09Z01S02[Cell22]", player), - lambda state: ( - state.has("D09Z01S02[NW]", player) - or state.has("D09Z01S02[N]", player) - or state.has("D09Z01S02[Cell1]", player) - or state.has("D09Z01S02[Cell6]", player) - or state.has("D09Z01S02[Cell4]", player) - or state.has("D09Z01S02[Cell3]", player) - or state.has("D09Z01S02[Cell23]", player) - )) - set_rule(world.get_entrance("D09Z01S02[Cell23]", player), - lambda state: ( - state.has("D09Z01S02[NW]", player) - or state.has("D09Z01S02[N]", player) - or state.has("D09Z01S02[Cell1]", player) - or state.has("D09Z01S02[Cell6]", player) - or state.has("D09Z01S02[Cell4]", player) - or state.has("D09Z01S02[Cell3]", player) - or state.has("D09Z01S02[Cell22]", player) - )) - add_rule(world.get_entrance("D09Z01S02[Cell23]", player), - lambda state: state.has("Key of the Secular", player)) - - - # D09Z01S03 (Wall of the Holy Prohibitions) - # Items - set_rule(world.get_location("WotHP: Quirce, Returned By The Flames", player), - lambda state: can_beat_boss(state, "Prison", logic, player)) - # Doors - set_rule(world.get_entrance("D09Z01S03[W]", player), - lambda state: ( - state.has("D09Z01S03[N]", player) - and can_beat_boss(state, "Prison", logic, player) - )) + ) - - # D09Z01S05 (Wall of the Holy Prohibitions) - # Event - set_rule(world.get_location("OpenedWOTHPGate", player), - lambda state: opened_wothp_gate(state, player)) - - - # D09Z01S06 (Wall of the Holy Prohibitions) - # No items - # Doors - set_rule(world.get_entrance("D09Z01S06[-E]", player), - lambda state: state.has("Key of the High Peaks", player)) - - - # D09Z01S07 (Wall of the Holy Prohibitions) - # No items - # Doors - set_rule(world.get_entrance("D09Z01S07[SW]", player), - lambda state: ( - state.has("D09Z01S07[SE]", player) - or state.has("D09Z01S07[W]", player) - or state.has("D09Z01S07[E]", player) - )) - set_rule(world.get_entrance("D09Z01S07[SE]", player), - lambda state: ( - state.has("D09Z01S07[SW]", player) - or state.has("D09Z01S07[W]", player) - or state.has("D09Z01S07[E]", player) - )) - set_rule(world.get_entrance("D09Z01S07[W]", player), - lambda state: ( - state.has("D09Z01S07[SW]", player) - or state.has("D09Z01S07[SE]", player) - or state.has("D09Z01S07[E]", player) - )) - set_rule(world.get_entrance("D09Z01S07[E]", player), - lambda state: ( - state.has("D09Z01S07[SW]", player) - or state.has("D09Z01S07[SE]", player) - or state.has("D09Z01S07[W]", player) - )) - set_rule(world.get_entrance("D09Z01S07[NW]", player), - lambda state: state.has("D09Z01S07[N]", player)) - set_rule(world.get_entrance("D09Z01S07[N]", player), - lambda state: state.has("D09Z01S07[NW]", player)) - set_rule(world.get_entrance("D09Z01S07[NE]", player), - lambda state: ( - state.has("D09Z01S07[SW]", player) - or state.has("D09Z01S07[SE]", player) - or state.has("D09Z01S07[W]", player) - or state.has("D09Z01S07[E]", player) - )) - add_rule(world.get_entrance("D09Z01S07[NE]", player), - lambda state: state.has("Blood Perpetuated in Sand", player)) - - - # D09Z01S08 (Wall of the Holy Prohibitions) - # Items - set_rule(world.get_location("WotHP: Collapsing floor ledge", player), - lambda state: ( - ( - state.has("D09Z01S08[W]", player) - or state.has("D09Z01S08[Cell18]", player) - ) - and state.has("OpenedWOTHPGate", player) - )) - # Doors - set_rule(world.get_entrance("D09Z01S08[W]", player), - lambda state: state.has("D09Z01S08[Cell14]", player)) - add_rule(world.get_entrance("D09Z01S08[W]", player), - lambda state: state.has("OpenedWOTHPGate", player)) - set_rule(world.get_entrance("D09Z01S08[S]", player), - lambda state: ( - state.has("D09Z01S08[W]", player) - or state.has("D09Z01S08[Cell14]", player) - )) - set_rule(world.get_entrance("D09Z01S08[SE]", player), - lambda state: ( - state.has("D09Z01S08[Cell15]", player) - or state.has("D09Z01S08[Cell16]", player) - or state.has("D09Z01S08[Cell18]", player) - or state.has("D09Z01S08[Cell17]", player) - and state.has("Dash Ability", player) - )) - set_rule(world.get_entrance("D09Z01S08[NE]", player), - lambda state: ( - state.has("D09Z01S08[Cell7]", player) - or state.has("D09Z01S08[Cell17]", player) - and state.has("Dash Ability", player) - )) - set_rule(world.get_entrance("D09Z01S08[Cell14]", player), - lambda state: state.has("D09Z01S08[W]", player)) - set_rule(world.get_entrance("D09Z01S08[Cell15]", player), - lambda state: ( - state.has("Key of the Scribe", player) - and ( - state.has("D09Z01S08[SE]", player) - or state.has("D09Z01S08[Cell16]", player) - or state.has("D09Z01S08[Cell18]", player) - or state.has("D09Z01S08[Cell17]", player) - and state.has("Dash Ability", player) - ) - )) - set_rule(world.get_entrance("D09Z01S08[Cell7]", player), - lambda state: ( - state.has("Key of the Inquisitor", player) - and ( - state.has("D09Z01S08[NE]", player) - or state.has("D09Z01S08[Cell17]", player) - and state.has("Dash Ability", player) - ) - )) - set_rule(world.get_entrance("D09Z01S08[Cell16]", player), - lambda state: ( - state.has("Key of the Inquisitor", player) - and ( - state.has("D09Z01S08[SE]", player) - or state.has("D09Z01S08[Cell15]", player) - or state.has("D09Z01S08[Cell18]", player) - or state.has("D09Z01S08[Cell17]", player) - and state.has("Dash Ability", player) - ) - )) - set_rule(world.get_entrance("D09Z01S08[Cell18]", player), - lambda state: ( - state.has("Key of the Scribe", player) - and ( - state.has("D09Z01S08[SE]", player) - or state.has("D09Z01S08[Cell15]", player) - or state.has("D09Z01S08[Cell16]", player) - or state.has("D09Z01S08[Cell17]", player) - and state.has("Dash Ability", player) - ) - )) - - - # D09Z01S09 (Wall of the Holy Prohibitions) - # Items - set_rule(world.get_location("WotHP: Lower west room, top ledge", player), - lambda state: ( - state.has("D09Z01S09[Cell24]", player) - or state.has("Dash Ability", player) - and ( - state.has("D09Z01S09[NW]", player) - or state.has("D09Z01S09[Cell19]", player) - or state.has("Purified Hand of the Nun", player) - and ( - can_air_stall(state, logic, player) - or can_dawn_jump(state, logic, player) - ) - ) - )) - # Doors - set_rule(world.get_entrance("D09Z01S09[SW]", player), - lambda state: ( - state.has("D09Z01S09[Cell21]", player) - or state.has("D09Z01S09[Cell20]", player) - or state.has("D09Z01S09[E]", player) - or state.has("Dash Ability", player) - )) - set_rule(world.get_entrance("D09Z01S09[NW]", player), - lambda state: ( - state.has("D09Z01S09[Cell19]", player) - or state.has("D09Z01S09[Cell24]", player) - )) - add_rule(world.get_entrance("D09Z01S09[NW]", player), - lambda state: ( - state.has("D09Z01S09[Cell19]", player) - or state.has("Dash Ability", player) - and ( - state.has("D09Z01S09[Cell24]", player) - or state.has("Purified Hand of the Nun", player) - and ( - can_air_stall(state, logic, player) - or can_dawn_jump(state, logic, player) - ) - ) - )) - set_rule(world.get_entrance("D09Z01S09[E]", player), - lambda state: ( - state.has("D09Z01S09[Cell21]", player) - or state.has("D09Z01S09[Cell20]", player) - or state.has("D09Z01S09[SW]", player) - or state.has("Dash Ability", player) - )) - set_rule(world.get_entrance("D09Z01S09[Cell24]", player), - lambda state: ( - state.has("D09Z01S09[NW]", player) - or state.has("D09Z01S09[Cell19]", player) - )) - add_rule(world.get_entrance("D09Z01S09[Cell24]", player), - lambda state: ( - state.has("Dash Ability", player) - and ( - state.has("D09Z01S09[NW]", player) - or state.has("D09Z01S09[Cell19]", player) - or state.has("Purified Hand of the Nun", player) - and ( - can_air_stall(state, logic, player) - or can_dawn_jump(state, logic, player) - ) - ) - )) - set_rule(world.get_entrance("D09Z01S09[Cell19]", player), - lambda state: ( - state.has("D09Z01S09[NW]", player) - or state.has("D09Z01S09[Cell24]", player) - )) - add_rule(world.get_entrance("D09Z01S09[Cell19]", player), - lambda state: ( - state.has("D09Z01S09[NW]", player) - or state.has("Dash Ability", player) - and ( - state.has("D09Z01S09[Cell24]", player) - or state.has("Purified Hand of the Nun", player) - and ( - can_air_stall(state, logic, player) - or can_dawn_jump(state, logic, player) - ) - ) - )) - set_rule(world.get_entrance("D09Z01S09[Cell20]", player), - lambda state: ( - state.has("Key of the Scribe", player) - and ( - state.has("D09Z01S09[Cell21]", player) - or state.has("D09Z01S09[SW]", player) - or state.has("D09Z01S09[E]", player) - or state.has("Dash Ability", player) - ) - )) - set_rule(world.get_entrance("D09Z01S09[Cell21]", player), - lambda state: ( - state.has("Key of the Inquisitor", player) - and ( - state.has("D09Z01S09[Cell20]", player) - or state.has("D09Z01S09[SW]", player) - or state.has("D09Z01S09[E]", player) - or state.has("Dash Ability", player) - ) - )) - - - # D09Z01S10 (Wall of the Holy Prohibitions) - # Items - set_rule(world.get_location("WotHP: Lower east room, top bronze cell", player), - lambda state: state.has("D09Z01S10[Cell13]", player)) - set_rule(world.get_location("WotHP: Lower east room, hidden ledge", player), - lambda state: ( - state.has("D09Z01S10[W]", player) - or state.has("D09Z01S10[Cell12]", player) - or state.has("D09Z01S10[Cell10]", player) - or state.has("D09Z01S10[Cell11]", player) - )) - # Doors - set_rule(world.get_entrance("D09Z01S10[W]", player), - lambda state: ( - state.has("D09Z01S10[Cell12]", player) - or state.has("D09Z01S10[Cell10]", player) - or state.has("D09Z01S10[Cell11]", player) - )) - set_rule(world.get_entrance("D09Z01S10[Cell12]", player), - lambda state: ( - state.has("D09Z01S10[W]", player) or \ - state.has("D09Z01S10[Cell10]", player) or \ - state.has("D09Z01S10[Cell11]", player) - )) - add_rule(world.get_entrance("D09Z01S10[Cell12]", player), - lambda state: state.has("Key of the Secular", player)) - set_rule(world.get_entrance("D09Z01S10[Cell10]", player), - lambda state: ( - state.has("D09Z01S10[W]", player) - or state.has("D09Z01S10[Cell12]", player) - or state.has("D09Z01S10[Cell11]", player) - )) - add_rule(world.get_entrance("D09Z01S10[Cell10]", player), - lambda state: state.has("Key of the Scribe", player)) - set_rule(world.get_entrance("D09Z01S10[Cell11]", player), - lambda state: ( - state.has("D09Z01S10[W]", player) - or state.has("D09Z01S10[Cell12]", player) - or state.has("D09Z01S10[Cell10]", player) - )) - add_rule(world.get_entrance("D09Z01S10[Cell11]", player), - lambda state: state.has("Key of the Scribe", player)) + def can_beat_ossuary_boss(self, state: CollectionState) -> bool: + return ( + self.has_boss_strength(state, "isidora") + and state.can_reach_region("D01BZ06S01[E]", self.player) + ) - # D09BZ01S01 (Wall of the Holy Prohibitions - Inside cells) - # Items - set_rule(world.get_location("WotHP: Upper east room, center cell ledge", player), - lambda state: state.has("D09BZ01S01[Cell22]", player)) - set_rule(world.get_location("WotHP: Upper east room, center cell floor", player), - lambda state: ( - state.has("D09BZ01S01[Cell22]", player) - or state.has("D09BZ01S01[Cell23]", player) - )) - set_rule(world.get_location("WotHP: Upper east room, top bronze cell", player), - lambda state: state.has("D09BZ01S01[Cell1]", player)) - set_rule(world.get_location("WotHP: Upper east room, top silver cell", player), - lambda state: state.has("D09BZ01S01[Cell6]", player)) - set_rule(world.get_location("WotHP: Upper west room, top silver cell", player), - lambda state: ( - state.has("D09BZ01S01[Cell14]", player) - or state.has("D09BZ01S01[Cell15]", player) - )) - set_rule(world.get_location("WotHP: Upper west room, center gold cell", player), - lambda state: state.has("D09BZ01S01[Cell16]", player)) - set_rule(world.get_location("WotHP: Lower west room, bottom gold cell", player), - lambda state: ( - state.has("D09BZ01S01[Cell21]", player) - and state.has("Blood Perpetuated in Sand", player) - and can_climb_on_root(state, player) - and can_survive_poison(state, logic, player, 2) - and state.has("Dash Ability", player) - )) - set_rule(world.get_location("WotHP: Lower east room, top silver cell", player), - lambda state: state.has("D09BZ01S01[Cell10]", player)) - set_rule(world.get_location("WotHP: Lower east room, bottom silver cell", player), - lambda state: ( - state.has("D09BZ01S01[Cell11]", player) - and ( - can_survive_poison(state, logic, player, 1) - and state.has("Dash Ability", player) - or state.has_any({"Debla of the Lights", "Taranto to my Sister", "Cante Jondo of the Three Sisters", "Verdiales of the Forsaken Hamlet", "Cantina of the Blue Rose"}, player) - or aubade(state, player) - ) - )) - # Doors - set_rule(world.get_entrance("D09BZ01S01[Cell2]", player), - lambda state: state.has("D09BZ01S01[Cell3]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell3]", player), - lambda state: state.has("D09BZ01S01[Cell2]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell4]", player), - lambda state: state.has("D09BZ01S01[Cell5]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell5]", player), - lambda state: state.has("D09BZ01S01[Cell5]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell12]", player), - lambda state: state.has("D09BZ01S01[Cell13]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell13]", player), - lambda state: state.has("D09BZ01S01[Cell12]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell14]", player), - lambda state: state.has("D09BZ01S01[Cell15]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell15]", player), - lambda state: state.has("D09BZ01S01[Cell14]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell17]", player), - lambda state: state.has("D09BZ01S01[Cell18]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell19]", player), - lambda state: state.has("D09BZ01S01[Cell20]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell20]", player), - lambda state: state.has("D09BZ01S01[Cell19]", player)) - set_rule(world.get_entrance("D09BZ01S01[Cell23]", player), - lambda state: state.has("D09BZ01S01[Cell22]", player)) - add_rule(world.get_entrance("D09BZ01S01[Cell23]", player), - lambda state: state.has("Key of the Secular", player)) - - - # D17Z01S01 (Brotherhood of the Silent Sorrow) - set_rule(world.get_location("BotSS: Starting room ledge", player), - lambda state: state.has("D17Z01S01[Cherubs3]", player)) - set_rule(world.get_location("BotSS: Starting room Child of Moonlight", player), - lambda state: ( - state.has("D17Z01S01[Cherubs1]", player) - or state.has("Taranto to my Sister", player) - or ( - can_climb_on_root(state, player) - or can_cross_gap(state, logic, player, 9) - ) - and ( - state.has_any({"Blood Perpetuated in Sand", "Purified Hand of the Nun", "Debla of the Lights", "Verdiales of the Forsaken Hamlet", "Cloistered Ruby"}, player) - or tirana(state, player) - ) - )) - - - # D17Z01S02 (Brotherhood of the Silent Sorrow) - # No items - # Doors - set_rule(world.get_entrance("D17Z01S02[W]", player), - lambda state: state.has("Dash Ability", player)) - set_rule(world.get_entrance("D17Z01S02[E]", player), - lambda state: ( - state.has("D17Z01S02[N]", player) - or state.has("Dash Ability", player) - )) - set_rule(world.get_entrance("D17Z01S02[N]", player), - lambda state: ( - state.has("Blood Perpetuated in Sand", player) - and ( - state.has("D17Z01S02[E]", player) - or state.has("D17Z01S02[W]", player) - and state.has("Dash Ability", player) - ) - )) - - - # D17Z01S03 (Brotherhood of the Silent Sorrow) - # No items - # Doors - set_rule(world.get_entrance("D17Z01S03[relic]", player), - lambda state: state.has("Key to the Chamber of the Eldest Brother", player)) - - - # D17Z01S04 (Brotherhood of the Silent Sorrow) - # Items - if world.boots_of_pleading[player]: - set_rule(world.get_location("BotSS: 2nd meeting with Redento", player), - lambda state: redento(state, blasphemousworld, player, 2)) - # Doors - set_rule(world.get_entrance("D17Z01S04[N]", player), - lambda state: state.has("D17Z01S04[FrontR]", player)) - set_rule(world.get_entrance("D17Z01S04[FrontR]", player), - lambda state: state.has("D17Z01S04[N]", player)) - # Event - set_rule(world.get_location("OpenedBOTSSLadder", player), - lambda state: opened_botss_ladder(state, player)) - - - # D17Z01S05 (Brotherhood of the Silent Sorrow) - # No items - # Doors - set_rule(world.get_entrance("D17Z01S05[S]", player), - lambda state: state.has("OpenedBOTSSLadder", player)) - - - # D17Z01S10 (Brotherhood of the Silent Sorrow) - # No items - # Doors - set_rule(world.get_entrance("D17Z01S10[W]", player), - lambda state: state.has_any({"Blood Perpetuated in Sand", "Purified Hand of the Nun"}, player)) - - - # D17Z01S11 (Brotherhood of the Silent Sorrow) - # Items - set_rule(world.get_location("BotSS: Warden of the Silent Sorrow", player), - lambda state: can_beat_boss(state, "Brotherhood", logic, player)) - # Doors - set_rule(world.get_entrance("D17Z01S11[W]", player), - lambda state: can_beat_boss(state, "Brotherhood", logic, player)) - set_rule(world.get_entrance("D17Z01S11[E]", player), - lambda state: can_beat_boss(state, "Brotherhood", logic, player)) - - - # D17Z01S14 (Brotherhood of the Silent Sorrow) - # Items - set_rule(world.get_location("BotSS: Outside church", player), - lambda state: ( - state.has("D17Z01S14[W]", player) - or state.has("Blood Perpetuated in Sand", player) - )) - # Doors - set_rule(world.get_entrance("D17Z01S14[W]", player), - lambda state: ( - state.has("Incomplete Scapular", player) - and state.has("Blood Perpetuated in Sand", player) - )) - set_rule(world.get_entrance("D17Z01S14[E]", player), - lambda state: state.has("Blood Perpetuated in Sand", player)) - set_rule(world.get_entrance("D17Z01S14[-Cherubs1]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) + def can_beat_mourning_boss(self, state: CollectionState) -> bool: + return ( + self.has_boss_strength(state, "sierpes") + and state.can_reach_region("D20Z02S07[W]", self.player) + ) + + def can_beat_graveyard_boss(self, state: CollectionState) -> bool: + return ( + self.has_boss_strength(state, "amanecida") + and self.wall_climb(state) + and state.can_reach_region("D01Z06S01[Santos]", self.player) + and state.can_reach_region("D02Z03S18[NW]", self.player) + and state.can_reach_region("D02Z02S03[NE]", self.player) + ) + + def can_beat_jondo_boss(self, state: CollectionState) -> bool: + return ( + self.has_boss_strength(state, "amanecida") + and state.can_reach_region("D01Z06S01[Santos]", self.player) and ( - state.has("D17Z01S14[W]", player) - or state.has("Blood Perpetuated in Sand", player) - or can_cross_gap(state, logic, player, 11) + state.can_reach_region("D20Z01S06[NE]", self.player) + or state.can_reach_region("D20Z01S04[W]", self.player) ) - )) - set_rule(world.get_entrance("D17Z01S14[-Cherubs2]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) and ( - state.has("D17Z01S14[E]", player) - and can_cross_gap(state, logic, player, 8) - or state.has("D17Z01S14[W]", player) - and can_cross_gap(state, logic, player, 10) - or state.has("Blood Perpetuated in Sand", player) + state.can_reach_region("D03Z01S04[E]", self.player) + or state.can_reach_region("D03Z02S10[N]", self.player) ) - )) - set_rule(world.get_entrance("D17Z01S14[-Cherubs3]", player), - lambda state: ( - state.has("Linen of Golden Thread", player) + ) + + def can_beat_patio_boss(self, state: CollectionState) -> bool: + return ( + self.has_boss_strength(state, "amanecida") + and state.can_reach_region("D01Z06S01[Santos]", self.player) + and state.can_reach_region("D06Z01S02[W]", self.player) and ( - state.has("D17Z01S14[E]", player) - or state.has("Blood Perpetuated in Sand", player) + state.can_reach_region("D04Z01S03[E]", self.player) + or state.can_reach_region("D04Z01S01[W]", self.player) + or state.can_reach_region("D06Z01S18[-Cherubs]", self.player) ) - )) - - - # D17Z01S15 (Brotherhood of the Silent Sorrow) - # Items - set_rule(world.get_location("BotSS: Esdras' final gift", player), - lambda state: ( - can_beat_boss(state, "Bridge", logic, player) - and state.has_group("wounds", player, 3) - )) - set_rule(world.get_location("BotSS: Crisanta's gift", player), - lambda state: ( - can_beat_boss(state, "Rooftops", logic, player) - and state.has("Apodictic Heart of Mea Culpa", player) - )) - # No doors - - - # D17BZ02S01 (Brotherhood of the Silent Sorrow - Platforming challenge) - # Items - set_rule(world.get_location("BotSS: Platforming gauntlet", player), - lambda state: ( - #state.has("D17BZ02S01[FrontR]", player) or - # TODO: actually fix this once door rando is real - state.has_all({"Dash Ability", "Wall Climb Ability"}, player) - )) - # Doors - set_rule(world.get_entrance("D17BZ02S01[FrontR]", player), - lambda state: state.has_all({"Dash Ability", "Wall Climb Ability"}, player)) - - - # D20Z01S04 (Echoes of Salt) - # No items - # Doors - set_rule(world.get_entrance("D20Z01S04[E]", player), - lambda state: state.has("OpenedDCGateW", player)) - - - # D20Z01S09 (Echoes of Salt) - # Items - set_rule(world.get_location("EoS: Lantern jump near elevator", player), - lambda state: ( - state.has("D20Z01S09[W]", player) - or state.has("Dash Ability", player) - )) - # Doors - set_rule(world.get_entrance("D20Z01S09[W]", player), - lambda state: state.has("Dash Ability", player)) - set_rule(world.get_entrance("D20Z01S09[E]", player), - lambda state: state.has_all({"Blood Perpetuated in Sand", "Dash Ability"}, player)) - - - # D20Z01S10 (Echoes of Salt) - # No items - # Doors - set_rule(world.get_entrance("D20Z01S10[W]", player), - lambda state: state.has_all({"Blood Perpetuated in Sand", "Dash Ability"}, player)) - set_rule(world.get_entrance("D20Z01S10[E]", player), - lambda state: state.has_all({"Blood Perpetuated in Sand", "Dash Ability"}, player)) - - - # D20Z02S03 (Mourning and Havoc) - # No items - # Doors - set_rule(world.get_entrance("D20Z02S03[NE]", player), - lambda state: ( - can_walk_on_root(state, player) - or can_cross_gap(state, logic, player, 5) - )) - - - # D20Z02S04 (Mourning and Havoc) - # No items - # Doors - set_rule(world.get_entrance("D20Z02S04[W]", player), - lambda state: state.has("Dash Ability", player)) - set_rule(world.get_entrance("D20Z02S04[E]", player), - lambda state: state.has("Dash Ability", player)) - - - # D20Z02S05 (Mourning and Havoc) - # No items - # Doors - set_rule(world.get_entrance("D20Z02S05[NW]", player), - lambda state: ( - state.has("Nail Uprooted from Dirt", player) - or can_cross_gap(state, logic, player, 3) - )) - - - # D20Z02S06 (Mourning and Havoc) - # No items - # Doors - set_rule(world.get_entrance("D20Z02S06[NW]", player), - lambda state: ( - state.has("D20Z02S06[NE]", player) - or state.has("Purified Hand of the Nun", player) - or can_climb_on_root(state, player) - or can_dive_laser(state, logic, player) - )) - set_rule(world.get_entrance("D20Z02S06[NE]", player), - lambda state: ( - state.has("D20Z02S06[NW]", player) - or state.has("Purified Hand of the Nun", player) - or can_climb_on_root(state, player) - or can_dive_laser(state, logic, player) - )) - - - # D20Z02S08 (Mourning and Havoc) - # Items - set_rule(world.get_location("MaH: Sierpes", player), - lambda state: can_beat_boss(state, "Mourning", logic, player)) - set_rule(world.get_location("MaH: Sierpes' eye", player), - lambda state: can_beat_boss(state, "Mourning", logic, player)) - # No doors - - - # D20Z02S11 (Mourning and Havoc) - # No items - # Doors - set_rule(world.get_entrance("D20Z02S11[NW]", player), - lambda state: state.has("D20Z02S11[E]", player)) - set_rule(world.get_entrance("D20Z02S11[NW]", player), - lambda state: ( - mourning_skips_allowed(logic) + ) + + def can_beat_wall_boss(self, state: CollectionState) -> bool: + return ( + self.has_boss_strength(state, "amanecida") + and state.can_reach_region("D01Z06S01[Santos]", self.player) + and state.can_reach_region("D09Z01S09[Cell24]", self.player) and ( - state.has("Purified Hand of the Nun", player) - or can_break_tirana(state, logic, player) - or state.has("D20Z02S11[E]", player) + state.can_reach_region("D09Z01S11[E]", self.player) + or state.can_reach_region("D06Z01S13[W]", self.player) ) - )) - set_rule(world.get_entrance("D20Z02S11[E]", player), - lambda state: ( - mourning_skips_allowed(logic) + ) + + def can_beat_hall_boss(self, state: CollectionState) -> bool: + return ( + self.has_boss_strength(state, "laudes") and ( - state.has("Purified Hand of the Nun", player) - or can_break_tirana(state, logic, player) - or state.has("D20Z02S11[NW]", player) - and can_cross_gap(state, logic, player, 5) + state.can_reach_region("D08Z01S02[NE]", self.player) + or state.can_reach_region("D08Z03S02[NW]", self.player) ) - )) + ) + def can_beat_perpetua(self, state: CollectionState) -> bool: + return self.has_boss_strength(state, "perpetua") + + def can_beat_legionary(self, state: CollectionState) -> bool: + return self.has_boss_strength(state, "legionary") + + + def has_boss_strength(self, state: CollectionState, boss: str) -> bool: + life: int = state.count("Life Upgrade", self.player) + sword: int = state.count("Mea Culpa Upgrade", self.player) + fervour: int = state.count("Fervour Upgrade", self.player) + flasks: int = self.flasks(state) + quicksilver: int = self.quicksilver(state) + + player_strength: float = ( + min(6, life) * 0.25 / 6 + + min(7, sword) * 0.25 / 7 + + min(6, fervour) * 0.20 / 6 + + min(8, flasks) * 0.15 / 8 + + min(5, quicksilver) * 0.15 / 5 + ) - # Misc Items - set_rule(world.get_location("Second red candle", player), - lambda state: ( - state.has("Bead of Red Wax", player) - and ( - state.can_reach(world.get_region("D02Z03S06", player), player) - or state.has("D05Z01S02[W]", player) - ) - )) - set_rule(world.get_location("Third red candle", player), - lambda state: ( - state.has("Bead of Red Wax", player) - and state.has("D05Z01S02[W]", player) - and state.can_reach(world.get_region("D02Z03S06", player), player) - )) - set_rule(world.get_location("Second blue candle", player), - lambda state: ( - state.has("Bead of Blue Wax", player) - and ( - state.has("OpenedBOTSSLadder", player) - or state.can_reach(world.get_region("D01Z04S16", player), player) - ) - )) - set_rule(world.get_location("Third blue candle", player), - lambda state: ( - state.has("Bead of Blue Wax", player) - and state.has("OpenedBOTSSLadder", player) - and state.can_reach(world.get_region("D01Z04S16", player), player) - )) - set_rule(world.get_location("Defeat 1 Amanecida", player), - lambda state: amanecida_rooms(state, logic, player, 1)) - set_rule(world.get_location("Defeat 2 Amanecidas", player), - lambda state: amanecida_rooms(state, logic, player, 2)) - set_rule(world.get_location("Defeat 3 Amanecidas", player), - lambda state: amanecida_rooms(state, logic, player, 3)) - set_rule(world.get_location("Defeat 4 Amanecidas", player), - lambda state: amanecida_rooms(state, logic, player, 4)) - set_rule(world.get_location("Defeat all Amanecidas", player), - lambda state: amanecida_rooms(state, logic, player, 4)) - set_rule(world.get_location("Confessor Dungeon 1 main", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 1) - )) - set_rule(world.get_location("Confessor Dungeon 2 main", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 2) - )) - set_rule(world.get_location("Confessor Dungeon 3 main", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 3) - )) - set_rule(world.get_location("Confessor Dungeon 4 main", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 4) - )) - set_rule(world.get_location("Confessor Dungeon 5 main", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 5) - )) - set_rule(world.get_location("Confessor Dungeon 6 main", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 6) - )) - set_rule(world.get_location("Confessor Dungeon 7 main", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 7) - )) - set_rule(world.get_location("Confessor Dungeon 1 extra", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 1) - )) - set_rule(world.get_location("Confessor Dungeon 2 extra", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 2) - )) - set_rule(world.get_location("Confessor Dungeon 3 extra", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 3) - )) - set_rule(world.get_location("Confessor Dungeon 4 extra", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 4) - )) - set_rule(world.get_location("Confessor Dungeon 5 extra", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 5) - )) - set_rule(world.get_location("Confessor Dungeon 6 extra", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 6) - )) - set_rule(world.get_location("Confessor Dungeon 7 extra", player), - lambda state: ( - state.has("Weight of True Guilt", player) - and guilt_rooms(state, player, 7) - )) - set_rule(world.get_location("Skill 1, Tier 1", player), - lambda state: sword_rooms(state, player, 1)) - set_rule(world.get_location("Skill 1, Tier 2", player), - lambda state: sword_rooms(state, player, 2)) - set_rule(world.get_location("Skill 1, Tier 3", player), - lambda state: sword_rooms(state, player, 4)) - set_rule(world.get_location("Skill 2, Tier 1", player), - lambda state: sword_rooms(state, player, 1)) - set_rule(world.get_location("Skill 2, Tier 2", player), - lambda state: sword_rooms(state, player, 3)) - set_rule(world.get_location("Skill 2, Tier 3", player), - lambda state: sword_rooms(state, player, 6)) - set_rule(world.get_location("Skill 3, Tier 1", player), - lambda state: sword_rooms(state, player, 2)) - set_rule(world.get_location("Skill 3, Tier 2", player), - lambda state: sword_rooms(state, player, 5)) - set_rule(world.get_location("Skill 3, Tier 3", player), - lambda state: sword_rooms(state, player, 7)) - set_rule(world.get_location("Skill 4, Tier 1", player), - lambda state: sword_rooms(state, player, 1)) - set_rule(world.get_location("Skill 4, Tier 2", player), - lambda state: sword_rooms(state, player, 3)) - set_rule(world.get_location("Skill 4, Tier 3", player), - lambda state: sword_rooms(state, player, 6)) - set_rule(world.get_location("Skill 5, Tier 1", player), - lambda state: sword_rooms(state, player, 1)) - set_rule(world.get_location("Skill 5, Tier 2", player), - lambda state: sword_rooms(state, player, 2)) - set_rule(world.get_location("Skill 5, Tier 3", player), - lambda state: sword_rooms(state, player, 4)) \ No newline at end of file + bosses: Dict[str, float] = { + "warden": -0.10, + "ten-piedad": 0.05, + "charred-visage": 0.20, + "tres-angustias": 0.15, + "esdras": 0.25, + "melquiades": 0.25, + "exposito": 0.30, + "quirce": 0.35, + "crisanta": 0.50, + "isidora": 0.70, + "sierpes": 0.70, + "amanecida": 0.60, + "laudes": 0.60, + "perpetua": -0.05, + "legionary": 0.20 + } + boss_strength: float = bosses[boss] + return player_strength >= (boss_strength - 0.10 if self.world.options.difficulty >= 2 else + (boss_strength if self.world.options.difficulty >= 1 else boss_strength + 0.10)) + + def guilt_rooms(self, state: CollectionState) -> int: + doors = [ + "D01Z04S01[NE]", + "D02Z02S11[W]", + "D03Z03S02[NE]", + "D04Z02S02[SE]", + "D05Z01S05[NE]", + "D09Z01S05[W]", + "D17Z01S04[W]", + ] + + return sum(state.can_reach_region(door, self.player) for door in doors) + + def sword_rooms(self, state: CollectionState) -> int: + doors = [ + ["D01Z02S07[E]", "D01Z02S02[SW]"], + ["D20Z01S04[E]", "D01Z05S23[W]"], + ["D02Z03S02[NE]"], + ["D04Z02S21[NE]"], + ["D05Z01S21[NW]"], + ["D06Z01S15[NE]"], + ["D17Z01S07[SW]"] + ] + + total: int = 0 + for subdoors in doors: + for door in subdoors: + if state.can_reach_region(door, self.player): + total += 1 + break + + return total + + def redento_rooms(self, state: CollectionState) -> int: + if ( + state.can_reach_region("D03Z01S04[E]", self.player) + or state.can_reach_region("D03Z02S10[N]", self.player) + ): + if ( + state.can_reach_region("D17Z01S05[S]", self.player) + or state.can_reach_region("D17BZ02S01[FrontR]", self.player) + ): + if ( + state.can_reach_region("D01Z03S04[E]", self.player) + or state.can_reach_region("D08Z01S01[W]", self.player) + ): + if ( + state.can_reach_region("D04Z01S03[E]", self.player) + or state.can_reach_region("D04Z02S01[W]", self.player) + or state.can_reach_region("D06Z01S18[-Cherubs]", self.player) + ): + if ( + self.knots(state) >= 1 + and self.limestones(state) >= 3 + and ( + state.can_reach_region("D04Z02S08[E]", self.player) + or state.can_reach_region("D04BZ02S01[Redento]", self.player) + ) + ): + return 5 + return 4 + return 3 + return 2 + return 1 + return 0 + + def miriam_rooms(self, state: CollectionState) -> int: + doors = [ + "D02Z03S07[NWW]", + "D03Z03S07[NW]", + "D04Z04S01[E]", + "D05Z01S06[W]", + "D06Z01S17[E]" + ] + + return sum(state.can_reach_region(door, self.player) for door in doors) + + def amanecida_rooms(self, state: CollectionState) -> int: + total: int = 0 + if self.can_beat_graveyard_boss(state): + total += 1 + if self.can_beat_jondo_boss(state): + total += 1 + if self.can_beat_patio_boss(state): + total += 1 + if self.can_beat_wall_boss(state): + total += 1 + + return total + + def chalice_rooms(self, state: CollectionState) -> int: + doors = [ + ["D03Z01S02[E]", "D01Z05S02[W]", "D20Z01S03[N]"], + ["D05Z01S11[SE]", "D05Z02S02[NW]"], + ["D09Z01S09[E]", "D09Z01S10[W]", "D09Z01S08[SE]", "D09Z01S02[SW]"] + ] + + total: int = 0 + for subdoors in doors: + for door in subdoors: + if state.can_reach_region(door, self.player): + total += 1 + break + + return total diff --git a/worlds/blasphemous/Vanilla.py b/worlds/blasphemous/Vanilla.py index 034a2a295b6b..9cefe9df8ac4 100644 --- a/worlds/blasphemous/Vanilla.py +++ b/worlds/blasphemous/Vanilla.py @@ -8,12 +8,12 @@ } -junk_locations: Set[str] = [ +junk_locations: Set[str] = { "Albero: Donate 50000 Tears", "Ossuary: 11th reward", "AtTotS: Miriam's gift", "TSC: Jocinero's final reward" -] +} thorn_set: Set[str] = { @@ -44,4 +44,4 @@ "Skill 5, Tier 1": "Lunge Skill", "Skill 5, Tier 2": "Lunge Skill", "Skill 5, Tier 3": "Lunge Skill", -} \ No newline at end of file +} diff --git a/worlds/blasphemous/__init__.py b/worlds/blasphemous/__init__.py index a46fb55b9541..b110c316da48 100644 --- a/worlds/blasphemous/__init__.py +++ b/worlds/blasphemous/__init__.py @@ -1,15 +1,15 @@ from typing import Dict, List, Set, Any from collections import Counter -from BaseClasses import Region, Entrance, Location, Item, Tutorial, ItemClassification +from BaseClasses import Region, Location, Item, Tutorial, ItemClassification +from Options import OptionError from worlds.AutoWorld import World, WebWorld -from .Items import base_id, item_table, group_table, tears_set, reliquary_set, event_table -from .Locations import location_table -from .Rooms import room_table, door_table -from .Rules import rules -from worlds.generic.Rules import set_rule, add_rule -from .Options import blasphemous_options +from .Items import base_id, item_table, group_table, tears_list, reliquary_set +from .Locations import location_names +from .Rules import BlasRules +from worlds.generic.Rules import set_rule +from .Options import BlasphemousOptions, blas_option_groups from .Vanilla import unrandomized_dict, junk_locations, thorn_set, skill_dict - +from .region_data import regions, locations class BlasphemousWeb(WebWorld): theme = "stone" @@ -21,39 +21,33 @@ class BlasphemousWeb(WebWorld): "setup/en", ["TRPG"] )] + option_groups = blas_option_groups class BlasphemousWorld(World): """ Blasphemous is a challenging Metroidvania set in the cursed land of Cvstodia. Play as the Penitent One, trapped - in an endless cycle of death and rebirth, and free the world from it's terrible fate in your quest to break + in an endless cycle of death and rebirth, and free the world from its terrible fate in your quest to break your eternal damnation! """ - game: str = "Blasphemous" + game = "Blasphemous" web = BlasphemousWeb() item_name_to_id = {item["name"]: (base_id + index) for index, item in enumerate(item_table)} - location_name_to_id = {loc["name"]: (base_id + index) for index, loc in enumerate(location_table)} - location_name_to_game_id = {loc["name"]: loc["game_id"] for loc in location_table} + location_name_to_id = {loc: (base_id + index) for index, loc in enumerate(location_names.values())} item_name_groups = group_table - option_definitions = blasphemous_options + options_dataclass = BlasphemousOptions + options: BlasphemousOptions - required_client_version = (0, 4, 2) + required_client_version = (0, 4, 7) def __init__(self, multiworld, player): super(BlasphemousWorld, self).__init__(multiworld, player) self.start_room: str = "D17Z01S01" - self.door_connections: Dict[str, str] = {} - - - def set_rules(self): - rules(self) - for door in door_table: - add_rule(self.multiworld.get_location(door["Id"], self.player), - lambda state: state.can_reach(self.get_connected_door(door["Id"])), self.player) + self.disabled_locations: List[str] = [] def create_item(self, name: str) -> "BlasphemousItem": @@ -68,64 +62,56 @@ def create_event(self, event: str): def get_filler_item_name(self) -> str: - return self.multiworld.random.choice(tears_set) + return self.random.choice(tears_list) def generate_early(self): - world = self.multiworld - player = self.player - - if not world.starting_location[player].randomized: - if world.starting_location[player].value == 6 and world.difficulty[player].value < 2: - raise Exception(f"[Blasphemous - '{world.get_player_name(player)}'] {world.starting_location[player]}" - " cannot be chosen if Difficulty is lower than Hard.") - - if (world.starting_location[player].value == 0 or world.starting_location[player].value == 6) \ - and world.dash_shuffle[player]: - raise Exception(f"[Blasphemous - '{world.get_player_name(player)}'] {world.starting_location[player]}" - " cannot be chosen if Shuffle Dash is enabled.") + if not self.options.starting_location.randomized: + if self.options.starting_location == "mourning_havoc" and self.options.difficulty < 2: + raise OptionError(f"[Blasphemous - '{self.player_name}'] " + f"{self.options.starting_location} cannot be chosen if Difficulty is lower than Hard.") + + if (self.options.starting_location == "brotherhood" or self.options.starting_location == "mourning_havoc") \ + and self.options.dash_shuffle: + raise OptionError(f"[Blasphemous - '{self.player_name}'] " + f"{self.options.starting_location} cannot be chosen if Shuffle Dash is enabled.") - if world.starting_location[player].value == 3 and world.wall_climb_shuffle[player]: - raise Exception(f"[Blasphemous - '{world.get_player_name(player)}'] {world.starting_location[player]}" - " cannot be chosen if Shuffle Wall Climb is enabled.") + if self.options.starting_location == "grievance" and self.options.wall_climb_shuffle: + raise OptionError(f"[Blasphemous - '{self.player_name}'] " + f"{self.options.starting_location} cannot be chosen if Shuffle Wall Climb is enabled.") else: locations: List[int] = [ 0, 1, 2, 3, 4, 5, 6 ] - invalid: bool = False - if world.difficulty[player].value < 2: + if self.options.difficulty < 2: locations.remove(6) - if world.dash_shuffle[player]: + if self.options.dash_shuffle: locations.remove(0) if 6 in locations: locations.remove(6) - if world.wall_climb_shuffle[player]: + if self.options.wall_climb_shuffle: locations.remove(3) - if world.starting_location[player].value == 6 and world.difficulty[player].value < 2: - invalid = True - - if (world.starting_location[player].value == 0 or world.starting_location[player].value == 6) \ - and world.dash_shuffle[player]: - invalid = True - - if world.starting_location[player].value == 3 and world.wall_climb_shuffle[player]: - invalid = True - - if invalid: - world.starting_location[player].value = world.random.choice(locations) + if self.options.starting_location.value not in locations: + self.options.starting_location.value = self.random.choice(locations) - if not world.dash_shuffle[player]: - world.push_precollected(self.create_item("Dash Ability")) + if not self.options.dash_shuffle: + self.multiworld.push_precollected(self.create_item("Dash Ability")) - if not world.wall_climb_shuffle[player]: - world.push_precollected(self.create_item("Wall Climb Ability")) + if not self.options.wall_climb_shuffle: + self.multiworld.push_precollected(self.create_item("Wall Climb Ability")) - if world.skip_long_quests[player]: + if not self.options.boots_of_pleading: + self.disabled_locations.append("RE401") + + if not self.options.purified_hand: + self.disabled_locations.append("RE402") + + if self.options.skip_long_quests: for loc in junk_locations: - world.exclude_locations[player].value.add(loc) + self.options.exclude_locations.value.add(loc) start_rooms: Dict[int, str] = { 0: "D17Z01S01", @@ -137,13 +123,10 @@ def generate_early(self): 6: "D20Z02S09" } - self.start_room = start_rooms[world.starting_location[player].value] + self.start_room = start_rooms[self.options.starting_location.value] def create_items(self): - world = self.multiworld - player = self.player - removed: int = 0 to_remove: List[str] = [ "Tears of Atonement (250)", @@ -156,46 +139,46 @@ def create_items(self): skipped_items = [] junk: int = 0 - for item, count in world.start_inventory[player].value.items(): + for item, count in self.options.start_inventory.value.items(): for _ in range(count): skipped_items.append(item) junk += 1 skipped_items.extend(unrandomized_dict.values()) - if world.thorn_shuffle[player] == 2: - for i in range(8): + if self.options.thorn_shuffle == "vanilla": + for _ in range(8): skipped_items.append("Thorn Upgrade") - if world.dash_shuffle[player]: + if self.options.dash_shuffle: skipped_items.append(to_remove[removed]) removed += 1 - elif not world.dash_shuffle[player]: + elif not self.options.dash_shuffle: skipped_items.append("Dash Ability") - if world.wall_climb_shuffle[player]: + if self.options.wall_climb_shuffle: skipped_items.append(to_remove[removed]) removed += 1 - elif not world.wall_climb_shuffle[player]: + elif not self.options.wall_climb_shuffle: skipped_items.append("Wall Climb Ability") - if not world.reliquary_shuffle[player]: + if not self.options.reliquary_shuffle: skipped_items.extend(reliquary_set) - elif world.reliquary_shuffle[player]: - for i in range(3): + elif self.options.reliquary_shuffle: + for _ in range(3): skipped_items.append(to_remove[removed]) removed += 1 - if not world.boots_of_pleading[player]: + if not self.options.boots_of_pleading: skipped_items.append("Boots of Pleading") - if not world.purified_hand[player]: + if not self.options.purified_hand: skipped_items.append("Purified Hand of the Nun") - if world.start_wheel[player]: + if self.options.start_wheel: skipped_items.append("The Young Mason's Wheel") - if not world.skill_randomizer[player]: + if not self.options.skill_randomizer: skipped_items.extend(skill_dict.values()) counter = Counter(skipped_items) @@ -208,184 +191,140 @@ def create_items(self): if count <= 0: continue else: - for i in range(count): + for _ in range(count): pool.append(self.create_item(item["name"])) for _ in range(junk): pool.append(self.create_item(self.get_filler_item_name())) - world.itempool += pool + self.multiworld.itempool += pool def pre_fill(self): - world = self.multiworld - player = self.player - self.place_items_from_dict(unrandomized_dict) - if world.thorn_shuffle[player] == 2: + if self.options.thorn_shuffle == "vanilla": self.place_items_from_set(thorn_set, "Thorn Upgrade") - if world.start_wheel[player]: - world.get_location("Beginning gift", player)\ - .place_locked_item(self.create_item("The Young Mason's Wheel")) + if self.options.start_wheel: + self.get_location("Beginning gift").place_locked_item(self.create_item("The Young Mason's Wheel")) - if not world.skill_randomizer[player]: + if not self.options.skill_randomizer: self.place_items_from_dict(skill_dict) - if world.thorn_shuffle[player] == 1: - world.local_items[player].value.add("Thorn Upgrade") + if self.options.thorn_shuffle == "local_only": + self.options.local_items.value.add("Thorn Upgrade") def place_items_from_set(self, location_set: Set[str], name: str): for loc in location_set: - self.multiworld.get_location(loc, self.player)\ - .place_locked_item(self.create_item(name)) + self.get_location(loc).place_locked_item(self.create_item(name)) def place_items_from_dict(self, option_dict: Dict[str, str]): for loc, item in option_dict.items(): - self.multiworld.get_location(loc, self.player)\ - .place_locked_item(self.create_item(item)) + self.get_location(loc).place_locked_item(self.create_item(item)) def create_regions(self) -> None: + multiworld = self.multiworld player = self.player - world = self.multiworld - - menu_region = Region("Menu", player, world) - misc_region = Region("Misc", player, world) - world.regions += [menu_region, misc_region] - for room in room_table: - region = Region(room, player, world) - world.regions.append(region) + created_regions: List[str] = [] - menu_region.add_exits({self.start_room: "New Game"}) - world.get_region(self.start_room, player).add_exits({"Misc": "Misc"}) + for r in regions: + multiworld.regions.append(Region(r["name"], player, multiworld)) + created_regions.append(r["name"]) - for door in door_table: - if door.get("OriginalDoor") is None: - continue - else: - if not door["Id"] in self.door_connections.keys(): - self.door_connections[door["Id"]] = door["OriginalDoor"] - self.door_connections[door["OriginalDoor"]] = door["Id"] - - parent_region: Region = self.get_room_from_door(door["Id"]) - target_region: Region = self.get_room_from_door(door["OriginalDoor"]) - parent_region.add_exits({ - target_region.name: door["Id"] - }, { - target_region.name: lambda x: door.get("VisibilityFlags") != 1 - }) - - for index, loc in enumerate(location_table): - if not world.boots_of_pleading[player] and loc["name"] == "BotSS: 2nd meeting with Redento": - continue - if not world.purified_hand[player] and loc["name"] == "MoM: Western room ledge": - continue + self.get_region("Menu").add_exits({self.start_room: "New Game"}) + + blas_logic = BlasRules(self) + + for r in regions: + region = self.get_region(r["name"]) + + for e in r["exits"]: + region.add_exits({e["target"]}, {e["target"]: blas_logic.load_rule(True, r["name"], e)}) - region: Region = world.get_region(loc["room"], player) - region.add_locations({loc["name"]: base_id + index}) - #id = base_id + location_table.index(loc) - #reg.locations.append(BlasphemousLocation(player, loc["name"], id, reg)) - - for e, r in event_table.items(): - region: Region = world.get_region(r, player) - event = BlasphemousLocation(player, e, None, region) - event.show_in_spoiler = False - event.place_locked_item(self.create_event(e)) - region.locations.append(event) - - for door in door_table: - region: Region = self.get_room_from_door(self.door_connections[door["Id"]]) - event = BlasphemousLocation(player, door["Id"], None, region) - event.show_in_spoiler = False - event.place_locked_item(self.create_event(door["Id"])) - region.locations.append(event) + for l in [l for l in r["locations"] if l not in self.disabled_locations]: + region.add_locations({location_names[l]: self.location_name_to_id[location_names[l]]}, BlasphemousLocation) + + for t in r["transitions"]: + if t == r["name"]: + continue + + if t in created_regions: + region.add_exits({t}) + else: + multiworld.regions.append(Region(t, player, multiworld)) + created_regions.append(t) + region.add_exits({t}) + + + for l in [l for l in locations if l["name"] not in self.disabled_locations]: + location = self.get_location(location_names[l["name"]]) + set_rule(location, blas_logic.load_rule(False, l["name"], l)) + + for rname, ename in blas_logic.indirect_conditions: + self.multiworld.register_indirect_condition(self.get_region(rname), self.get_entrance(ename)) + #from Utils import visualize_regions + #visualize_regions(self.get_region("Menu"), "blasphemous_regions.puml") - victory = Location(player, "His Holiness Escribar", None, world.get_region("D07Z01S03", player)) + victory = Location(player, "His Holiness Escribar", None, self.get_region("D07Z01S03[W]")) victory.place_locked_item(self.create_event("Victory")) - world.get_region("D07Z01S03", player).locations.append(victory) + self.get_region("D07Z01S03[W]").locations.append(victory) - if world.ending[self.player].value == 1: + if self.options.ending == "ending_a": set_rule(victory, lambda state: state.has("Thorn Upgrade", player, 8)) - elif world.ending[self.player].value == 2: + elif self.options.ending == "ending_c": set_rule(victory, lambda state: state.has("Thorn Upgrade", player, 8) and state.has("Holy Wound of Abnegation", player)) - world.completion_condition[self.player] = lambda state: state.has("Victory", player) - - - def get_room_from_door(self, door: str) -> Region: - return self.multiworld.get_region(door.split("[")[0], self.player) - - - def get_connected_door(self, door: str) -> Entrance: - return self.multiworld.get_entrance(self.door_connections[door], self.player) + multiworld.completion_condition[self.player] = lambda state: state.has("Victory", player) def fill_slot_data(self) -> Dict[str, Any]: slot_data: Dict[str, Any] = {} - locations = [] doors: Dict[str, str] = {} - - world = self.multiworld - player = self.player thorns: bool = True - if world.thorn_shuffle[player].value == 2: + if self.options.thorn_shuffle == "vanilla": thorns = False - for loc in world.get_filled_locations(player): - if loc.item.code == None: - continue - else: - data = { - "id": self.location_name_to_game_id[loc.name], - "ap_id": loc.address, - "name": loc.item.name, - "player_name": world.player_name[loc.item.player], - "type": int(loc.item.classification) - } - - locations.append(data) - config = { - "LogicDifficulty": world.difficulty[player].value, - "StartingLocation": world.starting_location[player].value, + "LogicDifficulty": self.options.difficulty.value, + "StartingLocation": self.options.starting_location.value, "VersionCreated": "AP", - "UnlockTeleportation": bool(world.prie_dieu_warp[player].value), - "AllowHints": bool(world.corpse_hints[player].value), - "AllowPenitence": bool(world.penitence[player].value), + "UnlockTeleportation": bool(self.options.prie_dieu_warp.value), + "AllowHints": bool(self.options.corpse_hints.value), + "AllowPenitence": bool(self.options.penitence.value), - "ShuffleReliquaries": bool(world.reliquary_shuffle[player].value), - "ShuffleBootsOfPleading": bool(world.boots_of_pleading[player].value), - "ShufflePurifiedHand": bool(world.purified_hand[player].value), - "ShuffleDash": bool(world.dash_shuffle[player].value), - "ShuffleWallClimb": bool(world.wall_climb_shuffle[player].value), + "ShuffleReliquaries": bool(self.options.reliquary_shuffle.value), + "ShuffleBootsOfPleading": bool(self.options.boots_of_pleading.value), + "ShufflePurifiedHand": bool(self.options.purified_hand.value), + "ShuffleDash": bool(self.options.dash_shuffle.value), + "ShuffleWallClimb": bool(self.options.wall_climb_shuffle.value), - "ShuffleSwordSkills": bool(world.skill_randomizer[player].value), + "ShuffleSwordSkills": bool(self.options.wall_climb_shuffle.value), "ShuffleThorns": thorns, - "JunkLongQuests": bool(world.skip_long_quests[player].value), - "StartWithWheel": bool(world.start_wheel[player].value), + "JunkLongQuests": bool(self.options.skip_long_quests.value), + "StartWithWheel": bool(self.options.start_wheel.value), - "EnemyShuffleType": world.enemy_randomizer[player].value, - "MaintainClass": bool(world.enemy_groups[player].value), - "AreaScaling": bool(world.enemy_scaling[player].value), + "EnemyShuffleType": self.options.enemy_randomizer.value, + "MaintainClass": bool(self.options.enemy_groups.value), + "AreaScaling": bool(self.options.enemy_scaling.value), "BossShuffleType": 0, "DoorShuffleType": 0 } slot_data = { - "locations": locations, + "locationinfo": [{"gameId": loc, "apId": (base_id + index)} for index, loc in enumerate(location_names)], "doors": doors, "cfg": config, - "ending": world.ending[self.player].value, - "death_link": bool(world.death_link[self.player].value) + "ending": self.options.ending.value, + "death_link": bool(self.options.death_link.value) } return slot_data diff --git a/worlds/blasphemous/docs/setup_en.md b/worlds/blasphemous/docs/setup_en.md index 070d1ca4964b..068990be1f3a 100644 --- a/worlds/blasphemous/docs/setup_en.md +++ b/worlds/blasphemous/docs/setup_en.md @@ -1,48 +1,17 @@ # Blasphemous Multiworld Setup Guide -## Useful Links +It is recommended to use the [Mod Installer](https://github.com/BrandenEK/Blasphemous.Modding.Installer) to handle installing and updating mods. If you would prefer to install mods manually, instructions can also be found at the Mod Installer repository. -Required: -- Blasphemous: [Steam](https://store.steampowered.com/app/774361/Blasphemous/) - - The GOG version of Blasphemous will also work. -- Blasphemous Mod Installer: [GitHub](https://github.com/BrandenEK/Blasphemous-Mod-Installer) -- Blasphemous Modding API: [GitHub](https://github.com/BrandenEK/Blasphemous-Modding-API) -- Blasphemous Randomizer: [GitHub](https://github.com/BrandenEK/Blasphemous-Randomizer) -- Blasphemous Multiworld: [GitHub](https://github.com/BrandenEK/Blasphemous-Multiworld) +You will need the [Multiworld](https://github.com/BrandenEK/Blasphemous.Randomizer.Multiworld) mod to play an Archipelago randomizer. -Optional: -- In-game map tracker: [GitHub](https://github.com/BrandenEK/Blasphemous-Rando-Map) -- Quick Prie Dieu warp mod: [GitHub](https://github.com/BadMagic100/Blasphemous-PrieWarp) -- Boots of Pleading mod: [GitHub](https://github.com/BrandenEK/Blasphemous-Boots-of-Pleading) -- Double Jump mod: [GitHub](https://github.com/BrandenEK/Blasphemous-Double-Jump) +Some optional mods are also recommended: +- [Rando Map](https://github.com/BrandenEK/Blasphemous.Randomizer.MapTracker) +- [Boots of Pleading](https://github.com/BrandenEK/Blasphemous.BootsOfPleading) (Required if the "Boots of Pleading" option is enabled) +- [Double Jump](https://github.com/BrandenEK/Blasphemous.DoubleJump) (Required if the "Purified Hand of the Nun" option is enabled) -## Mod Installer (Recommended) +To connect to a multiworld: Choose a save file and enter the address, your name, and the password (if the server has one) into the menu. -1. Download the [Mod Installer](https://github.com/BrandenEK/Blasphemous-Mod-Installer), -and point it to your install directory for Blasphemous. - -2. Install the `Modding API`, `Randomizer`, and `Multiworld` mods. Optionally, you can also install the -`Rando Map`, `PrieWarp`, `Boots of Pleading`, and `Double Jump` mods, and set up the PopTracker pack if desired. - -3. Start Blasphemous. To verfy that the mods are working, look for a version number for both -the Randomizer and Multiworld on the title screen. - -## Manual Installation - -1. Download the [Modding API](https://github.com/BrandenEK/Blasphemous-Modding-API/releases), and follow -the [installation instructions](https://github.com/BrandenEK/Blasphemous-Modding-API#installation) on the GitHub page. - -2. After the Modding API has been installed, download the -[Randomizer](https://github.com/BrandenEK/Blasphemous-Randomizer/releases) and -[Multiworld](https://github.com/BrandenEK/Blasphemous-Multiworld/releases) archives, and extract the contents of both -into the `Modding` folder. Then, add any desired additional mods. - -3. Start Blasphemous. To verfy that the mods are working, look for a version number for both -the Randomizer and Multiworld on the title screen. - -## Connecting - -To connect to an Archipelago server, open the in-game console by pressing backslash `\` and use -the command `multiworld connect [address:port] [name] [password]`. -The port and password are both optional - if no port is provided then the default port of 38281 is used. -**Make sure to connect to the server before attempting to start a new save file.** \ No newline at end of file +After connecting, there are some commands you can use in the console, which can be opened by pressing backslash `\`: +- `ap status` - Display connection status. +- `ap say [message]` - Send a message to the server. +- `ap hint [item]` - Request a hint for an item from the server. \ No newline at end of file diff --git a/worlds/blasphemous/region_data.py b/worlds/blasphemous/region_data.py new file mode 100644 index 000000000000..b072b7931857 --- /dev/null +++ b/worlds/blasphemous/region_data.py @@ -0,0 +1,48070 @@ +# This file is programmatically generated, do not modify by hand + +regions = [ + { + "name": "Menu", + "exits": [], + "locations": [ + "QI106", + "QI107", + "QI108", + "QI109", + "QI110", + "PR101", + "QI32", + "QI33", + "QI34", + "QI35", + "QI79", + "QI80", + "QI81", + "Arena_NailManager[1000]", + "HE10", + "Arena_NailManager[3000]", + "RB34", + "Arena_NailManager[5000]", + "RB35", + "RB36", + "COMBO_1", + "COMBO_2", + "COMBO_3", + "CHARGED_1", + "CHARGED_2", + "CHARGED_3", + "RANGED_1", + "RANGED_2", + "RANGED_3", + "VERTICAL_1", + "VERTICAL_2", + "VERTICAL_3", + "LUNGE_1", + "LUNGE_2", + "LUNGE_3" + ], + "transitions": [] + }, + { + "name": "D01Z01S07", + "exits": [ + { + "logic": [], + "target": "D01Z01S07[W]" + }, + { + "logic": [], + "target": "D01Z01S07[E]" + } + ], + "locations": [ + "QI31" + ], + "transitions": [] + }, + { + "name": "D01Z01S01[W]", + "exits": [ + { + "logic": [], + "target": "D01Z01S07" + } + ], + "locations": [], + "transitions": [ + "D01Z01S01[W]" + ] + }, + { + "name": "D17Z01S03[E]", + "exits": [ + { + "logic": [], + "target": "D01Z01S07" + } + ], + "locations": [], + "transitions": [ + "D17Z01S03[E]" + ] + }, + { + "name": "D01Z01S02", + "exits": [ + { + "logic": [], + "target": "D01Z01S02[W]" + }, + { + "logic": [], + "target": "D01Z01S02[E]" + } + ], + "locations": [ + "PR14", + "RB07" + ], + "transitions": [] + }, + { + "name": "D01Z01S01[E]", + "exits": [ + { + "logic": [], + "target": "D01Z01S02" + } + ], + "locations": [], + "transitions": [ + "D01Z01S01[E]" + ] + }, + { + "name": "D01Z01S03[W]", + "exits": [ + { + "logic": [], + "target": "D01Z01S02" + } + ], + "locations": [], + "transitions": [ + "D01Z01S03[W]" + ] + }, + { + "name": "D01Z06S01", + "exits": [ + { + "logic": [], + "target": "D01Z06S01[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "bell" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z06S01[Santos]" + } + ], + "locations": [ + "QI101" + ], + "transitions": [] + }, + { + "name": "D01Z01S01[S]", + "exits": [ + { + "logic": [], + "target": "D01Z06S01" + } + ], + "locations": [], + "transitions": [ + "D01Z01S01[S]" + ] + }, + { + "name": "D01BZ07S01[Santos]", + "exits": [ + { + "logic": [], + "target": "D01Z06S01" + } + ], + "locations": [], + "transitions": [ + "D01BZ07S01[Santos]" + ] + }, + { + "name": "D01Z01S02[W]", + "exits": [ + { + "logic": [], + "target": "D01Z01S01[W]" + }, + { + "logic": [], + "target": "D01Z01S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBreakHoles" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z01S01[S]" + } + ], + "locations": [], + "transitions": [ + "D01Z01S02[W]" + ] + }, + { + "name": "D01Z01S07[E]", + "exits": [ + { + "logic": [], + "target": "D01Z01S01[W]" + }, + { + "logic": [], + "target": "D01Z01S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBreakHoles" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z01S01[S]" + } + ], + "locations": [], + "transitions": [ + "D01Z01S07[E]" + ] + }, + { + "name": "D01Z06S01[N]", + "exits": [ + { + "logic": [], + "target": "D01Z01S01[S]" + }, + { + "logic": [], + "target": "D01Z01S01[W]" + }, + { + "logic": [], + "target": "D01Z01S01[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z06S01[N]" + ] + }, + { + "name": "D01Z01S03", + "exits": [ + { + "logic": [], + "target": "D01Z01S03[W]" + }, + { + "logic": [], + "target": "D01Z01S03[E]" + } + ], + "locations": [ + "CO04", + "QI55", + "RESCUED_CHERUB_07" + ], + "transitions": [] + }, + { + "name": "D01Z01S02[E]", + "exits": [ + { + "logic": [], + "target": "D01Z01S03" + } + ], + "locations": [], + "transitions": [ + "D01Z01S02[E]" + ] + }, + { + "name": "D01Z02S01[W]", + "exits": [ + { + "logic": [], + "target": "D01Z01S03" + } + ], + "locations": [], + "transitions": [ + "D01Z02S01[W]" + ] + }, + { + "name": "D01Z02S01", + "exits": [ + { + "logic": [], + "target": "D01Z02S01[W]" + }, + { + "logic": [], + "target": "D01Z02S01[E]" + } + ], + "locations": [ + "RE02", + "RE04", + "RE10" + ], + "transitions": [] + }, + { + "name": "D01Z01S03[E]", + "exits": [ + { + "logic": [], + "target": "D01Z02S01" + }, + { + "logic": [ + { + "item_requirements": [ + "ceremonyItems3", + "hatchedEgg" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB06" + } + ], + "locations": [], + "transitions": [ + "D01Z01S03[E]" + ] + }, + { + "name": "D01Z02S02[W]", + "exits": [ + { + "logic": [], + "target": "D01Z02S01" + }, + { + "logic": [ + { + "item_requirements": [ + "ceremonyItems3", + "hatchedEgg" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB06" + } + ], + "locations": [], + "transitions": [ + "D01Z02S02[W]" + ] + }, + { + "name": "D01Z01S07[W]", + "exits": [ + { + "logic": [], + "target": "D17Z01S03[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "elderKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S03[relic]" + }, + { + "logic": [], + "target": "D17Z01S11[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z01S07[W]" + ] + }, + { + "name": "D17Z01S11[E]", + "exits": [ + { + "logic": [], + "target": "D17Z01S03[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "elderKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S03[relic]" + }, + { + "logic": [], + "target": "D17Z01S11" + } + ], + "locations": [], + "transitions": [ + "D17Z01S11[E]", + "D17Z01S03[W]" + ] + }, + { + "name": "D17BZ01S01[relic]", + "exits": [ + { + "logic": [], + "target": "D17Z01S03[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "elderKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S03[relic]" + }, + { + "logic": [], + "target": "D17Z01S11[E]" + } + ], + "locations": [], + "transitions": [ + "D17BZ01S01[relic]" + ] + }, + { + "name": "D01Z02S02", + "exits": [ + { + "logic": [], + "target": "D01Z02S02[SW]" + }, + { + "logic": [], + "target": "D01Z02S02[SE]" + }, + { + "logic": [], + "target": "D01Z02S02[W]" + }, + { + "logic": [], + "target": "D01Z02S02[E]" + }, + { + "logic": [], + "target": "D01Z02S02[NE]" + } + ], + "locations": [ + "RB01", + "QI66", + "Tirso[500]", + "Tirso[1000]", + "Tirso[2000]", + "Tirso[5000]", + "Tirso[10000]", + "QI56" + ], + "transitions": [] + }, + { + "name": "D01Z02S01[E]", + "exits": [ + { + "logic": [], + "target": "D01Z02S02" + } + ], + "locations": [], + "transitions": [ + "D01Z02S01[E]" + ] + }, + { + "name": "D01Z02S03[W]", + "exits": [ + { + "logic": [], + "target": "D01Z02S02" + } + ], + "locations": [], + "transitions": [ + "D01Z02S03[W]" + ] + }, + { + "name": "D01Z02S03[NW]", + "exits": [ + { + "logic": [], + "target": "D01Z02S02" + } + ], + "locations": [], + "transitions": [ + "D01Z02S03[NW]" + ] + }, + { + "name": "D01Z02S04[W]", + "exits": [ + { + "logic": [], + "target": "D01Z02S02" + } + ], + "locations": [], + "transitions": [ + "D01Z02S04[W]" + ] + }, + { + "name": "D01Z02S06[E]", + "exits": [ + { + "logic": [], + "target": "D01Z02S02" + } + ], + "locations": [], + "transitions": [ + "D01Z02S06[E]" + ] + }, + { + "name": "D01Z02S06", + "exits": [ + { + "logic": [], + "target": "D01Z02S06[W]" + }, + { + "logic": [], + "target": "D01Z02S06[E]" + } + ], + "locations": [ + "Sword[D01Z02S06]" + ], + "transitions": [] + }, + { + "name": "D01Z02S02[SW]", + "exits": [ + { + "logic": [], + "target": "D01Z02S06" + } + ], + "locations": [], + "transitions": [ + "D01Z02S02[SW]" + ] + }, + { + "name": "D01Z02S07[E]", + "exits": [ + { + "logic": [], + "target": "D01Z02S06" + } + ], + "locations": [], + "transitions": [ + "D01Z02S07[E]" + ] + }, + { + "name": "D01Z02S04", + "exits": [ + { + "logic": [], + "target": "D01Z02S04[W]" + }, + { + "logic": [], + "target": "D01Z02S04[E]" + }, + { + "logic": [], + "target": "D01Z02S04[Ossary]" + } + ], + "locations": [ + "CO43" + ], + "transitions": [] + }, + { + "name": "D01Z02S02[SE]", + "exits": [ + { + "logic": [], + "target": "D01Z02S04" + } + ], + "locations": [], + "transitions": [ + "D01Z02S02[SE]" + ] + }, + { + "name": "D01BZ06S01[Ossary]", + "exits": [ + { + "logic": [], + "target": "D01Z02S04" + } + ], + "locations": [], + "transitions": [ + "D01BZ06S01[Ossary]" + ] + }, + { + "name": "D01Z05S01[N]", + "exits": [ + { + "logic": [], + "target": "D01Z02S04" + } + ], + "locations": [], + "transitions": [ + "D01Z05S01[N]" + ] + }, + { + "name": "D01Z02S03", + "exits": [ + { + "logic": [], + "target": "D01Z02S03[W]" + }, + { + "logic": [], + "target": "D01Z02S03[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatMercyBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canBeatConventBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canBeatGrievanceBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z02S03[church]" + }, + { + "logic": [ + { + "item_requirements": [ + "rodeGotPElevator" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_08" + } + ], + "locations": [ + "Lvdovico[500]", + "Lvdovico[1000]", + "PR03" + ], + "transitions": [] + }, + { + "name": "D01Z02S02[E]", + "exits": [ + { + "logic": [], + "target": "D01Z02S03" + } + ], + "locations": [], + "transitions": [ + "D01Z02S02[E]" + ] + }, + { + "name": "D01Z02S02[NE]", + "exits": [ + { + "logic": [], + "target": "D01Z02S03" + }, + { + "logic": [], + "target": "D01Z02S03[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "chargeBeam" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "rangedAttack" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_08" + } + ], + "locations": [], + "transitions": [ + "D01Z02S02[NE]" + ] + }, + { + "name": "D01Z02S05[W]", + "exits": [ + { + "logic": [], + "target": "D01Z02S03" + } + ], + "locations": [], + "transitions": [ + "D01Z02S05[W]" + ] + }, + { + "name": "D01BZ04S01[church]", + "exits": [ + { + "logic": [], + "target": "D01Z02S03" + } + ], + "locations": [], + "transitions": [ + "D01BZ04S01[church]" + ] + }, + { + "name": "D02Z02S11[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D01Z02S03" + } + ], + "locations": [], + "transitions": [ + "D02Z02S11[-Cherubs]" + ] + }, + { + "name": "D01Z02S05", + "exits": [ + { + "logic": [], + "target": "D01Z02S05[W]" + }, + { + "logic": [], + "target": "D01Z02S05[E]" + } + ], + "locations": [ + "CO16" + ], + "transitions": [] + }, + { + "name": "D01Z02S03[E]", + "exits": [ + { + "logic": [], + "target": "D01Z02S05" + } + ], + "locations": [], + "transitions": [ + "D01Z02S03[E]" + ] + }, + { + "name": "D01Z03S01[W]", + "exits": [ + { + "logic": [], + "target": "D01Z02S05" + } + ], + "locations": [], + "transitions": [ + "D01Z03S01[W]" + ] + }, + { + "name": "D01BZ04S01", + "exits": [ + { + "logic": [], + "target": "D01BZ04S01[church]" + } + ], + "locations": [ + "RB104", + "RB105" + ], + "transitions": [] + }, + { + "name": "D01Z02S03[church]", + "exits": [ + { + "logic": [], + "target": "D01BZ04S01" + } + ], + "locations": [], + "transitions": [ + "D01Z02S03[church]" + ] + }, + { + "name": "D01Z02S04[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S01[N]" + }, + { + "logic": [], + "target": "D01Z05S02[N]" + } + ], + "locations": [], + "transitions": [ + "D01Z02S04[E]" + ] + }, + { + "name": "D01Z05S02[N]", + "exits": [ + { + "logic": [], + "target": "D01Z05S01[N]" + }, + { + "logic": [], + "target": "D01Z05S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z05S03[NW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedDCLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S02[S]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S02[N]", + "D01Z05S01[S]", + "D01Z05S27[E]", + "D01Z05S01[W]" + ] + }, + { + "name": "D01BZ06S01", + "exits": [ + { + "logic": [], + "target": "D01BZ06S01[Ossary]" + }, + { + "logic": [ + { + "item_requirements": [ + "bones30" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01BZ06S01[E]" + } + ], + "locations": [ + "Undertaker[250]", + "Undertaker[500]", + "Undertaker[750]", + "Undertaker[1000]", + "Undertaker[1250]", + "Undertaker[1500]", + "Undertaker[1750]", + "Undertaker[2000]", + "Undertaker[2500]", + "Undertaker[3000]", + "Undertaker[5000]" + ], + "transitions": [] + }, + { + "name": "D01Z02S04[Ossary]", + "exits": [ + { + "logic": [], + "target": "D01BZ06S01" + } + ], + "locations": [], + "transitions": [ + "D01Z02S04[Ossary]" + ] + }, + { + "name": "D01BZ08S01[W]", + "exits": [ + { + "logic": [], + "target": "D01BZ06S01" + } + ], + "locations": [], + "transitions": [ + "D01BZ08S01[W]" + ] + }, + { + "name": "D01Z02S05[E]", + "exits": [ + { + "logic": [], + "target": "D01Z03S01[W]" + }, + { + "logic": [], + "target": "D01Z03S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z03S02[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z03S01[SE]" + } + ], + "locations": [], + "transitions": [ + "D01Z02S05[E]" + ] + }, + { + "name": "D01Z03S02[W]", + "exits": [ + { + "logic": [], + "target": "D01Z03S01[W]" + }, + { + "logic": [], + "target": "D01Z03S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z03S02[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z03S01[SE]" + } + ], + "locations": [], + "transitions": [ + "D01Z03S02[W]" + ] + }, + { + "name": "D01Z03S02[SW]", + "exits": [ + { + "logic": [], + "target": "D01Z03S01[W]" + }, + { + "logic": [], + "target": "D01Z03S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z03S02[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z03S01[SE]" + } + ], + "locations": [ + "RB04" + ], + "transitions": [ + "D01Z03S02[SW]" + ] + }, + { + "name": "D01Z02S07", + "exits": [ + { + "logic": [], + "target": "D01Z02S07[E]" + } + ], + "locations": [ + "QI65" + ], + "transitions": [] + }, + { + "name": "D01Z02S06[W]", + "exits": [ + { + "logic": [], + "target": "D01Z02S07" + } + ], + "locations": [], + "transitions": [ + "D01Z02S06[W]" + ] + }, + { + "name": "D01BZ08S01", + "exits": [ + { + "logic": [], + "target": "D01BZ08S01[W]" + } + ], + "locations": [ + "QI201" + ], + "transitions": [] + }, + { + "name": "D01BZ06S01[E]", + "exits": [ + { + "logic": [], + "target": "D01BZ08S01" + } + ], + "locations": [], + "transitions": [ + "D01BZ06S01[E]" + ] + }, + { + "name": "D01Z03S02", + "exits": [ + { + "logic": [], + "target": "D01Z03S02[W]" + }, + { + "logic": [], + "target": "D01Z03S02[SW]" + }, + { + "logic": [], + "target": "D01Z03S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z05S05[N]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z03S02[S]" + } + ], + "locations": [ + "CO14" + ], + "transitions": [] + }, + { + "name": "D01Z03S01[E]", + "exits": [ + { + "logic": [], + "target": "D01Z03S02" + } + ], + "locations": [], + "transitions": [ + "D01Z03S01[E]" + ] + }, + { + "name": "D01Z03S01[SE]", + "exits": [ + { + "logic": [], + "target": "D01Z03S02" + } + ], + "locations": [], + "transitions": [ + "D01Z03S01[SE]" + ] + }, + { + "name": "D01Z03S03[W]", + "exits": [ + { + "logic": [], + "target": "D01Z03S02" + } + ], + "locations": [], + "transitions": [ + "D01Z03S03[W]" + ] + }, + { + "name": "D01Z05S05[N]", + "exits": [ + { + "logic": [], + "target": "D01Z03S02" + } + ], + "locations": [], + "transitions": [ + "D01Z05S05[N]" + ] + }, + { + "name": "D01Z03S03", + "exits": [ + { + "logic": [], + "target": "D01Z03S03[W]" + }, + { + "logic": [], + "target": "D01Z03S03[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z03S03[-Cherubs]" + } + ], + "locations": [ + "CO36", + "RESCUED_CHERUB_10" + ], + "transitions": [] + }, + { + "name": "D01Z03S02[E]", + "exits": [ + { + "logic": [], + "target": "D01Z03S03" + } + ], + "locations": [], + "transitions": [ + "D01Z03S02[E]" + ] + }, + { + "name": "D01Z03S04[SW]", + "exits": [ + { + "logic": [], + "target": "D01Z03S03" + } + ], + "locations": [], + "transitions": [ + "D01Z03S04[SW]" + ] + }, + { + "name": "D01Z03S07[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D01Z03S03" + } + ], + "locations": [], + "transitions": [ + "D01Z03S07[-Cherubs]" + ] + }, + { + "name": "D01Z05S05", + "exits": [ + { + "logic": [], + "target": "D01Z05S05[N]" + }, + { + "logic": [], + "target": "D01Z05S05[NW]" + }, + { + "logic": [], + "target": "D01Z05S05[NE]" + }, + { + "logic": [], + "target": "D01Z05S05[SW]" + }, + { + "logic": [], + "target": "D01Z05S05[E]" + } + ], + "locations": [ + "CO09", + "QI67" + ], + "transitions": [] + }, + { + "name": "D01Z03S02[S]", + "exits": [ + { + "logic": [], + "target": "D01Z05S05" + } + ], + "locations": [], + "transitions": [ + "D01Z03S02[S]" + ] + }, + { + "name": "D01Z05S04[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S05" + } + ], + "locations": [], + "transitions": [ + "D01Z05S04[E]" + ] + }, + { + "name": "D01Z05S06[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S05" + } + ], + "locations": [], + "transitions": [ + "D01Z05S06[W]" + ] + }, + { + "name": "D01Z05S09[NW]", + "exits": [ + { + "logic": [], + "target": "D01Z05S05" + } + ], + "locations": [], + "transitions": [ + "D01Z05S09[NW]" + ] + }, + { + "name": "D01Z05S18[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S05" + } + ], + "locations": [], + "transitions": [ + "D01Z05S18[E]" + ] + }, + { + "name": "D01Z03S03[E]", + "exits": [ + { + "logic": [], + "target": "D01Z03S04[SW]" + }, + { + "logic": [], + "target": "D01Z03S04[W]" + }, + { + "logic": [], + "target": "D01Z03S04[SE]" + }, + { + "logic": [], + "target": "D01Z03S04[E]" + }, + { + "logic": [], + "target": "D02Z01S01[SE]" + } + ], + "locations": [], + "transitions": [ + "D01Z03S03[E]" + ] + }, + { + "name": "D01Z03S05[W]", + "exits": [ + { + "logic": [], + "target": "D01Z03S04[SW]" + }, + { + "logic": [], + "target": "D01Z03S04[W]" + }, + { + "logic": [], + "target": "D01Z03S04[SE]" + }, + { + "logic": [], + "target": "D01Z03S04[E]" + }, + { + "logic": [], + "target": "D02Z01S01[SE]" + } + ], + "locations": [], + "transitions": [ + "D01Z03S05[W]" + ] + }, + { + "name": "D01Z03S06[W]", + "exits": [ + { + "logic": [], + "target": "D01Z03S04[SW]" + }, + { + "logic": [], + "target": "D01Z03S04[W]" + }, + { + "logic": [], + "target": "D01Z03S04[SE]" + }, + { + "logic": [], + "target": "D01Z03S04[E]" + }, + { + "logic": [], + "target": "D02Z01S01[SE]" + } + ], + "locations": [], + "transitions": [ + "D01Z03S06[W]" + ] + }, + { + "name": "D01Z03S07[E]", + "exits": [ + { + "logic": [], + "target": "D01Z03S04[SW]" + }, + { + "logic": [], + "target": "D01Z03S04[W]" + }, + { + "logic": [], + "target": "D01Z03S04[SE]" + }, + { + "logic": [], + "target": "D01Z03S04[E]" + }, + { + "logic": [], + "target": "D02Z01S01[SE]" + } + ], + "locations": [], + "transitions": [ + "D01Z03S07[E]" + ] + }, + { + "name": "D02Z01S01[SE]", + "exits": [ + { + "logic": [], + "target": "D01Z03S04[SW]" + }, + { + "logic": [], + "target": "D01Z03S04[W]" + }, + { + "logic": [], + "target": "D01Z03S04[SE]" + }, + { + "logic": [], + "target": "D01Z03S04[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedWOTWCave", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "openedWOTWCave", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S01[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO11" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI59" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "fullThimble", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB10" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S02[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z01S01[SE]", + "D01Z03S04[NW]" + ] + }, + { + "name": "D01Z03S03[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "PR16" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_13" + }, + { + "logic": [], + "target": "D01Z05S06[W]" + } + ], + "locations": [], + "transitions": [ + "D01Z03S03[-Cherubs]" + ] + }, + { + "name": "D01Z05S05[NE]", + "exits": [ + { + "logic": [], + "target": "D01Z05S06[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canWaterJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "PR16" + }, + { + "logic": [ + { + "item_requirements": [ + "canWaterJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "tirana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_13" + } + ], + "locations": [], + "transitions": [ + "D01Z05S05[NE]" + ] + }, + { + "name": "D01Z03S07", + "exits": [ + { + "logic": [], + "target": "D01Z03S07[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z03S07[-Cherubs]" + } + ], + "locations": [ + "HE02", + "RESCUED_CHERUB_38" + ], + "transitions": [] + }, + { + "name": "D01Z03S04[W]", + "exits": [ + { + "logic": [], + "target": "D01Z03S07" + } + ], + "locations": [], + "transitions": [ + "D01Z03S04[W]" + ] + }, + { + "name": "D02Z01S02[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedWOTWCave" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S01[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S04[-N]" + }, + { + "logic": [], + "target": "CO11" + }, + { + "logic": [], + "target": "QI59" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB10" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI68" + }, + { + "logic": [], + "target": "D02Z01S01[SE]" + }, + { + "logic": [], + "target": "D02Z01S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S02[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S02[]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canCrossGap4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canCrossGap4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_23" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S03[SE]" + } + ], + "locations": [], + "transitions": [ + "D02Z01S02[E]", + "D02Z01S01[W]" + ] + }, + { + "name": "D02Z01S06[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedWOTWCave" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S01[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S04[-N]" + }, + { + "logic": [], + "target": "CO11" + }, + { + "logic": [ + { + "item_requirements": [ + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI59" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "fullThimble", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "fullThimble", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB10" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI68" + }, + { + "logic": [], + "target": "D02Z01S01[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S02[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z01S06[E]" + ] + }, + { + "name": "D02Z01S09[-CherubsL]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedWOTWCave" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S01[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S04[-N]" + }, + { + "logic": [], + "target": "CO11" + }, + { + "logic": [], + "target": "QI59" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB10" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI68" + }, + { + "logic": [], + "target": "D02Z01S01[SE]" + }, + { + "logic": [], + "target": "D02Z01S02[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z01S09[-CherubsL]" + ] + }, + { + "name": "D02Z01S09[-CherubsR]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedWOTWCave" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S01[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S04[-N]" + }, + { + "logic": [], + "target": "CO11" + }, + { + "logic": [ + { + "item_requirements": [ + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI59" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "fullThimble", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "fullThimble", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB10" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI68" + }, + { + "logic": [], + "target": "D02Z01S01[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S02[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z01S09[-CherubsR]" + ] + }, + { + "name": "D01Z03S05", + "exits": [ + { + "logic": [], + "target": "D01Z03S05[W]" + }, + { + "logic": [], + "target": "D01Z03S05[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z03S05[Cherubs]" + } + ], + "locations": [ + "QI06" + ], + "transitions": [] + }, + { + "name": "D01Z03S04[SE]", + "exits": [ + { + "logic": [], + "target": "D01Z03S05" + } + ], + "locations": [], + "transitions": [ + "D01Z03S04[SE]" + ] + }, + { + "name": "D01Z04S01[NW]", + "exits": [ + { + "logic": [], + "target": "D01Z03S05" + } + ], + "locations": [], + "transitions": [ + "D01Z04S01[NW]" + ] + }, + { + "name": "D01Z03S06", + "exits": [ + { + "logic": [], + "target": "D01Z03S06[W]" + }, + { + "logic": [], + "target": "D01Z03S06[E]" + } + ], + "locations": [ + "RB20" + ], + "transitions": [] + }, + { + "name": "D01Z03S04[E]", + "exits": [ + { + "logic": [], + "target": "D01Z03S06" + } + ], + "locations": [], + "transitions": [ + "D01Z03S04[E]" + ] + }, + { + "name": "D08Z01S01[W]", + "exits": [ + { + "logic": [], + "target": "D01Z03S06" + } + ], + "locations": [], + "transitions": [ + "D08Z01S01[W]" + ] + }, + { + "name": "D01Z03S05[E]", + "exits": [ + { + "logic": [], + "target": "D01Z04S01[NW]" + }, + { + "logic": [], + "target": "D01Z04S01[E]" + }, + { + "logic": [], + "target": "D01Z04S03[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z03S05[E]" + ] + }, + { + "name": "D01Z04S03[E]", + "exits": [ + { + "logic": [], + "target": "D01Z04S01[NW]" + }, + { + "logic": [], + "target": "D01Z04S01[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S03[E]", + "D01Z04S01[W]", + "D01Z04S17[W]", + "D01Z04S01[NE]" + ] + }, + { + "name": "D01Z04S05[NW]", + "exits": [ + { + "logic": [], + "target": "D01Z04S01[NW]" + }, + { + "logic": [], + "target": "D01Z04S01[E]" + }, + { + "logic": [], + "target": "D01Z04S03[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S05[NW]" + ] + }, + { + "name": "D01Z04S05[SW]", + "exits": [ + { + "logic": [], + "target": "D01Z04S01[SE]" + }, + { + "logic": [], + "target": "D01Z04S01[NW]" + }, + { + "logic": [], + "target": "D01Z04S01[E]" + }, + { + "logic": [], + "target": "D01Z04S03[E]" + }, + { + "logic": [], + "target": "D01Z04S15[N]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S05[SW]" + ] + }, + { + "name": "D01Z04S15[N]", + "exits": [ + { + "logic": [], + "target": "D01Z04S01[SE]" + }, + { + "logic": [], + "target": "D01Z04S01[NW]" + }, + { + "logic": [], + "target": "D01Z04S01[E]" + }, + { + "logic": [], + "target": "D01Z04S03[E]" + }, + { + "logic": [], + "target": "D01Z04S15[NE]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S15[N]", + "D01Z04S01[S]" + ] + }, + { + "name": "D01Z05S11", + "exits": [ + { + "logic": [], + "target": "D01Z05S11[W]" + } + ], + "locations": [ + "QI45" + ], + "transitions": [] + }, + { + "name": "D01Z03S05[Cherubs]", + "exits": [ + { + "logic": [], + "target": "D01Z05S11" + } + ], + "locations": [], + "transitions": [ + "D01Z03S05[Cherubs]" + ] + }, + { + "name": "D01Z05S10[NE]", + "exits": [ + { + "logic": [], + "target": "D01Z05S11" + } + ], + "locations": [], + "transitions": [ + "D01Z05S10[NE]" + ] + }, + { + "name": "D08Z01S01", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatBridgeBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z01S01[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "holyWounds3", + "canBeatBridgeBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z01S01[E]" + } + ], + "locations": [ + "BS12", + "PR09" + ], + "transitions": [] + }, + { + "name": "D01Z03S06[E]", + "exits": [ + { + "logic": [], + "target": "D08Z01S01" + }, + { + "logic": [], + "target": "D08Z01S01[W]" + } + ], + "locations": [], + "transitions": [ + "D01Z03S06[E]" + ] + }, + { + "name": "D08Z01S02[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D08Z01S01" + }, + { + "logic": [ + { + "item_requirements": [ + "holyWounds3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z01S01[E]" + } + ], + "locations": [], + "transitions": [ + "D08Z01S02[-Cherubs]" + ] + }, + { + "name": "D08Z02S01[W]", + "exits": [ + { + "logic": [], + "target": "D08Z01S01" + }, + { + "logic": [ + { + "item_requirements": [ + "holyWounds3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z01S01[E]" + } + ], + "locations": [], + "transitions": [ + "D08Z02S01[W]" + ] + }, + { + "name": "D01Z04S05", + "exits": [ + { + "logic": [], + "target": "D01Z04S05[NW]" + }, + { + "logic": [], + "target": "D01Z04S05[SW]" + } + ], + "locations": [ + "CO30" + ], + "transitions": [] + }, + { + "name": "D01Z04S01[E]", + "exits": [ + { + "logic": [], + "target": "D01Z04S05" + } + ], + "locations": [], + "transitions": [ + "D01Z04S01[E]" + ] + }, + { + "name": "D01Z04S01[SE]", + "exits": [ + { + "logic": [], + "target": "D01Z04S05" + } + ], + "locations": [], + "transitions": [ + "D01Z04S01[SE]" + ] + }, + { + "name": "D01Z04S06[NW]", + "exits": [ + { + "logic": [], + "target": "D01Z04S15[N]" + }, + { + "logic": [], + "target": "D01Z04S15[NE]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S06[NW]" + ] + }, + { + "name": "D01Z04S06[SW]", + "exits": [ + { + "logic": [], + "target": "D01Z04S15[W]" + }, + { + "logic": [], + "target": "D01Z04S15[E]" + }, + { + "logic": [], + "target": "D01Z04S15[N]" + }, + { + "logic": [], + "target": "D01Z04S15[NE]" + }, + { + "logic": [], + "target": "D01Z04S09[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S06[SW]" + ] + }, + { + "name": "D01Z04S08[E]", + "exits": [ + { + "logic": [], + "target": "D01Z04S15[W]" + }, + { + "logic": [], + "target": "D01Z04S15[E]" + }, + { + "logic": [], + "target": "D01Z04S15[N]" + }, + { + "logic": [], + "target": "D01Z04S15[NE]" + }, + { + "logic": [], + "target": "D01Z04S09[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S08[E]" + ] + }, + { + "name": "D01Z04S09[E]", + "exits": [ + { + "logic": [], + "target": "D01Z04S15[W]" + }, + { + "logic": [], + "target": "D01Z04S15[E]" + }, + { + "logic": [], + "target": "D01Z04S15[N]" + }, + { + "logic": [], + "target": "D01Z04S15[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedDCGateE" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z04S09[W]" + }, + { + "logic": [], + "target": "D01Z04S09[C]" + }, + { + "logic": [], + "target": "D01Z04S10[SW]" + }, + { + "logic": [], + "target": "D01Z04S13[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "canDiveLaser", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogic", + "canDiveLaser", + "wheel" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogic", + "canDiveLaser", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogic", + "canDiveLaser", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z04S13[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "canDiveLaser", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser", + "wheel" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO21" + }, + { + "logic": [], + "target": "D01Z04S18" + } + ], + "locations": [], + "transitions": [ + "D01Z04S09[E]", + "D01Z04S15[SW]", + "D01Z04S10[NW]", + "D01Z04S15[SE]", + "D01Z04S10[SE]", + "D01Z04S12[NW]", + "D01Z04S12[SE]", + "D01Z04S13[NW]", + "D01Z04S18[E]", + "D01Z04S12[W]", + "D01Z04S02[W]", + "D01Z04S13[NE]" + ] + }, + { + "name": "D01Z04S14[E]", + "exits": [ + { + "logic": [], + "target": "D01Z04S13[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "canDiveLaser", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogic", + "canDiveLaser", + "wheel" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogic", + "canDiveLaser", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogic", + "canDiveLaser", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z04S13[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "canDiveLaser", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser", + "wheel" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO21" + }, + { + "logic": [], + "target": "D01Z04S09[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S14[E]" + ] + }, + { + "name": "D01Z04S16[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "HardLogic" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z04S13[SE]" + }, + { + "logic": [], + "target": "CO21" + }, + { + "logic": [], + "target": "D01Z04S13[SW]" + }, + { + "logic": [], + "target": "D01Z04S09[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S16[W]" + ] + }, + { + "name": "D01Z04S07", + "exits": [ + { + "logic": [], + "target": "D01Z04S07[W]" + } + ], + "locations": [ + "PR01" + ], + "transitions": [] + }, + { + "name": "D01Z04S06[E]", + "exits": [ + { + "logic": [], + "target": "D01Z04S07" + } + ], + "locations": [], + "transitions": [ + "D01Z04S06[E]" + ] + }, + { + "name": "D01Z04S06", + "exits": [ + { + "logic": [], + "target": "D01Z04S06[E]" + }, + { + "logic": [], + "target": "D01Z04S06[NW]" + }, + { + "logic": [], + "target": "D01Z04S06[SW]" + } + ], + "locations": [ + "CO03", + "RESCUED_CHERUB_09" + ], + "transitions": [] + }, + { + "name": "D01Z04S07[W]", + "exits": [ + { + "logic": [], + "target": "D01Z04S06" + } + ], + "locations": [], + "transitions": [ + "D01Z04S07[W]" + ] + }, + { + "name": "D01Z04S15[NE]", + "exits": [ + { + "logic": [], + "target": "D01Z04S06" + } + ], + "locations": [], + "transitions": [ + "D01Z04S15[NE]" + ] + }, + { + "name": "D01Z04S15[E]", + "exits": [ + { + "logic": [], + "target": "D01Z04S06" + } + ], + "locations": [], + "transitions": [ + "D01Z04S15[E]" + ] + }, + { + "name": "D01Z04S09[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S12[E]" + }, + { + "logic": [], + "target": "D01Z05S10[SE]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S09[W]" + ] + }, + { + "name": "D01Z05S10[SE]", + "exits": [ + { + "logic": [], + "target": "D01Z05S12[E]" + }, + { + "logic": [], + "target": "D01Z05S10[NE]" + }, + { + "logic": [], + "target": "D01Z05S10[S]" + }, + { + "logic": [], + "target": "D01Z05S09[NW]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S10[SE]", + "D01Z05S12[W]", + "D01Z05S10[W]", + "D01Z05S09[SE]" + ] + }, + { + "name": "D01BZ02S01", + "exits": [ + { + "logic": [], + "target": "D01BZ02S01[C]" + } + ], + "locations": [ + "QI58", + "RB05", + "RB09" + ], + "transitions": [] + }, + { + "name": "D01Z04S09[C]", + "exits": [ + { + "logic": [], + "target": "D01BZ02S01" + } + ], + "locations": [], + "transitions": [ + "D01Z04S09[C]" + ] + }, + { + "name": "D01Z04S11", + "exits": [ + { + "logic": [], + "target": "D01Z04S11[NE]" + } + ], + "locations": [ + "QI48" + ], + "transitions": [] + }, + { + "name": "D01Z04S10[SW]", + "exits": [ + { + "logic": [], + "target": "D01Z04S11" + } + ], + "locations": [], + "transitions": [ + "D01Z04S10[SW]" + ] + }, + { + "name": "D01Z04S11[NE]", + "exits": [ + { + "logic": [], + "target": "D01Z04S10[SW]" + }, + { + "logic": [], + "target": "D01Z04S09[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S11[NE]" + ] + }, + { + "name": "D01Z04S18", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatMercyBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z04S18[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatMercyBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z04S09[E]" + } + ], + "locations": [ + "BS01" + ], + "transitions": [] + }, + { + "name": "D01Z04S19[E]", + "exits": [ + { + "logic": [], + "target": "D01Z04S18" + }, + { + "logic": [], + "target": "D01Z04S18[W]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S19[E]" + ] + }, + { + "name": "D01Z04S14", + "exits": [ + { + "logic": [], + "target": "D01Z04S14[E]" + } + ], + "locations": [ + "CO38" + ], + "transitions": [] + }, + { + "name": "D01Z04S13[SW]", + "exits": [ + { + "logic": [], + "target": "D01Z04S14" + } + ], + "locations": [], + "transitions": [ + "D01Z04S13[SW]" + ] + }, + { + "name": "D01Z04S16", + "exits": [ + { + "logic": [], + "target": "D01Z04S16[W]" + }, + { + "logic": [], + "target": "D01Z04S16[E]" + } + ], + "locations": [ + "RESCUED_CHERUB_33" + ], + "transitions": [] + }, + { + "name": "D01Z04S13[SE]", + "exits": [ + { + "logic": [], + "target": "D01Z04S16" + }, + { + "logic": [ + { + "item_requirements": [ + "blueWax1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB25" + } + ], + "locations": [], + "transitions": [ + "D01Z04S13[SE]" + ] + }, + { + "name": "D05Z02S12[W]", + "exits": [ + { + "logic": [], + "target": "D01Z04S16" + }, + { + "logic": [ + { + "item_requirements": [ + "blueWax1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB25" + } + ], + "locations": [], + "transitions": [ + "D05Z02S12[W]" + ] + }, + { + "name": "D01Z04S08", + "exits": [ + { + "logic": [], + "target": "D01Z04S08[E]" + } + ], + "locations": [ + "RB17" + ], + "transitions": [] + }, + { + "name": "D01Z04S15[W]", + "exits": [ + { + "logic": [], + "target": "D01Z04S08" + } + ], + "locations": [], + "transitions": [ + "D01Z04S15[W]" + ] + }, + { + "name": "D01BZ02S01[C]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedDCGateE" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z04S09[W]" + }, + { + "logic": [], + "target": "D01Z04S09[E]" + }, + { + "logic": [], + "target": "D01Z04S09[C]" + } + ], + "locations": [], + "transitions": [ + "D01BZ02S01[C]" + ] + }, + { + "name": "D01Z05S12[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedDCGateE" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z04S09[W]" + }, + { + "logic": [], + "target": "D01Z04S09[E]" + }, + { + "logic": [], + "target": "D01Z04S09[C]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S12[E]" + ] + }, + { + "name": "D01Z04S16[E]", + "exits": [ + { + "logic": [], + "target": "D05Z02S12[W]" + }, + { + "logic": [], + "target": "D05Z02S12[N]" + }, + { + "logic": [], + "target": "D05Z02S04[W]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S16[E]" + ] + }, + { + "name": "D05Z02S04[W]", + "exits": [ + { + "logic": [], + "target": "D05Z02S12[W]" + }, + { + "logic": [], + "target": "D05Z02S12[N]" + }, + { + "logic": [], + "target": "D05Z02S04[C]" + }, + { + "logic": [], + "target": "D05Z02S03[E]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S04[W]", + "D05Z02S12[E]", + "D05Z02S04[E]", + "D05Z02S03[W]" + ] + }, + { + "name": "D05Z02S15[S]", + "exits": [ + { + "logic": [], + "target": "D05Z02S12[W]" + }, + { + "logic": [], + "target": "D05Z02S12[N]" + }, + { + "logic": [], + "target": "D05Z02S04[W]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S15[S]" + ] + }, + { + "name": "D01Z04S19", + "exits": [ + { + "logic": [], + "target": "D01Z04S19[W]" + }, + { + "logic": [], + "target": "D01Z04S19[E]" + } + ], + "locations": [ + "QI38" + ], + "transitions": [] + }, + { + "name": "D01Z04S18[W]", + "exits": [ + { + "logic": [], + "target": "D01Z04S19" + } + ], + "locations": [], + "transitions": [ + "D01Z04S18[W]" + ] + }, + { + "name": "D01Z05S19[E]", + "exits": [ + { + "logic": [], + "target": "D01Z04S19" + } + ], + "locations": [], + "transitions": [ + "D01Z05S19[E]" + ] + }, + { + "name": "D01Z04S19[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S19[W]" + }, + { + "logic": [], + "target": "D01Z05S19[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z04S19[W]" + ] + }, + { + "name": "D01Z05S15[SE]", + "exits": [ + { + "logic": [], + "target": "D01Z05S19[W]" + }, + { + "logic": [], + "target": "D01Z05S19[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S15[SE]" + ] + }, + { + "name": "D01Z05S03[NW]", + "exits": [ + { + "logic": [], + "target": "D01Z05S02[N]" + }, + { + "logic": [], + "target": "D01Z05S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z05S03[NW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedDCLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S02[S]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S03[NW]" + ] + }, + { + "name": "D01Z05S20[N]", + "exits": [ + { + "logic": [], + "target": "D01Z05S02[N]" + }, + { + "logic": [], + "target": "D01Z05S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z05S03[NW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedDCLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S02[S]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S20[N]" + ] + }, + { + "name": "D03Z01S01[NE]", + "exits": [ + { + "logic": [], + "target": "D01Z05S02[N]" + }, + { + "logic": [], + "target": "D01Z05S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z05S03[NW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedDCLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S02[S]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S01[NE]" + ] + }, + { + "name": "D03Z01S01", + "exits": [ + { + "logic": [], + "target": "D03Z01S01[W]" + }, + { + "logic": [], + "target": "D03Z01S01[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "D20Z01S03[N]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S01[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S01[-Cherubs]" + } + ], + "locations": [ + "CO13" + ], + "transitions": [] + }, + { + "name": "D01Z05S02[W]", + "exits": [ + { + "logic": [], + "target": "D03Z01S01" + } + ], + "locations": [], + "transitions": [ + "D01Z05S02[W]" + ] + }, + { + "name": "D03Z01S02[E]", + "exits": [ + { + "logic": [], + "target": "D03Z01S01" + } + ], + "locations": [], + "transitions": [ + "D03Z01S02[E]" + ] + }, + { + "name": "D20Z01S03[N]", + "exits": [ + { + "logic": [], + "target": "D03Z01S01" + } + ], + "locations": [], + "transitions": [ + "D20Z01S03[N]" + ] + }, + { + "name": "D01Z05S02[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S03[NW]" + }, + { + "logic": [], + "target": "D01Z05S03[W]" + }, + { + "logic": [], + "target": "D01Z05S03[E]" + }, + { + "logic": [], + "target": "D01Z05S04[W]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S02[E]" + ] + }, + { + "name": "D01Z05S04[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S03[NW]" + }, + { + "logic": [], + "target": "D01Z05S03[W]" + }, + { + "logic": [], + "target": "D01Z05S03[E]" + }, + { + "logic": [], + "target": "D01Z05S04[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z05S14[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S13[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S04[W]", + "D01Z05S03[NE]", + "D01Z05S13[N]", + "D01Z05S03[S]" + ] + }, + { + "name": "D01Z05S07[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S03[NW]" + }, + { + "logic": [], + "target": "D01Z05S03[W]" + }, + { + "logic": [], + "target": "D01Z05S03[E]" + }, + { + "logic": [], + "target": "D01Z05S04[W]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S07[E]" + ] + }, + { + "name": "D01Z05S08[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S03[NW]" + }, + { + "logic": [], + "target": "D01Z05S03[W]" + }, + { + "logic": [], + "target": "D01Z05S03[E]" + }, + { + "logic": [], + "target": "D01Z05S04[W]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S08[W]" + ] + }, + { + "name": "D01Z05S20", + "exits": [ + { + "logic": [], + "target": "D01Z05S20[W]" + }, + { + "logic": [], + "target": "D01Z05S20[N]" + } + ], + "locations": [ + "RESCUED_CHERUB_15" + ], + "transitions": [] + }, + { + "name": "D01Z05S02[S]", + "exits": [ + { + "logic": [], + "target": "D01Z05S20" + } + ], + "locations": [], + "transitions": [ + "D01Z05S02[S]" + ] + }, + { + "name": "D01Z05S25[NE]", + "exits": [ + { + "logic": [], + "target": "D01Z05S20" + } + ], + "locations": [], + "transitions": [ + "D01Z05S25[NE]" + ] + }, + { + "name": "D01Z05S05[NW]", + "exits": [ + { + "logic": [], + "target": "D01Z05S04[W]" + }, + { + "logic": [], + "target": "D01Z05S04[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S05[NW]" + ] + }, + { + "name": "D01Z05S07", + "exits": [ + { + "logic": [], + "target": "D01Z05S07[E]" + } + ], + "locations": [ + "Oil[D01Z05S07]" + ], + "transitions": [] + }, + { + "name": "D01Z05S03[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S07" + } + ], + "locations": [], + "transitions": [ + "D01Z05S03[W]" + ] + }, + { + "name": "D01Z05S08", + "exits": [ + { + "logic": [], + "target": "D01Z05S08[W]" + } + ], + "locations": [ + "QI12", + "RESCUED_CHERUB_14" + ], + "transitions": [] + }, + { + "name": "D01Z05S03[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S08" + } + ], + "locations": [], + "transitions": [ + "D01Z05S03[E]" + ] + }, + { + "name": "D01Z05S14[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canSurvivePoison3", + "canWaterJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_12" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z05S03[S]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canSurvivePoison3", + "canWaterJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S04[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z05S14[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S13[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z05S16[N]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canSurvivePoison3", + "canWaterJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S16[N]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S14[W]" + ] + }, + { + "name": "D01Z05S16[N]", + "exits": [ + { + "logic": [], + "target": "RESCUED_CHERUB_12" + }, + { + "logic": [ + { + "item_requirements": [ + "D01Z05S14[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S13[E]" + }, + { + "logic": [], + "target": "D01Z05S21[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "shroud" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S21[Reward]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "canWaterJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S17[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canWaterJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO32" + } + ], + "locations": [], + "transitions": [ + "D01Z05S16[N]", + "D01Z05S13[SW]", + "D01Z05S21[E]", + "D01Z05S16[SW]", + "D01Z05S17[W]", + "D01Z05S16[SE]" + ] + }, + { + "name": "D01Z05S05[SW]", + "exits": [ + { + "logic": [], + "target": "D01Z05S18[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S05[SW]" + ] + }, + { + "name": "D01Z05S05[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S09[NW]" + }, + { + "logic": [], + "target": "D01Z05S10[SE]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S05[E]" + ] + }, + { + "name": "D01Z05S11[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S10[NE]" + }, + { + "logic": [], + "target": "D01Z05S10[SE]" + }, + { + "logic": [], + "target": "D01Z05S10[S]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S11[W]" + ] + }, + { + "name": "D01Z05S14[N]", + "exits": [ + { + "logic": [], + "target": "D01Z05S10[NE]" + }, + { + "logic": [], + "target": "D01Z05S10[SE]" + }, + { + "logic": [], + "target": "D01Z05S10[S]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S14[N]" + ] + }, + { + "name": "D01Z05S14", + "exits": [ + { + "logic": [], + "target": "D01Z05S14[W]" + }, + { + "logic": [], + "target": "D01Z05S14[N]" + }, + { + "logic": [], + "target": "D01Z05S14[SE]" + } + ], + "locations": [ + "RESCUED_CHERUB_11" + ], + "transitions": [] + }, + { + "name": "D01Z05S10[S]", + "exits": [ + { + "logic": [], + "target": "D01Z05S14" + } + ], + "locations": [], + "transitions": [ + "D01Z05S10[S]" + ] + }, + { + "name": "D01Z05S13[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S14" + } + ], + "locations": [], + "transitions": [ + "D01Z05S13[E]" + ] + }, + { + "name": "D01Z05S15[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S14" + } + ], + "locations": [], + "transitions": [ + "D01Z05S15[W]" + ] + }, + { + "name": "D01Z05S15", + "exits": [ + { + "logic": [], + "target": "D01Z05S15[W]" + }, + { + "logic": [], + "target": "D01Z05S15[SW]" + }, + { + "logic": [], + "target": "D01Z05S15[SE]" + } + ], + "locations": [ + "CO41" + ], + "transitions": [] + }, + { + "name": "D01Z05S14[SE]", + "exits": [ + { + "logic": [], + "target": "D01Z05S15" + } + ], + "locations": [], + "transitions": [ + "D01Z05S14[SE]" + ] + }, + { + "name": "D01Z05S19[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S15" + } + ], + "locations": [], + "transitions": [ + "D01Z05S19[W]" + ] + }, + { + "name": "D01Z05S22[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S15" + } + ], + "locations": [], + "transitions": [ + "D01Z05S22[E]" + ] + }, + { + "name": "D01Z05S22", + "exits": [ + { + "logic": [], + "target": "D01Z05S22[E]" + } + ], + "locations": [ + "Lady[D01Z05S22]" + ], + "transitions": [] + }, + { + "name": "D01Z05S15[SW]", + "exits": [ + { + "logic": [], + "target": "D01Z05S22" + } + ], + "locations": [], + "transitions": [ + "D01Z05S15[SW]" + ] + }, + { + "name": "D01Z05S25[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S21[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "shroud" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S21[Reward]" + }, + { + "logic": [], + "target": "D01Z05S16[N]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S25[E]" + ] + }, + { + "name": "D01BZ05S01[Reward]", + "exits": [ + { + "logic": [], + "target": "D01Z05S21[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "shroud" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S21[Reward]" + }, + { + "logic": [], + "target": "D01Z05S16[N]" + } + ], + "locations": [], + "transitions": [ + "D01BZ05S01[Reward]" + ] + }, + { + "name": "D01BZ09S01[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S17[E]" + }, + { + "logic": [], + "target": "CO32" + }, + { + "logic": [], + "target": "D01Z05S16[N]" + } + ], + "locations": [], + "transitions": [ + "D01BZ09S01[W]" + ] + }, + { + "name": "D01Z05S17[E]", + "exits": [ + { + "logic": [], + "target": "D01BZ09S01[W]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S17[E]" + ] + }, + { + "name": "D01Z05S20[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S25[NE]" + }, + { + "logic": [], + "target": "D01Z05S25[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO44" + }, + { + "logic": [ + { + "item_requirements": [ + "obscureSkipsAllowed", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "obscureSkipsAllowed", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_22" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "tirana", + "obscureSkipsAllowed", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogic", + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogic", + "linen", + "canAirStall", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S09[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogic", + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogic", + "linen", + "canAirStall", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S10[W]" + }, + { + "logic": [], + "target": "D03Z03S17[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S20[W]" + ] + }, + { + "name": "D01Z05S21[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_22" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO44" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogic", + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogic", + "linen", + "canAirStall", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S09[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogic", + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogic", + "linen", + "canAirStall", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S10[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S17[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S21[W]" + ] + }, + { + "name": "D01Z05S23[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S25[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "tirana", + "obscureSkipsAllowed", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogic", + "tirana", + "obscureSkipsAllowed", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogic", + "tirana", + "obscureSkipsAllowed", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "pillar", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_22" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO44" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogic", + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogic", + "linen", + "canAirStall", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S09[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogic", + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogic", + "linen", + "canAirStall", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S10[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S17[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S23[E]" + ] + }, + { + "name": "D01Z05S26[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S25[NE]" + }, + { + "logic": [], + "target": "D01Z05S25[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO44" + }, + { + "logic": [ + { + "item_requirements": [ + "obscureSkipsAllowed", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "obscureSkipsAllowed", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_22" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "tirana", + "obscureSkipsAllowed", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogic", + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogic", + "linen", + "canAirStall", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S09[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogic", + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogic", + "linen", + "canAirStall", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S10[W]" + }, + { + "logic": [], + "target": "D03Z03S17[E]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S26[W]" + ] + }, + { + "name": "D03Z03S17[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S25[NE]" + }, + { + "logic": [], + "target": "D01Z05S25[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO44" + }, + { + "logic": [ + { + "item_requirements": [ + "obscureSkipsAllowed", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "obscureSkipsAllowed", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_22" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "tirana", + "obscureSkipsAllowed", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogic", + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogic", + "linen", + "canAirStall", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S09[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogic", + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogic", + "linen", + "canAirStall", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S10[W]" + }, + { + "logic": [], + "target": "D03Z03S17[W]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S17[E]", + "D01Z05S25[SW]" + ] + }, + { + "name": "D20Z01S09[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D20Z01S10[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S10[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "tirana", + "obscureSkipsAllowed", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO44" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_22" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S17[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB202" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S01[S]" + } + ], + "locations": [], + "transitions": [ + "D20Z01S09[E]", + "D01Z05S25[EchoesW]" + ] + }, + { + "name": "D20Z01S10[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D20Z01S09[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S09[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "tirana", + "obscureSkipsAllowed", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S25[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO44" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_22" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S17[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S11[W]" + } + ], + "locations": [], + "transitions": [ + "D20Z01S10[W]", + "D01Z05S25[EchoesE]" + ] + }, + { + "name": "D01BZ05S01", + "exits": [ + { + "logic": [], + "target": "D01BZ05S01[Reward]" + } + ], + "locations": [ + "RB03" + ], + "transitions": [] + }, + { + "name": "D01Z05S21[Reward]", + "exits": [ + { + "logic": [], + "target": "D01BZ05S01" + } + ], + "locations": [], + "transitions": [ + "D01Z05S21[Reward]" + ] + }, + { + "name": "D01Z05S24", + "exits": [ + { + "logic": [], + "target": "D01Z05S24[W]" + }, + { + "logic": [], + "target": "D01Z05S24[E]" + } + ], + "locations": [ + "Sword[D01Z05S24]" + ], + "transitions": [] + }, + { + "name": "D01Z05S23[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S24" + } + ], + "locations": [], + "transitions": [ + "D01Z05S23[W]" + ] + }, + { + "name": "D20Z01S04[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S24" + } + ], + "locations": [], + "transitions": [ + "D20Z01S04[E]" + ] + }, + { + "name": "D01Z05S24[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedDCGateW" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S04[E]" + }, + { + "logic": [], + "target": "D20Z01S01[S]" + } + ], + "locations": [], + "transitions": [ + "D01Z05S24[W]" + ] + }, + { + "name": "D20Z01S01[S]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedDCGateW" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S04[E]" + }, + { + "logic": [], + "target": "D20Z01S01[W]" + }, + { + "logic": [], + "target": "D20Z01S01[E]" + }, + { + "logic": [], + "target": "RB202" + }, + { + "logic": [ + { + "item_requirements": [ + "blood", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S09[E]" + } + ], + "locations": [], + "transitions": [ + "D20Z01S01[S]", + "D20Z01S04[N]", + "D20Z01S05[E]", + "D20Z01S04[W]", + "D20Z01S06[NE]", + "D20Z01S05[W]", + "D20Z01S07[NW]", + "D20Z01S06[SE]", + "D20Z01S07[SE]", + "D20Z01S09[W]", + "D20Z01S08[W]", + "D20Z01S07[NE]" + ] + }, + { + "name": "D01Z05S23", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "chalice", + "chaliceRooms3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D01Z05S23[W]" + }, + { + "logic": [], + "target": "D01Z05S23[E]" + } + ], + "locations": [ + "QI75" + ], + "transitions": [] + }, + { + "name": "D01Z05S24[E]", + "exits": [ + { + "logic": [], + "target": "D01Z05S23" + } + ], + "locations": [], + "transitions": [ + "D01Z05S24[E]" + ] + }, + { + "name": "D01Z05S25[W]", + "exits": [ + { + "logic": [], + "target": "D01Z05S23" + } + ], + "locations": [], + "transitions": [ + "D01Z05S25[W]" + ] + }, + { + "name": "D03Z03S16[E]", + "exits": [ + { + "logic": [], + "target": "D03Z03S17[W]" + }, + { + "logic": [], + "target": "D03Z03S17[E]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S16[E]" + ] + }, + { + "name": "D01Z05S26", + "exits": [ + { + "logic": [], + "target": "D01Z05S26[W]" + } + ], + "locations": [ + "Lady[D01Z05S26]" + ], + "transitions": [] + }, + { + "name": "D01Z05S25[SE]", + "exits": [ + { + "logic": [], + "target": "D01Z05S26" + } + ], + "locations": [], + "transitions": [ + "D01Z05S25[SE]" + ] + }, + { + "name": "D20Z01S11[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "blood", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z01S10[W]" + }, + { + "logic": [], + "target": "D20Z01S13[E]" + }, + { + "logic": [], + "target": "D20Z02S12[E]" + }, + { + "logic": [], + "target": "D20Z01S14[E]" + } + ], + "locations": [], + "transitions": [ + "D20Z01S11[W]", + "D20Z01S10[E]", + "D20Z01S12[E]", + "D20Z01S11[NW]", + "D20Z01S13[W]", + "D20Z01S11[NE]", + "D20Z02S12[W]", + "D20Z01S11[SE]", + "D20Z01S14[S]", + "D20Z01S13[N]" + ] + }, + { + "name": "D01Z06S01[Santos]", + "exits": [ + { + "logic": [], + "target": "D01BZ07S01[Santos]" + } + ], + "locations": [], + "transitions": [ + "D01Z06S01[Santos]" + ] + }, + { + "name": "D02Z01S01[SW]", + "exits": [ + { + "logic": [], + "target": "D02Z01S06[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S06[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "blood", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO19" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "wallClimb", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "wallClimb", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "wallClimb", + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "dash", + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "dash", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "dash", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "dash", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_27" + } + ], + "locations": [], + "transitions": [ + "D02Z01S01[SW]" + ] + }, + { + "name": "D02Z01S02[]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO19" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S06[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S06[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "wallClimb", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "wallClimb", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "wallClimb", + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "dash", + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "dash", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "dash", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "dash", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_27" + } + ], + "locations": [], + "transitions": [ + "D02Z01S02[]" + ] + }, + { + "name": "D02Z01S08[E]", + "exits": [ + { + "logic": [], + "target": "D02Z01S06[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_27" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S06[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "blood", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO19" + } + ], + "locations": [], + "transitions": [ + "D02Z01S08[E]" + ] + }, + { + "name": "D02Z01S03[SE]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S02[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_23" + }, + { + "logic": [], + "target": "D02Z01S02[W]" + }, + { + "logic": [], + "target": "D02Z01S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S02[]" + }, + { + "logic": [], + "target": "D02Z01S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S08[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S02[SE]" + } + ], + "locations": [], + "transitions": [ + "D02Z01S03[SE]", + "D02Z01S02[NW]", + "D02Z02S01[E]", + "D02Z01S03[W]" + ] + }, + { + "name": "D02Z01S04[E]", + "exits": [ + { + "logic": [], + "target": "D02Z01S02[W]" + }, + { + "logic": [], + "target": "D02Z01S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S02[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S02[]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canCrossGap4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canCrossGap4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_23" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S03[SE]" + } + ], + "locations": [], + "transitions": [ + "D02Z01S04[E]" + ] + }, + { + "name": "D02Z01S09[W]", + "exits": [ + { + "logic": [], + "target": "D02Z01S02[NE]" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_23" + }, + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S03[SE]" + }, + { + "logic": [], + "target": "D02Z01S02[W]" + }, + { + "logic": [], + "target": "D02Z01S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S02[]" + } + ], + "locations": [], + "transitions": [ + "D02Z01S09[W]" + ] + }, + { + "name": "D02Z01S04", + "exits": [ + { + "logic": [], + "target": "D02Z01S04[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "fullThimble", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S04[-N]" + }, + { + "logic": [ + { + "item_requirements": [ + "fullThimble", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "fullThimble", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI68" + } + ], + "locations": [ + "QI20" + ], + "transitions": [] + }, + { + "name": "D02Z01S02[W]", + "exits": [ + { + "logic": [], + "target": "D02Z01S04" + } + ], + "locations": [], + "transitions": [ + "D02Z01S02[W]" + ] + }, + { + "name": "D02Z01S05[E]", + "exits": [ + { + "logic": [], + "target": "D02Z01S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S03[SE]" + } + ], + "locations": [], + "transitions": [ + "D02Z01S05[E]" + ] + }, + { + "name": "D02Z02S14[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D02Z01S03[SE]" + }, + { + "logic": [], + "target": "D02Z01S03[SW]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S14[-Cherubs]" + ] + }, + { + "name": "D02Z01S09", + "exits": [ + { + "logic": [], + "target": "D02Z01S09[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S09[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canCrossGap2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canEnemyBounce", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S09[-CherubsR]" + } + ], + "locations": [ + "HE05" + ], + "transitions": [] + }, + { + "name": "D02Z01S02[NE]", + "exits": [ + { + "logic": [], + "target": "D02Z01S09" + } + ], + "locations": [], + "transitions": [ + "D02Z01S02[NE]" + ] + }, + { + "name": "D02Z01S05", + "exits": [ + { + "logic": [], + "target": "D02Z01S05[E]" + } + ], + "locations": [ + "QI07" + ], + "transitions": [] + }, + { + "name": "D02Z01S03[SW]", + "exits": [ + { + "logic": [], + "target": "D02Z01S05" + } + ], + "locations": [], + "transitions": [ + "D02Z01S03[SW]" + ] + }, + { + "name": "D02Z02S02[SE]", + "exits": [ + { + "logic": [], + "target": "D02Z01S03[SE]" + }, + { + "logic": [], + "target": "D02Z02S08[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S02[-CherubsR]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "tirana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_24" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S03[SW]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S02[SE]", + "D02Z02S01[NW]" + ] + }, + { + "name": "D02Z02S03[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D02Z01S03[SE]" + }, + { + "logic": [], + "target": "D02Z02S08[E]" + }, + { + "logic": [], + "target": "D02Z02S02[SE]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S03[-Cherubs]" + ] + }, + { + "name": "D02Z02S08[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z01S03[SE]" + }, + { + "logic": [], + "target": "D02Z02S08[W]" + }, + { + "logic": [], + "target": "D02Z02S08[C]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canBreakHoles" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO42" + }, + { + "logic": [ + { + "item_requirements": [ + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_31" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S02[SE]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S08[E]", + "D02Z02S01[W]" + ] + }, + { + "name": "D02Z01S08", + "exits": [ + { + "logic": [], + "target": "D02Z01S08[E]" + } + ], + "locations": [ + "PR04" + ], + "transitions": [] + }, + { + "name": "D02Z01S04[-N]", + "exits": [ + { + "logic": [], + "target": "D02Z01S08" + } + ], + "locations": [], + "transitions": [ + "D02Z01S04[-N]" + ] + }, + { + "name": "D02Z01S06[W]", + "exits": [ + { + "logic": [], + "target": "D02Z01S08" + } + ], + "locations": [], + "transitions": [ + "D02Z01S06[W]" + ] + }, + { + "name": "D02Z02S02[-CherubsR]", + "exits": [ + { + "logic": [], + "target": "CO42" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_31" + }, + { + "logic": [], + "target": "D02Z02S08[W]" + }, + { + "logic": [], + "target": "D02Z02S08[E]" + }, + { + "logic": [], + "target": "D02Z02S08[C]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S02[-CherubsR]" + ] + }, + { + "name": "D02Z02S04[-CherubsL]", + "exits": [ + { + "logic": [], + "target": "D02Z02S08[W]" + }, + { + "logic": [], + "target": "D02Z02S08[E]" + }, + { + "logic": [], + "target": "D02Z02S08[C]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canBreakHoles" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO42" + }, + { + "logic": [ + { + "item_requirements": [ + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_31" + } + ], + "locations": [], + "transitions": [ + "D02Z02S04[-CherubsL]" + ] + }, + { + "name": "D02Z02S11[SE]", + "exits": [ + { + "logic": [], + "target": "D02Z02S08[W]" + }, + { + "logic": [], + "target": "D02Z02S08[E]" + }, + { + "logic": [], + "target": "D02Z02S08[C]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canBreakHoles" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO42" + }, + { + "logic": [ + { + "item_requirements": [ + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_31" + } + ], + "locations": [], + "transitions": [ + "D02Z02S11[SE]" + ] + }, + { + "name": "D02BZ02S01[C]", + "exits": [ + { + "logic": [], + "target": "D02Z02S08[W]" + }, + { + "logic": [], + "target": "D02Z02S08[E]" + }, + { + "logic": [], + "target": "D02Z02S08[C]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canBreakHoles" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO42" + }, + { + "logic": [ + { + "item_requirements": [ + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_31" + } + ], + "locations": [], + "transitions": [ + "D02BZ02S01[C]" + ] + }, + { + "name": "D02Z02S03[SW]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "tirana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_24" + }, + { + "logic": [], + "target": "D02Z02S02[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S02[-CherubsR]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "canCrossGap11" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "blood", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "blood", + "canCrossGap7" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canWalkOnRoot", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canWalkOnRoot", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S03[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S03[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI46" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO29" + }, + { + "logic": [ + { + "item_requirements": [ + "canClimbOnRoot", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI08" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO01" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "blood", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash", + "blood", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash", + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash", + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_25" + }, + { + "logic": [ + { + "item_requirements": [ + "D02Z02S05[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S09[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S03[SW]", + "D02Z02S02[NE]", + "D02Z02S04[SE]", + "D02Z02S02[NW]" + ] + }, + { + "name": "D02Z02S05[-CherubsL]", + "exits": [ + { + "logic": [], + "target": "RESCUED_CHERUB_24" + }, + { + "logic": [], + "target": "D02Z02S02[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S02[-CherubsR]" + }, + { + "logic": [], + "target": "D02Z02S03[SW]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S05[-CherubsL]" + ] + }, + { + "name": "D02Z02S05[-CherubsR]", + "exits": [ + { + "logic": [], + "target": "RESCUED_CHERUB_24" + }, + { + "logic": [], + "target": "D02Z02S02[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S02[-CherubsR]" + }, + { + "logic": [], + "target": "D02Z02S03[SW]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S05[-CherubsR]" + ] + }, + { + "name": "D02Z02S05[SW]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "dash", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO01" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_25" + }, + { + "logic": [ + { + "item_requirements": [ + "D02Z02S05[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S09[E]" + } + ], + "locations": [ + "RB32" + ], + "transitions": [ + "D02Z02S05[SW]" + ] + }, + { + "name": "D02Z02S05[W]", + "exits": [ + { + "logic": [], + "target": "D02Z02S04[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[-CherubsL]" + }, + { + "logic": [], + "target": "CO01" + }, + { + "logic": [ + { + "item_requirements": [ + "blood", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_25" + }, + { + "logic": [ + { + "item_requirements": [ + "D02Z02S05[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[E]" + }, + { + "logic": [], + "target": "D02Z02S03[SW]" + }, + { + "logic": [], + "target": "D02Z02S09[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S05[W]" + ] + }, + { + "name": "D02Z02S09[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO01" + }, + { + "logic": [ + { + "item_requirements": [ + "blood", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_25" + }, + { + "logic": [ + { + "item_requirements": [ + "D02Z02S05[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S04[E]" + }, + { + "logic": [], + "target": "D02Z02S03[SW]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S09[E]", + "D02Z02S04[W]" + ] + }, + { + "name": "D02Z02S05[SE]", + "exits": [ + { + "logic": [], + "target": "QI46" + }, + { + "logic": [], + "target": "CO29" + }, + { + "logic": [], + "target": "D02Z02S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "canCrossGap11" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "blood", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "blood", + "canCrossGap7" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canWalkOnRoot", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canWalkOnRoot", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S03[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S03[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "canClimbOnRoot", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI08" + }, + { + "logic": [], + "target": "D02Z02S05[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "EnemySkipsAndDoubleJump", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[-CherubsR]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB15" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S05[SE]", + "D02Z02S03[NW]" + ] + }, + { + "name": "D02Z02S14[W]", + "exits": [ + { + "logic": [], + "target": "D02Z02S03[NE]" + }, + { + "logic": [], + "target": "QI46" + }, + { + "logic": [], + "target": "CO29" + }, + { + "logic": [ + { + "item_requirements": [ + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI08" + }, + { + "logic": [], + "target": "D02Z02S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S03[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[SE]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S14[W]" + ] + }, + { + "name": "D02Z02S04[E]", + "exits": [ + { + "logic": [], + "target": "D02Z02S05[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "EnemySkipsAndDoubleJump", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[W]" + }, + { + "logic": [], + "target": "D02Z02S05[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[-CherubsR]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB15" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S04[E]" + ] + }, + { + "name": "D02Z02S04[NE]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "EnemySkipsAndDoubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[W]" + }, + { + "logic": [], + "target": "D02Z02S05[SW]" + }, + { + "logic": [], + "target": "D02Z02S05[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[-CherubsR]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB15" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S04[NE]" + ] + }, + { + "name": "D02Z02S07[E]", + "exits": [ + { + "logic": [], + "target": "D02Z02S05[E]" + }, + { + "logic": [], + "target": "RB15" + }, + { + "logic": [], + "target": "D02Z02S05[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "EnemySkipsAndDoubleJump", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[W]" + }, + { + "logic": [], + "target": "D02Z02S05[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[-CherubsR]" + }, + { + "logic": [], + "target": "D02Z03S08[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D02Z03S07[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S08[W]" + }, + { + "logic": [], + "target": "D02Z02S11" + }, + { + "logic": [], + "target": "D01Z02S03[NW]" + }, + { + "logic": [], + "target": "D02Z02S11[E]" + }, + { + "logic": [], + "target": "D02Z02S11[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S02[W]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S07[E]", + "D02Z02S05[NW]", + "D02Z03S01[E]", + "D02Z02S07[W]", + "D02Z03S08[E]", + "D02Z03S01[W]", + "D02Z03S08[SE]", + "D02Z03S14[W]", + "D02Z03S14[E]", + "D02Z02S11[NW]", + "D02Z03S16[W]", + "D02Z03S08[NE]", + "D02Z03S02[S]", + "D02Z03S16[N]" + ] + }, + { + "name": "D02Z02S10[W]", + "exits": [ + { + "logic": [], + "target": "D02Z02S05[E]" + }, + { + "logic": [], + "target": "D02Z02S05[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "EnemySkipsAndDoubleJump", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[W]" + }, + { + "logic": [], + "target": "D02Z02S05[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S05[-CherubsR]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB15" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S10[W]" + ] + }, + { + "name": "D02Z02S14", + "exits": [ + { + "logic": [], + "target": "D02Z02S14[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S14[-Cherubs]" + } + ], + "locations": [ + "RB106", + "Amanecida[D02Z02S14]" + ], + "transitions": [] + }, + { + "name": "D02Z02S03[NE]", + "exits": [ + { + "logic": [], + "target": "D02Z02S14" + } + ], + "locations": [], + "transitions": [ + "D02Z02S03[NE]" + ] + }, + { + "name": "D02Z02S10", + "exits": [ + { + "logic": [], + "target": "D02Z02S10[W]" + } + ], + "locations": [ + "Oil[D02Z02S10]" + ], + "transitions": [] + }, + { + "name": "D02Z02S05[E]", + "exits": [ + { + "logic": [], + "target": "D02Z02S10" + } + ], + "locations": [], + "transitions": [ + "D02Z02S05[E]" + ] + }, + { + "name": "D02Z03S10[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S10[-Cherubs]" + ] + }, + { + "name": "D02Z02S11", + "exits": [ + { + "logic": [], + "target": "D02Z02S11[W]" + }, + { + "logic": [], + "target": "D02Z02S11[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap6" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S11[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z02S11[-Cherubs]" + } + ], + "locations": [ + "QI53", + "RESCUED_CHERUB_26" + ], + "transitions": [] + }, + { + "name": "D02Z02S06[E]", + "exits": [ + { + "logic": [], + "target": "D02Z02S11" + }, + { + "logic": [], + "target": "D01Z02S03[NW]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S06[E]" + ] + }, + { + "name": "D02Z02S08[W]", + "exits": [ + { + "logic": [], + "target": "D02Z02S11" + }, + { + "logic": [], + "target": "D01Z02S03[NW]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S08[W]" + ] + }, + { + "name": "D02Z02S12[W]", + "exits": [ + { + "logic": [], + "target": "D02Z02S11" + }, + { + "logic": [], + "target": "D01Z02S03[NW]" + }, + { + "logic": [], + "target": "D02Z02S11[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S12[W]" + ] + }, + { + "name": "D02Z02S13[W]", + "exits": [ + { + "logic": [], + "target": "D02Z02S11" + }, + { + "logic": [], + "target": "D01Z02S03[NW]" + }, + { + "logic": [], + "target": "D02Z02S11[E]" + }, + { + "logic": [], + "target": "D02Z02S11[NE]" + }, + { + "logic": [], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z02S13[W]" + ] + }, + { + "name": "D02BZ02S01", + "exits": [ + { + "logic": [], + "target": "D02BZ02S01[C]" + } + ], + "locations": [ + "QI11", + "RB37", + "RB02" + ], + "transitions": [] + }, + { + "name": "D02Z02S08[C]", + "exits": [ + { + "logic": [], + "target": "D02BZ02S01" + } + ], + "locations": [], + "transitions": [ + "D02Z02S08[C]" + ] + }, + { + "name": "D02Z02S06", + "exits": [ + { + "logic": [], + "target": "D02Z02S06[E]" + } + ], + "locations": [ + "RB38" + ], + "transitions": [] + }, + { + "name": "D02Z02S11[W]", + "exits": [ + { + "logic": [], + "target": "D02Z02S06" + } + ], + "locations": [], + "transitions": [ + "D02Z02S11[W]" + ] + }, + { + "name": "D02Z02S12", + "exits": [ + { + "logic": [], + "target": "D02Z02S12[W]" + } + ], + "locations": [ + "Lady[D02Z02S12]" + ], + "transitions": [] + }, + { + "name": "D02Z02S11[E]", + "exits": [ + { + "logic": [], + "target": "D02Z02S12" + } + ], + "locations": [], + "transitions": [ + "D02Z02S11[E]" + ] + }, + { + "name": "D02Z02S13", + "exits": [ + { + "logic": [], + "target": "D02Z02S13[W]" + } + ], + "locations": [ + "HE11" + ], + "transitions": [] + }, + { + "name": "D02Z02S11[NE]", + "exits": [ + { + "logic": [], + "target": "D02Z02S13" + } + ], + "locations": [], + "transitions": [ + "D02Z02S11[NE]" + ] + }, + { + "name": "D02Z03S07[E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S08[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D02Z03S07[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S08[W]" + }, + { + "logic": [], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S07[E]" + ] + }, + { + "name": "D02Z03S12[E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S08[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D02Z03S07[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S08[W]" + }, + { + "logic": [], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S12[E]" + ] + }, + { + "name": "D02Z03S02[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO05" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S05[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S05[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB08" + }, + { + "logic": [], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S02[W]", + "D02Z03S03[E]", + "D02Z03S05[E]", + "D02Z03S03[W]" + ] + }, + { + "name": "D02Z03S05[NE]", + "exits": [ + { + "logic": [], + "target": "CO05" + }, + { + "logic": [], + "target": "D02Z03S05[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB08" + }, + { + "logic": [], + "target": "D02Z03S02[W]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S05[NE]", + "D02Z03S03[NW]" + ] + }, + { + "name": "D02Z03S21", + "exits": [ + { + "logic": [], + "target": "D02Z03S21[W]" + }, + { + "logic": [], + "target": "D02Z03S21[E]" + } + ], + "locations": [ + "QI40", + "QI57" + ], + "transitions": [] + }, + { + "name": "D02Z03S02[NW]", + "exits": [ + { + "logic": [], + "target": "D02Z03S21" + } + ], + "locations": [], + "transitions": [ + "D02Z03S02[NW]" + ] + }, + { + "name": "D02Z03S20[E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S21" + } + ], + "locations": [], + "transitions": [ + "D02Z03S20[E]" + ] + }, + { + "name": "D02Z03S13", + "exits": [ + { + "logic": [], + "target": "D02Z03S13[W]" + } + ], + "locations": [ + "Sword[D02Z03S13]" + ], + "transitions": [] + }, + { + "name": "D02Z03S02[NE]", + "exits": [ + { + "logic": [], + "target": "D02Z03S13" + } + ], + "locations": [], + "transitions": [ + "D02Z03S02[NE]" + ] + }, + { + "name": "D02Z03S02[N]", + "exits": [ + { + "logic": [], + "target": "D02Z03S11[S]" + }, + { + "logic": [], + "target": "D02Z03S11[W]" + }, + { + "logic": [], + "target": "D02Z03S11[NW]" + }, + { + "logic": [], + "target": "D02Z03S10[W]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S02[N]" + ] + }, + { + "name": "D02Z03S10[W]", + "exits": [ + { + "logic": [], + "target": "D02Z03S11[S]" + }, + { + "logic": [], + "target": "D02Z03S11[W]" + }, + { + "logic": [], + "target": "D02Z03S11[NW]" + }, + { + "logic": [], + "target": "D02Z03S10[-W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S10[-Cherubs]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S10[W]", + "D02Z03S11[E]", + "D02Z03S22[W]", + "D02Z03S11[NE]" + ] + }, + { + "name": "D02Z03S15[E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S11[S]" + }, + { + "logic": [], + "target": "D02Z03S11[W]" + }, + { + "logic": [], + "target": "D02Z03S11[NW]" + }, + { + "logic": [], + "target": "D02Z03S10[W]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S15[E]" + ] + }, + { + "name": "D02Z03S19[E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S11[S]" + }, + { + "logic": [], + "target": "D02Z03S11[W]" + }, + { + "logic": [], + "target": "D02Z03S11[NW]" + }, + { + "logic": [], + "target": "D02Z03S10[W]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S19[E]" + ] + }, + { + "name": "D02Z03S07[N]", + "exits": [ + { + "logic": [], + "target": "D02Z03S05[S]" + }, + { + "logic": [], + "target": "D02Z03S05[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB08" + }, + { + "logic": [], + "target": "D02Z03S02[W]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S07[N]" + ] + }, + { + "name": "D02Z03S11[S]", + "exits": [ + { + "logic": [], + "target": "D02Z03S02[W]" + }, + { + "logic": [], + "target": "D02Z03S02[NW]" + }, + { + "logic": [], + "target": "D02Z03S02[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedConventLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S02[N]" + }, + { + "logic": [], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S11[S]" + ] + }, + { + "name": "D02Z03S13[W]", + "exits": [ + { + "logic": [], + "target": "D02Z03S02[W]" + }, + { + "logic": [], + "target": "D02Z03S02[NW]" + }, + { + "logic": [], + "target": "D02Z03S02[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedConventLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S02[N]" + }, + { + "logic": [], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S13[W]" + ] + }, + { + "name": "D02Z03S21[E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S02[W]" + }, + { + "logic": [], + "target": "D02Z03S02[NW]" + }, + { + "logic": [], + "target": "D02Z03S02[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedConventLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S02[N]" + }, + { + "logic": [], + "target": "D02Z02S07[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S21[E]" + ] + }, + { + "name": "D02Z03S07", + "exits": [ + { + "logic": [], + "target": "D02Z03S07[W]" + }, + { + "logic": [], + "target": "D02Z03S07[NWW]" + }, + { + "logic": [], + "target": "D02Z03S07[NW]" + }, + { + "logic": [], + "target": "D02Z03S07[N]" + }, + { + "logic": [], + "target": "D02Z03S07[E]" + } + ], + "locations": [ + "CO15" + ], + "transitions": [] + }, + { + "name": "D02Z03S05[S]", + "exits": [ + { + "logic": [], + "target": "D02Z03S07" + } + ], + "locations": [], + "transitions": [ + "D02Z03S05[S]" + ] + }, + { + "name": "D02Z03S06[S]", + "exits": [ + { + "logic": [], + "target": "D02Z03S07" + } + ], + "locations": [], + "transitions": [ + "D02Z03S06[S]" + ] + }, + { + "name": "D02Z03S08[W]", + "exits": [ + { + "logic": [], + "target": "D02Z03S07" + } + ], + "locations": [], + "transitions": [ + "D02Z03S08[W]" + ] + }, + { + "name": "D02Z03S17[E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S07" + } + ], + "locations": [], + "transitions": [ + "D02Z03S17[E]" + ] + }, + { + "name": "D02Z03S24[E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S07" + } + ], + "locations": [], + "transitions": [ + "D02Z03S24[E]" + ] + }, + { + "name": "D02Z03S06[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S18[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S18[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "redWax1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB18" + }, + { + "logic": [], + "target": "D02Z03S06[S]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S06[W]", + "D02Z03S18[SE]" + ] + }, + { + "name": "D02Z03S09[W]", + "exits": [ + { + "logic": [], + "target": "D02Z03S18[NW]" + }, + { + "logic": [], + "target": "D02Z03S18[NE]" + }, + { + "logic": [], + "target": "D02Z03S06[W]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S09[W]" + ] + }, + { + "name": "D02Z03S23[E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S18[NW]" + }, + { + "logic": [], + "target": "D02Z03S18[NE]" + }, + { + "logic": [], + "target": "D02Z03S06[W]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S23[E]" + ] + }, + { + "name": "D02Z03S17", + "exits": [ + { + "logic": [], + "target": "D02Z03S17[E]" + } + ], + "locations": [ + "RB24" + ], + "transitions": [] + }, + { + "name": "D02Z03S07[W]", + "exits": [ + { + "logic": [], + "target": "D02Z03S17" + } + ], + "locations": [], + "transitions": [ + "D02Z03S07[W]" + ] + }, + { + "name": "D02Z03S07[NWW]", + "exits": [ + { + "logic": [], + "target": "D02Z03S24[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S07[NWW]" + ] + }, + { + "name": "D02Z03S07[NW]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "redWax1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB18" + }, + { + "logic": [], + "target": "D02Z03S06[W]" + }, + { + "logic": [], + "target": "D02Z03S06[S]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S07[NW]" + ] + }, + { + "name": "D02Z03S12", + "exits": [ + { + "logic": [], + "target": "D02Z03S12[E]" + } + ], + "locations": [ + "HE03" + ], + "transitions": [] + }, + { + "name": "D02Z03S08[SW]", + "exits": [ + { + "logic": [], + "target": "D02Z03S12" + } + ], + "locations": [], + "transitions": [ + "D02Z03S08[SW]" + ] + }, + { + "name": "D02Z03S20", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatConventBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S20[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatConventBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S20[E]" + } + ], + "locations": [ + "BS03" + ], + "transitions": [] + }, + { + "name": "D02Z03S09[E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S20" + }, + { + "logic": [], + "target": "D02Z03S20[W]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S09[E]" + ] + }, + { + "name": "D02Z03S21[W]", + "exits": [ + { + "logic": [], + "target": "D02Z03S20" + }, + { + "logic": [], + "target": "D02Z03S20[E]" + } + ], + "locations": [], + "transitions": [ + "D02Z03S21[W]" + ] + }, + { + "name": "D09Z01S06", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "peaksKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S06[-E]" + }, + { + "logic": [], + "target": "D09Z01S06[E]" + } + ], + "locations": [ + "RESCUED_CHERUB_05" + ], + "transitions": [] + }, + { + "name": "D02Z03S10[-W]", + "exits": [ + { + "logic": [], + "target": "D09Z01S06" + } + ], + "locations": [], + "transitions": [ + "D02Z03S10[-W]" + ] + }, + { + "name": "D09Z01S04[W]", + "exits": [ + { + "logic": [], + "target": "D09Z01S06" + } + ], + "locations": [], + "transitions": [ + "D09Z01S04[W]" + ] + }, + { + "name": "D02Z03S15", + "exits": [ + { + "logic": [], + "target": "D02Z03S15[E]" + } + ], + "locations": [ + "Lady[D02Z03S15]" + ], + "transitions": [] + }, + { + "name": "D02Z03S11[W]", + "exits": [ + { + "logic": [], + "target": "D02Z03S15" + } + ], + "locations": [], + "transitions": [ + "D02Z03S11[W]" + ] + }, + { + "name": "D02Z03S19", + "exits": [ + { + "logic": [], + "target": "D02Z03S19[E]" + } + ], + "locations": [ + "QI61" + ], + "transitions": [] + }, + { + "name": "D02Z03S11[NW]", + "exits": [ + { + "logic": [], + "target": "D02Z03S19" + } + ], + "locations": [], + "transitions": [ + "D02Z03S11[NW]" + ] + }, + { + "name": "D09Z01S06[-E]", + "exits": [ + { + "logic": [], + "target": "D02Z03S10[W]" + }, + { + "logic": [], + "target": "D02Z03S10[-W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D02Z03S10[-Cherubs]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S06[-E]" + ] + }, + { + "name": "D02Z03S23", + "exits": [ + { + "logic": [], + "target": "D02Z03S23[E]" + } + ], + "locations": [ + "RB107" + ], + "transitions": [] + }, + { + "name": "D02Z03S18[NW]", + "exits": [ + { + "logic": [], + "target": "D02Z03S23" + } + ], + "locations": [], + "transitions": [ + "D02Z03S18[NW]" + ] + }, + { + "name": "D02Z03S09", + "exits": [ + { + "logic": [], + "target": "D02Z03S09[W]" + }, + { + "logic": [], + "target": "D02Z03S09[E]" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D02Z03S18[NE]", + "exits": [ + { + "logic": [], + "target": "D02Z03S09" + } + ], + "locations": [], + "transitions": [ + "D02Z03S18[NE]" + ] + }, + { + "name": "D02Z03S20[W]", + "exits": [ + { + "logic": [], + "target": "D02Z03S09" + } + ], + "locations": [], + "transitions": [ + "D02Z03S20[W]" + ] + }, + { + "name": "D03Z01S01[W]", + "exits": [ + { + "logic": [], + "target": "D03Z01S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S06[E]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S01[W]" + ] + }, + { + "name": "D03Z01S06[E]", + "exits": [ + { + "logic": [], + "target": "D03Z01S06" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap7" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S02[E]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S06[E]", + "D03Z01S02[W]" + ] + }, + { + "name": "D03Z01S01[S]", + "exits": [ + { + "logic": [], + "target": "D20Z01S03[W]" + }, + { + "logic": [], + "target": "D20Z01S03[N]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S01[S]" + ] + }, + { + "name": "D20Z01S02[E]", + "exits": [ + { + "logic": [], + "target": "D20Z01S03[W]" + }, + { + "logic": [], + "target": "D20Z01S03[N]" + } + ], + "locations": [], + "transitions": [ + "D20Z01S02[E]" + ] + }, + { + "name": "D03Z01S01[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D20Z01S01[W]" + }, + { + "logic": [], + "target": "D20Z01S01[E]" + }, + { + "logic": [], + "target": "D20Z01S01[S]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S01[-Cherubs]" + ] + }, + { + "name": "D03Z02S15[E]", + "exits": [ + { + "logic": [], + "target": "D20Z01S01[W]" + }, + { + "logic": [], + "target": "D20Z01S01[E]" + }, + { + "logic": [], + "target": "D20Z01S01[S]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S15[E]" + ] + }, + { + "name": "D20Z01S02[W]", + "exits": [ + { + "logic": [], + "target": "D20Z01S01[W]" + }, + { + "logic": [], + "target": "D20Z01S01[E]" + }, + { + "logic": [], + "target": "D20Z01S01[S]" + } + ], + "locations": [], + "transitions": [ + "D20Z01S02[W]" + ] + }, + { + "name": "D03Z01S06", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatPerpetua" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S06[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatPerpetua" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[E]" + } + ], + "locations": [ + "RB13", + "QI14" + ], + "transitions": [] + }, + { + "name": "D03Z01S03[E]", + "exits": [ + { + "logic": [], + "target": "D03Z01S06" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[SW]" + }, + { + "logic": [], + "target": "D03Z01S03[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-WestL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-WestR]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-EastL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-EastR]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI47" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB22" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_16" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatJondoBoss", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "Amanecida[D03Z01S03]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S03[E]", + "D03Z01S06[W]" + ] + }, + { + "name": "D03Z01S04", + "exits": [ + { + "logic": [], + "target": "D03Z01S04[NW]" + }, + { + "logic": [], + "target": "D03Z01S04[E]" + } + ], + "locations": [ + "QI63" + ], + "transitions": [] + }, + { + "name": "D03Z01S03[W]", + "exits": [ + { + "logic": [], + "target": "D03Z01S04" + } + ], + "locations": [], + "transitions": [ + "D03Z01S03[W]" + ] + }, + { + "name": "D03Z01S05[E]", + "exits": [ + { + "logic": [], + "target": "D03Z01S04" + } + ], + "locations": [], + "transitions": [ + "D03Z01S05[E]" + ] + }, + { + "name": "D03Z02S10", + "exits": [ + { + "logic": [], + "target": "D03Z02S10[W]" + }, + { + "logic": [], + "target": "D03Z02S10[N]" + }, + { + "logic": [], + "target": "D03Z02S10[S]" + }, + { + "logic": [], + "target": "D03Z02S10[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S10[-Cherubs]" + } + ], + "locations": [ + "RESCUED_CHERUB_17" + ], + "transitions": [] + }, + { + "name": "D03Z01S03[SW]", + "exits": [ + { + "logic": [], + "target": "D03Z02S10" + } + ], + "locations": [], + "transitions": [ + "D03Z01S03[SW]" + ] + }, + { + "name": "D03Z01S03[-WestL]", + "exits": [ + { + "logic": [], + "target": "D03Z02S10" + } + ], + "locations": [], + "transitions": [ + "D03Z01S03[-WestL]" + ] + }, + { + "name": "D03Z02S02[W]", + "exits": [ + { + "logic": [], + "target": "D03Z02S10" + } + ], + "locations": [], + "transitions": [ + "D03Z02S02[W]" + ] + }, + { + "name": "D03Z02S09[N]", + "exits": [ + { + "logic": [], + "target": "D03Z02S10" + } + ], + "locations": [], + "transitions": [ + "D03Z02S09[N]" + ] + }, + { + "name": "D03Z02S13[E]", + "exits": [ + { + "logic": [], + "target": "D03Z02S10" + } + ], + "locations": [], + "transitions": [ + "D03Z02S13[E]" + ] + }, + { + "name": "D03Z02S01", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "PR10" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[SE]" + } + ], + "locations": [ + "CO08" + ], + "transitions": [] + }, + { + "name": "D03Z01S03[SE]", + "exits": [ + { + "logic": [], + "target": "D03Z02S01" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-WestL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-WestR]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-EastL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-EastR]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI47" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB22" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_16" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatJondoBoss", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "Amanecida[D03Z01S03]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S03[SE]", + "D03Z02S01[N]" + ] + }, + { + "name": "D03Z01S03[-EastR]", + "exits": [ + { + "logic": [], + "target": "D03Z02S01" + }, + { + "logic": [], + "target": "PR10" + } + ], + "locations": [], + "transitions": [ + "D03Z01S03[-EastR]" + ] + }, + { + "name": "D03Z02S02[E]", + "exits": [ + { + "logic": [], + "target": "D03Z02S01" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S02[W]" + }, + { + "logic": [], + "target": "D03Z02S03[N]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S02[E]", + "D03Z02S01[W]" + ] + }, + { + "name": "D03Z01S03[-WestR]", + "exits": [ + { + "logic": [], + "target": "D03Z02S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S02[E]" + }, + { + "logic": [], + "target": "D03Z02S03[N]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S03[-WestR]" + ] + }, + { + "name": "D03Z01S03[-EastL]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S02[E]" + }, + { + "logic": [], + "target": "D03Z02S03[N]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S03[-EastL]" + ] + }, + { + "name": "D03Z02S03[N]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "doubleJump", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "brokeJondoBellW", + "brokeJondoBellE" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "brokeJondoBellW", + "brokeJondoBellE" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "brokeJondoBellW", + "brokeJondoBellE" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S01[NL]" + }, + { + "logic": [ + { + "item_requirements": [ + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "boots" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S05[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S04[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO33" + } + ], + "locations": [], + "transitions": [ + "D03Z02S03[N]", + "D03Z02S02[S]", + "D03Z02S04[NW]", + "D03Z02S03[SE2]" + ] + }, + { + "name": "D03Z02S10[E]", + "exits": [ + { + "logic": [], + "target": "D03Z02S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S02[E]" + }, + { + "logic": [], + "target": "D03Z02S03[N]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S10[E]" + ] + }, + { + "name": "D03Z01S04[NW]", + "exits": [ + { + "logic": [], + "target": "D03Z01S05[E]" + }, + { + "logic": [], + "target": "D17Z01S07[SE]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S04[NW]" + ] + }, + { + "name": "D17Z01S07[SE]", + "exits": [ + { + "logic": [], + "target": "D03Z01S05[E]" + }, + { + "logic": [], + "target": "D17Z01S07[SW]" + }, + { + "logic": [], + "target": "D17Z01S07[N]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S07[SE]", + "D03Z01S05[W]", + "D17Z01S06[E]", + "D17Z01S07[W]", + "D17Z01S09[E]", + "D17Z01S07[NW]" + ] + }, + { + "name": "D03Z01S04[E]", + "exits": [ + { + "logic": [], + "target": "D03Z01S03[W]" + }, + { + "logic": [], + "target": "D03Z01S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-WestL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-WestR]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-EastL]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI47" + }, + { + "logic": [], + "target": "RB22" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_16" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatJondoBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "Amanecida[D03Z01S03]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[E]" + }, + { + "logic": [], + "target": "D03Z01S03[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-EastR]" + } + ], + "locations": [], + "transitions": [ + "D03Z01S04[E]" + ] + }, + { + "name": "D03Z02S10[N]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[W]" + }, + { + "logic": [], + "target": "D03Z01S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-WestL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-WestR]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-EastL]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI47" + }, + { + "logic": [], + "target": "RB22" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_16" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatJondoBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "Amanecida[D03Z01S03]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[E]" + }, + { + "logic": [], + "target": "D03Z01S03[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z01S03[-EastR]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S10[N]" + ] + }, + { + "name": "D17Z01S04[S]", + "exits": [ + { + "logic": [], + "target": "D17Z01S07[SW]" + }, + { + "logic": [], + "target": "D17Z01S07[SE]" + }, + { + "logic": [], + "target": "D17Z01S07[N]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S04[S]" + ] + }, + { + "name": "D17Z01S08[E]", + "exits": [ + { + "logic": [], + "target": "D17Z01S07[SW]" + }, + { + "logic": [], + "target": "D17Z01S07[SE]" + }, + { + "logic": [], + "target": "D17Z01S07[N]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S08[E]" + ] + }, + { + "name": "D03Z02S05[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[W]" + }, + { + "logic": [], + "target": "D03Z02S03[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "brokeJondoBellW", + "brokeJondoBellE" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "brokeJondoBellW", + "brokeJondoBellE" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "brokeJondoBellW", + "brokeJondoBellE" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S01[NL]" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyBounce", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_18" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyBounce", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S04[NE]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S05[W]", + "D03Z02S03[E]" + ] + }, + { + "name": "D03Z02S06[W]", + "exits": [ + { + "logic": [], + "target": "D03Z02S03[SW]" + }, + { + "logic": [], + "target": "D03Z02S03[SE]" + }, + { + "logic": [], + "target": "D03Z03S01[NL]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S06[W]" + ] + }, + { + "name": "D03Z02S07[E]", + "exits": [ + { + "logic": [], + "target": "D03Z02S03[SW]" + }, + { + "logic": [], + "target": "D03Z02S03[SE]" + }, + { + "logic": [], + "target": "D03Z03S01[NL]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S07[E]" + ] + }, + { + "name": "D03Z02S07[N]", + "exits": [ + { + "logic": [], + "target": "D03Z02S03[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "brokeJondoBellW", + "brokeJondoBellE", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "brokeJondoBellW", + "brokeJondoBellE", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "brokeJondoBellW", + "brokeJondoBellE", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S01[NL]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S07[N]" + ] + }, + { + "name": "D03Z03S01[NL]", + "exits": [ + { + "logic": [], + "target": "D03Z02S03[SW]" + }, + { + "logic": [], + "target": "D03Z02S03[SE]" + }, + { + "logic": [], + "target": "D03Z03S12[W]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S01[NL]", + "D03Z02S03[SSL]", + "D03Z02S03[SSC]", + "D03Z02S03[SSR]", + "D03Z03S01[NR]" + ] + }, + { + "name": "D03Z02S07", + "exits": [ + { + "logic": [], + "target": "D03Z02S07[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D03Z02S03[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S07[E]" + }, + { + "logic": [], + "target": "D03Z02S07[N]" + } + ], + "locations": [ + "CO07" + ], + "transitions": [] + }, + { + "name": "D03Z02S03[W]", + "exits": [ + { + "logic": [], + "target": "D03Z02S07" + } + ], + "locations": [], + "transitions": [ + "D03Z02S03[W]" + ] + }, + { + "name": "D03Z02S03[SW]", + "exits": [ + { + "logic": [], + "target": "D03Z02S07" + } + ], + "locations": [], + "transitions": [ + "D03Z02S03[SW]" + ] + }, + { + "name": "D03Z02S08[E]", + "exits": [ + { + "logic": [], + "target": "D03Z02S07" + } + ], + "locations": [], + "transitions": [ + "D03Z02S08[E]" + ] + }, + { + "name": "D03Z02S04[NE]", + "exits": [ + { + "logic": [], + "target": "RESCUED_CHERUB_18" + }, + { + "logic": [], + "target": "D03Z02S04[S]" + }, + { + "logic": [], + "target": "CO33" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "HE06" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canCrossGap2", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_37" + }, + { + "logic": [], + "target": "D03Z02S05[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canCrossGap2", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S11[E]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S04[NE]", + "D03Z02S05[S]", + "D03Z02S11[W]", + "D03Z02S05[E]" + ] + }, + { + "name": "D03Z02S06[N]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S04[NE]" + }, + { + "logic": [], + "target": "D03Z02S04[S]" + }, + { + "logic": [], + "target": "CO33" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S03[N]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S06[N]" + ] + }, + { + "name": "D03Z02S06", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D03Z02S03[SE]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S06[W]" + }, + { + "logic": [], + "target": "D03Z02S06[N]" + } + ], + "locations": [ + "QI19" + ], + "transitions": [] + }, + { + "name": "D03Z02S03[SE]", + "exits": [ + { + "logic": [], + "target": "D03Z02S06" + } + ], + "locations": [], + "transitions": [ + "D03Z02S03[SE]" + ] + }, + { + "name": "D03Z02S04[S]", + "exits": [ + { + "logic": [], + "target": "D03Z02S06" + } + ], + "locations": [], + "transitions": [ + "D03Z02S04[S]" + ] + }, + { + "name": "D03Z03S12[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S01[NL]" + }, + { + "logic": [], + "target": "D03Z03S02" + } + ], + "locations": [], + "transitions": [ + "D03Z03S12[W]", + "D03Z03S01[S]", + "D03Z03S18[E]", + "D03Z03S01[W]", + "D03Z03S02[W]", + "D03Z03S12[E]" + ] + }, + { + "name": "D03Z02S15[W]", + "exits": [ + { + "logic": [], + "target": "D03Z02S11[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canCrossGap2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "preciseSkipsAllowed", + "canCrossGap1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "HE06" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "canCrossGap1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_37" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canCrossGap2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "preciseSkipsAllowed", + "canCrossGap1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S04[NE]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S15[W]" + ] + }, + { + "name": "D03Z02S07[W]", + "exits": [ + { + "logic": [], + "target": "D03Z02S08[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI41" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S09[S]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S07[W]" + ] + }, + { + "name": "D03Z02S09[S]", + "exits": [ + { + "logic": [], + "target": "QI41" + }, + { + "logic": [], + "target": "D03Z02S09[N]" + }, + { + "logic": [], + "target": "D03Z02S08[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S09[W]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S09[S]", + "D03Z02S08[N]", + "D03Z02S14[E]", + "D03Z02S08[W]" + ] + }, + { + "name": "D03Z02S10[S]", + "exits": [ + { + "logic": [], + "target": "D03Z02S09[N]" + }, + { + "logic": [], + "target": "D03Z02S09[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S09[W]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S10[S]" + ] + }, + { + "name": "D03Z02S10[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D03Z02S09[N]" + }, + { + "logic": [], + "target": "D03Z02S09[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S09[W]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S10[-Cherubs]" + ] + }, + { + "name": "D03Z02S12[E]", + "exits": [ + { + "logic": [], + "target": "D03Z02S09[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S09[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S09[S]" + } + ], + "locations": [], + "transitions": [ + "D03Z02S12[E]" + ] + }, + { + "name": "D03Z02S12", + "exits": [ + { + "logic": [], + "target": "D03Z02S12[E]" + } + ], + "locations": [ + "QI52" + ], + "transitions": [] + }, + { + "name": "D03Z02S09[W]", + "exits": [ + { + "logic": [], + "target": "D03Z02S12" + } + ], + "locations": [], + "transitions": [ + "D03Z02S09[W]" + ] + }, + { + "name": "D03Z02S13[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D03Z02S12" + } + ], + "locations": [], + "transitions": [ + "D03Z02S13[-Cherubs]" + ] + }, + { + "name": "D03Z02S13", + "exits": [ + { + "logic": [], + "target": "D03Z02S13[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z02S13[-Cherubs]" + } + ], + "locations": [ + "RB28" + ], + "transitions": [] + }, + { + "name": "D03Z02S10[W]", + "exits": [ + { + "logic": [], + "target": "D03Z02S13" + } + ], + "locations": [], + "transitions": [ + "D03Z02S10[W]" + ] + }, + { + "name": "D03Z02S15", + "exits": [ + { + "logic": [], + "target": "D03Z02S15[W]" + }, + { + "logic": [], + "target": "D03Z02S15[E]" + } + ], + "locations": [ + "QI103" + ], + "transitions": [] + }, + { + "name": "D03Z02S11[E]", + "exits": [ + { + "logic": [], + "target": "D03Z02S15" + } + ], + "locations": [], + "transitions": [ + "D03Z02S11[E]" + ] + }, + { + "name": "D20Z01S01[W]", + "exits": [ + { + "logic": [], + "target": "D03Z02S15" + } + ], + "locations": [], + "transitions": [ + "D20Z01S01[W]" + ] + }, + { + "name": "D03Z03S02[NE]", + "exits": [ + { + "logic": [], + "target": "D03Z03S02" + }, + { + "logic": [], + "target": "D03Z03S12[W]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S02[NE]", + "D03Z03S14[W]" + ] + }, + { + "name": "D03Z03S02[E]", + "exits": [ + { + "logic": [], + "target": "D03Z03S03[W]" + }, + { + "logic": [], + "target": "D03Z03S04[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D03Z03S04[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S03[SE]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S02[E]" + ] + }, + { + "name": "D03Z03S04[NW]", + "exits": [ + { + "logic": [], + "target": "D03Z03S03[W]" + }, + { + "logic": [], + "target": "D03Z03S04[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S05[NW]" + }, + { + "logic": [], + "target": "D03Z03S05[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D03Z03S04[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S03[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[-Cherubs]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S04[NW]", + "D03Z03S03[NE]" + ] + }, + { + "name": "D03Z03S04[SW]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D03Z03S04[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S03[SE]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S04[SW]" + ] + }, + { + "name": "D03Z03S02", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S02[NE]" + }, + { + "logic": [], + "target": "D03Z03S02[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S12[W]" + } + ], + "locations": [ + "QI44" + ], + "transitions": [] + }, + { + "name": "D03Z03S03[W]", + "exits": [ + { + "logic": [], + "target": "D03Z03S02" + } + ], + "locations": [], + "transitions": [ + "D03Z03S03[W]" + ] + }, + { + "name": "D03Z03S03[SE]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[NW]" + }, + { + "logic": [], + "target": "D03Z03S04[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S05[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S05[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[-Cherubs]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S03[SE]" + ] + }, + { + "name": "D03Z03S05[NW]", + "exits": [ + { + "logic": [], + "target": "D03Z03S04[NW]" + }, + { + "logic": [], + "target": "D03Z03S04[SW]" + }, + { + "logic": [], + "target": "D03Z03S05[NE]" + }, + { + "logic": [], + "target": "D03Z03S05[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[-Cherubs]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S05[NW]", + "D03Z03S04[NE]" + ] + }, + { + "name": "D03Z03S05[SW]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[NW]" + }, + { + "logic": [], + "target": "D03Z03S04[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S05[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S07[NE]" + }, + { + "logic": [], + "target": "D03Z03S07[E]" + }, + { + "logic": [], + "target": "D03Z03S07[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S19[E]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S05[SW]", + "D03Z03S04[E]", + "D03Z03S07[SW]", + "D03Z03S05[SE]" + ] + }, + { + "name": "D03Z03S13[W]", + "exits": [ + { + "logic": [], + "target": "D03Z03S04[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S04[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S05[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S05[SW]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S13[W]" + ] + }, + { + "name": "D03Z03S06[W]", + "exits": [ + { + "logic": [], + "target": "D03Z03S05[NW]" + }, + { + "logic": [], + "target": "D03Z03S05[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S05[SW]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S06[W]" + ] + }, + { + "name": "D03Z03S13", + "exits": [ + { + "logic": [], + "target": "D03Z03S13[W]" + } + ], + "locations": [ + "Oil[D03Z03S13]" + ], + "transitions": [] + }, + { + "name": "D03Z03S04[SE]", + "exits": [ + { + "logic": [], + "target": "D03Z03S13" + } + ], + "locations": [], + "transitions": [ + "D03Z03S04[SE]" + ] + }, + { + "name": "D03Z03S10", + "exits": [ + { + "logic": [], + "target": "D03Z03S10[E]" + } + ], + "locations": [ + "QI13" + ], + "transitions": [] + }, + { + "name": "D03Z03S04[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D03Z03S10" + } + ], + "locations": [], + "transitions": [ + "D03Z03S04[-Cherubs]" + ] + }, + { + "name": "D03Z03S09[SW]", + "exits": [ + { + "logic": [], + "target": "D03Z03S10" + } + ], + "locations": [], + "transitions": [ + "D03Z03S09[SW]" + ] + }, + { + "name": "D03Z03S06", + "exits": [ + { + "logic": [], + "target": "D03Z03S06[W]" + } + ], + "locations": [ + "CO12", + "RE07", + "RESCUED_CHERUB_19" + ], + "transitions": [] + }, + { + "name": "D03Z03S05[NE]", + "exits": [ + { + "logic": [], + "target": "D03Z03S06" + } + ], + "locations": [], + "transitions": [ + "D03Z03S05[NE]" + ] + }, + { + "name": "D03Z03S08[W]", + "exits": [ + { + "logic": [], + "target": "D03Z03S07[NE]" + }, + { + "logic": [], + "target": "D03Z03S07[E]" + }, + { + "logic": [], + "target": "D03Z03S07[S]" + }, + { + "logic": [], + "target": "D03Z03S05[SW]" + }, + { + "logic": [], + "target": "D03Z03S19[E]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S08[W]" + ] + }, + { + "name": "D03Z03S09[N]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S07[NE]" + }, + { + "logic": [], + "target": "D03Z03S07[E]" + }, + { + "logic": [], + "target": "D03Z03S07[S]" + }, + { + "logic": [], + "target": "D03Z03S05[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S19[E]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S09[N]" + ] + }, + { + "name": "D03Z03S11[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S07[NE]" + }, + { + "logic": [], + "target": "D03Z03S07[E]" + }, + { + "logic": [], + "target": "D03Z03S07[S]" + }, + { + "logic": [], + "target": "D03Z03S05[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S19[E]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S11[W]" + ] + }, + { + "name": "D03Z03S19[E]", + "exits": [ + { + "logic": [], + "target": "D03Z03S07[NE]" + }, + { + "logic": [], + "target": "D03Z03S07[E]" + }, + { + "logic": [], + "target": "D03Z03S07[S]" + }, + { + "logic": [], + "target": "D03Z03S05[SW]" + } + ], + "locations": [], + "transitions": [ + "D03Z03S19[E]", + "D03Z03S07[NW]" + ] + }, + { + "name": "D03Z03S08", + "exits": [ + { + "logic": [], + "target": "D03Z03S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S08[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S08[-CherubsR]" + } + ], + "locations": [ + "QI10", + "RESCUED_CHERUB_21" + ], + "transitions": [] + }, + { + "name": "D03Z03S07[NE]", + "exits": [ + { + "logic": [], + "target": "D03Z03S08" + } + ], + "locations": [], + "transitions": [ + "D03Z03S07[NE]" + ] + }, + { + "name": "D03Z03S11", + "exits": [ + { + "logic": [], + "target": "D03Z03S11[W]" + }, + { + "logic": [], + "target": "D03Z03S11[E]" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D03Z03S07[E]", + "exits": [ + { + "logic": [], + "target": "D03Z03S11" + } + ], + "locations": [], + "transitions": [ + "D03Z03S07[E]" + ] + }, + { + "name": "D03Z03S08[-CherubsL]", + "exits": [ + { + "logic": [], + "target": "D03Z03S11" + } + ], + "locations": [], + "transitions": [ + "D03Z03S08[-CherubsL]" + ] + }, + { + "name": "D03Z03S08[-CherubsR]", + "exits": [ + { + "logic": [], + "target": "D03Z03S11" + } + ], + "locations": [], + "transitions": [ + "D03Z03S08[-CherubsR]" + ] + }, + { + "name": "D03Z03S15[W]", + "exits": [ + { + "logic": [], + "target": "D03Z03S11" + } + ], + "locations": [], + "transitions": [ + "D03Z03S15[W]" + ] + }, + { + "name": "D03Z03S09", + "exits": [ + { + "logic": [], + "target": "D03Z03S09[SW]" + }, + { + "logic": [], + "target": "D03Z03S09[N]" + } + ], + "locations": [ + "RESCUED_CHERUB_20" + ], + "transitions": [] + }, + { + "name": "D03Z03S07[S]", + "exits": [ + { + "logic": [], + "target": "D03Z03S09" + } + ], + "locations": [], + "transitions": [ + "D03Z03S07[S]" + ] + }, + { + "name": "D03Z03S10[E]", + "exits": [ + { + "logic": [], + "target": "D03Z03S09" + } + ], + "locations": [], + "transitions": [ + "D03Z03S10[E]" + ] + }, + { + "name": "D03Z03S15", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatGrievanceBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S15[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatGrievanceBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D03Z03S15[E]" + } + ], + "locations": [ + "BS04" + ], + "transitions": [] + }, + { + "name": "D03Z03S11[E]", + "exits": [ + { + "logic": [], + "target": "D03Z03S15" + } + ], + "locations": [], + "transitions": [ + "D03Z03S11[E]" + ] + }, + { + "name": "D03Z03S16[W]", + "exits": [ + { + "logic": [], + "target": "D03Z03S15" + } + ], + "locations": [], + "transitions": [ + "D03Z03S16[W]" + ] + }, + { + "name": "D03Z03S16", + "exits": [ + { + "logic": [], + "target": "D03Z03S16[W]" + }, + { + "logic": [], + "target": "D03Z03S16[E]" + } + ], + "locations": [ + "QI39" + ], + "transitions": [] + }, + { + "name": "D03Z03S15[E]", + "exits": [ + { + "logic": [], + "target": "D03Z03S16" + } + ], + "locations": [], + "transitions": [ + "D03Z03S15[E]" + ] + }, + { + "name": "D03Z03S17[W]", + "exits": [ + { + "logic": [], + "target": "D03Z03S16" + } + ], + "locations": [], + "transitions": [ + "D03Z03S17[W]" + ] + }, + { + "name": "D04Z01S01[W]", + "exits": [ + { + "logic": [], + "target": "D08Z02S01[W]" + }, + { + "logic": [], + "target": "D08Z02S01[E]" + }, + { + "logic": [], + "target": "D08Z02S02[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z01S01[W]" + ] + }, + { + "name": "D08Z01S01[E]", + "exits": [ + { + "logic": [], + "target": "D08Z02S01[W]" + }, + { + "logic": [], + "target": "D08Z02S01[E]" + }, + { + "logic": [], + "target": "D08Z02S02[W]" + } + ], + "locations": [], + "transitions": [ + "D08Z01S01[E]" + ] + }, + { + "name": "D08Z02S02[W]", + "exits": [ + { + "logic": [], + "target": "D08Z02S01[W]" + }, + { + "logic": [], + "target": "D08Z02S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "brokeBotTCStatue" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z02S03[W]" + }, + { + "logic": [], + "target": "D08Z02S03[E]" + } + ], + "locations": [], + "transitions": [ + "D08Z02S02[W]", + "D08Z02S01[SE]", + "D08Z02S03[S]", + "D08Z02S01[N]" + ] + }, + { + "name": "D04Z01S02", + "exits": [ + { + "logic": [], + "target": "D04Z01S02[W]" + }, + { + "logic": [], + "target": "D04Z01S02[NW]" + }, + { + "logic": [], + "target": "D04Z01S02[E]" + } + ], + "locations": [ + "RB14" + ], + "transitions": [] + }, + { + "name": "D04Z01S01[E]", + "exits": [ + { + "logic": [], + "target": "D04Z01S02" + } + ], + "locations": [], + "transitions": [ + "D04Z01S01[E]" + ] + }, + { + "name": "D04Z01S01[NE]", + "exits": [ + { + "logic": [], + "target": "D04Z01S02" + } + ], + "locations": [], + "transitions": [ + "D04Z01S01[NE]" + ] + }, + { + "name": "D04Z01S03[W]", + "exits": [ + { + "logic": [], + "target": "D04Z01S02" + } + ], + "locations": [], + "transitions": [ + "D04Z01S03[W]" + ] + }, + { + "name": "D04Z01S01[N]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "blood", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S05[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S05[-Cherubs]" + }, + { + "logic": [], + "target": "D04Z01S01" + }, + { + "logic": [], + "target": "D04Z01S01[NE]" + }, + { + "logic": [], + "target": "CO23" + } + ], + "locations": [], + "transitions": [ + "D04Z01S01[N]", + "D04Z01S05[S]" + ] + }, + { + "name": "D04Z01S06[S]", + "exits": [ + { + "logic": [], + "target": "D04Z01S05[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S05[-Cherubs]" + }, + { + "logic": [], + "target": "D04Z01S01[N]" + } + ], + "locations": [], + "transitions": [ + "D04Z01S06[S]" + ] + }, + { + "name": "D04Z01S06[Cherubs]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "blood", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S05[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S05[-Cherubs]" + }, + { + "logic": [], + "target": "D04Z01S01[N]" + } + ], + "locations": [], + "transitions": [ + "D04Z01S06[Cherubs]" + ] + }, + { + "name": "D04Z01S01", + "exits": [ + { + "logic": [], + "target": "D04Z01S01[W]" + }, + { + "logic": [], + "target": "D04Z01S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S01[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S01[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO23" + } + ], + "locations": [ + "RESCUED_CHERUB_35" + ], + "transitions": [] + }, + { + "name": "D04Z01S02[W]", + "exits": [ + { + "logic": [], + "target": "D04Z01S01" + } + ], + "locations": [], + "transitions": [ + "D04Z01S02[W]" + ] + }, + { + "name": "D04Z01S02[NW]", + "exits": [ + { + "logic": [], + "target": "D04Z01S01" + }, + { + "logic": [], + "target": "D04Z01S01[NE]" + }, + { + "logic": [], + "target": "D04Z01S01[N]" + }, + { + "logic": [], + "target": "CO23" + } + ], + "locations": [], + "transitions": [ + "D04Z01S02[NW]" + ] + }, + { + "name": "D04Z01S05[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D04Z01S01" + } + ], + "locations": [], + "transitions": [ + "D04Z01S05[-Cherubs]" + ] + }, + { + "name": "D08Z02S01[E]", + "exits": [ + { + "logic": [], + "target": "D04Z01S01" + } + ], + "locations": [], + "transitions": [ + "D08Z02S01[E]" + ] + }, + { + "name": "D04Z01S03", + "exits": [ + { + "logic": [], + "target": "D04Z01S03[W]" + }, + { + "logic": [], + "target": "D04Z01S03[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "D05Z01S20[N]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S03[S]" + } + ], + "locations": [ + "QI37", + "CO39", + "RESCUED_CHERUB_28" + ], + "transitions": [] + }, + { + "name": "D04Z01S02[E]", + "exits": [ + { + "logic": [], + "target": "D04Z01S03" + } + ], + "locations": [], + "transitions": [ + "D04Z01S02[E]" + ] + }, + { + "name": "D04Z01S04[W]", + "exits": [ + { + "logic": [], + "target": "D04Z01S03" + } + ], + "locations": [], + "transitions": [ + "D04Z01S04[W]" + ] + }, + { + "name": "D05Z01S20[N]", + "exits": [ + { + "logic": [], + "target": "D04Z01S03" + } + ], + "locations": [], + "transitions": [ + "D05Z01S20[N]" + ] + }, + { + "name": "D04Z01S04", + "exits": [ + { + "logic": [], + "target": "D04Z01S04[W]" + }, + { + "logic": [], + "target": "D04Z01S04[E]" + } + ], + "locations": [ + "RB21", + "Amanecida[D04Z01S04]" + ], + "transitions": [] + }, + { + "name": "D04Z01S03[E]", + "exits": [ + { + "logic": [], + "target": "D04Z01S04" + } + ], + "locations": [], + "transitions": [ + "D04Z01S03[E]" + ] + }, + { + "name": "D04Z02S01[W]", + "exits": [ + { + "logic": [], + "target": "D04Z01S04" + } + ], + "locations": [], + "transitions": [ + "D04Z02S01[W]" + ] + }, + { + "name": "D06Z01S18[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D04Z01S04" + } + ], + "locations": [], + "transitions": [ + "D06Z01S18[-Cherubs]" + ] + }, + { + "name": "D04Z01S03[S]", + "exits": [ + { + "logic": [], + "target": "D05Z01S20[N]" + }, + { + "logic": [], + "target": "D05Z01S06[E]" + } + ], + "locations": [], + "transitions": [ + "D04Z01S03[S]" + ] + }, + { + "name": "D05Z01S06[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S20[N]" + }, + { + "logic": [], + "target": "D05Z01S07[E]" + }, + { + "logic": [], + "target": "D05Z01S08[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "canSurvivePoison3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S06[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canSurvivePoison3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB31" + } + ], + "locations": [], + "transitions": [ + "D05Z01S06[E]", + "D05Z01S20[W]", + "D05Z01S07[NW]", + "D05Z01S20[E]" + ] + }, + { + "name": "D04Z01S04[E]", + "exits": [ + { + "logic": [], + "target": "D04Z02S01[W]" + }, + { + "logic": [], + "target": "D04Z02S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_30" + } + ], + "locations": [], + "transitions": [ + "D04Z01S04[E]" + ] + }, + { + "name": "D04Z02S02[S]", + "exits": [ + { + "logic": [], + "target": "D04Z02S01[N]" + }, + { + "logic": [], + "target": "RE402" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_30" + }, + { + "logic": [], + "target": "D04Z02S01[W]" + }, + { + "logic": [], + "target": "D04Z02S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "canCrossGap1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S03[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S02[S]" + ] + }, + { + "name": "D04Z02S03[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "dash", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S01[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RE402" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canCrossGap1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_30" + }, + { + "logic": [], + "target": "D04Z02S01[W]" + }, + { + "logic": [], + "target": "D04Z02S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedMoMLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S04[N]" + }, + { + "logic": [], + "target": "D04Z02S04[SW]" + }, + { + "logic": [], + "target": "D04Z02S04[W]" + }, + { + "logic": [], + "target": "D04Z02S05[W]" + }, + { + "logic": [], + "target": "D04Z02S19[E]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S03[W]", + "D04Z02S01[NE]", + "D04Z02S04[NW]", + "D04Z02S03[E]", + "D04Z02S19[W]", + "D04Z02S04[NE]" + ] + }, + { + "name": "D04Z03S01[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S01[W]" + }, + { + "logic": [], + "target": "D04Z02S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_30" + } + ], + "locations": [], + "transitions": [ + "D04Z03S01[W]" + ] + }, + { + "name": "D04Z01S06", + "exits": [ + { + "logic": [], + "target": "D04Z01S06[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "DoubleJump", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S06[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S06[Cherubs]" + } + ], + "locations": [ + "QI102" + ], + "transitions": [] + }, + { + "name": "D04Z01S05[N]", + "exits": [ + { + "logic": [], + "target": "D04Z01S06" + } + ], + "locations": [], + "transitions": [ + "D04Z01S05[N]" + ] + }, + { + "name": "D09Z01S09[SW]", + "exits": [ + { + "logic": [], + "target": "D04Z01S06" + }, + { + "logic": [ + { + "item_requirements": [ + "DoubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z01S06[E]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S09[SW]" + ] + }, + { + "name": "D04Z01S06[E]", + "exits": [ + { + "logic": [], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell16]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [ + "D04Z01S06[E]" + ] + }, + { + "name": "D09Z01S07[SW]", + "exits": [ + { + "logic": [], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [ + "D09Z01S07[SW]", + "D09Z01S09[E]", + "D09Z01S02[SW]", + "D09Z01S07[E]", + "D09Z01S08[SE]", + "D09Z01S07[W]", + "D09Z01S10[W]", + "D09Z01S07[SE]" + ] + }, + { + "name": "D09Z01S12[E]", + "exits": [ + { + "logic": [], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [ + "D09Z01S12[E]" + ] + }, + { + "name": "D09BZ01S01[Cell19]", + "exits": [ + { + "logic": [], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D09BZ01S01[Cell24]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S12[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell19]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S12[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell19]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D04Z02S02", + "exits": [ + { + "logic": [], + "target": "D04Z02S02[S]" + }, + { + "logic": [], + "target": "D04Z02S02[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogicAndDoubleJump", + "doubleJump", + "upwarpSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogicAndDoubleJump", + "doubleJump", + "canEnemyUpslash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogicAndDoubleJump", + "canEnemyUpslash", + "upwarpSkipsAllowed", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "EnemySkips", + "doubleJump", + "upwarpSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "EnemySkips", + "doubleJump", + "canEnemyUpslash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "EnemySkips", + "canEnemyUpslash", + "upwarpSkipsAllowed", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S02[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S02[S]" + } + ], + "locations": [ + "CO17" + ], + "transitions": [] + }, + { + "name": "D04Z02S01[N]", + "exits": [ + { + "logic": [], + "target": "D04Z02S02" + } + ], + "locations": [], + "transitions": [ + "D04Z02S01[N]" + ] + }, + { + "name": "D04Z02S15[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S02" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogicAndDoubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "EnemySkips" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S02[NE]" + }, + { + "logic": [], + "target": "D06Z01S02[S]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S15[W]" + ] + }, + { + "name": "D04Z02S17[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S02" + } + ], + "locations": [], + "transitions": [ + "D04Z02S17[W]" + ] + }, + { + "name": "D06Z01S02[S]", + "exits": [ + { + "logic": [], + "target": "D04Z02S02" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogicAndDoubleJump", + "canEnemyUpslash", + "upwarpSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "EnemySkips", + "canEnemyUpslash", + "upwarpSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S02[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S18[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "EnemySkipsAndDoubleJump", + "wallClimb", + "doubleJump", + "canEnemyBounce", + "preciseSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S08[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[SW]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S02[S]", + "D04Z02S02[N]", + "D06Z01S18[E]", + "D06Z01S02[W]", + "D06Z01S08[W]", + "D06Z01S02[E]" + ] + }, + { + "name": "D04Z03S01", + "exits": [ + { + "logic": [], + "target": "D04Z03S01[W]" + }, + { + "logic": [], + "target": "D04Z03S01[E]" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D04Z02S01[E]", + "exits": [ + { + "logic": [], + "target": "D04Z03S01" + } + ], + "locations": [], + "transitions": [ + "D04Z02S01[E]" + ] + }, + { + "name": "D04Z02S04[W]", + "exits": [ + { + "logic": [], + "target": "D04Z03S01" + } + ], + "locations": [], + "transitions": [ + "D04Z02S04[W]" + ] + }, + { + "name": "D04Z02S02[SE]", + "exits": [ + { + "logic": [], + "target": "D04Z02S17[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S02[SE]" + ] + }, + { + "name": "D04Z02S15", + "exits": [ + { + "logic": [], + "target": "D04Z02S15[W]" + }, + { + "logic": [], + "target": "D04Z02S15[E]" + } + ], + "locations": [ + "QI60" + ], + "transitions": [] + }, + { + "name": "D04Z02S02[NE]", + "exits": [ + { + "logic": [], + "target": "D04Z02S15" + } + ], + "locations": [], + "transitions": [ + "D04Z02S02[NE]" + ] + }, + { + "name": "D04Z02S22[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S15" + } + ], + "locations": [], + "transitions": [ + "D04Z02S22[W]" + ] + }, + { + "name": "D04Z02S05[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S04[SW]" + }, + { + "logic": [], + "target": "D04Z02S04[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "openedMoMLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S04[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S03[W]" + }, + { + "logic": [], + "target": "D04Z02S05[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "D05Z01S15[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S02[W]" + }, + { + "logic": [], + "target": "D05Z01S03[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S05[W]", + "D04Z02S04[E]", + "D05Z01S01[NW]", + "D04Z02S04[SE]", + "D05Z01S02[E]", + "D05Z01S01[W]", + "D05Z01S16[W]", + "D05Z01S01[E]", + "D05Z01S03[E]", + "D05Z01S02[NW]" + ] + }, + { + "name": "D04Z02S06[S]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedMoMLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S04[N]" + }, + { + "logic": [], + "target": "D04Z02S03[W]" + }, + { + "logic": [], + "target": "D04Z02S04[SW]" + }, + { + "logic": [], + "target": "D04Z02S04[W]" + }, + { + "logic": [], + "target": "D04Z02S05[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S06[S]" + ] + }, + { + "name": "D04Z02S06[-Cherubs]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedMoMLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S04[N]" + }, + { + "logic": [], + "target": "D04Z02S03[W]" + }, + { + "logic": [], + "target": "D04Z02S04[SW]" + }, + { + "logic": [], + "target": "D04Z02S04[W]" + }, + { + "logic": [], + "target": "D04Z02S05[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S06[-Cherubs]" + ] + }, + { + "name": "D04Z02S14[E]", + "exits": [ + { + "logic": [], + "target": "D04Z02S04[SW]" + }, + { + "logic": [], + "target": "D04Z02S04[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "openedMoMLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S04[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S03[W]" + }, + { + "logic": [], + "target": "D04Z02S05[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S14[E]" + ] + }, + { + "name": "D04Z03S01[E]", + "exits": [ + { + "logic": [], + "target": "D04Z02S04[SW]" + }, + { + "logic": [], + "target": "D04Z02S04[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "openedMoMLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S04[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S03[W]" + }, + { + "logic": [], + "target": "D04Z02S05[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z03S01[E]" + ] + }, + { + "name": "D04Z02S14", + "exits": [ + { + "logic": [], + "target": "D04Z02S14[E]" + } + ], + "locations": [ + "Oil[D04Z02S14]" + ], + "transitions": [] + }, + { + "name": "D04Z02S04[SW]", + "exits": [ + { + "logic": [], + "target": "D04Z02S14" + } + ], + "locations": [], + "transitions": [ + "D04Z02S04[SW]" + ] + }, + { + "name": "D04Z02S07[SW]", + "exits": [ + { + "logic": [], + "target": "D04Z02S05[W]" + }, + { + "logic": [], + "target": "D04Z02S05[E]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S07[SW]" + ] + }, + { + "name": "D04Z02S07[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S19[E]" + }, + { + "logic": [], + "target": "D04Z02S03[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S07[W]" + ] + }, + { + "name": "D04Z02S04[N]", + "exits": [ + { + "logic": [], + "target": "D04Z02S06[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "openedARLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO34" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S09[W]" + }, + { + "logic": [], + "target": "D04Z02S10[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S04[N]" + ] + }, + { + "name": "D04Z02S09[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S06[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedARLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[N]" + }, + { + "logic": [], + "target": "CO34" + }, + { + "logic": [], + "target": "D04Z02S06[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S09[NE]" + }, + { + "logic": [], + "target": "D04Z02S10[W]" + }, + { + "logic": [], + "target": "D04Z02S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "redentoRooms5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S20[Redento]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S09[W]", + "D04Z02S06[NE]", + "D04Z02S08[W]", + "D04Z02S09[E]", + "D04Z02S20[W]", + "D04Z02S08[E]" + ] + }, + { + "name": "D04Z02S10[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S06[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "openedARLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO34" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S09[W]" + } + ], + "locations": [ + "QI01", + "PR11" + ], + "transitions": [ + "D04Z02S10[W]", + "D04Z02S06[E]" + ] + }, + { + "name": "D04Z02S11[E]", + "exits": [ + { + "logic": [], + "target": "D04Z02S06[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedARLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[N]" + }, + { + "logic": [], + "target": "CO34" + }, + { + "logic": [], + "target": "D04Z02S06[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[-Cherubs]" + }, + { + "logic": [], + "target": "D04Z02S09[W]" + }, + { + "logic": [], + "target": "D04Z02S10[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S11[E]" + ] + }, + { + "name": "D06Z01S23[S]", + "exits": [ + { + "logic": [], + "target": "D04Z02S06[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedARLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[N]" + }, + { + "logic": [], + "target": "CO34" + }, + { + "logic": [], + "target": "D04Z02S06[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S06[-Cherubs]" + }, + { + "logic": [], + "target": "D04Z02S09[W]" + }, + { + "logic": [], + "target": "D04Z02S10[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S23[S]" + ] + }, + { + "name": "D04Z02S07", + "exits": [ + { + "logic": [], + "target": "D04Z02S07[SW]" + }, + { + "logic": [], + "target": "D04Z02S07[W]" + }, + { + "logic": [], + "target": "D04Z02S07[N]" + }, + { + "logic": [], + "target": "D04Z02S07[NE]" + }, + { + "logic": [], + "target": "D04Z02S07[SE]" + } + ], + "locations": [ + "CO35", + "RB33" + ], + "transitions": [] + }, + { + "name": "D04Z02S05[E]", + "exits": [ + { + "logic": [], + "target": "D04Z02S07" + } + ], + "locations": [], + "transitions": [ + "D04Z02S05[E]" + ] + }, + { + "name": "D04Z02S08[S]", + "exits": [ + { + "logic": [], + "target": "D04Z02S07" + } + ], + "locations": [], + "transitions": [ + "D04Z02S08[S]" + ] + }, + { + "name": "D04Z02S13[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S07" + } + ], + "locations": [], + "transitions": [ + "D04Z02S13[W]" + ] + }, + { + "name": "D04Z02S19[E]", + "exits": [ + { + "logic": [], + "target": "D04Z02S07" + } + ], + "locations": [], + "transitions": [ + "D04Z02S19[E]" + ] + }, + { + "name": "D04Z02S23[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S07" + } + ], + "locations": [], + "transitions": [ + "D04Z02S23[W]" + ] + }, + { + "name": "D04Z02S11", + "exits": [ + { + "logic": [], + "target": "D04Z02S11[W]" + }, + { + "logic": [], + "target": "D04Z02S11[E]" + } + ], + "locations": [ + "CO20", + "RESCUED_CHERUB_29" + ], + "transitions": [] + }, + { + "name": "D04Z02S06[NW]", + "exits": [ + { + "logic": [], + "target": "D04Z02S11" + } + ], + "locations": [], + "transitions": [ + "D04Z02S06[NW]" + ] + }, + { + "name": "D04Z02S21[SE]", + "exits": [ + { + "logic": [], + "target": "D04Z02S11" + } + ], + "locations": [], + "transitions": [ + "D04Z02S21[SE]" + ] + }, + { + "name": "D04Z02S06[N]", + "exits": [ + { + "logic": [], + "target": "D06Z01S23[Sword]" + }, + { + "logic": [], + "target": "D06Z01S23[S]" + }, + { + "logic": [], + "target": "D06Z01S20[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S06[N]" + ] + }, + { + "name": "D06Z01S01[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D06Z01S23[Sword]" + }, + { + "logic": [], + "target": "D06Z01S23[S]" + }, + { + "logic": [], + "target": "D06Z01S20[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S01[-Cherubs]" + ] + }, + { + "name": "D06Z01S20[W]", + "exits": [ + { + "logic": [], + "target": "D06Z01S23[Sword]" + }, + { + "logic": [], + "target": "D06Z01S23[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S24[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canSurvivePoison2", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canSurvivePoison2", + "blood", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canSurvivePoison2", + "dash", + "preciseSkipsAllowed", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce", + "preciseSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S04[Health]" + }, + { + "logic": [], + "target": "D06Z01S03" + } + ], + "locations": [], + "transitions": [ + "D06Z01S20[W]", + "D06Z01S23[E]", + "D06Z01S20[E]", + "D06Z01S04[SW]", + "D06Z01S04[W]", + "D06Z01S03[E]" + ] + }, + { + "name": "D06Z01S22[Sword]", + "exits": [ + { + "logic": [], + "target": "D06Z01S23[Sword]" + }, + { + "logic": [], + "target": "D06Z01S23[S]" + }, + { + "logic": [], + "target": "D06Z01S20[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S22[Sword]" + ] + }, + { + "name": "D04Z02S16[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S09[NE]" + }, + { + "logic": [], + "target": "D04Z02S09[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S16[W]" + ] + }, + { + "name": "D04Z02S07[N]", + "exits": [ + { + "logic": [], + "target": "D04Z02S08[S]" + }, + { + "logic": [], + "target": "D04Z02S09[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S07[N]" + ] + }, + { + "name": "D04Z02S16[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D04Z02S08[S]" + }, + { + "logic": [], + "target": "D04Z02S09[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S16[-Cherubs]" + ] + }, + { + "name": "D04Z02S07[NE]", + "exits": [ + { + "logic": [], + "target": "D04Z02S13[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S07[NE]" + ] + }, + { + "name": "D04Z02S07[SE]", + "exits": [ + { + "logic": [], + "target": "D04Z02S23[W]" + }, + { + "logic": [], + "target": "D04Z02S23[NE]" + }, + { + "logic": [], + "target": "D04Z02S24[NW]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S07[SE]" + ] + }, + { + "name": "D04Z02S24[NW]", + "exits": [ + { + "logic": [], + "target": "D04Z02S23[W]" + }, + { + "logic": [], + "target": "D04Z02S23[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z02S03[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z02S05[E]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S24[NW]", + "D04Z02S23[SE]", + "D20Z02S01[E]", + "D04Z02S24[SW]", + "D04Z02S25[W]", + "D04Z02S24[SE]", + "D20Z02S03[SE]", + "D20Z02S01[W]", + "D20Z02S04[E]", + "D20Z02S03[W]" + ] + }, + { + "name": "D04Z04S01[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S23[W]" + }, + { + "logic": [], + "target": "D04Z02S23[NE]" + }, + { + "logic": [], + "target": "D04Z02S24[NW]" + } + ], + "locations": [], + "transitions": [ + "D04Z04S01[W]" + ] + }, + { + "name": "D04BZ02S01[Redento]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "redentoRooms5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S20[Redento]" + }, + { + "logic": [], + "target": "D04Z02S09[W]" + } + ], + "locations": [], + "transitions": [ + "D04BZ02S01[Redento]" + ] + }, + { + "name": "D04Z02S16", + "exits": [ + { + "logic": [], + "target": "D04Z02S16[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S16[-Cherubs]" + } + ], + "locations": [ + "HE01" + ], + "transitions": [] + }, + { + "name": "D04Z02S09[NE]", + "exits": [ + { + "logic": [], + "target": "D04Z02S16" + } + ], + "locations": [], + "transitions": [ + "D04Z02S09[NE]" + ] + }, + { + "name": "D04Z02S11[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S21[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S21[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S22[E]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S11[W]" + ] + }, + { + "name": "D04Z02S12[W]", + "exits": [ + { + "logic": [], + "target": "D04Z02S21[NE]" + }, + { + "logic": [], + "target": "D04Z02S22[E]" + }, + { + "logic": [], + "target": "D04Z02S21[SE]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S12[W]" + ] + }, + { + "name": "D04Z02S22[E]", + "exits": [ + { + "logic": [], + "target": "D04Z02S22" + }, + { + "logic": [], + "target": "D04Z02S21[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S21[NE]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S22[E]", + "D04Z02S21[W]" + ] + }, + { + "name": "D04Z02S22", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatMothersBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S22[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatMothersBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S22[E]" + } + ], + "locations": [ + "BS05" + ], + "transitions": [] + }, + { + "name": "D04Z02S15[E]", + "exits": [ + { + "logic": [], + "target": "D04Z02S22" + }, + { + "logic": [], + "target": "D04Z02S22[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z02S15[E]" + ] + }, + { + "name": "D04BZ02S01", + "exits": [ + { + "logic": [], + "target": "D04BZ02S01[Redento]" + } + ], + "locations": [ + "RE03", + "QI54" + ], + "transitions": [] + }, + { + "name": "D04Z02S20[Redento]", + "exits": [ + { + "logic": [], + "target": "D04BZ02S01" + } + ], + "locations": [], + "transitions": [ + "D04Z02S20[Redento]" + ] + }, + { + "name": "D04Z02S12", + "exits": [ + { + "logic": [], + "target": "D04Z02S12[W]" + } + ], + "locations": [ + "Sword[D04Z02S12]" + ], + "transitions": [] + }, + { + "name": "D04Z02S21[NE]", + "exits": [ + { + "logic": [], + "target": "D04Z02S12" + } + ], + "locations": [], + "transitions": [ + "D04Z02S21[NE]" + ] + }, + { + "name": "D04Z04S01", + "exits": [ + { + "logic": [], + "target": "D04Z04S01[W]" + }, + { + "logic": [], + "target": "D04Z04S01[E]" + } + ], + "locations": [ + "PR201" + ], + "transitions": [] + }, + { + "name": "D04Z02S23[NE]", + "exits": [ + { + "logic": [], + "target": "D04Z04S01" + } + ], + "locations": [], + "transitions": [ + "D04Z02S23[NE]" + ] + }, + { + "name": "D04Z04S02[W]", + "exits": [ + { + "logic": [], + "target": "D04Z04S01" + } + ], + "locations": [], + "transitions": [ + "D04Z04S02[W]" + ] + }, + { + "name": "D04Z03S02[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S22[FrontalN]" + }, + { + "logic": [], + "target": "D05Z01S22[E]" + } + ], + "locations": [], + "transitions": [ + "D04Z03S02[W]" + ] + }, + { + "name": "D05BZ01S01[FrontalN]", + "exits": [ + { + "logic": [], + "target": "D05Z01S22[FrontalN]" + }, + { + "logic": [], + "target": "D05Z01S22[E]" + } + ], + "locations": [], + "transitions": [ + "D05BZ01S01[FrontalN]" + ] + }, + { + "name": "D04Z04S01[E]", + "exits": [ + { + "logic": [], + "target": "D04Z04S02[W]" + } + ], + "locations": [], + "transitions": [ + "D04Z04S01[E]" + ] + }, + { + "name": "D05Z01S15[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "redWax1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB18" + }, + { + "logic": [ + { + "item_requirements": [ + "D05Z01S15[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S02[W]" + }, + { + "logic": [], + "target": "D04Z02S05[W]" + } + ], + "locations": [ + "RB19" + ], + "transitions": [ + "D05Z01S15[E]" + ] + }, + { + "name": "D05Z01S15", + "exits": [ + { + "logic": [], + "target": "D05Z01S15[W]" + }, + { + "logic": [], + "target": "D05Z01S15[E]" + } + ], + "locations": [ + "QI62" + ], + "transitions": [] + }, + { + "name": "D05Z01S02[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S15" + } + ], + "locations": [], + "transitions": [ + "D05Z01S02[W]" + ] + }, + { + "name": "D05Z01S21[NE]", + "exits": [ + { + "logic": [], + "target": "D05Z01S15" + } + ], + "locations": [], + "transitions": [ + "D05Z01S21[NE]" + ] + }, + { + "name": "D05Z01S04[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S03[W]" + }, + { + "logic": [], + "target": "D04Z02S05[W]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S04[E]" + ] + }, + { + "name": "D05BZ01S01[FrontalS]", + "exits": [ + { + "logic": [], + "target": "D05Z01S03[W]" + }, + { + "logic": [], + "target": "D04Z02S05[W]" + } + ], + "locations": [], + "transitions": [ + "D05BZ01S01[FrontalS]" + ] + }, + { + "name": "D05Z01S04", + "exits": [ + { + "logic": [], + "target": "D05Z01S04[W]" + }, + { + "logic": [], + "target": "D05Z01S04[E]" + } + ], + "locations": [ + "CO18", + "RESCUED_CHERUB_01" + ], + "transitions": [] + }, + { + "name": "D05Z01S03[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S04" + } + ], + "locations": [], + "transitions": [ + "D05Z01S03[W]" + ] + }, + { + "name": "D05Z01S05[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S04" + } + ], + "locations": [], + "transitions": [ + "D05Z01S05[E]" + ] + }, + { + "name": "D05BZ01S01", + "exits": [ + { + "logic": [], + "target": "D05BZ01S01[FrontalS]" + }, + { + "logic": [], + "target": "D05BZ01S01[FrontalN]" + } + ], + "locations": [ + "RB301" + ], + "transitions": [] + }, + { + "name": "D05Z01S03[Frontal]", + "exits": [ + { + "logic": [], + "target": "D05BZ01S01" + } + ], + "locations": [], + "transitions": [ + "D05Z01S03[Frontal]" + ] + }, + { + "name": "D05Z01S22[FrontalN]", + "exits": [ + { + "logic": [], + "target": "D05BZ01S01" + } + ], + "locations": [], + "transitions": [ + "D05Z01S22[FrontalN]" + ] + }, + { + "name": "D05Z01S05", + "exits": [ + { + "logic": [], + "target": "D05Z01S05[SW]" + }, + { + "logic": [], + "target": "D05Z01S05[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canClimbOnRoot", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO22" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S17[W]" + } + ], + "locations": [ + "QI50" + ], + "transitions": [] + }, + { + "name": "D05Z01S04[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S05" + } + ], + "locations": [], + "transitions": [ + "D05Z01S04[W]" + ] + }, + { + "name": "D05Z01S07[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S05" + } + ], + "locations": [], + "transitions": [ + "D05Z01S07[E]" + ] + }, + { + "name": "D05Z01S17[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S05" + }, + { + "logic": [ + { + "item_requirements": [ + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO22" + } + ], + "locations": [], + "transitions": [ + "D05Z01S17[W]", + "D05Z01S05[NE]" + ] + }, + { + "name": "D05Z01S05[SW]", + "exits": [ + { + "logic": [], + "target": "D05Z01S07[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap7" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S06[E]" + }, + { + "logic": [], + "target": "D05Z01S08[NE]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S05[SW]" + ] + }, + { + "name": "D05Z01S08[NE]", + "exits": [ + { + "logic": [], + "target": "D05Z01S07[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap7" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S06[E]" + }, + { + "logic": [], + "target": "D05Z01S08[W]" + }, + { + "logic": [], + "target": "D05Z01S08[Health]" + }, + { + "logic": [], + "target": "D05Z01S09[E]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S08[NE]", + "D05Z01S07[SW]", + "D05Z01S12[E]", + "D05Z01S08[NW]", + "D05Z01S09[W]", + "D05Z01S08[E]" + ] + }, + { + "name": "D05Z01S06[W]", + "exits": [ + { + "logic": [], + "target": "RB31" + }, + { + "logic": [ + { + "item_requirements": [ + "canSurvivePoison3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S06[E]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S06[W]", + "D05Z01S24[E]" + ] + }, + { + "name": "D05Z01S10[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S08[W]" + }, + { + "logic": [], + "target": "D05Z01S08[Health]" + }, + { + "logic": [], + "target": "D05Z01S08[NE]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S10[E]" + ] + }, + { + "name": "D05Z01S14[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S08[W]" + }, + { + "logic": [], + "target": "D05Z01S08[Health]" + }, + { + "logic": [], + "target": "D05Z01S08[NE]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S14[W]" + ] + }, + { + "name": "D05Z01S10", + "exits": [ + { + "logic": [], + "target": "D05Z01S10[W]" + }, + { + "logic": [], + "target": "D05Z01S10[NW]" + }, + { + "logic": [], + "target": "D05Z01S10[E]" + } + ], + "locations": [ + "PR07" + ], + "transitions": [] + }, + { + "name": "D05Z01S08[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S10" + } + ], + "locations": [], + "transitions": [ + "D05Z01S08[W]" + ] + }, + { + "name": "D05Z01S11[NE]", + "exits": [ + { + "logic": [], + "target": "D05Z01S10" + } + ], + "locations": [], + "transitions": [ + "D05Z01S11[NE]" + ] + }, + { + "name": "D05Z01S11[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S10" + } + ], + "locations": [], + "transitions": [ + "D05Z01S11[E]" + ] + }, + { + "name": "D05Z01S18[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S09[E]" + }, + { + "logic": [], + "target": "D05Z01S08[NE]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S18[W]" + ] + }, + { + "name": "D05Z01S14", + "exits": [ + { + "logic": [], + "target": "D05Z01S14[W]" + } + ], + "locations": [ + "Lady[D05Z01S14]" + ], + "transitions": [] + }, + { + "name": "D05Z01S08[Health]", + "exits": [ + { + "logic": [], + "target": "D05Z01S14" + } + ], + "locations": [], + "transitions": [ + "D05Z01S08[Health]" + ] + }, + { + "name": "D05Z01S18", + "exits": [ + { + "logic": [], + "target": "D05Z01S18[W]" + } + ], + "locations": [ + "PR15" + ], + "transitions": [] + }, + { + "name": "D05Z01S09[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S18" + } + ], + "locations": [], + "transitions": [ + "D05Z01S09[E]" + ] + }, + { + "name": "D05Z01S11", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "tirana", + "obscureSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S11[SW]" + }, + { + "logic": [], + "target": "D05Z01S11[SE]" + }, + { + "logic": [], + "target": "D05Z01S11[E]" + } + ], + "locations": [ + "RB30", + "RESCUED_CHERUB_02" + ], + "transitions": [] + }, + { + "name": "D05Z01S10[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S11" + } + ], + "locations": [], + "transitions": [ + "D05Z01S10[W]" + ] + }, + { + "name": "D05Z01S10[NW]", + "exits": [ + { + "logic": [], + "target": "D05Z01S11" + }, + { + "logic": [], + "target": "D05Z01S11[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "D05Z01S11[NW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB203" + }, + { + "logic": [], + "target": "CO28" + }, + { + "logic": [], + "target": "D05Z01S23[E]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S10[NW]" + ] + }, + { + "name": "D05Z01S19[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S11" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S11[SW]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S19[E]" + ] + }, + { + "name": "D05Z01S23[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S11" + }, + { + "logic": [], + "target": "D05Z01S11[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "D05Z01S11[NW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB203" + }, + { + "logic": [], + "target": "CO28" + }, + { + "logic": [ + { + "item_requirements": [ + "woodKey", + "D05Z01S23[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "woodKey", + "D05Z01S10[NW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S03[Frontal]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S23[E]", + "D05Z01S11[NW]" + ] + }, + { + "name": "D05Z02S01[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S11" + } + ], + "locations": [], + "transitions": [ + "D05Z02S01[W]" + ] + }, + { + "name": "D05Z01S19", + "exits": [ + { + "logic": [], + "target": "D05Z01S19[W]" + }, + { + "logic": [], + "target": "D05Z01S19[E]" + } + ], + "locations": [ + "Oil[D05Z01S19]" + ], + "transitions": [] + }, + { + "name": "D05Z01S11[SW]", + "exits": [ + { + "logic": [], + "target": "D05Z01S19" + } + ], + "locations": [], + "transitions": [ + "D05Z01S11[SW]" + ] + }, + { + "name": "D05Z02S15[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S19" + } + ], + "locations": [], + "transitions": [ + "D05Z02S15[E]" + ] + }, + { + "name": "D05Z01S11[SE]", + "exits": [ + { + "logic": [], + "target": "D05Z02S01[W]" + }, + { + "logic": [], + "target": "D05Z02S01[E]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S11[SE]" + ] + }, + { + "name": "D05Z02S02[NW]", + "exits": [ + { + "logic": [], + "target": "D05Z02S01[W]" + }, + { + "logic": [], + "target": "D05Z02S01[E]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S02[NW]" + ] + }, + { + "name": "D05Z01S21", + "exits": [ + { + "logic": [], + "target": "D05Z01S21[SW]" + }, + { + "logic": [], + "target": "D05Z01S21[NW]" + }, + { + "logic": [], + "target": "D05Z01S21[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z01S21[-Cherubs]" + } + ], + "locations": [ + "RESCUED_CHERUB_32" + ], + "transitions": [] + }, + { + "name": "D05Z01S13[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S21" + } + ], + "locations": [], + "transitions": [ + "D05Z01S13[E]" + ] + }, + { + "name": "D05Z01S15[W]", + "exits": [ + { + "logic": [], + "target": "D05Z01S21" + } + ], + "locations": [], + "transitions": [ + "D05Z01S15[W]" + ] + }, + { + "name": "D05Z02S14[E]", + "exits": [ + { + "logic": [], + "target": "D05Z01S21" + } + ], + "locations": [], + "transitions": [ + "D05Z02S14[E]" + ] + }, + { + "name": "D05Z02S15", + "exits": [ + { + "logic": [], + "target": "D05Z02S15[S]" + }, + { + "logic": [], + "target": "D05Z02S15[E]" + } + ], + "locations": [ + "QI104" + ], + "transitions": [] + }, + { + "name": "D05Z01S19[W]", + "exits": [ + { + "logic": [], + "target": "D05Z02S15" + } + ], + "locations": [], + "transitions": [ + "D05Z01S19[W]" + ] + }, + { + "name": "D05Z02S12[N]", + "exits": [ + { + "logic": [], + "target": "D05Z02S15" + } + ], + "locations": [], + "transitions": [ + "D05Z02S12[N]" + ] + }, + { + "name": "D05Z02S14", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatCanvasesBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z02S14[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatCanvasesBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z02S06[NE]" + } + ], + "locations": [ + "BS06" + ], + "transitions": [] + }, + { + "name": "D05Z01S21[SW]", + "exits": [ + { + "logic": [], + "target": "D05Z02S14" + }, + { + "logic": [], + "target": "D05Z02S14[E]" + } + ], + "locations": [], + "transitions": [ + "D05Z01S21[SW]" + ] + }, + { + "name": "D05Z02S06[NE]", + "exits": [ + { + "logic": [], + "target": "D05Z02S14" + }, + { + "logic": [ + { + "item_requirements": [ + "openedTSCGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z02S06[SE]" + }, + { + "logic": [], + "target": "D05Z02S05[W]" + }, + { + "logic": [], + "target": "D05Z02S07[W]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S06[NE]", + "D05Z02S14[W]", + "D05Z02S06[SW]", + "D05Z02S05[E]", + "D05Z02S07[E]", + "D05Z02S06[NW]" + ] + }, + { + "name": "D05Z01S13", + "exits": [ + { + "logic": [], + "target": "D05Z01S13[E]" + } + ], + "locations": [ + "Sword[D05Z01S13]" + ], + "transitions": [] + }, + { + "name": "D05Z01S21[NW]", + "exits": [ + { + "logic": [], + "target": "D05Z01S13" + } + ], + "locations": [], + "transitions": [ + "D05Z01S21[NW]" + ] + }, + { + "name": "D05Z02S11", + "exits": [ + { + "logic": [], + "target": "D05Z02S11[W]" + } + ], + "locations": [ + "CO31" + ], + "transitions": [] + }, + { + "name": "D05Z01S21[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D05Z02S11" + } + ], + "locations": [], + "transitions": [ + "D05Z01S21[-Cherubs]" + ] + }, + { + "name": "D05Z02S06[SE]", + "exits": [ + { + "logic": [], + "target": "D05Z02S11" + } + ], + "locations": [], + "transitions": [ + "D05Z02S06[SE]" + ] + }, + { + "name": "D04Z03S02", + "exits": [ + { + "logic": [], + "target": "D04Z03S02[W]" + } + ], + "locations": [ + "HE201" + ], + "transitions": [] + }, + { + "name": "D05Z01S22[E]", + "exits": [ + { + "logic": [], + "target": "D04Z03S02" + } + ], + "locations": [], + "transitions": [ + "D05Z01S22[E]" + ] + }, + { + "name": "D05Z02S02", + "exits": [ + { + "logic": [], + "target": "D05Z02S02[SW]" + }, + { + "logic": [], + "target": "D05Z02S02[NW]" + }, + { + "logic": [], + "target": "D05Z02S02[SE]" + }, + { + "logic": [], + "target": "D05Z02S02[NE]" + } + ], + "locations": [ + "QI64" + ], + "transitions": [] + }, + { + "name": "D05Z02S01[E]", + "exits": [ + { + "logic": [], + "target": "D05Z02S02" + } + ], + "locations": [], + "transitions": [ + "D05Z02S01[E]" + ] + }, + { + "name": "D05Z02S03[E]", + "exits": [ + { + "logic": [], + "target": "D05Z02S02" + } + ], + "locations": [], + "transitions": [ + "D05Z02S03[E]" + ] + }, + { + "name": "D05Z02S05[W]", + "exits": [ + { + "logic": [], + "target": "D05Z02S02" + } + ], + "locations": [], + "transitions": [ + "D05Z02S05[W]" + ] + }, + { + "name": "D05Z02S09[W]", + "exits": [ + { + "logic": [], + "target": "D05Z02S02" + } + ], + "locations": [], + "transitions": [ + "D05Z02S09[W]" + ] + }, + { + "name": "D05Z02S02[SW]", + "exits": [ + { + "logic": [], + "target": "D05Z02S03[E]" + }, + { + "logic": [], + "target": "D05Z02S04[W]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S02[SW]" + ] + }, + { + "name": "D05Z02S02[SE]", + "exits": [ + { + "logic": [], + "target": "D05Z02S09[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "redWax3", + "blueWax3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z02S09[E]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S02[SE]" + ] + }, + { + "name": "D05Z02S08[W]", + "exits": [ + { + "logic": [], + "target": "D05Z02S09[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "redWax3", + "blueWax3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z02S09[E]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S08[W]" + ] + }, + { + "name": "D05Z02S02[NE]", + "exits": [ + { + "logic": [], + "target": "D05Z02S05[W]" + }, + { + "logic": [], + "target": "D05Z02S06[NE]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S02[NE]" + ] + }, + { + "name": "D05BZ02S01[C]", + "exits": [ + { + "logic": [], + "target": "D05Z02S04[W]" + }, + { + "logic": [], + "target": "D05Z02S04[C]" + } + ], + "locations": [], + "transitions": [ + "D05BZ02S01[C]" + ] + }, + { + "name": "D05BZ02S01", + "exits": [ + { + "logic": [], + "target": "D05BZ02S01[C]" + } + ], + "locations": [ + "RB12", + "QI49", + "QI71" + ], + "transitions": [] + }, + { + "name": "D05Z02S04[C]", + "exits": [ + { + "logic": [], + "target": "D05BZ02S01" + } + ], + "locations": [], + "transitions": [ + "D05Z02S04[C]" + ] + }, + { + "name": "D05Z02S11[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedTSCGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z02S06[SE]" + }, + { + "logic": [], + "target": "D05Z02S06[NE]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S11[W]" + ] + }, + { + "name": "D05Z02S10[E]", + "exits": [ + { + "logic": [], + "target": "D05Z02S07[W]" + }, + { + "logic": [], + "target": "D05Z02S06[NE]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S10[E]" + ] + }, + { + "name": "D05Z02S10", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z02S10[W]" + }, + { + "logic": [], + "target": "D05Z02S10[E]" + } + ], + "locations": [ + "RE05", + "PR05" + ], + "transitions": [] + }, + { + "name": "D05Z02S07[W]", + "exits": [ + { + "logic": [], + "target": "D05Z02S10" + } + ], + "locations": [], + "transitions": [ + "D05Z02S07[W]" + ] + }, + { + "name": "D05Z02S13[E]", + "exits": [ + { + "logic": [], + "target": "D05Z02S10" + } + ], + "locations": [], + "transitions": [ + "D05Z02S13[E]" + ] + }, + { + "name": "D05Z02S08", + "exits": [ + { + "logic": [], + "target": "D05Z02S08[W]" + } + ], + "locations": [ + "HE07" + ], + "transitions": [] + }, + { + "name": "D05Z02S09[E]", + "exits": [ + { + "logic": [], + "target": "D05Z02S08" + } + ], + "locations": [], + "transitions": [ + "D05Z02S09[E]" + ] + }, + { + "name": "D05Z02S10[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D05Z02S13[E]" + } + ], + "locations": [], + "transitions": [ + "D05Z02S10[W]" + ] + }, + { + "name": "D06Z01S01[SW]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "masks1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NNW]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NNE]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[-Cherubs]" + }, + { + "logic": [], + "target": "D06Z01S03" + }, + { + "logic": [ + { + "item_requirements": [ + "EnemySkipsAndDoubleJump", + "wallClimb", + "doubleJump", + "canEnemyBounce", + "preciseSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S08[N]" + }, + { + "logic": [], + "target": "D06Z01S02[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO06" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "taranto" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_36" + } + ], + "locations": [], + "transitions": [ + "D06Z01S01[SW]", + "D06Z01S14[E]", + "D06Z01S01[SE]", + "D06Z01S03[W]", + "D06Z01S08[E]", + "D06Z01S14[W]", + "D06Z01S12[S]", + "D06Z01S14[N]" + ] + }, + { + "name": "D06Z01S03", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatLegionary" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatLegionary" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S20[W]" + } + ], + "locations": [ + "QI02" + ], + "transitions": [] + }, + { + "name": "D06Z01S01[W]", + "exits": [ + { + "logic": [], + "target": "D06Z01S01[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NNW]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NNE]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatLegionary" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI03" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S04[NW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canBeatLegionary" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S04[NW]" + }, + { + "logic": [], + "target": "CO06" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_36" + }, + { + "logic": [], + "target": "D06Z01S13[W]" + }, + { + "logic": [], + "target": "D06Z01S13[S]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S01[W]", + "D06Z01S07[E]", + "D06Z01S01[E]", + "D06Z01S06[WW]", + "D06Z01S12[E]", + "D06Z01S07[W]", + "D06Z01S13[E]", + "D06Z01S12[W]" + ] + }, + { + "name": "D06Z01S16[-CherubsL]", + "exits": [ + { + "logic": [], + "target": "D06Z01S01[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S16[-CherubsL]" + ] + }, + { + "name": "D06Z01S16[-CherubsR]", + "exits": [ + { + "logic": [], + "target": "D06Z01S01[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S16[-CherubsR]" + ] + }, + { + "name": "D06Z01S04[NW]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatLegionary" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI03" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S06[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S20[E]", + "wallClimb", + "canSurvivePoison2", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S20[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S20[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S03[E]", + "wallClimb", + "canSurvivePoison2", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S03[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S03[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "wallClimb", + "canSurvivePoison2", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "canSurvivePoison2", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "canSurvivePoison2", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S04[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S01[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canBeatLegionary" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S04[NW]", + "D06Z01S06[E]" + ] + }, + { + "name": "D06Z01S04[NE]", + "exits": [ + { + "logic": [], + "target": "D06Z01S06[EE]" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S06[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S17[-Cherubs]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S20[E]", + "wallClimb", + "canSurvivePoison2", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S20[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S20[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S03[E]", + "wallClimb", + "canSurvivePoison2", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S03[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S03[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "wallClimb", + "canSurvivePoison2", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "canSurvivePoison2", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "canSurvivePoison2", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S04[NW]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S04[NE]", + "D06Z01S06[W]" + ] + }, + { + "name": "D06Z01S15[SW]", + "exits": [ + { + "logic": [], + "target": "D06Z01S06[EE]" + }, + { + "logic": [], + "target": "D06Z01S04[NE]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S15[SW]" + ] + }, + { + "name": "D06Z01S01[NW]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canCrossGap7" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S16[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S16[-CherubsR]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks2", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NNW]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks2", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NNE]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks3", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canWalkOnRoot", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap7", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap7", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S12[NE2]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S01[NW]", + "D06Z01S16[E]" + ] + }, + { + "name": "D06Z01S09[-CherubsL]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S16[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S16[-CherubsR]" + }, + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S12[NE2]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S09[-CherubsL]" + ] + }, + { + "name": "D06Z01S09[-CherubsR]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "linen", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canAirStall", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canAirStall", + "wheel" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S16[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S16[-CherubsR]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canAirStall", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canAirStall", + "wheel" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canAirStall", + "canWalkOnRoot", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canAirStall", + "canWalkOnRoot", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canAirStall", + "wheel", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canAirStall", + "wheel", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S12[NE2]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S09[-CherubsR]" + ] + }, + { + "name": "D06Z01S12[NE2]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S16[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canCrossGap1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S16[-CherubsR]" + }, + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S05[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S09[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S12[NE]" + }, + { + "logic": [], + "target": "CO06" + }, + { + "logic": [], + "target": "PR12" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_36" + }, + { + "logic": [], + "target": "D06Z01S01[W]" + }, + { + "logic": [], + "target": "D06Z01S01[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S05[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S09[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S05[E]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S12[NE2]", + "D06Z01S16[W]" + ] + }, + { + "name": "D06Z01S01[NE]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks2", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NNW]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks2", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NNE]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks3", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S17[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S26[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S01[NE]", + "D06Z01S17[W]" + ] + }, + { + "name": "D06Z01S10[-CherubsL]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S17[-Cherubs]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S26[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S10[-CherubsL]" + ] + }, + { + "name": "D06Z01S10[-CherubsR]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S17[-Cherubs]" + }, + { + "logic": [], + "target": "D06Z01S26[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S10[-CherubsR]" + ] + }, + { + "name": "D06Z01S26[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S17[-Cherubs]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S26[W]", + "D06Z01S17[E]" + ] + }, + { + "name": "D06Z01S09", + "exits": [ + { + "logic": [], + "target": "D06Z01S09[W]" + }, + { + "logic": [], + "target": "D06Z01S09[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S09[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S09[-CherubsR]" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D06Z01S01[NNW]", + "exits": [ + { + "logic": [], + "target": "D06Z01S09" + } + ], + "locations": [], + "transitions": [ + "D06Z01S01[NNW]" + ] + }, + { + "name": "D06Z01S12[NE]", + "exits": [ + { + "logic": [], + "target": "D06Z01S09" + } + ], + "locations": [], + "transitions": [ + "D06Z01S12[NE]" + ] + }, + { + "name": "D06Z01S01[NNE]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S10[-CherubsL]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S10[-CherubsR]" + }, + { + "logic": [], + "target": "D06Z01S01[SW]" + }, + { + "logic": [], + "target": "D06Z01S01[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NE]" + }, + { + "logic": [], + "target": "D06Z01S01[NNW]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[-Cherubs]" + }, + { + "logic": [], + "target": "D06Z01S21" + } + ], + "locations": [], + "transitions": [ + "D06Z01S01[NNE]", + "D06Z01S10[W]", + "D06Z01S21[W]", + "D06Z01S10[E]" + ] + }, + { + "name": "D06Z01S01[N]", + "exits": [ + { + "logic": [], + "target": "D06Z01S19[S]" + }, + { + "logic": [], + "target": "D06Z01S25[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S01[N]" + ] + }, + { + "name": "D06Z01S25[W]", + "exits": [ + { + "logic": [], + "target": "D06Z01S19[S]" + }, + { + "logic": [], + "target": "D06Z01S25" + } + ], + "locations": [], + "transitions": [ + "D06Z01S25[W]", + "D06Z01S19[E]" + ] + }, + { + "name": "D06Z01S13[S]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "EnemySkipsAndDoubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S08[N]" + }, + { + "logic": [], + "target": "D06Z01S01[SW]" + }, + { + "logic": [], + "target": "D06Z01S02[S]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S13[S]" + ] + }, + { + "name": "D06Z01S09[E]", + "exits": [ + { + "logic": [], + "target": "D06Z01S01[SW]" + }, + { + "logic": [], + "target": "D06Z01S01[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NE]" + }, + { + "logic": [], + "target": "D06Z01S01[NNW]" + }, + { + "logic": [], + "target": "D06Z01S01[NNE]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[-Cherubs]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S09[E]" + ] + }, + { + "name": "D06Z01S19[S]", + "exits": [ + { + "logic": [], + "target": "D06Z01S01[SW]" + }, + { + "logic": [], + "target": "D06Z01S01[W]" + }, + { + "logic": [], + "target": "D06Z01S01[NNW]" + }, + { + "logic": [], + "target": "D06Z01S01[NNE]" + }, + { + "logic": [ + { + "item_requirements": [ + "masks3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[N]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S19[S]" + ] + }, + { + "name": "D06Z01S17[-Cherubs]", + "exits": [ + { + "logic": [], + "target": "D06Z01S04[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S06[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S20[E]", + "wallClimb", + "canSurvivePoison2", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S20[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S20[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S03[E]", + "wallClimb", + "canSurvivePoison2", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S03[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S03[E]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "wallClimb", + "canSurvivePoison2", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "wallClimb", + "canSurvivePoison2", + "doubleJump", + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "canSurvivePoison2", + "canCrossGap9" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S24[W]", + "canSurvivePoison2", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S04[NE]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S17[-Cherubs]" + ] + }, + { + "name": "D06Z01S24[W]", + "exits": [ + { + "logic": [], + "target": "D06Z01S04[Health]" + }, + { + "logic": [], + "target": "D06Z01S20[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S24[W]" + ] + }, + { + "name": "D06Z01S24", + "exits": [ + { + "logic": [], + "target": "D06Z01S24[W]" + } + ], + "locations": [ + "Lady[D06Z01S24]" + ], + "transitions": [] + }, + { + "name": "D06Z01S04[Health]", + "exits": [ + { + "logic": [], + "target": "D06Z01S24" + } + ], + "locations": [], + "transitions": [ + "D06Z01S04[Health]" + ] + }, + { + "name": "D06Z01S05[E]", + "exits": [ + { + "logic": [], + "target": "D06Z01S12[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S16[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S12[NE2]" + }, + { + "logic": [], + "target": "CO06" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "PR12" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_36" + }, + { + "logic": [], + "target": "D06Z01S01[W]" + }, + { + "logic": [], + "target": "D06Z01S01[SW]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S05[E]", + "D06Z01S12[NW]" + ] + }, + { + "name": "D06Z01S09[W]", + "exits": [ + { + "logic": [], + "target": "D06Z01S12[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S16[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S12[NE2]" + }, + { + "logic": [], + "target": "CO06" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "PR12" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_36" + }, + { + "logic": [], + "target": "D06Z01S01[W]" + }, + { + "logic": [], + "target": "D06Z01S01[SW]" + }, + { + "logic": [], + "target": "D06Z01S05[E]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S09[W]" + ] + }, + { + "name": "D06Z01S06[EE]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D06Z01S06[EE]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S15[SW]" + } + ], + "locations": [ + "CO40" + ], + "transitions": [ + "D06Z01S06[EE]" + ] + }, + { + "name": "D06Z01S11[W]", + "exits": [ + { + "logic": [], + "target": "D06Z01S15[NE]" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S21[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S06[EE]", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S06[EE]", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S06[EE]", + "doubleJump", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S21[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S06[EE]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S15[SW]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S11[W]" + ] + }, + { + "name": "D06Z01S21[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D06Z01S11[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S06[EE]", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S06[EE]", + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D06Z01S06[EE]", + "doubleJump", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S15[NE]" + }, + { + "logic": [], + "target": "D06Z01S21" + }, + { + "logic": [ + { + "item_requirements": [ + "D06Z01S06[EE]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S15[SW]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S21[E]", + "D06Z01S15[NW]" + ] + }, + { + "name": "D06Z01S08[N]", + "exits": [ + { + "logic": [], + "target": "D06Z01S13[W]" + }, + { + "logic": [], + "target": "D06Z01S13[S]" + }, + { + "logic": [], + "target": "D06Z01S01[W]" + } + ], + "locations": [], + "transitions": [ + "D06Z01S08[N]" + ] + }, + { + "name": "D09Z01S01[E]", + "exits": [ + { + "logic": [], + "target": "D06Z01S13[W]" + }, + { + "logic": [], + "target": "D06Z01S13[S]" + }, + { + "logic": [], + "target": "D06Z01S01[W]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S01[E]" + ] + }, + { + "name": "D06Z01S21", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatLegionary" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S21[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatLegionary" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S01[NNE]" + } + ], + "locations": [ + "QI04" + ], + "transitions": [] + }, + { + "name": "D09Z01S01", + "exits": [ + { + "logic": [], + "target": "D09Z01S01[W]" + }, + { + "logic": [], + "target": "D09Z01S01[E]" + } + ], + "locations": [ + "Amanecida[D09Z01S01]" + ], + "transitions": [] + }, + { + "name": "D06Z01S13[W]", + "exits": [ + { + "logic": [], + "target": "D09Z01S01" + } + ], + "locations": [], + "transitions": [ + "D06Z01S13[W]" + ] + }, + { + "name": "D09Z01S11[E]", + "exits": [ + { + "logic": [], + "target": "D09Z01S01" + } + ], + "locations": [], + "transitions": [ + "D09Z01S11[E]" + ] + }, + { + "name": "D06Z01S11", + "exits": [ + { + "logic": [], + "target": "D06Z01S11[W]" + } + ], + "locations": [ + "Sword[D06Z01S11]" + ], + "transitions": [] + }, + { + "name": "D06Z01S15[NE]", + "exits": [ + { + "logic": [], + "target": "D06Z01S11" + } + ], + "locations": [], + "transitions": [ + "D06Z01S15[NE]" + ] + }, + { + "name": "D06Z01S25", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatRooftopsBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S25[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatRooftopsBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D06Z01S25[E]" + } + ], + "locations": [ + "BS16" + ], + "transitions": [] + }, + { + "name": "D07Z01S01[W]", + "exits": [ + { + "logic": [], + "target": "D06Z01S25" + }, + { + "logic": [], + "target": "D06Z01S25[E]" + } + ], + "locations": [], + "transitions": [ + "D07Z01S01[W]" + ] + }, + { + "name": "D06Z01S22", + "exits": [ + { + "logic": [], + "target": "D06Z01S22[Sword]" + } + ], + "locations": [ + "HE04" + ], + "transitions": [] + }, + { + "name": "D06Z01S23[Sword]", + "exits": [ + { + "logic": [], + "target": "D06Z01S22" + } + ], + "locations": [], + "transitions": [ + "D06Z01S23[Sword]" + ] + }, + { + "name": "D07Z01S01", + "exits": [ + { + "logic": [], + "target": "D07Z01S01[W]" + }, + { + "logic": [], + "target": "D07Z01S01[E]" + } + ], + "locations": [ + "PR08" + ], + "transitions": [] + }, + { + "name": "D06Z01S25[E]", + "exits": [ + { + "logic": [], + "target": "D07Z01S01" + } + ], + "locations": [], + "transitions": [ + "D06Z01S25[E]" + ] + }, + { + "name": "D07Z01S02[W]", + "exits": [ + { + "logic": [], + "target": "D07Z01S01" + } + ], + "locations": [], + "transitions": [ + "D07Z01S02[W]" + ] + }, + { + "name": "D07Z01S01[E]", + "exits": [ + { + "logic": [], + "target": "D07Z01S02[W]" + }, + { + "logic": [], + "target": "D07Z01S03[W]" + } + ], + "locations": [], + "transitions": [ + "D07Z01S01[E]" + ] + }, + { + "name": "D07Z01S03[W]", + "exits": [ + { + "logic": [], + "target": "D07Z01S02[W]" + } + ], + "locations": [], + "transitions": [ + "D07Z01S03[W]", + "D07Z01S02[E]" + ] + }, + { + "name": "D08Z03S03", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatHallBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z03S03[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatHallBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z03S02[NW]" + } + ], + "locations": [ + "LaudesBossTrigger[30000]" + ], + "transitions": [] + }, + { + "name": "D08Z01S02[NE]", + "exits": [ + { + "logic": [], + "target": "D08Z03S03" + }, + { + "logic": [], + "target": "D08Z03S03[W]" + } + ], + "locations": [], + "transitions": [ + "D08Z01S02[NE]" + ] + }, + { + "name": "D08Z03S02[NW]", + "exits": [ + { + "logic": [], + "target": "D08Z03S03" + }, + { + "logic": [], + "target": "D08Z03S02[SW]" + } + ], + "locations": [], + "transitions": [ + "D08Z03S02[NW]", + "D08Z03S03[E]" + ] + }, + { + "name": "D08Z01S02[SE]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "brokeBotTCStatue" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z02S03[W]" + }, + { + "logic": [], + "target": "D08Z02S03[E]" + }, + { + "logic": [], + "target": "D08Z02S02[W]" + } + ], + "locations": [], + "transitions": [ + "D08Z01S02[SE]" + ] + }, + { + "name": "D08Z03S01[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "brokeBotTCStatue" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z02S03[W]" + }, + { + "logic": [], + "target": "D08Z02S03[E]" + }, + { + "logic": [], + "target": "D08Z02S02[W]" + } + ], + "locations": [], + "transitions": [ + "D08Z03S01[W]" + ] + }, + { + "name": "D08Z01S02", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D08Z03S03[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z01S02[NE]" + }, + { + "logic": [], + "target": "D08Z01S02[SE]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z01S02[-Cherubs]" + } + ], + "locations": [ + "HE101" + ], + "transitions": [] + }, + { + "name": "D08Z02S03[W]", + "exits": [ + { + "logic": [], + "target": "D08Z01S02" + } + ], + "locations": [], + "transitions": [ + "D08Z02S03[W]" + ] + }, + { + "name": "D08Z03S03[W]", + "exits": [ + { + "logic": [], + "target": "D08Z01S02" + } + ], + "locations": [], + "transitions": [ + "D08Z03S03[W]" + ] + }, + { + "name": "D08Z03S01", + "exits": [ + { + "logic": [], + "target": "D08Z03S01[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "verses4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z03S01[E]" + } + ], + "locations": [ + "QI105" + ], + "transitions": [] + }, + { + "name": "D08Z02S03[E]", + "exits": [ + { + "logic": [], + "target": "D08Z03S01" + } + ], + "locations": [], + "transitions": [ + "D08Z02S03[E]" + ] + }, + { + "name": "D08Z03S02[SW]", + "exits": [ + { + "logic": [], + "target": "D08Z03S01" + } + ], + "locations": [], + "transitions": [ + "D08Z03S02[SW]" + ] + }, + { + "name": "D08Z03S01[E]", + "exits": [ + { + "logic": [], + "target": "D08Z03S02[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D08Z03S02[NW]" + } + ], + "locations": [], + "transitions": [ + "D08Z03S01[E]" + ] + }, + { + "name": "D09Z01S01[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S04[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S11[W]" + }, + { + "logic": [], + "target": "D09Z01S11[E]" + }, + { + "logic": [], + "target": "D09Z01S02[N]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S01[W]" + ] + }, + { + "name": "D09Z01S02[N]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S04[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S11[W]" + }, + { + "logic": [], + "target": "D09Z01S11[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "goldKey", + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S02[N]", + "D09Z01S11[S]", + "D09Z01S02[NW]", + "D09Z01S07[NE]" + ] + }, + { + "name": "D09Z01S04[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S04[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S11[W]" + }, + { + "logic": [], + "target": "D09Z01S11[E]" + }, + { + "logic": [], + "target": "D09Z01S02[N]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S04[E]" + ] + }, + { + "name": "D09Z01S04[S]", + "exits": [ + { + "logic": [], + "target": "D09Z01S04[W]" + }, + { + "logic": [], + "target": "D09Z01S04[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [ + "D09Z01S04[S]", + "D09Z01S07[N]", + "D09Z01S08[NE]", + "D09Z01S07[NW]" + ] + }, + { + "name": "D09Z01S02[Cell1]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [ + "RESCUED_CHERUB_03" + ], + "transitions": [] + }, + { + "name": "D09Z01S02[Cell6]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [ + "CO24" + ], + "transitions": [] + }, + { + "name": "D09Z01S02[Cell22]", + "exits": [ + { + "logic": [], + "target": "QI69" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "bronzeKey", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + } + ], + "locations": [ + "CO10" + ], + "transitions": [] + }, + { + "name": "D09Z01S08[Cell7]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D09Z01S08[Cell16]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [ + "CO26" + ], + "transitions": [] + }, + { + "name": "D09Z01S08[Cell18]", + "exits": [ + { + "logic": [], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D09Z01S09[Cell24]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D09Z01S09[Cell21]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [ + "CO02" + ], + "transitions": [] + }, + { + "name": "D09Z01S10[Cell10]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [ + "CO37" + ], + "transitions": [] + }, + { + "name": "D09Z01S10[Cell11]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [ + "RESCUED_CHERUB_04" + ], + "transitions": [] + }, + { + "name": "D09Z01S03[W]", + "exits": [ + { + "logic": [], + "target": "D09Z01S05[SE]" + }, + { + "logic": [], + "target": "D09Z01S05[NE]" + }, + { + "logic": [], + "target": "D09Z01S13[E]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S03[W]" + ] + }, + { + "name": "D09Z01S08[W]", + "exits": [ + { + "logic": [], + "target": "D09Z01S05[SE]" + }, + { + "logic": [], + "target": "D09Z01S05[NE]" + }, + { + "logic": [], + "target": "D09Z01S13[E]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S08[W]" + ] + }, + { + "name": "D09Z01S13[E]", + "exits": [ + { + "logic": [], + "target": "D09Z01S05[SE]" + }, + { + "logic": [], + "target": "D09Z01S05[NE]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S13[E]", + "D09Z01S05[W]" + ] + }, + { + "name": "D09Z01S03", + "exits": [], + "locations": [ + "BS14" + ], + "transitions": [] + }, + { + "name": "D09Z01S05[SE]", + "exits": [ + { + "logic": [], + "target": "D09Z01S03" + } + ], + "locations": [], + "transitions": [ + "D09Z01S05[SE]" + ] + }, + { + "name": "D09Z01S08[S]", + "exits": [ + { + "logic": [], + "target": "D09Z01S03" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatPrisonBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S03[W]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S08[S]" + ] + }, + { + "name": "D09Z01S05[NE]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [ + "D09Z01S05[NE]" + ] + }, + { + "name": "D09BZ01S01[Cell17]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "goldKey", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell21]", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell21]", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "silverKey", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell17]", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "silverKey", + "dash", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D09Z01S06[E]", + "exits": [ + { + "logic": [], + "target": "D09Z01S04[W]" + }, + { + "logic": [], + "target": "D09Z01S04[E]" + }, + { + "logic": [], + "target": "D09Z01S04[S]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S06[E]" + ] + }, + { + "name": "D09Z01S11[W]", + "exits": [ + { + "logic": [], + "target": "D09Z01S04[W]" + }, + { + "logic": [], + "target": "D09Z01S04[E]" + }, + { + "logic": [], + "target": "D09Z01S04[S]" + } + ], + "locations": [], + "transitions": [ + "D09Z01S11[W]" + ] + }, + { + "name": "D09BZ01S01[Cell13]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell7]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell16]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell18]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell1]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell6]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell22]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell1]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell6]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell22]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell1]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell1]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell6]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell6]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell22]", + "goldKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell22]", + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell5]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell1]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell6]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell13]", + "D09Z01S02[Cell22]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [ + "QI70" + ], + "transitions": [] + }, + { + "name": "D09BZ01S01[Cell5]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell24]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "goldKey", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell21]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S07[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S09[Cell24]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB16" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "NormalLogicAndDoubleJump", + "dash", + "doubleJump", + "canDawnJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S09[Cell21]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell19]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "goldKey", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell7]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell7]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "D09BZ01S01[Cell17]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell17]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "goldKey", + "D09Z01S08[Cell16]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "goldKey", + "D09Z01S08[Cell18]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell16]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[Cell18]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_34" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "silverKey", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell16]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S08[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell18]", + "openedWotHPGate" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI72" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S08[Cell7]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S04[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell10]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell10]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell11]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S10[Cell11]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO27" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell10]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "D09Z01S10[Cell11]", + "D09BZ01S01[Cell13]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "bronzeKey", + "D09Z01S10[Cell10]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "bronzeKey", + "D09Z01S10[Cell11]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09BZ01S01[Cell13]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell1]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "silverKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell6]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D09Z01S02[Cell22]" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB11" + }, + { + "logic": [ + { + "item_requirements": [ + "D09BZ01S01[Cell5]", + "bronzeKey" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "QI69" + } + ], + "locations": [ + "QI51" + ], + "transitions": [] + }, + { + "name": "D09Z01S12", + "exits": [ + { + "logic": [], + "target": "D09Z01S12[E]" + } + ], + "locations": [ + "Oil[D09Z01S12]" + ], + "transitions": [] + }, + { + "name": "D09Z01S09[NW]", + "exits": [ + { + "logic": [], + "target": "D09Z01S12" + } + ], + "locations": [], + "transitions": [ + "D09Z01S09[NW]" + ] + }, + { + "name": "D17Z01S01[E]", + "exits": [ + { + "logic": [], + "target": "D17Z01S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S05[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S10[S]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S01[E]" + ] + }, + { + "name": "D17Z01S05[W]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S02[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedBotSSLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S05[S]" + }, + { + "logic": [], + "target": "D17Z01S11" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S10[S]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S05[W]", + "D17Z01S02[E]", + "D17Z01S11[W]", + "D17Z01S05[E]" + ] + }, + { + "name": "D17Z01S10[S]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S02[W]" + }, + { + "logic": [], + "target": "D17Z01S05[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S13[E]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S10[S]", + "D17Z01S02[N]" + ] + }, + { + "name": "D17Z01S01", + "exits": [ + { + "logic": [], + "target": "D17Z01S01[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "taranto" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot", + "debla" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot", + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot", + "tirana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot", + "ruby" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap9", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap9", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap9", + "debla" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap9", + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap9", + "tirana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap9", + "ruby" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RESCUED_CHERUB_06" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D17Z01S02[W]", + "exits": [ + { + "logic": [], + "target": "D17Z01S01" + } + ], + "locations": [], + "transitions": [ + "D17Z01S02[W]" + ] + }, + { + "name": "D17Z01S14[-Cherubs1]", + "exits": [ + { + "logic": [], + "target": "D17Z01S01" + }, + { + "logic": [], + "target": "RESCUED_CHERUB_06" + } + ], + "locations": [], + "transitions": [ + "D17Z01S14[-Cherubs1]" + ] + }, + { + "name": "D17Z01S14[-Cherubs2]", + "exits": [ + { + "logic": [], + "target": "D17Z01S01" + } + ], + "locations": [], + "transitions": [ + "D17Z01S14[-Cherubs2]" + ] + }, + { + "name": "D17Z01S14[-Cherubs3]", + "exits": [ + { + "logic": [], + "target": "D17Z01S01" + } + ], + "locations": [ + "RB204" + ], + "transitions": [ + "D17Z01S14[-Cherubs3]" + ] + }, + { + "name": "D17Z01S04[N]", + "exits": [ + { + "logic": [], + "target": "D17Z01S05[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "openedBotSSLadder" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S05[S]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S04[N]" + ] + }, + { + "name": "D17Z01S13[E]", + "exits": [ + { + "logic": [], + "target": "D17Z01S10[S]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canCrossGap8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S14[-Cherubs2]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S14[-Cherubs3]" + }, + { + "logic": [ + { + "item_requirements": [ + "scapular", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S14[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "canCrossGap11" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S14[-Cherubs1]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "PR203" + } + ], + "locations": [], + "transitions": [ + "D17Z01S13[E]", + "D17Z01S10[W]", + "D17Z01S14[E]", + "D17Z01S13[W]" + ] + }, + { + "name": "D17Z01S11", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "canBeatBrotherhoodBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S11[E]" + }, + { + "logic": [ + { + "item_requirements": [ + "canBeatBrotherhoodBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S05[W]" + } + ], + "locations": [ + "BS13" + ], + "transitions": [] + }, + { + "name": "D17BZ01S01", + "exits": [ + { + "logic": [], + "target": "D17BZ01S01[relic]" + } + ], + "locations": [ + "RE01" + ], + "transitions": [] + }, + { + "name": "D17Z01S03[relic]", + "exits": [ + { + "logic": [], + "target": "D17BZ01S01" + } + ], + "locations": [], + "transitions": [ + "D17Z01S03[relic]" + ] + }, + { + "name": "D17Z01S04[W]", + "exits": [ + { + "logic": [], + "target": "D17Z01S12[E]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S04[W]" + ] + }, + { + "name": "D17Z01S04[FrontL]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "D17Z01S04[FrontL]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17BZ02S01[FrontL]" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "CO25" + }, + { + "logic": [ + { + "item_requirements": [ + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S04[FrontR]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S04[FrontL]" + ] + }, + { + "name": "D17Z01S04[FrontR]", + "exits": [ + { + "logic": [], + "target": "CO25" + }, + { + "logic": [], + "target": "D17Z01S04" + }, + { + "logic": [], + "target": "D17Z01S04[N]" + }, + { + "logic": [ + { + "item_requirements": [ + "blueWax1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB25" + }, + { + "logic": [ + { + "item_requirements": [ + "blueWax1", + "D01Z04S13[SE]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blueWax1", + "D05Z02S12[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB26" + }, + { + "logic": [ + { + "item_requirements": [ + "D17Z01S04[FrontL]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17BZ02S01[FrontL]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S04[FrontR]", + "D17BZ02S01[FrontR]" + ] + }, + { + "name": "D17Z01S04", + "exits": [ + { + "logic": [], + "target": "D17Z01S04[W]" + }, + { + "logic": [], + "target": "D17Z01S04[S]" + }, + { + "logic": [], + "target": "D17Z01S04[FrontL]" + } + ], + "locations": [ + "RE401" + ], + "transitions": [] + }, + { + "name": "D17Z01S05[S]", + "exits": [ + { + "logic": [], + "target": "D17Z01S04" + }, + { + "logic": [], + "target": "D17Z01S04[N]" + }, + { + "logic": [], + "target": "D17Z01S04[FrontR]" + }, + { + "logic": [ + { + "item_requirements": [ + "blueWax1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB25" + }, + { + "logic": [ + { + "item_requirements": [ + "blueWax1", + "D01Z04S13[SE]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blueWax1", + "D05Z02S12[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "RB26" + } + ], + "locations": [], + "transitions": [ + "D17Z01S05[S]" + ] + }, + { + "name": "D17Z01S07[N]", + "exits": [ + { + "logic": [], + "target": "D17Z01S04" + } + ], + "locations": [], + "transitions": [ + "D17Z01S07[N]" + ] + }, + { + "name": "D17Z01S12[E]", + "exits": [ + { + "logic": [], + "target": "D17Z01S04" + } + ], + "locations": [], + "transitions": [ + "D17Z01S12[E]" + ] + }, + { + "name": "D17BZ02S01[FrontL]", + "exits": [ + { + "logic": [], + "target": "D17Z01S04" + } + ], + "locations": [], + "transitions": [ + "D17BZ02S01[FrontL]" + ] + }, + { + "name": "D17Z01S08", + "exits": [ + { + "logic": [], + "target": "D17Z01S08[E]" + } + ], + "locations": [ + "Sword[D17Z01S08]" + ], + "transitions": [] + }, + { + "name": "D17Z01S07[SW]", + "exits": [ + { + "logic": [], + "target": "D17Z01S08" + } + ], + "locations": [], + "transitions": [ + "D17Z01S07[SW]" + ] + }, + { + "name": "D17Z01S15[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "scapular" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S14[W]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S14[-Cherubs1]" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "linen", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S14[-Cherubs2]" + }, + { + "logic": [], + "target": "PR203" + }, + { + "logic": [ + { + "item_requirements": [ + "linen", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S14[-Cherubs3]" + }, + { + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D17Z01S13[E]" + } + ], + "locations": [], + "transitions": [ + "D17Z01S15[E]" + ] + }, + { + "name": "D17Z01S15", + "exits": [ + { + "logic": [], + "target": "D17Z01S15[E]" + } + ], + "locations": [ + "QI204", + "QI301" + ], + "transitions": [] + }, + { + "name": "D17Z01S14[W]", + "exits": [ + { + "logic": [], + "target": "D17Z01S15" + } + ], + "locations": [], + "transitions": [ + "D17Z01S14[W]" + ] + }, + { + "name": "D20Z01S02", + "exits": [ + { + "logic": [], + "target": "D20Z01S02[W]" + }, + { + "logic": [], + "target": "D20Z01S02[E]" + } + ], + "locations": [ + "RB108" + ], + "transitions": [] + }, + { + "name": "D20Z01S01[E]", + "exits": [ + { + "logic": [], + "target": "D20Z01S02" + } + ], + "locations": [], + "transitions": [ + "D20Z01S01[E]" + ] + }, + { + "name": "D20Z01S03[W]", + "exits": [ + { + "logic": [], + "target": "D20Z01S02" + } + ], + "locations": [], + "transitions": [ + "D20Z01S03[W]" + ] + }, + { + "name": "D20Z02S11[NW]", + "exits": [ + { + "logic": [], + "target": "D20Z01S13[E]" + }, + { + "logic": [], + "target": "D20Z01S11[W]" + } + ], + "locations": [], + "transitions": [ + "D20Z02S11[NW]" + ] + }, + { + "name": "D20Z02S11[SW]", + "exits": [ + { + "logic": [], + "target": "D20Z02S12[E]" + }, + { + "logic": [], + "target": "D20Z01S11[W]" + } + ], + "locations": [], + "transitions": [ + "D20Z02S11[SW]" + ] + }, + { + "name": "D20Z02S11", + "exits": [ + { + "logic": [], + "target": "D20Z02S11[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "mourningSkipAllowed", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogic", + "mourningSkipAllowed", + "tirana", + "obscureSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z02S11[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "mourningSkipAllowed", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "HardLogic", + "mourningSkipAllowed", + "tirana", + "obscureSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z02S11[E]" + } + ], + "locations": [ + "PR202" + ], + "transitions": [] + }, + { + "name": "D20Z01S13[E]", + "exits": [ + { + "logic": [], + "target": "D20Z02S11" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z02S11[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "mourningSkipAllowed", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z02S11[E]" + } + ], + "locations": [], + "transitions": [ + "D20Z01S13[E]" + ] + }, + { + "name": "D20Z02S10[W]", + "exits": [ + { + "logic": [], + "target": "D20Z02S11" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic", + "mourningSkipAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z02S11[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "HardLogic" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z02S11[E]" + } + ], + "locations": [], + "transitions": [ + "D20Z02S10[W]" + ] + }, + { + "name": "D20Z02S12[E]", + "exits": [ + { + "logic": [], + "target": "D20Z02S11" + } + ], + "locations": [], + "transitions": [ + "D20Z02S12[E]" + ] + }, + { + "name": "D20Z03S01[W]", + "exits": [ + { + "logic": [], + "target": "D20Z01S14[E]" + }, + { + "logic": [], + "target": "D20Z01S11[W]" + } + ], + "locations": [], + "transitions": [ + "D20Z03S01[W]" + ] + }, + { + "name": "D20Z03S01", + "exits": [ + { + "logic": [], + "target": "D20Z03S01[W]" + } + ], + "locations": [ + "QI203" + ], + "transitions": [] + }, + { + "name": "D20Z01S14[E]", + "exits": [ + { + "logic": [], + "target": "D20Z03S01" + } + ], + "locations": [], + "transitions": [ + "D20Z01S14[E]" + ] + }, + { + "name": "D20Z02S02[W]", + "exits": [ + { + "logic": [], + "target": "D20Z02S03[NE]" + }, + { + "logic": [], + "target": "D04Z02S24[NW]" + } + ], + "locations": [], + "transitions": [ + "D20Z02S02[W]" + ] + }, + { + "name": "D20Z02S05[E]", + "exits": [ + { + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D04Z02S24[NW]" + }, + { + "logic": [ + { + "item_requirements": [ + "nail" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z02S06[NE]" + }, + { + "logic": [], + "target": "D20Z02S06[SW]" + } + ], + "locations": [], + "transitions": [ + "D20Z02S05[E]", + "D20Z02S04[W]", + "D20Z02S06[SE]", + "D20Z02S05[SW]" + ] + }, + { + "name": "D20Z02S02", + "exits": [ + { + "logic": [], + "target": "D20Z02S02[W]" + } + ], + "locations": [ + "RB201" + ], + "transitions": [] + }, + { + "name": "D20Z02S03[NE]", + "exits": [ + { + "logic": [], + "target": "D20Z02S02" + } + ], + "locations": [], + "transitions": [ + "D20Z02S03[NE]" + ] + }, + { + "name": "D20Z02S06[NE]", + "exits": [ + { + "logic": [], + "target": "D20Z02S05[E]" + }, + { + "logic": [], + "target": "D20Z02S06[SW]" + }, + { + "logic": [], + "target": "D20Z02S07[W]" + } + ], + "locations": [], + "transitions": [ + "D20Z02S06[NE]", + "D20Z02S05[NW]", + "D20Z02S07[E]", + "D20Z02S06[NW]" + ] + }, + { + "name": "D20Z02S09[E]", + "exits": [ + { + "logic": [], + "target": "D20Z02S06[SW]" + }, + { + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ], + "target": "D20Z02S06[NE]" + }, + { + "logic": [], + "target": "D20Z02S05[E]" + } + ], + "locations": [], + "transitions": [ + "D20Z02S09[E]" + ] + }, + { + "name": "D20Z02S09", + "exits": [ + { + "logic": [], + "target": "D20Z02S09[W]" + }, + { + "logic": [], + "target": "D20Z02S09[E]" + } + ], + "locations": [], + "transitions": [] + }, + { + "name": "D20Z02S06[SW]", + "exits": [ + { + "logic": [], + "target": "D20Z02S09" + } + ], + "locations": [], + "transitions": [ + "D20Z02S06[SW]" + ] + }, + { + "name": "D20Z02S10[E]", + "exits": [ + { + "logic": [], + "target": "D20Z02S09" + } + ], + "locations": [], + "transitions": [ + "D20Z02S10[E]" + ] + }, + { + "name": "D20Z02S08[E]", + "exits": [ + { + "logic": [], + "target": "D20Z02S07[W]" + }, + { + "logic": [], + "target": "D20Z02S06[NE]" + } + ], + "locations": [], + "transitions": [ + "D20Z02S08[E]" + ] + }, + { + "name": "D20Z02S08", + "exits": [ + { + "logic": [], + "target": "D20Z02S08[E]" + } + ], + "locations": [ + "BossTrigger[5000]", + "QI202" + ], + "transitions": [] + }, + { + "name": "D20Z02S07[W]", + "exits": [ + { + "logic": [], + "target": "D20Z02S08" + } + ], + "locations": [], + "transitions": [ + "D20Z02S07[W]" + ] + }, + { + "name": "D20Z02S09[W]", + "exits": [ + { + "logic": [], + "target": "D20Z02S10[W]" + }, + { + "logic": [], + "target": "D20Z02S10[E]" + } + ], + "locations": [], + "transitions": [ + "D20Z02S09[W]" + ] + }, + { + "name": "D20Z02S11[E]", + "exits": [ + { + "logic": [], + "target": "D20Z02S10[W]" + }, + { + "logic": [], + "target": "D20Z02S10[E]" + } + ], + "locations": [], + "transitions": [ + "D20Z02S11[E]" + ] + }, + { + "name": "RESCUED_CHERUB_08", + "exits": [], + "locations": [ + "RESCUED_CHERUB_08" + ], + "transitions": [] + }, + { + "name": "CO21", + "exits": [], + "locations": [ + "CO21" + ], + "transitions": [] + }, + { + "name": "PR16", + "exits": [], + "locations": [ + "PR16" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_13", + "exits": [], + "locations": [ + "RESCUED_CHERUB_13" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_12", + "exits": [], + "locations": [ + "RESCUED_CHERUB_12" + ], + "transitions": [] + }, + { + "name": "CO32", + "exits": [], + "locations": [ + "CO32" + ], + "transitions": [] + }, + { + "name": "CO44", + "exits": [], + "locations": [ + "CO44" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_22", + "exits": [], + "locations": [ + "RESCUED_CHERUB_22" + ], + "transitions": [] + }, + { + "name": "CO11", + "exits": [], + "locations": [ + "CO11" + ], + "transitions": [] + }, + { + "name": "QI59", + "exits": [], + "locations": [ + "QI59" + ], + "transitions": [] + }, + { + "name": "RB10", + "exits": [], + "locations": [ + "RB10" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_23", + "exits": [], + "locations": [ + "RESCUED_CHERUB_23" + ], + "transitions": [] + }, + { + "name": "QI68", + "exits": [], + "locations": [ + "QI68" + ], + "transitions": [] + }, + { + "name": "CO19", + "exits": [], + "locations": [ + "CO19" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_27", + "exits": [], + "locations": [ + "RESCUED_CHERUB_27" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_24", + "exits": [], + "locations": [ + "RESCUED_CHERUB_24" + ], + "transitions": [] + }, + { + "name": "QI46", + "exits": [], + "locations": [ + "QI46" + ], + "transitions": [] + }, + { + "name": "CO29", + "exits": [], + "locations": [ + "CO29" + ], + "transitions": [] + }, + { + "name": "QI08", + "exits": [], + "locations": [ + "QI08" + ], + "transitions": [] + }, + { + "name": "CO01", + "exits": [], + "locations": [ + "CO01" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_25", + "exits": [], + "locations": [ + "RESCUED_CHERUB_25" + ], + "transitions": [] + }, + { + "name": "RB15", + "exits": [], + "locations": [ + "RB15" + ], + "transitions": [] + }, + { + "name": "CO42", + "exits": [], + "locations": [ + "CO42" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_31", + "exits": [], + "locations": [ + "RESCUED_CHERUB_31" + ], + "transitions": [] + }, + { + "name": "CO05", + "exits": [], + "locations": [ + "CO05" + ], + "transitions": [] + }, + { + "name": "RB08", + "exits": [], + "locations": [ + "RB08" + ], + "transitions": [] + }, + { + "name": "QI47", + "exits": [], + "locations": [ + "QI47" + ], + "transitions": [] + }, + { + "name": "RB22", + "exits": [], + "locations": [ + "RB22" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_16", + "exits": [], + "locations": [ + "RESCUED_CHERUB_16" + ], + "transitions": [] + }, + { + "name": "Amanecida[D03Z01S03]", + "exits": [], + "locations": [ + "Amanecida[D03Z01S03]" + ], + "transitions": [] + }, + { + "name": "PR10", + "exits": [], + "locations": [ + "PR10" + ], + "transitions": [] + }, + { + "name": "CO33", + "exits": [], + "locations": [ + "CO33" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_18", + "exits": [], + "locations": [ + "RESCUED_CHERUB_18" + ], + "transitions": [] + }, + { + "name": "QI41", + "exits": [], + "locations": [ + "QI41" + ], + "transitions": [] + }, + { + "name": "HE06", + "exits": [], + "locations": [ + "HE06" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_37", + "exits": [], + "locations": [ + "RESCUED_CHERUB_37" + ], + "transitions": [] + }, + { + "name": "RB06", + "exits": [], + "locations": [ + "RB06" + ], + "transitions": [] + }, + { + "name": "CO23", + "exits": [], + "locations": [ + "CO23" + ], + "transitions": [] + }, + { + "name": "RE402", + "exits": [], + "locations": [ + "RE402" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_30", + "exits": [], + "locations": [ + "RESCUED_CHERUB_30" + ], + "transitions": [] + }, + { + "name": "CO34", + "exits": [], + "locations": [ + "CO34" + ], + "transitions": [] + }, + { + "name": "CO22", + "exits": [], + "locations": [ + "CO22" + ], + "transitions": [] + }, + { + "name": "RB31", + "exits": [], + "locations": [ + "RB31" + ], + "transitions": [] + }, + { + "name": "RB203", + "exits": [], + "locations": [ + "RB203" + ], + "transitions": [] + }, + { + "name": "CO28", + "exits": [], + "locations": [ + "CO28" + ], + "transitions": [] + }, + { + "name": "QI03", + "exits": [], + "locations": [ + "QI03" + ], + "transitions": [] + }, + { + "name": "CO06", + "exits": [], + "locations": [ + "CO06" + ], + "transitions": [] + }, + { + "name": "PR12", + "exits": [], + "locations": [ + "PR12" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_36", + "exits": [], + "locations": [ + "RESCUED_CHERUB_36" + ], + "transitions": [] + }, + { + "name": "RB11", + "exits": [], + "locations": [ + "RB11" + ], + "transitions": [] + }, + { + "name": "QI72", + "exits": [], + "locations": [ + "QI72" + ], + "transitions": [] + }, + { + "name": "RB16", + "exits": [], + "locations": [ + "RB16" + ], + "transitions": [] + }, + { + "name": "CO27", + "exits": [], + "locations": [ + "CO27" + ], + "transitions": [] + }, + { + "name": "QI69", + "exits": [], + "locations": [ + "QI69" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_34", + "exits": [], + "locations": [ + "RESCUED_CHERUB_34" + ], + "transitions": [] + }, + { + "name": "RESCUED_CHERUB_06", + "exits": [], + "locations": [ + "RESCUED_CHERUB_06" + ], + "transitions": [] + }, + { + "name": "PR203", + "exits": [], + "locations": [ + "PR203" + ], + "transitions": [] + }, + { + "name": "CO25", + "exits": [], + "locations": [ + "CO25" + ], + "transitions": [] + }, + { + "name": "RB202", + "exits": [], + "locations": [ + "RB202" + ], + "transitions": [] + }, + { + "name": "RB18", + "exits": [], + "locations": [ + "RB18" + ], + "transitions": [] + }, + { + "name": "RB25", + "exits": [], + "locations": [ + "RB25" + ], + "transitions": [] + }, + { + "name": "RB26", + "exits": [], + "locations": [ + "RB26" + ], + "transitions": [] + } +] +locations = [ + { + "name": "PR14", + "logic": [] + }, + { + "name": "RB07", + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CO04", + "logic": [] + }, + { + "name": "QI55", + "logic": [ + { + "item_requirements": [ + "blood", + "dash", + "canWaterJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RESCUED_CHERUB_07", + "logic": [] + }, + { + "name": "QI31", + "logic": [] + }, + { + "name": "RE02", + "logic": [ + { + "item_requirements": [ + "hand" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RE04", + "logic": [ + { + "item_requirements": [ + "cloth" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RE10", + "logic": [ + { + "item_requirements": [ + "hatchedEgg" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB01", + "logic": [] + }, + { + "name": "QI66", + "logic": [ + { + "item_requirements": [ + "herbs1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Tirso[500]", + "logic": [ + { + "item_requirements": [ + "herbs2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Tirso[1000]", + "logic": [ + { + "item_requirements": [ + "herbs3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Tirso[2000]", + "logic": [ + { + "item_requirements": [ + "herbs4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Tirso[5000]", + "logic": [ + { + "item_requirements": [ + "herbs5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Tirso[10000]", + "logic": [ + { + "item_requirements": [ + "herbs6" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI56", + "logic": [ + { + "item_requirements": [ + "herbs6", + "canBeatMercyBoss", + "canBeatConventBoss", + "canBeatGrievanceBoss", + "canBeatMothersBoss", + "canBeatCanvasesBoss", + "canBeatPrisonBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RESCUED_CHERUB_08", + "logic": [] + }, + { + "name": "Lvdovico[500]", + "logic": [ + { + "item_requirements": [ + "tentudiaRemains1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Lvdovico[1000]", + "logic": [ + { + "item_requirements": [ + "tentudiaRemains2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "PR03", + "logic": [ + { + "item_requirements": [ + "tentudiaRemains3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI01", + "logic": [] + }, + { + "name": "CO43", + "logic": [] + }, + { + "name": "CO16", + "logic": [] + }, + { + "name": "Sword[D01Z02S06]", + "logic": [] + }, + { + "name": "QI65", + "logic": [] + }, + { + "name": "RB104", + "logic": [] + }, + { + "name": "RB105", + "logic": [] + }, + { + "name": "PR11", + "logic": [ + { + "item_requirements": [ + "marksOfRefuge3", + "cord", + "D06Z01S02[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[250]", + "logic": [ + { + "item_requirements": [ + "bones4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[500]", + "logic": [ + { + "item_requirements": [ + "bones8" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[750]", + "logic": [ + { + "item_requirements": [ + "bones12" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[1000]", + "logic": [ + { + "item_requirements": [ + "bones16" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[1250]", + "logic": [ + { + "item_requirements": [ + "bones20" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[1500]", + "logic": [ + { + "item_requirements": [ + "bones24" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[1750]", + "logic": [ + { + "item_requirements": [ + "bones28" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[2000]", + "logic": [ + { + "item_requirements": [ + "bones32" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[2500]", + "logic": [ + { + "item_requirements": [ + "bones36" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[3000]", + "logic": [ + { + "item_requirements": [ + "bones40" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Undertaker[5000]", + "logic": [ + { + "item_requirements": [ + "bones44" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI201", + "logic": [ + { + "item_requirements": [ + "canBeatOssuaryBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB04", + "logic": [] + }, + { + "name": "CO14", + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CO36", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_10", + "logic": [] + }, + { + "name": "QI06", + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "boots" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB20", + "logic": [ + { + "item_requirements": [ + "redentoRooms3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "HE02", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_38", + "logic": [ + { + "item_requirements": [ + "canCrossGap2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "ruby" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "chargeBeam" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "rangedAttack" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "preciseSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CO30", + "logic": [] + }, + { + "name": "CO03", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_09", + "logic": [] + }, + { + "name": "PR01", + "logic": [] + }, + { + "name": "RB17", + "logic": [] + }, + { + "name": "QI48", + "logic": [] + }, + { + "name": "CO21", + "logic": [] + }, + { + "name": "CO38", + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RESCUED_CHERUB_33", + "logic": [ + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "tirana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "BS01", + "logic": [ + { + "item_requirements": [ + "canBeatMercyBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI38", + "logic": [] + }, + { + "name": "QI58", + "logic": [] + }, + { + "name": "RB05", + "logic": [] + }, + { + "name": "RB09", + "logic": [] + }, + { + "name": "CO09", + "logic": [] + }, + { + "name": "QI67", + "logic": [ + { + "item_requirements": [ + "dash", + "canWaterJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "PR16", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_13", + "logic": [] + }, + { + "name": "Oil[D01Z05S07]", + "logic": [] + }, + { + "name": "QI12", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_14", + "logic": [] + }, + { + "name": "QI45", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_12", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_11", + "logic": [] + }, + { + "name": "CO41", + "logic": [] + }, + { + "name": "CO32", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_15", + "logic": [] + }, + { + "name": "Lady[D01Z05S22]", + "logic": [] + }, + { + "name": "QI75", + "logic": [] + }, + { + "name": "Sword[D01Z05S24]", + "logic": [] + }, + { + "name": "CO44", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_22", + "logic": [] + }, + { + "name": "Lady[D01Z05S26]", + "logic": [] + }, + { + "name": "RB03", + "logic": [] + }, + { + "name": "QI101", + "logic": [] + }, + { + "name": "CO11", + "logic": [] + }, + { + "name": "QI59", + "logic": [] + }, + { + "name": "RB10", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_23", + "logic": [] + }, + { + "name": "QI20", + "logic": [] + }, + { + "name": "QI68", + "logic": [] + }, + { + "name": "QI07", + "logic": [] + }, + { + "name": "CO19", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_27", + "logic": [] + }, + { + "name": "PR04", + "logic": [ + { + "item_requirements": [ + "driedFlowers" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "HE05", + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap11" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RESCUED_CHERUB_24", + "logic": [] + }, + { + "name": "QI46", + "logic": [] + }, + { + "name": "CO29", + "logic": [] + }, + { + "name": "QI08", + "logic": [] + }, + { + "name": "RB32", + "logic": [] + }, + { + "name": "CO01", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_25", + "logic": [] + }, + { + "name": "RB15", + "logic": [] + }, + { + "name": "RB38", + "logic": [] + }, + { + "name": "CO42", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_31", + "logic": [] + }, + { + "name": "Oil[D02Z02S10]", + "logic": [] + }, + { + "name": "QI53", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_26", + "logic": [] + }, + { + "name": "Lady[D02Z02S12]", + "logic": [] + }, + { + "name": "HE11", + "logic": [] + }, + { + "name": "RB106", + "logic": [] + }, + { + "name": "Amanecida[D02Z02S14]", + "logic": [ + { + "item_requirements": [ + "canBeatGraveyardBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI11", + "logic": [] + }, + { + "name": "RB37", + "logic": [] + }, + { + "name": "RB02", + "logic": [] + }, + { + "name": "CO05", + "logic": [] + }, + { + "name": "RB08", + "logic": [] + }, + { + "name": "CO15", + "logic": [] + }, + { + "name": "HE03", + "logic": [ + { + "item_requirements": [ + "canSurvivePoison1", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Sword[D02Z03S13]", + "logic": [] + }, + { + "name": "Lady[D02Z03S15]", + "logic": [] + }, + { + "name": "RB24", + "logic": [] + }, + { + "name": "QI61", + "logic": [] + }, + { + "name": "BS03", + "logic": [ + { + "item_requirements": [ + "canBeatConventBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI40", + "logic": [] + }, + { + "name": "QI57", + "logic": [ + { + "item_requirements": [ + "emptyThimble" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB107", + "logic": [] + }, + { + "name": "CO13", + "logic": [] + }, + { + "name": "QI47", + "logic": [] + }, + { + "name": "RB22", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_16", + "logic": [] + }, + { + "name": "Amanecida[D03Z01S03]", + "logic": [] + }, + { + "name": "QI63", + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "upwarpSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB13", + "logic": [ + { + "item_requirements": [ + "canBeatPerpetua" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI14", + "logic": [ + { + "item_requirements": [ + "canBeatPerpetua", + "egg" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CO08", + "logic": [] + }, + { + "name": "PR10", + "logic": [] + }, + { + "name": "CO33", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_18", + "logic": [] + }, + { + "name": "QI19", + "logic": [] + }, + { + "name": "CO07", + "logic": [] + }, + { + "name": "QI41", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_17", + "logic": [] + }, + { + "name": "HE06", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_37", + "logic": [] + }, + { + "name": "QI52", + "logic": [] + }, + { + "name": "RB28", + "logic": [ + { + "item_requirements": [ + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI103", + "logic": [] + }, + { + "name": "QI44", + "logic": [ + { + "item_requirements": [ + "canSurvivePoison1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CO12", + "logic": [ + { + "item_requirements": [ + "canSurvivePoison1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RE07", + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RESCUED_CHERUB_19", + "logic": [ + { + "item_requirements": [ + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap11", + "taranto", + "obscureSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI10", + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap11" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyBounce", + "canCrossGap7" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RESCUED_CHERUB_21", + "logic": [ + { + "item_requirements": [ + "blood", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "tirana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "aubade", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap11", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap11", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap11", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap11", + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap11", + "tirana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap11", + "aubade", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyBounce", + "canCrossGap7", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyBounce", + "canCrossGap7", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyBounce", + "canCrossGap7", + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyBounce", + "canCrossGap7", + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyBounce", + "canCrossGap7", + "tirana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyBounce", + "canCrossGap7", + "aubade", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RESCUED_CHERUB_20", + "logic": [ + { + "item_requirements": [ + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "lorquiana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "zarabanda" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "tirana" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI13", + "logic": [ + { + "item_requirements": [ + "ceremonyItems3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB06", + "logic": [] + }, + { + "name": "Oil[D03Z03S13]", + "logic": [] + }, + { + "name": "BS04", + "logic": [ + { + "item_requirements": [ + "canBeatGrievanceBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI39", + "logic": [] + }, + { + "name": "CO23", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_35", + "logic": [] + }, + { + "name": "RB14", + "logic": [ + { + "item_requirements": [ + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI37", + "logic": [] + }, + { + "name": "CO39", + "logic": [ + { + "item_requirements": [ + "canClimbOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RESCUED_CHERUB_28", + "logic": [] + }, + { + "name": "RB21", + "logic": [ + { + "item_requirements": [ + "redentoRooms4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Amanecida[D04Z01S04]", + "logic": [ + { + "item_requirements": [ + "canBeatPatioBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI102", + "logic": [] + }, + { + "name": "RE402", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_30", + "logic": [] + }, + { + "name": "CO17", + "logic": [] + }, + { + "name": "CO34", + "logic": [] + }, + { + "name": "CO35", + "logic": [ + { + "item_requirements": [ + "dash", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "dash", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB33", + "logic": [] + }, + { + "name": "CO20", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_29", + "logic": [] + }, + { + "name": "Sword[D04Z02S12]", + "logic": [] + }, + { + "name": "Oil[D04Z02S14]", + "logic": [] + }, + { + "name": "QI60", + "logic": [] + }, + { + "name": "HE01", + "logic": [ + { + "item_requirements": [ + "wallClimb", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "BS05", + "logic": [ + { + "item_requirements": [ + "canBeatMothersBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RE03", + "logic": [] + }, + { + "name": "QI54", + "logic": [ + { + "item_requirements": [ + "redentoRooms5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "HE201", + "logic": [ + { + "item_requirements": [ + "traitorEyes2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "PR201", + "logic": [ + { + "item_requirements": [ + "miriamRooms5", + "dash", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CO18", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_01", + "logic": [] + }, + { + "name": "QI50", + "logic": [ + { + "item_requirements": [ + "canBreakHoles" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CO22", + "logic": [] + }, + { + "name": "RB31", + "logic": [] + }, + { + "name": "PR07", + "logic": [ + { + "item_requirements": [ + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyBounce", + "canCrossGap2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB203", + "logic": [] + }, + { + "name": "CO28", + "logic": [] + }, + { + "name": "RB30", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_02", + "logic": [] + }, + { + "name": "Sword[D05Z01S13]", + "logic": [] + }, + { + "name": "Lady[D05Z01S14]", + "logic": [] + }, + { + "name": "QI62", + "logic": [] + }, + { + "name": "PR15", + "logic": [] + }, + { + "name": "Oil[D05Z01S19]", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_32", + "logic": [ + { + "item_requirements": [ + "blood", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "blood", + "canCrossGap5", + "pillar" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "obscureSkipsAllowed", + "zarabanda" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "obscureSkipsAllowed", + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "obscureSkipsAllowed", + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB301", + "logic": [] + }, + { + "name": "QI64", + "logic": [] + }, + { + "name": "HE07", + "logic": [] + }, + { + "name": "RE05", + "logic": [ + { + "item_requirements": [ + "cherubs20" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "PR05", + "logic": [ + { + "item_requirements": [ + "cherubs38" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CO31", + "logic": [] + }, + { + "name": "BS06", + "logic": [ + { + "item_requirements": [ + "canBeatCanvasesBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI104", + "logic": [ + { + "item_requirements": [ + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB12", + "logic": [] + }, + { + "name": "QI49", + "logic": [] + }, + { + "name": "QI71", + "logic": [] + }, + { + "name": "QI02", + "logic": [ + { + "item_requirements": [ + "canBeatLegionary" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI03", + "logic": [] + }, + { + "name": "QI04", + "logic": [ + { + "item_requirements": [ + "canBeatLegionary" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Sword[D06Z01S11]", + "logic": [] + }, + { + "name": "CO06", + "logic": [] + }, + { + "name": "PR12", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_36", + "logic": [] + }, + { + "name": "CO40", + "logic": [ + { + "item_requirements": [ + "wallClimb", + "canCrossGap10" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canClimbOnRoot", + "blood" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canClimbOnRoot", + "preciseSkipsAllowed", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canClimbOnRoot", + "preciseSkipsAllowed", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "canClimbOnRoot", + "doubleJump", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "HE04", + "logic": [] + }, + { + "name": "Lady[D06Z01S24]", + "logic": [] + }, + { + "name": "BS16", + "logic": [ + { + "item_requirements": [ + "canBeatRooftopsBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "PR08", + "logic": [] + }, + { + "name": "BS12", + "logic": [ + { + "item_requirements": [ + "holyWounds3", + "canBeatBridgeBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "PR09", + "logic": [ + { + "item_requirements": [ + "holyWounds3", + "canBeatBridgeBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "HE101", + "logic": [] + }, + { + "name": "QI105", + "logic": [] + }, + { + "name": "LaudesBossTrigger[30000]", + "logic": [ + { + "item_requirements": [ + "canBeatHallBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Amanecida[D09Z01S01]", + "logic": [ + { + "item_requirements": [ + "canBeatWallBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI51", + "logic": [] + }, + { + "name": "RB11", + "logic": [] + }, + { + "name": "BS14", + "logic": [ + { + "item_requirements": [ + "canBeatPrisonBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RESCUED_CHERUB_05", + "logic": [] + }, + { + "name": "QI72", + "logic": [] + }, + { + "name": "RB16", + "logic": [] + }, + { + "name": "QI70", + "logic": [] + }, + { + "name": "CO27", + "logic": [] + }, + { + "name": "Oil[D09Z01S12]", + "logic": [] + }, + { + "name": "CO10", + "logic": [] + }, + { + "name": "QI69", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_03", + "logic": [] + }, + { + "name": "CO24", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_34", + "logic": [] + }, + { + "name": "CO26", + "logic": [] + }, + { + "name": "CO02", + "logic": [ + { + "item_requirements": [ + "blood", + "canClimbOnRoot", + "canSurvivePoison2", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CO37", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_04", + "logic": [ + { + "item_requirements": [ + "canSurvivePoison1", + "dash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "debla" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "taranto" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cante" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "verdiales" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "aubade" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "cantina" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB204", + "logic": [] + }, + { + "name": "RESCUED_CHERUB_06", + "logic": [] + }, + { + "name": "RE401", + "logic": [ + { + "item_requirements": [ + "redentoRooms2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Sword[D17Z01S08]", + "logic": [] + }, + { + "name": "BS13", + "logic": [ + { + "item_requirements": [ + "canBeatBrotherhoodBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "PR203", + "logic": [] + }, + { + "name": "QI204", + "logic": [ + { + "item_requirements": [ + "canBeatBridgeBoss", + "holyWounds3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI301", + "logic": [ + { + "item_requirements": [ + "canBeatRooftopsBoss", + "trueHeart" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RE01", + "logic": [] + }, + { + "name": "CO25", + "logic": [] + }, + { + "name": "RB108", + "logic": [] + }, + { + "name": "RB202", + "logic": [] + }, + { + "name": "RB201", + "logic": [] + }, + { + "name": "BossTrigger[5000]", + "logic": [ + { + "item_requirements": [ + "canBeatMourningBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI202", + "logic": [ + { + "item_requirements": [ + "canBeatMourningBoss" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "PR202", + "logic": [] + }, + { + "name": "QI203", + "logic": [] + }, + { + "name": "QI106", + "logic": [] + }, + { + "name": "RB18", + "logic": [] + }, + { + "name": "RB19", + "logic": [ + { + "item_requirements": [ + "redWax1", + "D02Z03S18[SE]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "redWax1", + "D02Z03S07[NW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB25", + "logic": [] + }, + { + "name": "RB26", + "logic": [] + }, + { + "name": "QI107", + "logic": [ + { + "item_requirements": [ + "amanecidaRooms1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI108", + "logic": [ + { + "item_requirements": [ + "amanecidaRooms2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI109", + "logic": [ + { + "item_requirements": [ + "amanecidaRooms3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI110", + "logic": [ + { + "item_requirements": [ + "amanecidaRooms4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "PR101", + "logic": [ + { + "item_requirements": [ + "amanecidaRooms4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI32", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI33", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI34", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI35", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI79", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI80", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms6" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "QI81", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms7" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Arena_NailManager[1000]", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms1" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "HE10", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms2" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Arena_NailManager[3000]", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB34", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms4" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "Arena_NailManager[5000]", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB35", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms6" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RB36", + "logic": [ + { + "item_requirements": [ + "guiltBead", + "guiltRooms7" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "COMBO_1", + "logic": [ + { + "item_requirements": [ + "swordRooms1", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "COMBO_2", + "logic": [ + { + "item_requirements": [ + "swordRooms2", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "COMBO_3", + "logic": [ + { + "item_requirements": [ + "swordRooms4", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CHARGED_1", + "logic": [ + { + "item_requirements": [ + "swordRooms1", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CHARGED_2", + "logic": [ + { + "item_requirements": [ + "swordRooms3", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "CHARGED_3", + "logic": [ + { + "item_requirements": [ + "swordRooms6", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RANGED_1", + "logic": [ + { + "item_requirements": [ + "swordRooms2", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RANGED_2", + "logic": [ + { + "item_requirements": [ + "swordRooms5", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "RANGED_3", + "logic": [ + { + "item_requirements": [ + "swordRooms7", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "VERTICAL_1", + "logic": [ + { + "item_requirements": [ + "swordRooms1", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "VERTICAL_2", + "logic": [ + { + "item_requirements": [ + "swordRooms3", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "VERTICAL_3", + "logic": [ + { + "item_requirements": [ + "swordRooms6", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "LUNGE_1", + "logic": [ + { + "item_requirements": [ + "swordRooms1", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "LUNGE_2", + "logic": [ + { + "item_requirements": [ + "swordRooms2", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "LUNGE_3", + "logic": [ + { + "item_requirements": [ + "swordRooms4", + "tears0" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + } +] +transitions = [ + { + "name": "D01Z01S01[W]", + "logic": [] + }, + { + "name": "D01Z01S01[E]", + "logic": [] + }, + { + "name": "D01Z01S01[S]", + "logic": [] + }, + { + "name": "D01Z01S02[W]", + "logic": [] + }, + { + "name": "D01Z01S02[E]", + "logic": [] + }, + { + "name": "D01Z01S03[W]", + "logic": [] + }, + { + "name": "D01Z01S03[E]", + "logic": [] + }, + { + "name": "D01Z01S07[W]", + "logic": [] + }, + { + "name": "D01Z01S07[E]", + "logic": [] + }, + { + "name": "D01Z02S01[W]", + "logic": [] + }, + { + "name": "D01Z02S01[E]", + "logic": [] + }, + { + "name": "D01Z02S02[SW]", + "logic": [] + }, + { + "name": "D01Z02S02[SE]", + "logic": [] + }, + { + "name": "D01Z02S02[W]", + "logic": [] + }, + { + "name": "D01Z02S02[E]", + "logic": [] + }, + { + "name": "D01Z02S02[NE]", + "logic": [] + }, + { + "name": "D01Z02S03[W]", + "logic": [] + }, + { + "name": "D01Z02S03[NW]", + "logic": [] + }, + { + "name": "D01Z02S03[E]", + "logic": [] + }, + { + "name": "D01Z02S03[church]", + "logic": [] + }, + { + "name": "D01Z02S04[W]", + "logic": [] + }, + { + "name": "D01Z02S04[E]", + "logic": [] + }, + { + "name": "D01Z02S04[Ossary]", + "logic": [] + }, + { + "name": "D01Z02S05[W]", + "logic": [] + }, + { + "name": "D01Z02S05[E]", + "logic": [] + }, + { + "name": "D01Z02S06[W]", + "logic": [] + }, + { + "name": "D01Z02S06[E]", + "logic": [] + }, + { + "name": "D01Z02S07[E]", + "logic": [] + }, + { + "name": "D01BZ04S01[church]", + "logic": [] + }, + { + "name": "D01BZ06S01[Ossary]", + "logic": [] + }, + { + "name": "D01BZ06S01[E]", + "logic": [] + }, + { + "name": "D01BZ08S01[W]", + "logic": [] + }, + { + "name": "D01Z03S01[W]", + "logic": [] + }, + { + "name": "D01Z03S01[E]", + "logic": [] + }, + { + "name": "D01Z03S01[SE]", + "logic": [] + }, + { + "name": "D01Z03S02[W]", + "logic": [] + }, + { + "name": "D01Z03S02[SW]", + "logic": [] + }, + { + "name": "D01Z03S02[E]", + "logic": [] + }, + { + "name": "D01Z03S02[S]", + "logic": [] + }, + { + "name": "D01Z03S03[W]", + "logic": [] + }, + { + "name": "D01Z03S03[E]", + "logic": [] + }, + { + "name": "D01Z03S03[-Cherubs]", + "logic": [] + }, + { + "name": "D01Z03S04[SW]", + "logic": [] + }, + { + "name": "D01Z03S04[W]", + "logic": [] + }, + { + "name": "D01Z03S04[NW]", + "logic": [] + }, + { + "name": "D01Z03S04[SE]", + "logic": [] + }, + { + "name": "D01Z03S04[E]", + "logic": [] + }, + { + "name": "D01Z03S05[W]", + "logic": [] + }, + { + "name": "D01Z03S05[E]", + "logic": [] + }, + { + "name": "D01Z03S05[Cherubs]", + "logic": [] + }, + { + "name": "D01Z03S06[W]", + "logic": [] + }, + { + "name": "D01Z03S06[E]", + "logic": [] + }, + { + "name": "D01Z03S07[E]", + "logic": [] + }, + { + "name": "D01Z03S07[-Cherubs]", + "logic": [] + }, + { + "name": "D01Z04S01[NW]", + "logic": [] + }, + { + "name": "D01Z04S01[NE]", + "logic": [] + }, + { + "name": "D01Z04S01[W]", + "logic": [] + }, + { + "name": "D01Z04S01[E]", + "logic": [] + }, + { + "name": "D01Z04S01[SE]", + "logic": [] + }, + { + "name": "D01Z04S01[S]", + "logic": [] + }, + { + "name": "D01Z04S02[W]", + "logic": [] + }, + { + "name": "D01Z04S03[E]", + "logic": [] + }, + { + "name": "D01Z04S05[NW]", + "logic": [] + }, + { + "name": "D01Z04S05[SW]", + "logic": [] + }, + { + "name": "D01Z04S06[E]", + "logic": [] + }, + { + "name": "D01Z04S06[NW]", + "logic": [] + }, + { + "name": "D01Z04S06[SW]", + "logic": [] + }, + { + "name": "D01Z04S07[W]", + "logic": [] + }, + { + "name": "D01Z04S08[E]", + "logic": [] + }, + { + "name": "D01Z04S09[W]", + "logic": [] + }, + { + "name": "D01Z04S09[E]", + "logic": [] + }, + { + "name": "D01Z04S09[C]", + "logic": [] + }, + { + "name": "D01Z04S10[NW]", + "logic": [] + }, + { + "name": "D01Z04S10[SW]", + "logic": [] + }, + { + "name": "D01Z04S10[SE]", + "logic": [] + }, + { + "name": "D01Z04S11[NE]", + "logic": [] + }, + { + "name": "D01Z04S12[NW]", + "logic": [] + }, + { + "name": "D01Z04S12[W]", + "logic": [] + }, + { + "name": "D01Z04S12[SE]", + "logic": [] + }, + { + "name": "D01Z04S13[NW]", + "logic": [] + }, + { + "name": "D01Z04S13[NE]", + "logic": [] + }, + { + "name": "D01Z04S13[SW]", + "logic": [] + }, + { + "name": "D01Z04S13[SE]", + "logic": [ + { + "item_requirements": [ + "D01Z04S16[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser", + "canAirStall" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser", + "wheel" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canDiveLaser", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "D01Z04S14[E]", + "logic": [] + }, + { + "name": "D01Z04S15[N]", + "logic": [] + }, + { + "name": "D01Z04S15[NE]", + "logic": [] + }, + { + "name": "D01Z04S15[W]", + "logic": [] + }, + { + "name": "D01Z04S15[E]", + "logic": [] + }, + { + "name": "D01Z04S15[SW]", + "logic": [] + }, + { + "name": "D01Z04S15[SE]", + "logic": [] + }, + { + "name": "D01Z04S16[W]", + "logic": [] + }, + { + "name": "D01Z04S16[E]", + "logic": [] + }, + { + "name": "D01Z04S17[W]", + "logic": [] + }, + { + "name": "D01Z04S18[W]", + "logic": [] + }, + { + "name": "D01Z04S18[E]", + "logic": [] + }, + { + "name": "D01Z04S19[W]", + "logic": [] + }, + { + "name": "D01Z04S19[E]", + "logic": [] + }, + { + "name": "D01BZ02S01[C]", + "logic": [] + }, + { + "name": "D01Z05S01[N]", + "logic": [] + }, + { + "name": "D01Z05S01[W]", + "logic": [] + }, + { + "name": "D01Z05S01[S]", + "logic": [] + }, + { + "name": "D01Z05S02[N]", + "logic": [] + }, + { + "name": "D01Z05S02[W]", + "logic": [] + }, + { + "name": "D01Z05S02[E]", + "logic": [] + }, + { + "name": "D01Z05S02[S]", + "logic": [] + }, + { + "name": "D01Z05S03[NW]", + "logic": [] + }, + { + "name": "D01Z05S03[NE]", + "logic": [] + }, + { + "name": "D01Z05S03[W]", + "logic": [] + }, + { + "name": "D01Z05S03[E]", + "logic": [] + }, + { + "name": "D01Z05S03[S]", + "logic": [] + }, + { + "name": "D01Z05S04[W]", + "logic": [] + }, + { + "name": "D01Z05S04[E]", + "logic": [] + }, + { + "name": "D01Z05S05[N]", + "logic": [] + }, + { + "name": "D01Z05S05[NW]", + "logic": [] + }, + { + "name": "D01Z05S05[NE]", + "logic": [] + }, + { + "name": "D01Z05S05[SW]", + "logic": [] + }, + { + "name": "D01Z05S05[E]", + "logic": [] + }, + { + "name": "D01Z05S06[W]", + "logic": [] + }, + { + "name": "D01Z05S07[E]", + "logic": [] + }, + { + "name": "D01Z05S08[W]", + "logic": [] + }, + { + "name": "D01Z05S09[NW]", + "logic": [] + }, + { + "name": "D01Z05S09[SE]", + "logic": [] + }, + { + "name": "D01Z05S10[W]", + "logic": [] + }, + { + "name": "D01Z05S10[NE]", + "logic": [] + }, + { + "name": "D01Z05S10[SE]", + "logic": [] + }, + { + "name": "D01Z05S10[S]", + "logic": [] + }, + { + "name": "D01Z05S11[W]", + "logic": [] + }, + { + "name": "D01Z05S12[W]", + "logic": [] + }, + { + "name": "D01Z05S12[E]", + "logic": [] + }, + { + "name": "D01Z05S13[SW]", + "logic": [] + }, + { + "name": "D01Z05S13[N]", + "logic": [] + }, + { + "name": "D01Z05S13[E]", + "logic": [] + }, + { + "name": "D01Z05S14[W]", + "logic": [] + }, + { + "name": "D01Z05S14[N]", + "logic": [] + }, + { + "name": "D01Z05S14[SE]", + "logic": [] + }, + { + "name": "D01Z05S15[W]", + "logic": [] + }, + { + "name": "D01Z05S15[SW]", + "logic": [] + }, + { + "name": "D01Z05S15[SE]", + "logic": [] + }, + { + "name": "D01Z05S16[N]", + "logic": [] + }, + { + "name": "D01Z05S16[SW]", + "logic": [] + }, + { + "name": "D01Z05S16[SE]", + "logic": [] + }, + { + "name": "D01Z05S17[W]", + "logic": [] + }, + { + "name": "D01Z05S17[E]", + "logic": [] + }, + { + "name": "D01Z05S18[E]", + "logic": [] + }, + { + "name": "D01Z05S19[W]", + "logic": [] + }, + { + "name": "D01Z05S19[E]", + "logic": [] + }, + { + "name": "D01Z05S20[W]", + "logic": [] + }, + { + "name": "D01Z05S20[N]", + "logic": [] + }, + { + "name": "D01Z05S21[W]", + "logic": [] + }, + { + "name": "D01Z05S21[E]", + "logic": [] + }, + { + "name": "D01Z05S21[Reward]", + "logic": [] + }, + { + "name": "D01Z05S22[E]", + "logic": [] + }, + { + "name": "D01Z05S23[W]", + "logic": [] + }, + { + "name": "D01Z05S23[E]", + "logic": [] + }, + { + "name": "D01Z05S24[W]", + "logic": [] + }, + { + "name": "D01Z05S24[E]", + "logic": [] + }, + { + "name": "D01Z05S25[NE]", + "logic": [] + }, + { + "name": "D01Z05S25[W]", + "logic": [] + }, + { + "name": "D01Z05S25[E]", + "logic": [ + { + "item_requirements": [ + "D01Z05S21[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "tirana", + "obscureSkipsAllowed", + "linen" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "tirana", + "obscureSkipsAllowed", + "D01Z05S23[E]", + "canWalkOnRoot" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "tirana", + "obscureSkipsAllowed", + "D01Z05S23[E]", + "canCrossGap3" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "D01Z05S25[SW]", + "logic": [] + }, + { + "name": "D01Z05S25[SE]", + "logic": [] + }, + { + "name": "D01Z05S25[EchoesW]", + "logic": [] + }, + { + "name": "D01Z05S25[EchoesE]", + "logic": [] + }, + { + "name": "D01Z05S26[W]", + "logic": [] + }, + { + "name": "D01Z05S27[E]", + "logic": [] + }, + { + "name": "D01BZ05S01[Reward]", + "logic": [] + }, + { + "name": "D01BZ09S01[W]", + "logic": [] + }, + { + "name": "D01Z06S01[N]", + "logic": [] + }, + { + "name": "D01Z06S01[Santos]", + "logic": [] + }, + { + "name": "D01BZ07S01[Santos]", + "logic": [] + }, + { + "name": "D02Z01S01[SW]", + "logic": [] + }, + { + "name": "D02Z01S01[W]", + "logic": [] + }, + { + "name": "D02Z01S01[SE]", + "logic": [] + }, + { + "name": "D02Z01S02[W]", + "logic": [] + }, + { + "name": "D02Z01S02[NW]", + "logic": [] + }, + { + "name": "D02Z01S02[E]", + "logic": [] + }, + { + "name": "D02Z01S02[NE]", + "logic": [] + }, + { + "name": "D02Z01S02[]", + "logic": [] + }, + { + "name": "D02Z01S03[SW]", + "logic": [] + }, + { + "name": "D02Z01S03[W]", + "logic": [] + }, + { + "name": "D02Z01S03[SE]", + "logic": [] + }, + { + "name": "D02Z01S04[E]", + "logic": [] + }, + { + "name": "D02Z01S04[-N]", + "logic": [] + }, + { + "name": "D02Z01S05[E]", + "logic": [] + }, + { + "name": "D02Z01S06[W]", + "logic": [] + }, + { + "name": "D02Z01S06[E]", + "logic": [] + }, + { + "name": "D02Z01S08[E]", + "logic": [] + }, + { + "name": "D02Z01S09[W]", + "logic": [] + }, + { + "name": "D02Z01S09[-CherubsL]", + "logic": [] + }, + { + "name": "D02Z01S09[-CherubsR]", + "logic": [] + }, + { + "name": "D02Z02S01[W]", + "logic": [] + }, + { + "name": "D02Z02S01[NW]", + "logic": [] + }, + { + "name": "D02Z02S01[E]", + "logic": [] + }, + { + "name": "D02Z02S02[SE]", + "logic": [] + }, + { + "name": "D02Z02S02[NW]", + "logic": [] + }, + { + "name": "D02Z02S02[NE]", + "logic": [] + }, + { + "name": "D02Z02S02[-CherubsR]", + "logic": [] + }, + { + "name": "D02Z02S03[SW]", + "logic": [] + }, + { + "name": "D02Z02S03[NW]", + "logic": [] + }, + { + "name": "D02Z02S03[NE]", + "logic": [] + }, + { + "name": "D02Z02S03[-Cherubs]", + "logic": [] + }, + { + "name": "D02Z02S04[W]", + "logic": [] + }, + { + "name": "D02Z02S04[SE]", + "logic": [] + }, + { + "name": "D02Z02S04[E]", + "logic": [] + }, + { + "name": "D02Z02S04[NE]", + "logic": [] + }, + { + "name": "D02Z02S04[-CherubsL]", + "logic": [] + }, + { + "name": "D02Z02S05[SW]", + "logic": [] + }, + { + "name": "D02Z02S05[W]", + "logic": [ + { + "item_requirements": [ + "D02Z02S04[NE]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyBounce" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "D02Z02S05[SE]", + "logic": [] + }, + { + "name": "D02Z02S05[E]", + "logic": [] + }, + { + "name": "D02Z02S05[NW]", + "logic": [] + }, + { + "name": "D02Z02S05[-CherubsL]", + "logic": [] + }, + { + "name": "D02Z02S05[-CherubsR]", + "logic": [] + }, + { + "name": "D02Z02S06[E]", + "logic": [] + }, + { + "name": "D02Z02S07[W]", + "logic": [] + }, + { + "name": "D02Z02S07[E]", + "logic": [] + }, + { + "name": "D02Z02S08[W]", + "logic": [] + }, + { + "name": "D02Z02S08[E]", + "logic": [] + }, + { + "name": "D02Z02S08[C]", + "logic": [] + }, + { + "name": "D02Z02S09[E]", + "logic": [] + }, + { + "name": "D02Z02S10[W]", + "logic": [] + }, + { + "name": "D02Z02S11[W]", + "logic": [] + }, + { + "name": "D02Z02S11[SE]", + "logic": [] + }, + { + "name": "D02Z02S11[E]", + "logic": [] + }, + { + "name": "D02Z02S11[NW]", + "logic": [] + }, + { + "name": "D02Z02S11[NE]", + "logic": [] + }, + { + "name": "D02Z02S11[-Cherubs]", + "logic": [] + }, + { + "name": "D02Z02S12[W]", + "logic": [] + }, + { + "name": "D02Z02S13[W]", + "logic": [] + }, + { + "name": "D02Z02S14[W]", + "logic": [] + }, + { + "name": "D02Z02S14[-Cherubs]", + "logic": [] + }, + { + "name": "D02BZ02S01[C]", + "logic": [] + }, + { + "name": "D02Z03S01[W]", + "logic": [] + }, + { + "name": "D02Z03S01[E]", + "logic": [] + }, + { + "name": "D02Z03S02[S]", + "logic": [] + }, + { + "name": "D02Z03S02[W]", + "logic": [] + }, + { + "name": "D02Z03S02[NW]", + "logic": [] + }, + { + "name": "D02Z03S02[NE]", + "logic": [] + }, + { + "name": "D02Z03S02[N]", + "logic": [] + }, + { + "name": "D02Z03S03[W]", + "logic": [] + }, + { + "name": "D02Z03S03[NW]", + "logic": [] + }, + { + "name": "D02Z03S03[E]", + "logic": [] + }, + { + "name": "D02Z03S05[S]", + "logic": [] + }, + { + "name": "D02Z03S05[E]", + "logic": [] + }, + { + "name": "D02Z03S05[NE]", + "logic": [] + }, + { + "name": "D02Z03S06[W]", + "logic": [] + }, + { + "name": "D02Z03S06[S]", + "logic": [] + }, + { + "name": "D02Z03S07[W]", + "logic": [] + }, + { + "name": "D02Z03S07[NWW]", + "logic": [] + }, + { + "name": "D02Z03S07[NW]", + "logic": [] + }, + { + "name": "D02Z03S07[N]", + "logic": [] + }, + { + "name": "D02Z03S07[E]", + "logic": [] + }, + { + "name": "D02Z03S08[SW]", + "logic": [] + }, + { + "name": "D02Z03S08[W]", + "logic": [] + }, + { + "name": "D02Z03S08[SE]", + "logic": [] + }, + { + "name": "D02Z03S08[E]", + "logic": [] + }, + { + "name": "D02Z03S08[NE]", + "logic": [] + }, + { + "name": "D02Z03S09[W]", + "logic": [] + }, + { + "name": "D02Z03S09[E]", + "logic": [] + }, + { + "name": "D02Z03S10[W]", + "logic": [] + }, + { + "name": "D02Z03S10[-W]", + "logic": [] + }, + { + "name": "D02Z03S10[-Cherubs]", + "logic": [] + }, + { + "name": "D02Z03S11[S]", + "logic": [] + }, + { + "name": "D02Z03S11[W]", + "logic": [] + }, + { + "name": "D02Z03S11[NW]", + "logic": [] + }, + { + "name": "D02Z03S11[E]", + "logic": [] + }, + { + "name": "D02Z03S11[NE]", + "logic": [] + }, + { + "name": "D02Z03S12[E]", + "logic": [] + }, + { + "name": "D02Z03S13[W]", + "logic": [] + }, + { + "name": "D02Z03S14[W]", + "logic": [] + }, + { + "name": "D02Z03S14[E]", + "logic": [] + }, + { + "name": "D02Z03S15[E]", + "logic": [] + }, + { + "name": "D02Z03S16[W]", + "logic": [] + }, + { + "name": "D02Z03S16[N]", + "logic": [] + }, + { + "name": "D02Z03S17[E]", + "logic": [] + }, + { + "name": "D02Z03S18[NW]", + "logic": [] + }, + { + "name": "D02Z03S18[SE]", + "logic": [] + }, + { + "name": "D02Z03S18[NE]", + "logic": [] + }, + { + "name": "D02Z03S19[E]", + "logic": [] + }, + { + "name": "D02Z03S20[W]", + "logic": [] + }, + { + "name": "D02Z03S20[E]", + "logic": [] + }, + { + "name": "D02Z03S21[W]", + "logic": [] + }, + { + "name": "D02Z03S21[E]", + "logic": [] + }, + { + "name": "D02Z03S22[W]", + "logic": [] + }, + { + "name": "D02Z03S23[E]", + "logic": [] + }, + { + "name": "D02Z03S24[E]", + "logic": [] + }, + { + "name": "D03Z01S01[W]", + "logic": [] + }, + { + "name": "D03Z01S01[NE]", + "logic": [] + }, + { + "name": "D03Z01S01[S]", + "logic": [] + }, + { + "name": "D03Z01S01[-Cherubs]", + "logic": [] + }, + { + "name": "D03Z01S02[W]", + "logic": [] + }, + { + "name": "D03Z01S02[E]", + "logic": [] + }, + { + "name": "D03Z01S03[W]", + "logic": [] + }, + { + "name": "D03Z01S03[E]", + "logic": [] + }, + { + "name": "D03Z01S03[SW]", + "logic": [] + }, + { + "name": "D03Z01S03[SE]", + "logic": [] + }, + { + "name": "D03Z01S03[-WestL]", + "logic": [] + }, + { + "name": "D03Z01S03[-WestR]", + "logic": [] + }, + { + "name": "D03Z01S03[-EastL]", + "logic": [] + }, + { + "name": "D03Z01S03[-EastR]", + "logic": [] + }, + { + "name": "D03Z01S04[NW]", + "logic": [] + }, + { + "name": "D03Z01S04[E]", + "logic": [] + }, + { + "name": "D03Z01S05[W]", + "logic": [] + }, + { + "name": "D03Z01S05[E]", + "logic": [] + }, + { + "name": "D03Z01S06[W]", + "logic": [] + }, + { + "name": "D03Z01S06[E]", + "logic": [] + }, + { + "name": "D03Z02S01[W]", + "logic": [] + }, + { + "name": "D03Z02S01[N]", + "logic": [] + }, + { + "name": "D03Z02S02[W]", + "logic": [] + }, + { + "name": "D03Z02S02[E]", + "logic": [] + }, + { + "name": "D03Z02S02[S]", + "logic": [] + }, + { + "name": "D03Z02S03[W]", + "logic": [] + }, + { + "name": "D03Z02S03[E]", + "logic": [] + }, + { + "name": "D03Z02S03[N]", + "logic": [] + }, + { + "name": "D03Z02S03[SE2]", + "logic": [] + }, + { + "name": "D03Z02S03[SW]", + "logic": [] + }, + { + "name": "D03Z02S03[SE]", + "logic": [] + }, + { + "name": "D03Z02S03[SSL]", + "logic": [] + }, + { + "name": "D03Z02S03[SSC]", + "logic": [] + }, + { + "name": "D03Z02S03[SSR]", + "logic": [] + }, + { + "name": "D03Z02S04[NW]", + "logic": [] + }, + { + "name": "D03Z02S04[NE]", + "logic": [] + }, + { + "name": "D03Z02S04[S]", + "logic": [] + }, + { + "name": "D03Z02S05[W]", + "logic": [] + }, + { + "name": "D03Z02S05[E]", + "logic": [] + }, + { + "name": "D03Z02S05[S]", + "logic": [] + }, + { + "name": "D03Z02S06[W]", + "logic": [] + }, + { + "name": "D03Z02S06[N]", + "logic": [] + }, + { + "name": "D03Z02S07[W]", + "logic": [] + }, + { + "name": "D03Z02S07[E]", + "logic": [] + }, + { + "name": "D03Z02S07[N]", + "logic": [] + }, + { + "name": "D03Z02S08[W]", + "logic": [] + }, + { + "name": "D03Z02S08[E]", + "logic": [] + }, + { + "name": "D03Z02S08[N]", + "logic": [] + }, + { + "name": "D03Z02S09[W]", + "logic": [] + }, + { + "name": "D03Z02S09[N]", + "logic": [] + }, + { + "name": "D03Z02S09[S]", + "logic": [] + }, + { + "name": "D03Z02S10[W]", + "logic": [] + }, + { + "name": "D03Z02S10[N]", + "logic": [] + }, + { + "name": "D03Z02S10[S]", + "logic": [] + }, + { + "name": "D03Z02S10[E]", + "logic": [] + }, + { + "name": "D03Z02S10[-Cherubs]", + "logic": [] + }, + { + "name": "D03Z02S11[W]", + "logic": [] + }, + { + "name": "D03Z02S11[E]", + "logic": [] + }, + { + "name": "D03Z02S12[E]", + "logic": [] + }, + { + "name": "D03Z02S13[E]", + "logic": [] + }, + { + "name": "D03Z02S13[-Cherubs]", + "logic": [] + }, + { + "name": "D03Z02S14[E]", + "logic": [] + }, + { + "name": "D03Z02S15[W]", + "logic": [] + }, + { + "name": "D03Z02S15[E]", + "logic": [] + }, + { + "name": "D03Z03S01[W]", + "logic": [] + }, + { + "name": "D03Z03S01[S]", + "logic": [] + }, + { + "name": "D03Z03S01[NL]", + "logic": [] + }, + { + "name": "D03Z03S01[NR]", + "logic": [] + }, + { + "name": "D03Z03S02[W]", + "logic": [] + }, + { + "name": "D03Z03S02[NE]", + "logic": [] + }, + { + "name": "D03Z03S02[E]", + "logic": [] + }, + { + "name": "D03Z03S03[W]", + "logic": [] + }, + { + "name": "D03Z03S03[NE]", + "logic": [] + }, + { + "name": "D03Z03S03[SE]", + "logic": [] + }, + { + "name": "D03Z03S04[NW]", + "logic": [] + }, + { + "name": "D03Z03S04[NE]", + "logic": [] + }, + { + "name": "D03Z03S04[E]", + "logic": [] + }, + { + "name": "D03Z03S04[SW]", + "logic": [] + }, + { + "name": "D03Z03S04[SE]", + "logic": [] + }, + { + "name": "D03Z03S04[-Cherubs]", + "logic": [] + }, + { + "name": "D03Z03S05[NW]", + "logic": [] + }, + { + "name": "D03Z03S05[NE]", + "logic": [] + }, + { + "name": "D03Z03S05[SW]", + "logic": [] + }, + { + "name": "D03Z03S05[SE]", + "logic": [] + }, + { + "name": "D03Z03S06[W]", + "logic": [] + }, + { + "name": "D03Z03S07[NW]", + "logic": [] + }, + { + "name": "D03Z03S07[NE]", + "logic": [] + }, + { + "name": "D03Z03S07[SW]", + "logic": [] + }, + { + "name": "D03Z03S07[E]", + "logic": [] + }, + { + "name": "D03Z03S07[S]", + "logic": [] + }, + { + "name": "D03Z03S08[W]", + "logic": [] + }, + { + "name": "D03Z03S08[-CherubsL]", + "logic": [] + }, + { + "name": "D03Z03S08[-CherubsR]", + "logic": [] + }, + { + "name": "D03Z03S09[SW]", + "logic": [] + }, + { + "name": "D03Z03S09[N]", + "logic": [] + }, + { + "name": "D03Z03S10[E]", + "logic": [] + }, + { + "name": "D03Z03S11[W]", + "logic": [] + }, + { + "name": "D03Z03S11[E]", + "logic": [] + }, + { + "name": "D03Z03S12[W]", + "logic": [] + }, + { + "name": "D03Z03S12[E]", + "logic": [] + }, + { + "name": "D03Z03S13[W]", + "logic": [] + }, + { + "name": "D03Z03S14[W]", + "logic": [] + }, + { + "name": "D03Z03S15[W]", + "logic": [] + }, + { + "name": "D03Z03S15[E]", + "logic": [] + }, + { + "name": "D03Z03S16[W]", + "logic": [] + }, + { + "name": "D03Z03S16[E]", + "logic": [] + }, + { + "name": "D03Z03S17[W]", + "logic": [] + }, + { + "name": "D03Z03S17[E]", + "logic": [] + }, + { + "name": "D03Z03S18[E]", + "logic": [] + }, + { + "name": "D03Z03S19[E]", + "logic": [] + }, + { + "name": "D04Z01S01[W]", + "logic": [] + }, + { + "name": "D04Z01S01[E]", + "logic": [] + }, + { + "name": "D04Z01S01[NE]", + "logic": [] + }, + { + "name": "D04Z01S01[N]", + "logic": [] + }, + { + "name": "D04Z01S02[W]", + "logic": [] + }, + { + "name": "D04Z01S02[NW]", + "logic": [] + }, + { + "name": "D04Z01S02[E]", + "logic": [] + }, + { + "name": "D04Z01S03[W]", + "logic": [] + }, + { + "name": "D04Z01S03[E]", + "logic": [] + }, + { + "name": "D04Z01S03[S]", + "logic": [] + }, + { + "name": "D04Z01S04[W]", + "logic": [] + }, + { + "name": "D04Z01S04[E]", + "logic": [] + }, + { + "name": "D04Z01S05[S]", + "logic": [] + }, + { + "name": "D04Z01S05[N]", + "logic": [] + }, + { + "name": "D04Z01S05[-Cherubs]", + "logic": [] + }, + { + "name": "D04Z01S06[S]", + "logic": [] + }, + { + "name": "D04Z01S06[E]", + "logic": [ + { + "item_requirements": [ + "D09Z01S09[SW]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "D04Z01S06[Cherubs]", + "logic": [] + }, + { + "name": "D04Z02S01[W]", + "logic": [] + }, + { + "name": "D04Z02S01[N]", + "logic": [] + }, + { + "name": "D04Z02S01[E]", + "logic": [] + }, + { + "name": "D04Z02S01[NE]", + "logic": [] + }, + { + "name": "D04Z02S02[S]", + "logic": [] + }, + { + "name": "D04Z02S02[SE]", + "logic": [] + }, + { + "name": "D04Z02S02[NE]", + "logic": [ + { + "item_requirements": [ + "D04Z02S15[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "upwarpSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "doubleJump", + "canEnemyUpslash" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyUpslash", + "upwarpSkipsAllowed", + "wallClimb" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "canEnemyUpslash", + "upwarpSkipsAllowed", + "D06Z01S02[S]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "D04Z02S02[N]", + "logic": [] + }, + { + "name": "D04Z02S03[W]", + "logic": [] + }, + { + "name": "D04Z02S03[E]", + "logic": [] + }, + { + "name": "D04Z02S04[SW]", + "logic": [] + }, + { + "name": "D04Z02S04[SE]", + "logic": [] + }, + { + "name": "D04Z02S04[W]", + "logic": [] + }, + { + "name": "D04Z02S04[E]", + "logic": [] + }, + { + "name": "D04Z02S04[NW]", + "logic": [] + }, + { + "name": "D04Z02S04[NE]", + "logic": [] + }, + { + "name": "D04Z02S04[N]", + "logic": [] + }, + { + "name": "D04Z02S05[W]", + "logic": [] + }, + { + "name": "D04Z02S05[E]", + "logic": [] + }, + { + "name": "D04Z02S06[S]", + "logic": [] + }, + { + "name": "D04Z02S06[NW]", + "logic": [] + }, + { + "name": "D04Z02S06[N]", + "logic": [] + }, + { + "name": "D04Z02S06[NE]", + "logic": [] + }, + { + "name": "D04Z02S06[E]", + "logic": [] + }, + { + "name": "D04Z02S06[-Cherubs]", + "logic": [] + }, + { + "name": "D04Z02S07[SW]", + "logic": [] + }, + { + "name": "D04Z02S07[W]", + "logic": [] + }, + { + "name": "D04Z02S07[N]", + "logic": [] + }, + { + "name": "D04Z02S07[NE]", + "logic": [] + }, + { + "name": "D04Z02S07[SE]", + "logic": [] + }, + { + "name": "D04Z02S08[W]", + "logic": [] + }, + { + "name": "D04Z02S08[E]", + "logic": [] + }, + { + "name": "D04Z02S08[S]", + "logic": [] + }, + { + "name": "D04Z02S09[W]", + "logic": [] + }, + { + "name": "D04Z02S09[E]", + "logic": [] + }, + { + "name": "D04Z02S09[NE]", + "logic": [] + }, + { + "name": "D04Z02S10[W]", + "logic": [] + }, + { + "name": "D04Z02S11[W]", + "logic": [] + }, + { + "name": "D04Z02S11[E]", + "logic": [] + }, + { + "name": "D04Z02S12[W]", + "logic": [] + }, + { + "name": "D04Z02S13[W]", + "logic": [] + }, + { + "name": "D04Z02S14[E]", + "logic": [] + }, + { + "name": "D04Z02S15[W]", + "logic": [] + }, + { + "name": "D04Z02S15[E]", + "logic": [] + }, + { + "name": "D04Z02S16[W]", + "logic": [] + }, + { + "name": "D04Z02S16[-Cherubs]", + "logic": [] + }, + { + "name": "D04Z02S17[W]", + "logic": [] + }, + { + "name": "D04Z02S19[W]", + "logic": [] + }, + { + "name": "D04Z02S19[E]", + "logic": [] + }, + { + "name": "D04Z02S20[W]", + "logic": [] + }, + { + "name": "D04Z02S20[Redento]", + "logic": [] + }, + { + "name": "D04Z02S21[W]", + "logic": [] + }, + { + "name": "D04Z02S21[SE]", + "logic": [] + }, + { + "name": "D04Z02S21[NE]", + "logic": [] + }, + { + "name": "D04Z02S22[W]", + "logic": [] + }, + { + "name": "D04Z02S22[E]", + "logic": [] + }, + { + "name": "D04Z02S23[W]", + "logic": [] + }, + { + "name": "D04Z02S23[SE]", + "logic": [] + }, + { + "name": "D04Z02S23[NE]", + "logic": [] + }, + { + "name": "D04Z02S24[NW]", + "logic": [] + }, + { + "name": "D04Z02S24[SW]", + "logic": [] + }, + { + "name": "D04Z02S24[SE]", + "logic": [] + }, + { + "name": "D04Z02S25[W]", + "logic": [] + }, + { + "name": "D04BZ02S01[Redento]", + "logic": [] + }, + { + "name": "D04Z03S01[W]", + "logic": [] + }, + { + "name": "D04Z03S01[E]", + "logic": [] + }, + { + "name": "D04Z03S02[W]", + "logic": [] + }, + { + "name": "D04Z04S01[W]", + "logic": [] + }, + { + "name": "D04Z04S01[E]", + "logic": [] + }, + { + "name": "D04Z04S02[W]", + "logic": [] + }, + { + "name": "D05Z01S01[W]", + "logic": [] + }, + { + "name": "D05Z01S01[NW]", + "logic": [] + }, + { + "name": "D05Z01S01[E]", + "logic": [] + }, + { + "name": "D05Z01S02[W]", + "logic": [] + }, + { + "name": "D05Z01S02[NW]", + "logic": [] + }, + { + "name": "D05Z01S02[E]", + "logic": [] + }, + { + "name": "D05Z01S03[W]", + "logic": [] + }, + { + "name": "D05Z01S03[E]", + "logic": [] + }, + { + "name": "D05Z01S03[Frontal]", + "logic": [] + }, + { + "name": "D05Z01S04[W]", + "logic": [] + }, + { + "name": "D05Z01S04[E]", + "logic": [] + }, + { + "name": "D05Z01S05[SW]", + "logic": [] + }, + { + "name": "D05Z01S05[E]", + "logic": [] + }, + { + "name": "D05Z01S05[NE]", + "logic": [] + }, + { + "name": "D05Z01S06[W]", + "logic": [] + }, + { + "name": "D05Z01S06[E]", + "logic": [] + }, + { + "name": "D05Z01S07[SW]", + "logic": [] + }, + { + "name": "D05Z01S07[NW]", + "logic": [] + }, + { + "name": "D05Z01S07[E]", + "logic": [] + }, + { + "name": "D05Z01S08[W]", + "logic": [] + }, + { + "name": "D05Z01S08[NW]", + "logic": [] + }, + { + "name": "D05Z01S08[E]", + "logic": [] + }, + { + "name": "D05Z01S08[Health]", + "logic": [] + }, + { + "name": "D05Z01S08[NE]", + "logic": [] + }, + { + "name": "D05Z01S09[W]", + "logic": [] + }, + { + "name": "D05Z01S09[E]", + "logic": [] + }, + { + "name": "D05Z01S10[W]", + "logic": [] + }, + { + "name": "D05Z01S10[NW]", + "logic": [] + }, + { + "name": "D05Z01S10[E]", + "logic": [] + }, + { + "name": "D05Z01S11[SW]", + "logic": [ + { + "item_requirements": [ + "D05Z01S19[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "tirana", + "obscureSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "D05Z01S11[NW]", + "logic": [] + }, + { + "name": "D05Z01S11[NE]", + "logic": [] + }, + { + "name": "D05Z01S11[SE]", + "logic": [] + }, + { + "name": "D05Z01S11[E]", + "logic": [] + }, + { + "name": "D05Z01S12[E]", + "logic": [] + }, + { + "name": "D05Z01S13[E]", + "logic": [] + }, + { + "name": "D05Z01S14[W]", + "logic": [] + }, + { + "name": "D05Z01S15[W]", + "logic": [] + }, + { + "name": "D05Z01S15[E]", + "logic": [] + }, + { + "name": "D05Z01S16[W]", + "logic": [] + }, + { + "name": "D05Z01S17[W]", + "logic": [] + }, + { + "name": "D05Z01S18[W]", + "logic": [] + }, + { + "name": "D05Z01S19[W]", + "logic": [] + }, + { + "name": "D05Z01S19[E]", + "logic": [] + }, + { + "name": "D05Z01S20[W]", + "logic": [] + }, + { + "name": "D05Z01S20[E]", + "logic": [] + }, + { + "name": "D05Z01S20[N]", + "logic": [] + }, + { + "name": "D05Z01S21[SW]", + "logic": [] + }, + { + "name": "D05Z01S21[NW]", + "logic": [] + }, + { + "name": "D05Z01S21[NE]", + "logic": [] + }, + { + "name": "D05Z01S21[-Cherubs]", + "logic": [] + }, + { + "name": "D05Z01S22[FrontalN]", + "logic": [] + }, + { + "name": "D05Z01S22[E]", + "logic": [] + }, + { + "name": "D05Z01S23[E]", + "logic": [] + }, + { + "name": "D05Z01S24[E]", + "logic": [] + }, + { + "name": "D05BZ01S01[FrontalS]", + "logic": [] + }, + { + "name": "D05BZ01S01[FrontalN]", + "logic": [] + }, + { + "name": "D05Z02S01[W]", + "logic": [] + }, + { + "name": "D05Z02S01[E]", + "logic": [] + }, + { + "name": "D05Z02S02[SW]", + "logic": [] + }, + { + "name": "D05Z02S02[NW]", + "logic": [] + }, + { + "name": "D05Z02S02[SE]", + "logic": [] + }, + { + "name": "D05Z02S02[NE]", + "logic": [] + }, + { + "name": "D05Z02S03[W]", + "logic": [] + }, + { + "name": "D05Z02S03[E]", + "logic": [] + }, + { + "name": "D05Z02S04[W]", + "logic": [] + }, + { + "name": "D05Z02S04[E]", + "logic": [] + }, + { + "name": "D05Z02S04[C]", + "logic": [] + }, + { + "name": "D05Z02S05[W]", + "logic": [] + }, + { + "name": "D05Z02S05[E]", + "logic": [] + }, + { + "name": "D05Z02S06[SW]", + "logic": [] + }, + { + "name": "D05Z02S06[NW]", + "logic": [] + }, + { + "name": "D05Z02S06[SE]", + "logic": [] + }, + { + "name": "D05Z02S06[NE]", + "logic": [] + }, + { + "name": "D05Z02S07[W]", + "logic": [] + }, + { + "name": "D05Z02S07[E]", + "logic": [] + }, + { + "name": "D05Z02S08[W]", + "logic": [] + }, + { + "name": "D05Z02S09[W]", + "logic": [] + }, + { + "name": "D05Z02S09[E]", + "logic": [] + }, + { + "name": "D05Z02S10[W]", + "logic": [] + }, + { + "name": "D05Z02S10[E]", + "logic": [] + }, + { + "name": "D05Z02S11[W]", + "logic": [] + }, + { + "name": "D05Z02S12[W]", + "logic": [] + }, + { + "name": "D05Z02S12[E]", + "logic": [] + }, + { + "name": "D05Z02S12[N]", + "logic": [] + }, + { + "name": "D05Z02S13[E]", + "logic": [] + }, + { + "name": "D05Z02S14[W]", + "logic": [] + }, + { + "name": "D05Z02S14[E]", + "logic": [] + }, + { + "name": "D05Z02S15[S]", + "logic": [] + }, + { + "name": "D05Z02S15[E]", + "logic": [] + }, + { + "name": "D05BZ02S01[C]", + "logic": [] + }, + { + "name": "D06Z01S01[SW]", + "logic": [] + }, + { + "name": "D06Z01S01[SE]", + "logic": [] + }, + { + "name": "D06Z01S01[W]", + "logic": [] + }, + { + "name": "D06Z01S01[E]", + "logic": [] + }, + { + "name": "D06Z01S01[NW]", + "logic": [] + }, + { + "name": "D06Z01S01[NE]", + "logic": [] + }, + { + "name": "D06Z01S01[NNW]", + "logic": [] + }, + { + "name": "D06Z01S01[NNE]", + "logic": [] + }, + { + "name": "D06Z01S01[N]", + "logic": [] + }, + { + "name": "D06Z01S01[-Cherubs]", + "logic": [] + }, + { + "name": "D06Z01S02[W]", + "logic": [] + }, + { + "name": "D06Z01S02[E]", + "logic": [] + }, + { + "name": "D06Z01S02[S]", + "logic": [] + }, + { + "name": "D06Z01S03[W]", + "logic": [] + }, + { + "name": "D06Z01S03[E]", + "logic": [] + }, + { + "name": "D06Z01S04[SW]", + "logic": [] + }, + { + "name": "D06Z01S04[W]", + "logic": [] + }, + { + "name": "D06Z01S04[Health]", + "logic": [] + }, + { + "name": "D06Z01S04[NW]", + "logic": [] + }, + { + "name": "D06Z01S04[NE]", + "logic": [] + }, + { + "name": "D06Z01S05[E]", + "logic": [] + }, + { + "name": "D06Z01S06[WW]", + "logic": [] + }, + { + "name": "D06Z01S06[E]", + "logic": [] + }, + { + "name": "D06Z01S06[W]", + "logic": [] + }, + { + "name": "D06Z01S06[EE]", + "logic": [] + }, + { + "name": "D06Z01S07[W]", + "logic": [] + }, + { + "name": "D06Z01S07[E]", + "logic": [] + }, + { + "name": "D06Z01S08[W]", + "logic": [] + }, + { + "name": "D06Z01S08[E]", + "logic": [] + }, + { + "name": "D06Z01S08[N]", + "logic": [ + { + "item_requirements": [ + "D06Z01S13[S]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "wallClimb", + "doubleJump", + "canEnemyBounce", + "preciseSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "D06Z01S09[W]", + "logic": [] + }, + { + "name": "D06Z01S09[E]", + "logic": [] + }, + { + "name": "D06Z01S09[-CherubsL]", + "logic": [] + }, + { + "name": "D06Z01S09[-CherubsR]", + "logic": [] + }, + { + "name": "D06Z01S10[W]", + "logic": [] + }, + { + "name": "D06Z01S10[E]", + "logic": [] + }, + { + "name": "D06Z01S10[-CherubsL]", + "logic": [] + }, + { + "name": "D06Z01S10[-CherubsR]", + "logic": [] + }, + { + "name": "D06Z01S11[W]", + "logic": [] + }, + { + "name": "D06Z01S12[S]", + "logic": [] + }, + { + "name": "D06Z01S12[W]", + "logic": [] + }, + { + "name": "D06Z01S12[E]", + "logic": [] + }, + { + "name": "D06Z01S12[NW]", + "logic": [] + }, + { + "name": "D06Z01S12[NE]", + "logic": [] + }, + { + "name": "D06Z01S12[NE2]", + "logic": [] + }, + { + "name": "D06Z01S13[W]", + "logic": [] + }, + { + "name": "D06Z01S13[E]", + "logic": [] + }, + { + "name": "D06Z01S13[S]", + "logic": [] + }, + { + "name": "D06Z01S14[W]", + "logic": [] + }, + { + "name": "D06Z01S14[E]", + "logic": [] + }, + { + "name": "D06Z01S14[N]", + "logic": [] + }, + { + "name": "D06Z01S15[SW]", + "logic": [] + }, + { + "name": "D06Z01S15[NW]", + "logic": [] + }, + { + "name": "D06Z01S15[NE]", + "logic": [] + }, + { + "name": "D06Z01S16[W]", + "logic": [] + }, + { + "name": "D06Z01S16[E]", + "logic": [] + }, + { + "name": "D06Z01S16[-CherubsL]", + "logic": [] + }, + { + "name": "D06Z01S16[-CherubsR]", + "logic": [] + }, + { + "name": "D06Z01S17[W]", + "logic": [] + }, + { + "name": "D06Z01S17[E]", + "logic": [] + }, + { + "name": "D06Z01S17[-Cherubs]", + "logic": [] + }, + { + "name": "D06Z01S18[E]", + "logic": [] + }, + { + "name": "D06Z01S18[-Cherubs]", + "logic": [] + }, + { + "name": "D06Z01S19[S]", + "logic": [] + }, + { + "name": "D06Z01S19[E]", + "logic": [] + }, + { + "name": "D06Z01S20[W]", + "logic": [] + }, + { + "name": "D06Z01S20[E]", + "logic": [] + }, + { + "name": "D06Z01S21[W]", + "logic": [] + }, + { + "name": "D06Z01S21[E]", + "logic": [] + }, + { + "name": "D06Z01S22[Sword]", + "logic": [] + }, + { + "name": "D06Z01S23[Sword]", + "logic": [] + }, + { + "name": "D06Z01S23[E]", + "logic": [] + }, + { + "name": "D06Z01S23[S]", + "logic": [] + }, + { + "name": "D06Z01S24[W]", + "logic": [] + }, + { + "name": "D06Z01S25[W]", + "logic": [] + }, + { + "name": "D06Z01S25[E]", + "logic": [] + }, + { + "name": "D06Z01S26[W]", + "logic": [] + }, + { + "name": "D07Z01S01[W]", + "logic": [] + }, + { + "name": "D07Z01S01[E]", + "logic": [] + }, + { + "name": "D07Z01S02[W]", + "logic": [] + }, + { + "name": "D07Z01S02[E]", + "logic": [] + }, + { + "name": "D07Z01S03[W]", + "logic": [] + }, + { + "name": "D08Z01S01[W]", + "logic": [] + }, + { + "name": "D08Z01S01[E]", + "logic": [] + }, + { + "name": "D08Z01S02[NE]", + "logic": [] + }, + { + "name": "D08Z01S02[SE]", + "logic": [] + }, + { + "name": "D08Z01S02[-Cherubs]", + "logic": [] + }, + { + "name": "D08Z02S01[W]", + "logic": [] + }, + { + "name": "D08Z02S01[SE]", + "logic": [] + }, + { + "name": "D08Z02S01[E]", + "logic": [] + }, + { + "name": "D08Z02S01[N]", + "logic": [] + }, + { + "name": "D08Z02S02[W]", + "logic": [] + }, + { + "name": "D08Z02S03[W]", + "logic": [] + }, + { + "name": "D08Z02S03[E]", + "logic": [] + }, + { + "name": "D08Z02S03[S]", + "logic": [] + }, + { + "name": "D08Z03S01[W]", + "logic": [] + }, + { + "name": "D08Z03S01[E]", + "logic": [] + }, + { + "name": "D08Z03S02[SW]", + "logic": [] + }, + { + "name": "D08Z03S02[NW]", + "logic": [] + }, + { + "name": "D08Z03S03[W]", + "logic": [] + }, + { + "name": "D08Z03S03[E]", + "logic": [] + }, + { + "name": "D09Z01S01[W]", + "logic": [] + }, + { + "name": "D09Z01S01[E]", + "logic": [] + }, + { + "name": "D09Z01S02[SW]", + "logic": [] + }, + { + "name": "D09Z01S02[NW]", + "logic": [] + }, + { + "name": "D09Z01S02[N]", + "logic": [] + }, + { + "name": "D09Z01S03[W]", + "logic": [] + }, + { + "name": "D09Z01S04[W]", + "logic": [] + }, + { + "name": "D09Z01S04[E]", + "logic": [] + }, + { + "name": "D09Z01S04[S]", + "logic": [] + }, + { + "name": "D09Z01S05[W]", + "logic": [] + }, + { + "name": "D09Z01S05[SE]", + "logic": [] + }, + { + "name": "D09Z01S05[NE]", + "logic": [] + }, + { + "name": "D09Z01S06[-E]", + "logic": [] + }, + { + "name": "D09Z01S06[E]", + "logic": [] + }, + { + "name": "D09Z01S07[SW]", + "logic": [] + }, + { + "name": "D09Z01S07[SE]", + "logic": [] + }, + { + "name": "D09Z01S07[W]", + "logic": [] + }, + { + "name": "D09Z01S07[E]", + "logic": [] + }, + { + "name": "D09Z01S07[NW]", + "logic": [] + }, + { + "name": "D09Z01S07[N]", + "logic": [] + }, + { + "name": "D09Z01S07[NE]", + "logic": [] + }, + { + "name": "D09Z01S08[W]", + "logic": [] + }, + { + "name": "D09Z01S08[S]", + "logic": [] + }, + { + "name": "D09Z01S08[SE]", + "logic": [] + }, + { + "name": "D09Z01S08[NE]", + "logic": [] + }, + { + "name": "D09Z01S09[SW]", + "logic": [] + }, + { + "name": "D09Z01S09[NW]", + "logic": [] + }, + { + "name": "D09Z01S09[E]", + "logic": [] + }, + { + "name": "D09Z01S10[W]", + "logic": [] + }, + { + "name": "D09Z01S11[W]", + "logic": [] + }, + { + "name": "D09Z01S11[E]", + "logic": [] + }, + { + "name": "D09Z01S11[S]", + "logic": [] + }, + { + "name": "D09Z01S12[E]", + "logic": [] + }, + { + "name": "D09Z01S13[E]", + "logic": [] + }, + { + "name": "D17Z01S01[E]", + "logic": [] + }, + { + "name": "D17Z01S02[W]", + "logic": [] + }, + { + "name": "D17Z01S02[E]", + "logic": [] + }, + { + "name": "D17Z01S02[N]", + "logic": [] + }, + { + "name": "D17Z01S03[W]", + "logic": [] + }, + { + "name": "D17Z01S03[E]", + "logic": [] + }, + { + "name": "D17Z01S03[relic]", + "logic": [] + }, + { + "name": "D17Z01S04[W]", + "logic": [] + }, + { + "name": "D17Z01S04[S]", + "logic": [] + }, + { + "name": "D17Z01S04[FrontL]", + "logic": [] + }, + { + "name": "D17Z01S04[N]", + "logic": [] + }, + { + "name": "D17Z01S04[FrontR]", + "logic": [] + }, + { + "name": "D17Z01S05[W]", + "logic": [] + }, + { + "name": "D17Z01S05[E]", + "logic": [] + }, + { + "name": "D17Z01S05[S]", + "logic": [] + }, + { + "name": "D17Z01S06[E]", + "logic": [] + }, + { + "name": "D17Z01S07[SW]", + "logic": [] + }, + { + "name": "D17Z01S07[SE]", + "logic": [] + }, + { + "name": "D17Z01S07[W]", + "logic": [] + }, + { + "name": "D17Z01S07[NW]", + "logic": [] + }, + { + "name": "D17Z01S07[N]", + "logic": [] + }, + { + "name": "D17Z01S08[E]", + "logic": [] + }, + { + "name": "D17Z01S09[E]", + "logic": [] + }, + { + "name": "D17Z01S10[W]", + "logic": [] + }, + { + "name": "D17Z01S10[S]", + "logic": [] + }, + { + "name": "D17Z01S11[W]", + "logic": [] + }, + { + "name": "D17Z01S11[E]", + "logic": [] + }, + { + "name": "D17Z01S12[E]", + "logic": [] + }, + { + "name": "D17Z01S13[W]", + "logic": [] + }, + { + "name": "D17Z01S13[E]", + "logic": [] + }, + { + "name": "D17Z01S14[W]", + "logic": [] + }, + { + "name": "D17Z01S14[E]", + "logic": [] + }, + { + "name": "D17Z01S14[-Cherubs1]", + "logic": [] + }, + { + "name": "D17Z01S14[-Cherubs2]", + "logic": [] + }, + { + "name": "D17Z01S14[-Cherubs3]", + "logic": [] + }, + { + "name": "D17Z01S15[E]", + "logic": [] + }, + { + "name": "D17BZ01S01[relic]", + "logic": [] + }, + { + "name": "D17BZ02S01[FrontL]", + "logic": [] + }, + { + "name": "D17BZ02S01[FrontR]", + "logic": [] + }, + { + "name": "D20Z01S01[W]", + "logic": [] + }, + { + "name": "D20Z01S01[E]", + "logic": [] + }, + { + "name": "D20Z01S01[S]", + "logic": [] + }, + { + "name": "D20Z01S02[W]", + "logic": [] + }, + { + "name": "D20Z01S02[E]", + "logic": [] + }, + { + "name": "D20Z01S03[W]", + "logic": [] + }, + { + "name": "D20Z01S03[N]", + "logic": [] + }, + { + "name": "D20Z01S04[W]", + "logic": [] + }, + { + "name": "D20Z01S04[E]", + "logic": [] + }, + { + "name": "D20Z01S04[N]", + "logic": [] + }, + { + "name": "D20Z01S05[W]", + "logic": [] + }, + { + "name": "D20Z01S05[E]", + "logic": [] + }, + { + "name": "D20Z01S06[NE]", + "logic": [] + }, + { + "name": "D20Z01S06[SE]", + "logic": [] + }, + { + "name": "D20Z01S07[NW]", + "logic": [] + }, + { + "name": "D20Z01S07[NE]", + "logic": [] + }, + { + "name": "D20Z01S07[SE]", + "logic": [] + }, + { + "name": "D20Z01S08[W]", + "logic": [] + }, + { + "name": "D20Z01S09[W]", + "logic": [] + }, + { + "name": "D20Z01S09[E]", + "logic": [] + }, + { + "name": "D20Z01S10[W]", + "logic": [] + }, + { + "name": "D20Z01S10[E]", + "logic": [] + }, + { + "name": "D20Z01S11[W]", + "logic": [] + }, + { + "name": "D20Z01S11[NW]", + "logic": [] + }, + { + "name": "D20Z01S11[NE]", + "logic": [] + }, + { + "name": "D20Z01S11[SE]", + "logic": [] + }, + { + "name": "D20Z01S12[E]", + "logic": [] + }, + { + "name": "D20Z01S13[W]", + "logic": [] + }, + { + "name": "D20Z01S13[E]", + "logic": [] + }, + { + "name": "D20Z01S13[N]", + "logic": [] + }, + { + "name": "D20Z01S14[S]", + "logic": [] + }, + { + "name": "D20Z01S14[E]", + "logic": [] + }, + { + "name": "D20Z02S01[W]", + "logic": [] + }, + { + "name": "D20Z02S01[E]", + "logic": [] + }, + { + "name": "D20Z02S02[W]", + "logic": [] + }, + { + "name": "D20Z02S03[W]", + "logic": [] + }, + { + "name": "D20Z02S03[NE]", + "logic": [] + }, + { + "name": "D20Z02S03[SE]", + "logic": [] + }, + { + "name": "D20Z02S04[W]", + "logic": [] + }, + { + "name": "D20Z02S04[E]", + "logic": [] + }, + { + "name": "D20Z02S05[SW]", + "logic": [] + }, + { + "name": "D20Z02S05[NW]", + "logic": [] + }, + { + "name": "D20Z02S05[E]", + "logic": [] + }, + { + "name": "D20Z02S06[SW]", + "logic": [] + }, + { + "name": "D20Z02S06[SE]", + "logic": [] + }, + { + "name": "D20Z02S06[NW]", + "logic": [] + }, + { + "name": "D20Z02S06[NE]", + "logic": [] + }, + { + "name": "D20Z02S07[W]", + "logic": [] + }, + { + "name": "D20Z02S07[E]", + "logic": [] + }, + { + "name": "D20Z02S08[E]", + "logic": [] + }, + { + "name": "D20Z02S09[W]", + "logic": [] + }, + { + "name": "D20Z02S09[E]", + "logic": [] + }, + { + "name": "D20Z02S10[W]", + "logic": [] + }, + { + "name": "D20Z02S10[E]", + "logic": [] + }, + { + "name": "D20Z02S11[SW]", + "logic": [] + }, + { + "name": "D20Z02S11[NW]", + "logic": [ + { + "item_requirements": [ + "D20Z01S13[E]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "mourningSkipAllowed", + "D20Z02S10[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "mourningSkipAllowed", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "mourningSkipAllowed", + "tirana", + "obscureSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "D20Z02S11[E]", + "logic": [ + { + "item_requirements": [ + "D20Z02S10[W]" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "mourningSkipAllowed", + "D20Z01S13[E]", + "canCrossGap5" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "mourningSkipAllowed", + "doubleJump" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + }, + { + "item_requirements": [ + "mourningSkipAllowed", + "tirana", + "obscureSkipsAllowed" + ], + "location_requirements": [], + "region_requirements": [], + "state_modifiers": [] + } + ] + }, + { + "name": "D20Z02S12[W]", + "logic": [] + }, + { + "name": "D20Z02S12[E]", + "logic": [] + }, + { + "name": "D20Z03S01[W]", + "logic": [] + } +] +transition_to_region_map = { + "D01Z01S01[W]": "D01Z01S01[W]", + "D17Z01S03[E]": "D17Z01S03[E]", + "D01Z01S01[E]": "D01Z01S01[E]", + "D01Z01S03[W]": "D01Z01S03[W]", + "D01Z01S01[S]": "D01Z01S01[S]", + "D01BZ07S01[Santos]": "D01BZ07S01[Santos]", + "D01Z01S02[W]": "D01Z01S02[W]", + "D01Z01S07[E]": "D01Z01S07[E]", + "D01Z06S01[N]": "D01Z06S01[N]", + "D01Z01S02[E]": "D01Z01S02[E]", + "D01Z02S01[W]": "D01Z02S01[W]", + "D01Z01S03[E]": "D01Z01S03[E]", + "D01Z02S02[W]": "D01Z02S02[W]", + "D01Z01S07[W]": "D01Z01S07[W]", + "D17Z01S11[E]": "D17Z01S11[E]", + "D17Z01S03[W]": "D17Z01S11[E]", + "D17BZ01S01[relic]": "D17BZ01S01[relic]", + "D01Z02S01[E]": "D01Z02S01[E]", + "D01Z02S03[W]": "D01Z02S03[W]", + "D01Z02S03[NW]": "D01Z02S03[NW]", + "D01Z02S04[W]": "D01Z02S04[W]", + "D01Z02S06[E]": "D01Z02S06[E]", + "D01Z02S02[SW]": "D01Z02S02[SW]", + "D01Z02S07[E]": "D01Z02S07[E]", + "D01Z02S02[SE]": "D01Z02S02[SE]", + "D01BZ06S01[Ossary]": "D01BZ06S01[Ossary]", + "D01Z05S01[N]": "D01Z05S01[N]", + "D01Z02S02[E]": "D01Z02S02[E]", + "D01Z02S02[NE]": "D01Z02S02[NE]", + "D01Z02S05[W]": "D01Z02S05[W]", + "D01BZ04S01[church]": "D01BZ04S01[church]", + "D02Z02S11[-Cherubs]": "D02Z02S11[-Cherubs]", + "D01Z02S03[E]": "D01Z02S03[E]", + "D01Z03S01[W]": "D01Z03S01[W]", + "D01Z02S03[church]": "D01Z02S03[church]", + "D01Z02S04[E]": "D01Z02S04[E]", + "D01Z05S02[N]": "D01Z05S02[N]", + "D01Z05S01[S]": "D01Z05S02[N]", + "D01Z05S27[E]": "D01Z05S02[N]", + "D01Z05S01[W]": "D01Z05S02[N]", + "D01Z02S04[Ossary]": "D01Z02S04[Ossary]", + "D01BZ08S01[W]": "D01BZ08S01[W]", + "D01Z02S05[E]": "D01Z02S05[E]", + "D01Z03S02[W]": "D01Z03S02[W]", + "D01Z03S02[SW]": "D01Z03S02[SW]", + "D01Z02S06[W]": "D01Z02S06[W]", + "D01BZ06S01[E]": "D01BZ06S01[E]", + "D01Z03S01[E]": "D01Z03S01[E]", + "D01Z03S01[SE]": "D01Z03S01[SE]", + "D01Z03S03[W]": "D01Z03S03[W]", + "D01Z05S05[N]": "D01Z05S05[N]", + "D01Z03S02[E]": "D01Z03S02[E]", + "D01Z03S04[SW]": "D01Z03S04[SW]", + "D01Z03S07[-Cherubs]": "D01Z03S07[-Cherubs]", + "D01Z03S02[S]": "D01Z03S02[S]", + "D01Z05S04[E]": "D01Z05S04[E]", + "D01Z05S06[W]": "D01Z05S06[W]", + "D01Z05S09[NW]": "D01Z05S09[NW]", + "D01Z05S18[E]": "D01Z05S18[E]", + "D01Z03S03[E]": "D01Z03S03[E]", + "D01Z03S05[W]": "D01Z03S05[W]", + "D01Z03S06[W]": "D01Z03S06[W]", + "D01Z03S07[E]": "D01Z03S07[E]", + "D02Z01S01[SE]": "D02Z01S01[SE]", + "D01Z03S04[NW]": "D02Z01S01[SE]", + "D01Z03S03[-Cherubs]": "D01Z03S03[-Cherubs]", + "D01Z05S05[NE]": "D01Z05S05[NE]", + "D01Z03S04[W]": "D01Z03S04[W]", + "D02Z01S02[E]": "D02Z01S02[E]", + "D02Z01S01[W]": "D02Z01S02[E]", + "D02Z01S06[E]": "D02Z01S06[E]", + "D02Z01S09[-CherubsL]": "D02Z01S09[-CherubsL]", + "D02Z01S09[-CherubsR]": "D02Z01S09[-CherubsR]", + "D01Z03S04[SE]": "D01Z03S04[SE]", + "D01Z04S01[NW]": "D01Z04S01[NW]", + "D01Z03S04[E]": "D01Z03S04[E]", + "D08Z01S01[W]": "D08Z01S01[W]", + "D01Z03S05[E]": "D01Z03S05[E]", + "D01Z04S03[E]": "D01Z04S03[E]", + "D01Z04S01[W]": "D01Z04S03[E]", + "D01Z04S17[W]": "D01Z04S03[E]", + "D01Z04S01[NE]": "D01Z04S03[E]", + "D01Z04S05[NW]": "D01Z04S05[NW]", + "D01Z04S05[SW]": "D01Z04S05[SW]", + "D01Z04S15[N]": "D01Z04S15[N]", + "D01Z04S01[S]": "D01Z04S15[N]", + "D01Z03S05[Cherubs]": "D01Z03S05[Cherubs]", + "D01Z05S10[NE]": "D01Z05S10[NE]", + "D01Z03S06[E]": "D01Z03S06[E]", + "D08Z01S02[-Cherubs]": "D08Z01S02[-Cherubs]", + "D08Z02S01[W]": "D08Z02S01[W]", + "D01Z04S01[E]": "D01Z04S01[E]", + "D01Z04S01[SE]": "D01Z04S01[SE]", + "D01Z04S06[NW]": "D01Z04S06[NW]", + "D01Z04S06[SW]": "D01Z04S06[SW]", + "D01Z04S08[E]": "D01Z04S08[E]", + "D01Z04S09[E]": "D01Z04S09[E]", + "D01Z04S15[SW]": "D01Z04S09[E]", + "D01Z04S10[NW]": "D01Z04S09[E]", + "D01Z04S15[SE]": "D01Z04S09[E]", + "D01Z04S10[SE]": "D01Z04S09[E]", + "D01Z04S12[NW]": "D01Z04S09[E]", + "D01Z04S12[SE]": "D01Z04S09[E]", + "D01Z04S13[NW]": "D01Z04S09[E]", + "D01Z04S18[E]": "D01Z04S09[E]", + "D01Z04S12[W]": "D01Z04S09[E]", + "D01Z04S02[W]": "D01Z04S09[E]", + "D01Z04S13[NE]": "D01Z04S09[E]", + "D01Z04S14[E]": "D01Z04S14[E]", + "D01Z04S16[W]": "D01Z04S16[W]", + "D01Z04S06[E]": "D01Z04S06[E]", + "D01Z04S07[W]": "D01Z04S07[W]", + "D01Z04S15[NE]": "D01Z04S15[NE]", + "D01Z04S15[E]": "D01Z04S15[E]", + "D01Z04S09[W]": "D01Z04S09[W]", + "D01Z05S10[SE]": "D01Z05S10[SE]", + "D01Z05S12[W]": "D01Z05S10[SE]", + "D01Z05S10[W]": "D01Z05S10[SE]", + "D01Z05S09[SE]": "D01Z05S10[SE]", + "D01Z04S09[C]": "D01Z04S09[C]", + "D01Z04S10[SW]": "D01Z04S10[SW]", + "D01Z04S11[NE]": "D01Z04S11[NE]", + "D01Z04S19[E]": "D01Z04S19[E]", + "D01Z04S13[SW]": "D01Z04S13[SW]", + "D01Z04S13[SE]": "D01Z04S13[SE]", + "D05Z02S12[W]": "D05Z02S12[W]", + "D01Z04S15[W]": "D01Z04S15[W]", + "D01BZ02S01[C]": "D01BZ02S01[C]", + "D01Z05S12[E]": "D01Z05S12[E]", + "D01Z04S16[E]": "D01Z04S16[E]", + "D05Z02S04[W]": "D05Z02S04[W]", + "D05Z02S12[E]": "D05Z02S04[W]", + "D05Z02S04[E]": "D05Z02S04[W]", + "D05Z02S03[W]": "D05Z02S04[W]", + "D05Z02S15[S]": "D05Z02S15[S]", + "D01Z04S18[W]": "D01Z04S18[W]", + "D01Z05S19[E]": "D01Z05S19[E]", + "D01Z04S19[W]": "D01Z04S19[W]", + "D01Z05S15[SE]": "D01Z05S15[SE]", + "D01Z05S03[NW]": "D01Z05S03[NW]", + "D01Z05S20[N]": "D01Z05S20[N]", + "D03Z01S01[NE]": "D03Z01S01[NE]", + "D01Z05S02[W]": "D01Z05S02[W]", + "D03Z01S02[E]": "D03Z01S02[E]", + "D20Z01S03[N]": "D20Z01S03[N]", + "D01Z05S02[E]": "D01Z05S02[E]", + "D01Z05S04[W]": "D01Z05S04[W]", + "D01Z05S03[NE]": "D01Z05S04[W]", + "D01Z05S13[N]": "D01Z05S04[W]", + "D01Z05S03[S]": "D01Z05S04[W]", + "D01Z05S07[E]": "D01Z05S07[E]", + "D01Z05S08[W]": "D01Z05S08[W]", + "D01Z05S02[S]": "D01Z05S02[S]", + "D01Z05S25[NE]": "D01Z05S25[NE]", + "D01Z05S05[NW]": "D01Z05S05[NW]", + "D01Z05S03[W]": "D01Z05S03[W]", + "D01Z05S03[E]": "D01Z05S03[E]", + "D01Z05S14[W]": "D01Z05S14[W]", + "D01Z05S16[N]": "D01Z05S16[N]", + "D01Z05S13[SW]": "D01Z05S16[N]", + "D01Z05S21[E]": "D01Z05S16[N]", + "D01Z05S16[SW]": "D01Z05S16[N]", + "D01Z05S17[W]": "D01Z05S16[N]", + "D01Z05S16[SE]": "D01Z05S16[N]", + "D01Z05S05[SW]": "D01Z05S05[SW]", + "D01Z05S05[E]": "D01Z05S05[E]", + "D01Z05S11[W]": "D01Z05S11[W]", + "D01Z05S14[N]": "D01Z05S14[N]", + "D01Z05S10[S]": "D01Z05S10[S]", + "D01Z05S13[E]": "D01Z05S13[E]", + "D01Z05S15[W]": "D01Z05S15[W]", + "D01Z05S14[SE]": "D01Z05S14[SE]", + "D01Z05S19[W]": "D01Z05S19[W]", + "D01Z05S22[E]": "D01Z05S22[E]", + "D01Z05S15[SW]": "D01Z05S15[SW]", + "D01Z05S25[E]": "D01Z05S25[E]", + "D01BZ05S01[Reward]": "D01BZ05S01[Reward]", + "D01BZ09S01[W]": "D01BZ09S01[W]", + "D01Z05S17[E]": "D01Z05S17[E]", + "D01Z05S20[W]": "D01Z05S20[W]", + "D01Z05S21[W]": "D01Z05S21[W]", + "D01Z05S23[E]": "D01Z05S23[E]", + "D01Z05S26[W]": "D01Z05S26[W]", + "D03Z03S17[E]": "D03Z03S17[E]", + "D01Z05S25[SW]": "D03Z03S17[E]", + "D20Z01S09[E]": "D20Z01S09[E]", + "D01Z05S25[EchoesW]": "D20Z01S09[E]", + "D20Z01S10[W]": "D20Z01S10[W]", + "D01Z05S25[EchoesE]": "D20Z01S10[W]", + "D01Z05S21[Reward]": "D01Z05S21[Reward]", + "D01Z05S23[W]": "D01Z05S23[W]", + "D20Z01S04[E]": "D20Z01S04[E]", + "D01Z05S24[W]": "D01Z05S24[W]", + "D20Z01S01[S]": "D20Z01S01[S]", + "D20Z01S04[N]": "D20Z01S01[S]", + "D20Z01S05[E]": "D20Z01S01[S]", + "D20Z01S04[W]": "D20Z01S01[S]", + "D20Z01S06[NE]": "D20Z01S01[S]", + "D20Z01S05[W]": "D20Z01S01[S]", + "D20Z01S07[NW]": "D20Z01S01[S]", + "D20Z01S06[SE]": "D20Z01S01[S]", + "D20Z01S07[SE]": "D20Z01S01[S]", + "D20Z01S09[W]": "D20Z01S01[S]", + "D20Z01S08[W]": "D20Z01S01[S]", + "D20Z01S07[NE]": "D20Z01S01[S]", + "D01Z05S24[E]": "D01Z05S24[E]", + "D01Z05S25[W]": "D01Z05S25[W]", + "D03Z03S16[E]": "D03Z03S16[E]", + "D01Z05S25[SE]": "D01Z05S25[SE]", + "D20Z01S11[W]": "D20Z01S11[W]", + "D20Z01S10[E]": "D20Z01S11[W]", + "D20Z01S12[E]": "D20Z01S11[W]", + "D20Z01S11[NW]": "D20Z01S11[W]", + "D20Z01S13[W]": "D20Z01S11[W]", + "D20Z01S11[NE]": "D20Z01S11[W]", + "D20Z02S12[W]": "D20Z01S11[W]", + "D20Z01S11[SE]": "D20Z01S11[W]", + "D20Z01S14[S]": "D20Z01S11[W]", + "D20Z01S13[N]": "D20Z01S11[W]", + "D01Z06S01[Santos]": "D01Z06S01[Santos]", + "D02Z01S01[SW]": "D02Z01S01[SW]", + "D02Z01S02[]": "D02Z01S02[]", + "D02Z01S08[E]": "D02Z01S08[E]", + "D02Z01S03[SE]": "D02Z01S03[SE]", + "D02Z01S02[NW]": "D02Z01S03[SE]", + "D02Z02S01[E]": "D02Z01S03[SE]", + "D02Z01S03[W]": "D02Z01S03[SE]", + "D02Z01S04[E]": "D02Z01S04[E]", + "D02Z01S09[W]": "D02Z01S09[W]", + "D02Z01S02[W]": "D02Z01S02[W]", + "D02Z01S05[E]": "D02Z01S05[E]", + "D02Z02S14[-Cherubs]": "D02Z02S14[-Cherubs]", + "D02Z01S02[NE]": "D02Z01S02[NE]", + "D02Z01S03[SW]": "D02Z01S03[SW]", + "D02Z02S02[SE]": "D02Z02S02[SE]", + "D02Z02S01[NW]": "D02Z02S02[SE]", + "D02Z02S03[-Cherubs]": "D02Z02S03[-Cherubs]", + "D02Z02S08[E]": "D02Z02S08[E]", + "D02Z02S01[W]": "D02Z02S08[E]", + "D02Z01S04[-N]": "D02Z01S04[-N]", + "D02Z01S06[W]": "D02Z01S06[W]", + "D02Z02S02[-CherubsR]": "D02Z02S02[-CherubsR]", + "D02Z02S04[-CherubsL]": "D02Z02S04[-CherubsL]", + "D02Z02S11[SE]": "D02Z02S11[SE]", + "D02BZ02S01[C]": "D02BZ02S01[C]", + "D02Z02S03[SW]": "D02Z02S03[SW]", + "D02Z02S02[NE]": "D02Z02S03[SW]", + "D02Z02S04[SE]": "D02Z02S03[SW]", + "D02Z02S02[NW]": "D02Z02S03[SW]", + "D02Z02S05[-CherubsL]": "D02Z02S05[-CherubsL]", + "D02Z02S05[-CherubsR]": "D02Z02S05[-CherubsR]", + "D02Z02S05[SW]": "D02Z02S05[SW]", + "D02Z02S05[W]": "D02Z02S05[W]", + "D02Z02S09[E]": "D02Z02S09[E]", + "D02Z02S04[W]": "D02Z02S09[E]", + "D02Z02S05[SE]": "D02Z02S05[SE]", + "D02Z02S03[NW]": "D02Z02S05[SE]", + "D02Z02S14[W]": "D02Z02S14[W]", + "D02Z02S04[E]": "D02Z02S04[E]", + "D02Z02S04[NE]": "D02Z02S04[NE]", + "D02Z02S07[E]": "D02Z02S07[E]", + "D02Z02S05[NW]": "D02Z02S07[E]", + "D02Z03S01[E]": "D02Z02S07[E]", + "D02Z02S07[W]": "D02Z02S07[E]", + "D02Z03S08[E]": "D02Z02S07[E]", + "D02Z03S01[W]": "D02Z02S07[E]", + "D02Z03S08[SE]": "D02Z02S07[E]", + "D02Z03S14[W]": "D02Z02S07[E]", + "D02Z03S14[E]": "D02Z02S07[E]", + "D02Z02S11[NW]": "D02Z02S07[E]", + "D02Z03S16[W]": "D02Z02S07[E]", + "D02Z03S08[NE]": "D02Z02S07[E]", + "D02Z03S02[S]": "D02Z02S07[E]", + "D02Z03S16[N]": "D02Z02S07[E]", + "D02Z02S10[W]": "D02Z02S10[W]", + "D02Z02S03[NE]": "D02Z02S03[NE]", + "D02Z02S05[E]": "D02Z02S05[E]", + "D02Z03S10[-Cherubs]": "D02Z03S10[-Cherubs]", + "D02Z02S06[E]": "D02Z02S06[E]", + "D02Z02S08[W]": "D02Z02S08[W]", + "D02Z02S12[W]": "D02Z02S12[W]", + "D02Z02S13[W]": "D02Z02S13[W]", + "D02Z02S08[C]": "D02Z02S08[C]", + "D02Z02S11[W]": "D02Z02S11[W]", + "D02Z02S11[E]": "D02Z02S11[E]", + "D02Z02S11[NE]": "D02Z02S11[NE]", + "D02Z03S07[E]": "D02Z03S07[E]", + "D02Z03S12[E]": "D02Z03S12[E]", + "D02Z03S02[W]": "D02Z03S02[W]", + "D02Z03S03[E]": "D02Z03S02[W]", + "D02Z03S05[E]": "D02Z03S02[W]", + "D02Z03S03[W]": "D02Z03S02[W]", + "D02Z03S05[NE]": "D02Z03S05[NE]", + "D02Z03S03[NW]": "D02Z03S05[NE]", + "D02Z03S02[NW]": "D02Z03S02[NW]", + "D02Z03S20[E]": "D02Z03S20[E]", + "D02Z03S02[NE]": "D02Z03S02[NE]", + "D02Z03S02[N]": "D02Z03S02[N]", + "D02Z03S10[W]": "D02Z03S10[W]", + "D02Z03S11[E]": "D02Z03S10[W]", + "D02Z03S22[W]": "D02Z03S10[W]", + "D02Z03S11[NE]": "D02Z03S10[W]", + "D02Z03S15[E]": "D02Z03S15[E]", + "D02Z03S19[E]": "D02Z03S19[E]", + "D02Z03S07[N]": "D02Z03S07[N]", + "D02Z03S11[S]": "D02Z03S11[S]", + "D02Z03S13[W]": "D02Z03S13[W]", + "D02Z03S21[E]": "D02Z03S21[E]", + "D02Z03S05[S]": "D02Z03S05[S]", + "D02Z03S06[S]": "D02Z03S06[S]", + "D02Z03S08[W]": "D02Z03S08[W]", + "D02Z03S17[E]": "D02Z03S17[E]", + "D02Z03S24[E]": "D02Z03S24[E]", + "D02Z03S06[W]": "D02Z03S06[W]", + "D02Z03S18[SE]": "D02Z03S06[W]", + "D02Z03S09[W]": "D02Z03S09[W]", + "D02Z03S23[E]": "D02Z03S23[E]", + "D02Z03S07[W]": "D02Z03S07[W]", + "D02Z03S07[NWW]": "D02Z03S07[NWW]", + "D02Z03S07[NW]": "D02Z03S07[NW]", + "D02Z03S08[SW]": "D02Z03S08[SW]", + "D02Z03S09[E]": "D02Z03S09[E]", + "D02Z03S21[W]": "D02Z03S21[W]", + "D02Z03S10[-W]": "D02Z03S10[-W]", + "D09Z01S04[W]": "D09Z01S04[W]", + "D02Z03S11[W]": "D02Z03S11[W]", + "D02Z03S11[NW]": "D02Z03S11[NW]", + "D09Z01S06[-E]": "D09Z01S06[-E]", + "D02Z03S18[NW]": "D02Z03S18[NW]", + "D02Z03S18[NE]": "D02Z03S18[NE]", + "D02Z03S20[W]": "D02Z03S20[W]", + "D03Z01S01[W]": "D03Z01S01[W]", + "D03Z01S06[E]": "D03Z01S06[E]", + "D03Z01S02[W]": "D03Z01S06[E]", + "D03Z01S01[S]": "D03Z01S01[S]", + "D20Z01S02[E]": "D20Z01S02[E]", + "D03Z01S01[-Cherubs]": "D03Z01S01[-Cherubs]", + "D03Z02S15[E]": "D03Z02S15[E]", + "D20Z01S02[W]": "D20Z01S02[W]", + "D03Z01S03[E]": "D03Z01S03[E]", + "D03Z01S06[W]": "D03Z01S03[E]", + "D03Z01S03[W]": "D03Z01S03[W]", + "D03Z01S05[E]": "D03Z01S05[E]", + "D03Z01S03[SW]": "D03Z01S03[SW]", + "D03Z01S03[-WestL]": "D03Z01S03[-WestL]", + "D03Z02S02[W]": "D03Z02S02[W]", + "D03Z02S09[N]": "D03Z02S09[N]", + "D03Z02S13[E]": "D03Z02S13[E]", + "D03Z01S03[SE]": "D03Z01S03[SE]", + "D03Z02S01[N]": "D03Z01S03[SE]", + "D03Z01S03[-EastR]": "D03Z01S03[-EastR]", + "D03Z02S02[E]": "D03Z02S02[E]", + "D03Z02S01[W]": "D03Z02S02[E]", + "D03Z01S03[-WestR]": "D03Z01S03[-WestR]", + "D03Z01S03[-EastL]": "D03Z01S03[-EastL]", + "D03Z02S03[N]": "D03Z02S03[N]", + "D03Z02S02[S]": "D03Z02S03[N]", + "D03Z02S04[NW]": "D03Z02S03[N]", + "D03Z02S03[SE2]": "D03Z02S03[N]", + "D03Z02S10[E]": "D03Z02S10[E]", + "D03Z01S04[NW]": "D03Z01S04[NW]", + "D17Z01S07[SE]": "D17Z01S07[SE]", + "D03Z01S05[W]": "D17Z01S07[SE]", + "D17Z01S06[E]": "D17Z01S07[SE]", + "D17Z01S07[W]": "D17Z01S07[SE]", + "D17Z01S09[E]": "D17Z01S07[SE]", + "D17Z01S07[NW]": "D17Z01S07[SE]", + "D03Z01S04[E]": "D03Z01S04[E]", + "D03Z02S10[N]": "D03Z02S10[N]", + "D17Z01S04[S]": "D17Z01S04[S]", + "D17Z01S08[E]": "D17Z01S08[E]", + "D03Z02S05[W]": "D03Z02S05[W]", + "D03Z02S03[E]": "D03Z02S05[W]", + "D03Z02S06[W]": "D03Z02S06[W]", + "D03Z02S07[E]": "D03Z02S07[E]", + "D03Z02S07[N]": "D03Z02S07[N]", + "D03Z03S01[NL]": "D03Z03S01[NL]", + "D03Z02S03[SSL]": "D03Z03S01[NL]", + "D03Z02S03[SSC]": "D03Z03S01[NL]", + "D03Z02S03[SSR]": "D03Z03S01[NL]", + "D03Z03S01[NR]": "D03Z03S01[NL]", + "D03Z02S03[W]": "D03Z02S03[W]", + "D03Z02S03[SW]": "D03Z02S03[SW]", + "D03Z02S08[E]": "D03Z02S08[E]", + "D03Z02S04[NE]": "D03Z02S04[NE]", + "D03Z02S05[S]": "D03Z02S04[NE]", + "D03Z02S11[W]": "D03Z02S04[NE]", + "D03Z02S05[E]": "D03Z02S04[NE]", + "D03Z02S06[N]": "D03Z02S06[N]", + "D03Z02S03[SE]": "D03Z02S03[SE]", + "D03Z02S04[S]": "D03Z02S04[S]", + "D03Z03S12[W]": "D03Z03S12[W]", + "D03Z03S01[S]": "D03Z03S12[W]", + "D03Z03S18[E]": "D03Z03S12[W]", + "D03Z03S01[W]": "D03Z03S12[W]", + "D03Z03S02[W]": "D03Z03S12[W]", + "D03Z03S12[E]": "D03Z03S12[W]", + "D03Z02S15[W]": "D03Z02S15[W]", + "D03Z02S07[W]": "D03Z02S07[W]", + "D03Z02S09[S]": "D03Z02S09[S]", + "D03Z02S08[N]": "D03Z02S09[S]", + "D03Z02S14[E]": "D03Z02S09[S]", + "D03Z02S08[W]": "D03Z02S09[S]", + "D03Z02S10[S]": "D03Z02S10[S]", + "D03Z02S10[-Cherubs]": "D03Z02S10[-Cherubs]", + "D03Z02S12[E]": "D03Z02S12[E]", + "D03Z02S09[W]": "D03Z02S09[W]", + "D03Z02S13[-Cherubs]": "D03Z02S13[-Cherubs]", + "D03Z02S10[W]": "D03Z02S10[W]", + "D03Z02S11[E]": "D03Z02S11[E]", + "D20Z01S01[W]": "D20Z01S01[W]", + "D03Z03S02[NE]": "D03Z03S02[NE]", + "D03Z03S14[W]": "D03Z03S02[NE]", + "D03Z03S02[E]": "D03Z03S02[E]", + "D03Z03S04[NW]": "D03Z03S04[NW]", + "D03Z03S03[NE]": "D03Z03S04[NW]", + "D03Z03S04[SW]": "D03Z03S04[SW]", + "D03Z03S03[W]": "D03Z03S03[W]", + "D03Z03S03[SE]": "D03Z03S03[SE]", + "D03Z03S05[NW]": "D03Z03S05[NW]", + "D03Z03S04[NE]": "D03Z03S05[NW]", + "D03Z03S05[SW]": "D03Z03S05[SW]", + "D03Z03S04[E]": "D03Z03S05[SW]", + "D03Z03S07[SW]": "D03Z03S05[SW]", + "D03Z03S05[SE]": "D03Z03S05[SW]", + "D03Z03S13[W]": "D03Z03S13[W]", + "D03Z03S06[W]": "D03Z03S06[W]", + "D03Z03S04[SE]": "D03Z03S04[SE]", + "D03Z03S04[-Cherubs]": "D03Z03S04[-Cherubs]", + "D03Z03S09[SW]": "D03Z03S09[SW]", + "D03Z03S05[NE]": "D03Z03S05[NE]", + "D03Z03S08[W]": "D03Z03S08[W]", + "D03Z03S09[N]": "D03Z03S09[N]", + "D03Z03S11[W]": "D03Z03S11[W]", + "D03Z03S19[E]": "D03Z03S19[E]", + "D03Z03S07[NW]": "D03Z03S19[E]", + "D03Z03S07[NE]": "D03Z03S07[NE]", + "D03Z03S07[E]": "D03Z03S07[E]", + "D03Z03S08[-CherubsL]": "D03Z03S08[-CherubsL]", + "D03Z03S08[-CherubsR]": "D03Z03S08[-CherubsR]", + "D03Z03S15[W]": "D03Z03S15[W]", + "D03Z03S07[S]": "D03Z03S07[S]", + "D03Z03S10[E]": "D03Z03S10[E]", + "D03Z03S11[E]": "D03Z03S11[E]", + "D03Z03S16[W]": "D03Z03S16[W]", + "D03Z03S15[E]": "D03Z03S15[E]", + "D03Z03S17[W]": "D03Z03S17[W]", + "D04Z01S01[W]": "D04Z01S01[W]", + "D08Z01S01[E]": "D08Z01S01[E]", + "D08Z02S02[W]": "D08Z02S02[W]", + "D08Z02S01[SE]": "D08Z02S02[W]", + "D08Z02S03[S]": "D08Z02S02[W]", + "D08Z02S01[N]": "D08Z02S02[W]", + "D04Z01S01[E]": "D04Z01S01[E]", + "D04Z01S01[NE]": "D04Z01S01[NE]", + "D04Z01S03[W]": "D04Z01S03[W]", + "D04Z01S01[N]": "D04Z01S01[N]", + "D04Z01S05[S]": "D04Z01S01[N]", + "D04Z01S06[S]": "D04Z01S06[S]", + "D04Z01S06[Cherubs]": "D04Z01S06[Cherubs]", + "D04Z01S02[W]": "D04Z01S02[W]", + "D04Z01S02[NW]": "D04Z01S02[NW]", + "D04Z01S05[-Cherubs]": "D04Z01S05[-Cherubs]", + "D08Z02S01[E]": "D08Z02S01[E]", + "D04Z01S02[E]": "D04Z01S02[E]", + "D04Z01S04[W]": "D04Z01S04[W]", + "D05Z01S20[N]": "D05Z01S20[N]", + "D04Z01S03[E]": "D04Z01S03[E]", + "D04Z02S01[W]": "D04Z02S01[W]", + "D06Z01S18[-Cherubs]": "D06Z01S18[-Cherubs]", + "D04Z01S03[S]": "D04Z01S03[S]", + "D05Z01S06[E]": "D05Z01S06[E]", + "D05Z01S20[W]": "D05Z01S06[E]", + "D05Z01S07[NW]": "D05Z01S06[E]", + "D05Z01S20[E]": "D05Z01S06[E]", + "D04Z01S04[E]": "D04Z01S04[E]", + "D04Z02S02[S]": "D04Z02S02[S]", + "D04Z02S03[W]": "D04Z02S03[W]", + "D04Z02S01[NE]": "D04Z02S03[W]", + "D04Z02S04[NW]": "D04Z02S03[W]", + "D04Z02S03[E]": "D04Z02S03[W]", + "D04Z02S19[W]": "D04Z02S03[W]", + "D04Z02S04[NE]": "D04Z02S03[W]", + "D04Z03S01[W]": "D04Z03S01[W]", + "D04Z01S05[N]": "D04Z01S05[N]", + "D09Z01S09[SW]": "D09Z01S09[SW]", + "D04Z01S06[E]": "D04Z01S06[E]", + "D09Z01S07[SW]": "D09Z01S07[SW]", + "D09Z01S09[E]": "D09Z01S07[SW]", + "D09Z01S02[SW]": "D09Z01S07[SW]", + "D09Z01S07[E]": "D09Z01S07[SW]", + "D09Z01S08[SE]": "D09Z01S07[SW]", + "D09Z01S07[W]": "D09Z01S07[SW]", + "D09Z01S10[W]": "D09Z01S07[SW]", + "D09Z01S07[SE]": "D09Z01S07[SW]", + "D09Z01S12[E]": "D09Z01S12[E]", + "D04Z02S01[N]": "D04Z02S01[N]", + "D04Z02S15[W]": "D04Z02S15[W]", + "D04Z02S17[W]": "D04Z02S17[W]", + "D06Z01S02[S]": "D06Z01S02[S]", + "D04Z02S02[N]": "D06Z01S02[S]", + "D06Z01S18[E]": "D06Z01S02[S]", + "D06Z01S02[W]": "D06Z01S02[S]", + "D06Z01S08[W]": "D06Z01S02[S]", + "D06Z01S02[E]": "D06Z01S02[S]", + "D04Z02S01[E]": "D04Z02S01[E]", + "D04Z02S04[W]": "D04Z02S04[W]", + "D04Z02S02[SE]": "D04Z02S02[SE]", + "D04Z02S02[NE]": "D04Z02S02[NE]", + "D04Z02S22[W]": "D04Z02S22[W]", + "D04Z02S05[W]": "D04Z02S05[W]", + "D04Z02S04[E]": "D04Z02S05[W]", + "D05Z01S01[NW]": "D04Z02S05[W]", + "D04Z02S04[SE]": "D04Z02S05[W]", + "D05Z01S02[E]": "D04Z02S05[W]", + "D05Z01S01[W]": "D04Z02S05[W]", + "D05Z01S16[W]": "D04Z02S05[W]", + "D05Z01S01[E]": "D04Z02S05[W]", + "D05Z01S03[E]": "D04Z02S05[W]", + "D05Z01S02[NW]": "D04Z02S05[W]", + "D04Z02S06[S]": "D04Z02S06[S]", + "D04Z02S06[-Cherubs]": "D04Z02S06[-Cherubs]", + "D04Z02S14[E]": "D04Z02S14[E]", + "D04Z03S01[E]": "D04Z03S01[E]", + "D04Z02S04[SW]": "D04Z02S04[SW]", + "D04Z02S07[SW]": "D04Z02S07[SW]", + "D04Z02S07[W]": "D04Z02S07[W]", + "D04Z02S04[N]": "D04Z02S04[N]", + "D04Z02S09[W]": "D04Z02S09[W]", + "D04Z02S06[NE]": "D04Z02S09[W]", + "D04Z02S08[W]": "D04Z02S09[W]", + "D04Z02S09[E]": "D04Z02S09[W]", + "D04Z02S20[W]": "D04Z02S09[W]", + "D04Z02S08[E]": "D04Z02S09[W]", + "D04Z02S10[W]": "D04Z02S10[W]", + "D04Z02S06[E]": "D04Z02S10[W]", + "D04Z02S11[E]": "D04Z02S11[E]", + "D06Z01S23[S]": "D06Z01S23[S]", + "D04Z02S05[E]": "D04Z02S05[E]", + "D04Z02S08[S]": "D04Z02S08[S]", + "D04Z02S13[W]": "D04Z02S13[W]", + "D04Z02S19[E]": "D04Z02S19[E]", + "D04Z02S23[W]": "D04Z02S23[W]", + "D04Z02S06[NW]": "D04Z02S06[NW]", + "D04Z02S21[SE]": "D04Z02S21[SE]", + "D04Z02S06[N]": "D04Z02S06[N]", + "D06Z01S01[-Cherubs]": "D06Z01S01[-Cherubs]", + "D06Z01S20[W]": "D06Z01S20[W]", + "D06Z01S23[E]": "D06Z01S20[W]", + "D06Z01S20[E]": "D06Z01S20[W]", + "D06Z01S04[SW]": "D06Z01S20[W]", + "D06Z01S04[W]": "D06Z01S20[W]", + "D06Z01S03[E]": "D06Z01S20[W]", + "D06Z01S22[Sword]": "D06Z01S22[Sword]", + "D04Z02S16[W]": "D04Z02S16[W]", + "D04Z02S07[N]": "D04Z02S07[N]", + "D04Z02S16[-Cherubs]": "D04Z02S16[-Cherubs]", + "D04Z02S07[NE]": "D04Z02S07[NE]", + "D04Z02S07[SE]": "D04Z02S07[SE]", + "D04Z02S24[NW]": "D04Z02S24[NW]", + "D04Z02S23[SE]": "D04Z02S24[NW]", + "D20Z02S01[E]": "D04Z02S24[NW]", + "D04Z02S24[SW]": "D04Z02S24[NW]", + "D04Z02S25[W]": "D04Z02S24[NW]", + "D04Z02S24[SE]": "D04Z02S24[NW]", + "D20Z02S03[SE]": "D04Z02S24[NW]", + "D20Z02S01[W]": "D04Z02S24[NW]", + "D20Z02S04[E]": "D04Z02S24[NW]", + "D20Z02S03[W]": "D04Z02S24[NW]", + "D04Z04S01[W]": "D04Z04S01[W]", + "D04BZ02S01[Redento]": "D04BZ02S01[Redento]", + "D04Z02S09[NE]": "D04Z02S09[NE]", + "D04Z02S11[W]": "D04Z02S11[W]", + "D04Z02S12[W]": "D04Z02S12[W]", + "D04Z02S22[E]": "D04Z02S22[E]", + "D04Z02S21[W]": "D04Z02S22[E]", + "D04Z02S15[E]": "D04Z02S15[E]", + "D04Z02S20[Redento]": "D04Z02S20[Redento]", + "D04Z02S21[NE]": "D04Z02S21[NE]", + "D04Z02S23[NE]": "D04Z02S23[NE]", + "D04Z04S02[W]": "D04Z04S02[W]", + "D04Z03S02[W]": "D04Z03S02[W]", + "D05BZ01S01[FrontalN]": "D05BZ01S01[FrontalN]", + "D04Z04S01[E]": "D04Z04S01[E]", + "D05Z01S15[E]": "D05Z01S15[E]", + "D05Z01S02[W]": "D05Z01S02[W]", + "D05Z01S21[NE]": "D05Z01S21[NE]", + "D05Z01S04[E]": "D05Z01S04[E]", + "D05BZ01S01[FrontalS]": "D05BZ01S01[FrontalS]", + "D05Z01S03[W]": "D05Z01S03[W]", + "D05Z01S05[E]": "D05Z01S05[E]", + "D05Z01S03[Frontal]": "D05Z01S03[Frontal]", + "D05Z01S22[FrontalN]": "D05Z01S22[FrontalN]", + "D05Z01S04[W]": "D05Z01S04[W]", + "D05Z01S07[E]": "D05Z01S07[E]", + "D05Z01S17[W]": "D05Z01S17[W]", + "D05Z01S05[NE]": "D05Z01S17[W]", + "D05Z01S05[SW]": "D05Z01S05[SW]", + "D05Z01S08[NE]": "D05Z01S08[NE]", + "D05Z01S07[SW]": "D05Z01S08[NE]", + "D05Z01S12[E]": "D05Z01S08[NE]", + "D05Z01S08[NW]": "D05Z01S08[NE]", + "D05Z01S09[W]": "D05Z01S08[NE]", + "D05Z01S08[E]": "D05Z01S08[NE]", + "D05Z01S06[W]": "D05Z01S06[W]", + "D05Z01S24[E]": "D05Z01S06[W]", + "D05Z01S10[E]": "D05Z01S10[E]", + "D05Z01S14[W]": "D05Z01S14[W]", + "D05Z01S08[W]": "D05Z01S08[W]", + "D05Z01S11[NE]": "D05Z01S11[NE]", + "D05Z01S11[E]": "D05Z01S11[E]", + "D05Z01S18[W]": "D05Z01S18[W]", + "D05Z01S08[Health]": "D05Z01S08[Health]", + "D05Z01S09[E]": "D05Z01S09[E]", + "D05Z01S10[W]": "D05Z01S10[W]", + "D05Z01S10[NW]": "D05Z01S10[NW]", + "D05Z01S19[E]": "D05Z01S19[E]", + "D05Z01S23[E]": "D05Z01S23[E]", + "D05Z01S11[NW]": "D05Z01S23[E]", + "D05Z02S01[W]": "D05Z02S01[W]", + "D05Z01S11[SW]": "D05Z01S11[SW]", + "D05Z02S15[E]": "D05Z02S15[E]", + "D05Z01S11[SE]": "D05Z01S11[SE]", + "D05Z02S02[NW]": "D05Z02S02[NW]", + "D05Z01S13[E]": "D05Z01S13[E]", + "D05Z01S15[W]": "D05Z01S15[W]", + "D05Z02S14[E]": "D05Z02S14[E]", + "D05Z01S19[W]": "D05Z01S19[W]", + "D05Z02S12[N]": "D05Z02S12[N]", + "D05Z01S21[SW]": "D05Z01S21[SW]", + "D05Z02S06[NE]": "D05Z02S06[NE]", + "D05Z02S14[W]": "D05Z02S06[NE]", + "D05Z02S06[SW]": "D05Z02S06[NE]", + "D05Z02S05[E]": "D05Z02S06[NE]", + "D05Z02S07[E]": "D05Z02S06[NE]", + "D05Z02S06[NW]": "D05Z02S06[NE]", + "D05Z01S21[NW]": "D05Z01S21[NW]", + "D05Z01S21[-Cherubs]": "D05Z01S21[-Cherubs]", + "D05Z02S06[SE]": "D05Z02S06[SE]", + "D05Z01S22[E]": "D05Z01S22[E]", + "D05Z02S01[E]": "D05Z02S01[E]", + "D05Z02S03[E]": "D05Z02S03[E]", + "D05Z02S05[W]": "D05Z02S05[W]", + "D05Z02S09[W]": "D05Z02S09[W]", + "D05Z02S02[SW]": "D05Z02S02[SW]", + "D05Z02S02[SE]": "D05Z02S02[SE]", + "D05Z02S08[W]": "D05Z02S08[W]", + "D05Z02S02[NE]": "D05Z02S02[NE]", + "D05BZ02S01[C]": "D05BZ02S01[C]", + "D05Z02S04[C]": "D05Z02S04[C]", + "D05Z02S11[W]": "D05Z02S11[W]", + "D05Z02S10[E]": "D05Z02S10[E]", + "D05Z02S07[W]": "D05Z02S07[W]", + "D05Z02S13[E]": "D05Z02S13[E]", + "D05Z02S09[E]": "D05Z02S09[E]", + "D05Z02S10[W]": "D05Z02S10[W]", + "D06Z01S01[SW]": "D06Z01S01[SW]", + "D06Z01S14[E]": "D06Z01S01[SW]", + "D06Z01S01[SE]": "D06Z01S01[SW]", + "D06Z01S03[W]": "D06Z01S01[SW]", + "D06Z01S08[E]": "D06Z01S01[SW]", + "D06Z01S14[W]": "D06Z01S01[SW]", + "D06Z01S12[S]": "D06Z01S01[SW]", + "D06Z01S14[N]": "D06Z01S01[SW]", + "D06Z01S01[W]": "D06Z01S01[W]", + "D06Z01S07[E]": "D06Z01S01[W]", + "D06Z01S01[E]": "D06Z01S01[W]", + "D06Z01S06[WW]": "D06Z01S01[W]", + "D06Z01S12[E]": "D06Z01S01[W]", + "D06Z01S07[W]": "D06Z01S01[W]", + "D06Z01S13[E]": "D06Z01S01[W]", + "D06Z01S12[W]": "D06Z01S01[W]", + "D06Z01S16[-CherubsL]": "D06Z01S16[-CherubsL]", + "D06Z01S16[-CherubsR]": "D06Z01S16[-CherubsR]", + "D06Z01S04[NW]": "D06Z01S04[NW]", + "D06Z01S06[E]": "D06Z01S04[NW]", + "D06Z01S04[NE]": "D06Z01S04[NE]", + "D06Z01S06[W]": "D06Z01S04[NE]", + "D06Z01S15[SW]": "D06Z01S15[SW]", + "D06Z01S01[NW]": "D06Z01S01[NW]", + "D06Z01S16[E]": "D06Z01S01[NW]", + "D06Z01S09[-CherubsL]": "D06Z01S09[-CherubsL]", + "D06Z01S09[-CherubsR]": "D06Z01S09[-CherubsR]", + "D06Z01S12[NE2]": "D06Z01S12[NE2]", + "D06Z01S16[W]": "D06Z01S12[NE2]", + "D06Z01S01[NE]": "D06Z01S01[NE]", + "D06Z01S17[W]": "D06Z01S01[NE]", + "D06Z01S10[-CherubsL]": "D06Z01S10[-CherubsL]", + "D06Z01S10[-CherubsR]": "D06Z01S10[-CherubsR]", + "D06Z01S26[W]": "D06Z01S26[W]", + "D06Z01S17[E]": "D06Z01S26[W]", + "D06Z01S01[NNW]": "D06Z01S01[NNW]", + "D06Z01S12[NE]": "D06Z01S12[NE]", + "D06Z01S01[NNE]": "D06Z01S01[NNE]", + "D06Z01S10[W]": "D06Z01S01[NNE]", + "D06Z01S21[W]": "D06Z01S01[NNE]", + "D06Z01S10[E]": "D06Z01S01[NNE]", + "D06Z01S01[N]": "D06Z01S01[N]", + "D06Z01S25[W]": "D06Z01S25[W]", + "D06Z01S19[E]": "D06Z01S25[W]", + "D06Z01S13[S]": "D06Z01S13[S]", + "D06Z01S09[E]": "D06Z01S09[E]", + "D06Z01S19[S]": "D06Z01S19[S]", + "D06Z01S17[-Cherubs]": "D06Z01S17[-Cherubs]", + "D06Z01S24[W]": "D06Z01S24[W]", + "D06Z01S04[Health]": "D06Z01S04[Health]", + "D06Z01S05[E]": "D06Z01S05[E]", + "D06Z01S12[NW]": "D06Z01S05[E]", + "D06Z01S09[W]": "D06Z01S09[W]", + "D06Z01S06[EE]": "D06Z01S06[EE]", + "D06Z01S11[W]": "D06Z01S11[W]", + "D06Z01S21[E]": "D06Z01S21[E]", + "D06Z01S15[NW]": "D06Z01S21[E]", + "D06Z01S08[N]": "D06Z01S08[N]", + "D09Z01S01[E]": "D09Z01S01[E]", + "D06Z01S13[W]": "D06Z01S13[W]", + "D09Z01S11[E]": "D09Z01S11[E]", + "D06Z01S15[NE]": "D06Z01S15[NE]", + "D07Z01S01[W]": "D07Z01S01[W]", + "D06Z01S23[Sword]": "D06Z01S23[Sword]", + "D06Z01S25[E]": "D06Z01S25[E]", + "D07Z01S02[W]": "D07Z01S02[W]", + "D07Z01S01[E]": "D07Z01S01[E]", + "D07Z01S03[W]": "D07Z01S03[W]", + "D07Z01S02[E]": "D07Z01S03[W]", + "D08Z01S02[NE]": "D08Z01S02[NE]", + "D08Z03S02[NW]": "D08Z03S02[NW]", + "D08Z03S03[E]": "D08Z03S02[NW]", + "D08Z01S02[SE]": "D08Z01S02[SE]", + "D08Z03S01[W]": "D08Z03S01[W]", + "D08Z02S03[W]": "D08Z02S03[W]", + "D08Z03S03[W]": "D08Z03S03[W]", + "D08Z02S03[E]": "D08Z02S03[E]", + "D08Z03S02[SW]": "D08Z03S02[SW]", + "D08Z03S01[E]": "D08Z03S01[E]", + "D09Z01S01[W]": "D09Z01S01[W]", + "D09Z01S02[N]": "D09Z01S02[N]", + "D09Z01S11[S]": "D09Z01S02[N]", + "D09Z01S02[NW]": "D09Z01S02[N]", + "D09Z01S07[NE]": "D09Z01S02[N]", + "D09Z01S04[E]": "D09Z01S04[E]", + "D09Z01S04[S]": "D09Z01S04[S]", + "D09Z01S07[N]": "D09Z01S04[S]", + "D09Z01S08[NE]": "D09Z01S04[S]", + "D09Z01S07[NW]": "D09Z01S04[S]", + "D09Z01S03[W]": "D09Z01S03[W]", + "D09Z01S08[W]": "D09Z01S08[W]", + "D09Z01S13[E]": "D09Z01S13[E]", + "D09Z01S05[W]": "D09Z01S13[E]", + "D09Z01S05[SE]": "D09Z01S05[SE]", + "D09Z01S08[S]": "D09Z01S08[S]", + "D09Z01S05[NE]": "D09Z01S05[NE]", + "D09Z01S06[E]": "D09Z01S06[E]", + "D09Z01S11[W]": "D09Z01S11[W]", + "D09Z01S09[NW]": "D09Z01S09[NW]", + "D17Z01S01[E]": "D17Z01S01[E]", + "D17Z01S05[W]": "D17Z01S05[W]", + "D17Z01S02[E]": "D17Z01S05[W]", + "D17Z01S11[W]": "D17Z01S05[W]", + "D17Z01S05[E]": "D17Z01S05[W]", + "D17Z01S10[S]": "D17Z01S10[S]", + "D17Z01S02[N]": "D17Z01S10[S]", + "D17Z01S02[W]": "D17Z01S02[W]", + "D17Z01S14[-Cherubs1]": "D17Z01S14[-Cherubs1]", + "D17Z01S14[-Cherubs2]": "D17Z01S14[-Cherubs2]", + "D17Z01S14[-Cherubs3]": "D17Z01S14[-Cherubs3]", + "D17Z01S04[N]": "D17Z01S04[N]", + "D17Z01S13[E]": "D17Z01S13[E]", + "D17Z01S10[W]": "D17Z01S13[E]", + "D17Z01S14[E]": "D17Z01S13[E]", + "D17Z01S13[W]": "D17Z01S13[E]", + "D17Z01S03[relic]": "D17Z01S03[relic]", + "D17Z01S04[W]": "D17Z01S04[W]", + "D17Z01S04[FrontL]": "D17Z01S04[FrontL]", + "D17Z01S04[FrontR]": "D17Z01S04[FrontR]", + "D17BZ02S01[FrontR]": "D17Z01S04[FrontR]", + "D17Z01S05[S]": "D17Z01S05[S]", + "D17Z01S07[N]": "D17Z01S07[N]", + "D17Z01S12[E]": "D17Z01S12[E]", + "D17BZ02S01[FrontL]": "D17BZ02S01[FrontL]", + "D17Z01S07[SW]": "D17Z01S07[SW]", + "D17Z01S15[E]": "D17Z01S15[E]", + "D17Z01S14[W]": "D17Z01S14[W]", + "D20Z01S01[E]": "D20Z01S01[E]", + "D20Z01S03[W]": "D20Z01S03[W]", + "D20Z02S11[NW]": "D20Z02S11[NW]", + "D20Z02S11[SW]": "D20Z02S11[SW]", + "D20Z01S13[E]": "D20Z01S13[E]", + "D20Z02S10[W]": "D20Z02S10[W]", + "D20Z02S12[E]": "D20Z02S12[E]", + "D20Z03S01[W]": "D20Z03S01[W]", + "D20Z01S14[E]": "D20Z01S14[E]", + "D20Z02S02[W]": "D20Z02S02[W]", + "D20Z02S05[E]": "D20Z02S05[E]", + "D20Z02S04[W]": "D20Z02S05[E]", + "D20Z02S06[SE]": "D20Z02S05[E]", + "D20Z02S05[SW]": "D20Z02S05[E]", + "D20Z02S03[NE]": "D20Z02S03[NE]", + "D20Z02S06[NE]": "D20Z02S06[NE]", + "D20Z02S05[NW]": "D20Z02S06[NE]", + "D20Z02S07[E]": "D20Z02S06[NE]", + "D20Z02S06[NW]": "D20Z02S06[NE]", + "D20Z02S09[E]": "D20Z02S09[E]", + "D20Z02S06[SW]": "D20Z02S06[SW]", + "D20Z02S10[E]": "D20Z02S10[E]", + "D20Z02S08[E]": "D20Z02S08[E]", + "D20Z02S07[W]": "D20Z02S07[W]", + "D20Z02S09[W]": "D20Z02S09[W]", + "D20Z02S11[E]": "D20Z02S11[E]" +} diff --git a/worlds/blasphemous/test/__init__.py b/worlds/blasphemous/test/__init__.py new file mode 100644 index 000000000000..9f89bd26c879 --- /dev/null +++ b/worlds/blasphemous/test/__init__.py @@ -0,0 +1,7 @@ +from test.bases import WorldTestBase +from .. import BlasphemousWorld + + +class BlasphemousTestBase(WorldTestBase): + game = "Blasphemous" + world: BlasphemousWorld diff --git a/worlds/blasphemous/test/test_background_zones.py b/worlds/blasphemous/test/test_background_zones.py new file mode 100644 index 000000000000..cd93f51766a9 --- /dev/null +++ b/worlds/blasphemous/test/test_background_zones.py @@ -0,0 +1,56 @@ +from . import BlasphemousTestBase +from ..Locations import location_names + + +class BotSSGauntletTest(BlasphemousTestBase): + options = { + "starting_location": "albero", + "wall_climb_shuffle": True, + "dash_shuffle": True + } + + @property + def run_default_tests(self) -> bool: + return False + + def test_botss_gauntlet(self) -> None: + self.assertAccessDependency([location_names["CO25"]], [["Dash Ability", "Wall Climb Ability"]], True) + + +class BackgroundZonesTest(BlasphemousTestBase): + @property + def run_default_tests(self) -> bool: + return False + + def test_dc_shroud(self) -> None: + self.assertAccessDependency([location_names["RB03"]], [["Shroud of Dreamt Sins"]], True) + + def test_wothp_bronze_cells(self) -> None: + bronze_locations = [ + location_names["QI70"], + location_names["RESCUED_CHERUB_03"] + ] + + self.assertAccessDependency(bronze_locations, [["Key of the Secular"]], True) + + def test_wothp_silver_cells(self) -> None: + silver_locations = [ + location_names["CO24"], + location_names["RESCUED_CHERUB_34"], + location_names["CO37"], + location_names["RESCUED_CHERUB_04"] + ] + + self.assertAccessDependency(silver_locations, [["Key of the Scribe"]], True) + + def test_wothp_gold_cells(self) -> None: + gold_locations = [ + location_names["QI51"], + location_names["CO26"], + location_names["CO02"] + ] + + self.assertAccessDependency(gold_locations, [["Key of the Inquisitor"]], True) + + def test_wothp_quirce(self) -> None: + self.assertAccessDependency([location_names["BS14"]], [["Key of the Secular", "Key of the Scribe", "Key of the Inquisitor"]], True) diff --git a/worlds/blasphemous/test/test_starting_locations.py b/worlds/blasphemous/test/test_starting_locations.py new file mode 100644 index 000000000000..9e04d52ef369 --- /dev/null +++ b/worlds/blasphemous/test/test_starting_locations.py @@ -0,0 +1,135 @@ +from . import BlasphemousTestBase + + +class TestBrotherhoodEasy(BlasphemousTestBase): + options = { + "starting_location": "brotherhood", + "difficulty": "easy" + } + + +class TestBrotherhoodNormal(BlasphemousTestBase): + options = { + "starting_location": "brotherhood", + "difficulty": "normal" + } + + +class TestBrotherhoodHard(BlasphemousTestBase): + options = { + "starting_location": "brotherhood", + "difficulty": "hard" + } + + +class TestAlberoEasy(BlasphemousTestBase): + options = { + "starting_location": "albero", + "difficulty": "easy" + } + + +class TestAlberoNormal(BlasphemousTestBase): + options = { + "starting_location": "albero", + "difficulty": "normal" + } + + +class TestAlberoHard(BlasphemousTestBase): + options = { + "starting_location": "albero", + "difficulty": "hard" + } + + +class TestConventEasy(BlasphemousTestBase): + options = { + "starting_location": "convent", + "difficulty": "easy" + } + + +class TestConventNormal(BlasphemousTestBase): + options = { + "starting_location": "convent", + "difficulty": "normal" + } + + +class TestConventHard(BlasphemousTestBase): + options = { + "starting_location": "convent", + "difficulty": "hard" + } + + +class TestGrievanceEasy(BlasphemousTestBase): + options = { + "starting_location": "grievance", + "difficulty": "easy" + } + + +class TestGrievanceNormal(BlasphemousTestBase): + options = { + "starting_location": "grievance", + "difficulty": "normal" + } + + +class TestGrievanceHard(BlasphemousTestBase): + options = { + "starting_location": "grievance", + "difficulty": "hard" + } + + +class TestKnotOfWordsEasy(BlasphemousTestBase): + options = { + "starting_location": "knot_of_words", + "difficulty": "easy" + } + + +class TestKnotOfWordsNormal(BlasphemousTestBase): + options = { + "starting_location": "knot_of_words", + "difficulty": "normal" + } + + +class TestKnotOfWordsHard(BlasphemousTestBase): + options = { + "starting_location": "knot_of_words", + "difficulty": "hard" + } + + +class TestRooftopsEasy(BlasphemousTestBase): + options = { + "starting_location": "rooftops", + "difficulty": "easy" + } + + +class TestRooftopsNormal(BlasphemousTestBase): + options = { + "starting_location": "rooftops", + "difficulty": "normal" + } + + +class TestRooftopsHard(BlasphemousTestBase): + options = { + "starting_location": "rooftops", + "difficulty": "hard" + } + + +# mourning and havoc can't be selected on easy or normal. hard only +class TestMourningHavocHard(BlasphemousTestBase): + options = { + "starting_location": "mourning_havoc", + "difficulty": "hard" + } diff --git a/worlds/kh1/Client.py b/worlds/kh1/Client.py new file mode 100644 index 000000000000..acfd5dba3825 --- /dev/null +++ b/worlds/kh1/Client.py @@ -0,0 +1,258 @@ +from __future__ import annotations +import os +import json +import sys +import asyncio +import shutil +import logging +import re +import time +from calendar import timegm + +import ModuleUpdate +ModuleUpdate.update() + +import Utils +death_link = False +item_num = 1 + +logger = logging.getLogger("Client") + +if __name__ == "__main__": + Utils.init_logging("KH1Client", exception_logger="Client") + +from NetUtils import NetworkItem, ClientStatus +from CommonClient import gui_enabled, logger, get_base_parser, ClientCommandProcessor, \ + CommonContext, server_loop + + +def check_stdin() -> None: + if Utils.is_windows and sys.stdin: + print("WARNING: Console input is not routed reliably on Windows, use the GUI instead.") + +class KH1ClientCommandProcessor(ClientCommandProcessor): + def _cmd_deathlink(self): + """Toggles Deathlink""" + global death_link + if death_link: + death_link = False + self.output(f"Death Link turned off") + else: + death_link = True + self.output(f"Death Link turned on") + +class KH1Context(CommonContext): + command_processor: int = KH1ClientCommandProcessor + game = "Kingdom Hearts" + items_handling = 0b111 # full remote + + def __init__(self, server_address, password): + super(KH1Context, self).__init__(server_address, password) + self.send_index: int = 0 + self.syncing = False + self.awaiting_bridge = False + # self.game_communication_path: files go in this path to pass data between us and the actual game + if "localappdata" in os.environ: + self.game_communication_path = os.path.expandvars(r"%localappdata%/KH1FM") + else: + self.game_communication_path = os.path.expandvars(r"$HOME/KH1FM") + if not os.path.exists(self.game_communication_path): + os.makedirs(self.game_communication_path) + for root, dirs, files in os.walk(self.game_communication_path): + for file in files: + if file.find("obtain") <= -1: + os.remove(root+"/"+file) + + async def server_auth(self, password_requested: bool = False): + if password_requested and not self.password: + await super(KH1Context, self).server_auth(password_requested) + await self.get_username() + await self.send_connect() + + async def connection_closed(self): + await super(KH1Context, self).connection_closed() + for root, dirs, files in os.walk(self.game_communication_path): + for file in files: + if file.find("obtain") <= -1: + os.remove(root + "/" + file) + global item_num + item_num = 1 + + @property + def endpoints(self): + if self.server: + return [self.server] + else: + return [] + + async def shutdown(self): + await super(KH1Context, self).shutdown() + for root, dirs, files in os.walk(self.game_communication_path): + for file in files: + if file.find("obtain") <= -1: + os.remove(root+"/"+file) + global item_num + item_num = 1 + + def on_package(self, cmd: str, args: dict): + if cmd in {"Connected"}: + if not os.path.exists(self.game_communication_path): + os.makedirs(self.game_communication_path) + for ss in self.checked_locations: + filename = f"send{ss}" + with open(os.path.join(self.game_communication_path, filename), 'w') as f: + f.close() + + #Handle Slot Data + for key in list(args['slot_data'].keys()): + with open(os.path.join(self.game_communication_path, key + ".cfg"), 'w') as f: + f.write(str(args['slot_data'][key])) + f.close() + + ###Support Legacy Games + if "Required Reports" in list(args['slot_data'].keys()) and "required_reports_eotw" not in list(args['slot_data'].keys()): + reports_required = args['slot_data']["Required Reports"] + with open(os.path.join(self.game_communication_path, "required_reports.cfg"), 'w') as f: + f.write(str(reports_required)) + f.close() + ###End Support Legacy Games + + #End Handle Slot Data + + if cmd in {"ReceivedItems"}: + start_index = args["index"] + if start_index != len(self.items_received): + global item_num + for item in args['items']: + found = False + item_filename = f"AP_{str(item_num)}.item" + for filename in os.listdir(self.game_communication_path): + if filename == item_filename: + found = True + if not found: + with open(os.path.join(self.game_communication_path, item_filename), 'w') as f: + f.write(str(NetworkItem(*item).item) + "\n" + str(NetworkItem(*item).location) + "\n" + str(NetworkItem(*item).player)) + f.close() + item_num = item_num + 1 + + if cmd in {"RoomUpdate"}: + if "checked_locations" in args: + for ss in self.checked_locations: + filename = f"send{ss}" + with open(os.path.join(self.game_communication_path, filename), 'w') as f: + f.close() + + if cmd in {"PrintJSON"} and "type" in args: + if args["type"] == "ItemSend": + item = args["item"] + networkItem = NetworkItem(*item) + recieverID = args["receiving"] + senderID = networkItem.player + locationID = networkItem.location + if recieverID != self.slot and senderID == self.slot: + itemName = self.item_names.lookup_in_slot(networkItem.item, recieverID) + itemCategory = networkItem.flags + recieverName = self.player_names[recieverID] + filename = "sent" + with open(os.path.join(self.game_communication_path, filename), 'w') as f: + f.write( + re.sub('[^A-Za-z0-9 ]+', '',str(itemName))[:15] + "\n" + + re.sub('[^A-Za-z0-9 ]+', '',str(recieverName))[:6] + "\n" + + str(itemCategory) + "\n" + + str(locationID)) + f.close() + + def on_deathlink(self, data: dict[str, object]): + self.last_death_link = max(data["time"], self.last_death_link) + text = data.get("cause", "") + if text: + logger.info(f"DeathLink: {text}") + else: + logger.info(f"DeathLink: Received from {data['source']}") + with open(os.path.join(self.game_communication_path, 'dlreceive'), 'w') as f: + f.write(str(int(data["time"]))) + f.close() + + def run_gui(self): + """Import kivy UI system and start running it as self.ui_task.""" + from kvui import GameManager + + class KH1Manager(GameManager): + logging_pairs = [ + ("Client", "Archipelago") + ] + base_title = "Archipelago KH1 Client" + + self.ui = KH1Manager(self) + self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI") + + +async def game_watcher(ctx: KH1Context): + from .Locations import lookup_id_to_name + while not ctx.exit_event.is_set(): + global death_link + if death_link and "DeathLink" not in ctx.tags: + await ctx.update_death_link(death_link) + if not death_link and "DeathLink" in ctx.tags: + await ctx.update_death_link(death_link) + if ctx.syncing == True: + sync_msg = [{'cmd': 'Sync'}] + if ctx.locations_checked: + sync_msg.append({"cmd": "LocationChecks", "locations": list(ctx.locations_checked)}) + await ctx.send_msgs(sync_msg) + ctx.syncing = False + sending = [] + victory = False + for root, dirs, files in os.walk(ctx.game_communication_path): + for file in files: + if file.find("send") > -1: + st = file.split("send", -1)[1] + if st != "nil": + sending = sending+[(int(st))] + if file.find("victory") > -1: + victory = True + if file.find("dlsend") > -1 and "DeathLink" in ctx.tags: + st = file.split("dlsend", -1)[1] + if st != "nil": + if timegm(time.strptime(st, '%Y%m%d%H%M%S')) > ctx.last_death_link and int(time.time()) % int(timegm(time.strptime(st, '%Y%m%d%H%M%S'))) < 10: + await ctx.send_death(death_text = "Sora was defeated!") + if file.find("insynthshop") > -1: + await ctx.send_msgs([{ + "cmd": "LocationScouts", + "locations": [2656401,2656402,2656403,2656404,2656405,2656406], + "create_as_hint": 2 + }]) + ctx.locations_checked = sending + message = [{"cmd": 'LocationChecks', "locations": sending}] + await ctx.send_msgs(message) + if not ctx.finished_game and victory: + await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}]) + ctx.finished_game = True + await asyncio.sleep(0.1) + + +def launch(): + async def main(args): + ctx = KH1Context(args.connect, args.password) + ctx.server_task = asyncio.create_task(server_loop(ctx), name="server loop") + if gui_enabled: + ctx.run_gui() + ctx.run_cli() + progression_watcher = asyncio.create_task( + game_watcher(ctx), name="KH1ProgressionWatcher") + + await ctx.exit_event.wait() + ctx.server_address = None + + await progression_watcher + + await ctx.shutdown() + + import colorama + + parser = get_base_parser(description="KH1 Client, for text interfacing.") + + args, rest = parser.parse_known_args() + colorama.init() + asyncio.run(main(args)) + colorama.deinit() diff --git a/worlds/kh1/Items.py b/worlds/kh1/Items.py new file mode 100644 index 000000000000..bac98a9b3284 --- /dev/null +++ b/worlds/kh1/Items.py @@ -0,0 +1,532 @@ +from typing import Dict, NamedTuple, Optional, Set + +from BaseClasses import Item, ItemClassification + + +class KH1Item(Item): + game: str = "Kingdom Hearts" + + +class KH1ItemData(NamedTuple): + category: str + code: int + classification: ItemClassification = ItemClassification.filler + max_quantity: int = 1 + weight: int = 1 + + +def get_items_by_category(category: str) -> Dict[str, KH1ItemData]: + item_dict: Dict[str, KH1ItemData] = {} + for name, data in item_table.items(): + if data.category == category: + item_dict.setdefault(name, data) + + return item_dict + + +item_table: Dict[str, KH1ItemData] = { + "Victory": KH1ItemData("VIC", code = 264_0000, classification = ItemClassification.progression, ), + "Potion": KH1ItemData("Item", code = 264_1001, classification = ItemClassification.filler, ), + "Hi-Potion": KH1ItemData("Item", code = 264_1002, classification = ItemClassification.filler, ), + "Ether": KH1ItemData("Item", code = 264_1003, classification = ItemClassification.filler, ), + "Elixir": KH1ItemData("Item", code = 264_1004, classification = ItemClassification.filler, ), + #"B05": KH1ItemData("Item", code = 264_1005, classification = ItemClassification.filler, ), + "Mega-Potion": KH1ItemData("Item", code = 264_1006, classification = ItemClassification.filler, ), + "Mega-Ether": KH1ItemData("Item", code = 264_1007, classification = ItemClassification.filler, ), + "Megalixir": KH1ItemData("Item", code = 264_1008, classification = ItemClassification.filler, ), + #"Fury Stone": KH1ItemData("Synthesis", code = 264_1009, classification = ItemClassification.filler, ), + #"Power Stone": KH1ItemData("Synthesis", code = 264_1010, classification = ItemClassification.filler, ), + #"Energy Stone": KH1ItemData("Synthesis", code = 264_1011, classification = ItemClassification.filler, ), + #"Blazing Stone": KH1ItemData("Synthesis", code = 264_1012, classification = ItemClassification.filler, ), + #"Frost Stone": KH1ItemData("Synthesis", code = 264_1013, classification = ItemClassification.filler, ), + #"Lightning Stone": KH1ItemData("Synthesis", code = 264_1014, classification = ItemClassification.filler, ), + #"Dazzling Stone": KH1ItemData("Synthesis", code = 264_1015, classification = ItemClassification.filler, ), + #"Stormy Stone": KH1ItemData("Synthesis", code = 264_1016, classification = ItemClassification.filler, ), + "Protect Chain": KH1ItemData("Accessory", code = 264_1017, classification = ItemClassification.useful, ), + "Protera Chain": KH1ItemData("Accessory", code = 264_1018, classification = ItemClassification.useful, ), + "Protega Chain": KH1ItemData("Accessory", code = 264_1019, classification = ItemClassification.useful, ), + "Fire Ring": KH1ItemData("Accessory", code = 264_1020, classification = ItemClassification.useful, ), + "Fira Ring": KH1ItemData("Accessory", code = 264_1021, classification = ItemClassification.useful, ), + "Firaga Ring": KH1ItemData("Accessory", code = 264_1022, classification = ItemClassification.useful, ), + "Blizzard Ring": KH1ItemData("Accessory", code = 264_1023, classification = ItemClassification.useful, ), + "Blizzara Ring": KH1ItemData("Accessory", code = 264_1024, classification = ItemClassification.useful, ), + "Blizzaga Ring": KH1ItemData("Accessory", code = 264_1025, classification = ItemClassification.useful, ), + "Thunder Ring": KH1ItemData("Accessory", code = 264_1026, classification = ItemClassification.useful, ), + "Thundara Ring": KH1ItemData("Accessory", code = 264_1027, classification = ItemClassification.useful, ), + "Thundaga Ring": KH1ItemData("Accessory", code = 264_1028, classification = ItemClassification.useful, ), + "Ability Stud": KH1ItemData("Accessory", code = 264_1029, classification = ItemClassification.useful, ), + "Guard Earring": KH1ItemData("Accessory", code = 264_1030, classification = ItemClassification.useful, ), + "Master Earring": KH1ItemData("Accessory", code = 264_1031, classification = ItemClassification.useful, ), + "Chaos Ring": KH1ItemData("Accessory", code = 264_1032, classification = ItemClassification.useful, ), + "Dark Ring": KH1ItemData("Accessory", code = 264_1033, classification = ItemClassification.useful, ), + "Element Ring": KH1ItemData("Accessory", code = 264_1034, classification = ItemClassification.useful, ), + "Three Stars": KH1ItemData("Accessory", code = 264_1035, classification = ItemClassification.useful, ), + "Power Chain": KH1ItemData("Accessory", code = 264_1036, classification = ItemClassification.useful, ), + "Golem Chain": KH1ItemData("Accessory", code = 264_1037, classification = ItemClassification.useful, ), + "Titan Chain": KH1ItemData("Accessory", code = 264_1038, classification = ItemClassification.useful, ), + "Energy Bangle": KH1ItemData("Accessory", code = 264_1039, classification = ItemClassification.useful, ), + "Angel Bangle": KH1ItemData("Accessory", code = 264_1040, classification = ItemClassification.useful, ), + "Gaia Bangle": KH1ItemData("Accessory", code = 264_1041, classification = ItemClassification.useful, ), + "Magic Armlet": KH1ItemData("Accessory", code = 264_1042, classification = ItemClassification.useful, ), + "Rune Armlet": KH1ItemData("Accessory", code = 264_1043, classification = ItemClassification.useful, ), + "Atlas Armlet": KH1ItemData("Accessory", code = 264_1044, classification = ItemClassification.useful, ), + "Heartguard": KH1ItemData("Accessory", code = 264_1045, classification = ItemClassification.useful, ), + "Ribbon": KH1ItemData("Accessory", code = 264_1046, classification = ItemClassification.useful, ), + "Crystal Crown": KH1ItemData("Accessory", code = 264_1047, classification = ItemClassification.useful, ), + "Brave Warrior": KH1ItemData("Accessory", code = 264_1048, classification = ItemClassification.useful, ), + "Ifrit's Horn": KH1ItemData("Accessory", code = 264_1049, classification = ItemClassification.useful, ), + "Inferno Band": KH1ItemData("Accessory", code = 264_1050, classification = ItemClassification.useful, ), + "White Fang": KH1ItemData("Accessory", code = 264_1051, classification = ItemClassification.useful, ), + "Ray of Light": KH1ItemData("Accessory", code = 264_1052, classification = ItemClassification.useful, ), + "Holy Circlet": KH1ItemData("Accessory", code = 264_1053, classification = ItemClassification.useful, ), + "Raven's Claw": KH1ItemData("Accessory", code = 264_1054, classification = ItemClassification.useful, ), + "Omega Arts": KH1ItemData("Accessory", code = 264_1055, classification = ItemClassification.useful, ), + "EXP Earring": KH1ItemData("Accessory", code = 264_1056, classification = ItemClassification.useful, ), + #"A41": KH1ItemData("Accessory", code = 264_1057, classification = ItemClassification.useful, ), + "EXP Ring": KH1ItemData("Accessory", code = 264_1058, classification = ItemClassification.useful, ), + "EXP Bracelet": KH1ItemData("Accessory", code = 264_1059, classification = ItemClassification.useful, ), + "EXP Necklace": KH1ItemData("Accessory", code = 264_1060, classification = ItemClassification.useful, ), + "Firagun Band": KH1ItemData("Accessory", code = 264_1061, classification = ItemClassification.useful, ), + "Blizzagun Band": KH1ItemData("Accessory", code = 264_1062, classification = ItemClassification.useful, ), + "Thundagun Band": KH1ItemData("Accessory", code = 264_1063, classification = ItemClassification.useful, ), + "Ifrit Belt": KH1ItemData("Accessory", code = 264_1064, classification = ItemClassification.useful, ), + "Shiva Belt": KH1ItemData("Accessory", code = 264_1065, classification = ItemClassification.useful, ), + "Ramuh Belt": KH1ItemData("Accessory", code = 264_1066, classification = ItemClassification.useful, ), + "Moogle Badge": KH1ItemData("Accessory", code = 264_1067, classification = ItemClassification.useful, ), + "Cosmic Arts": KH1ItemData("Accessory", code = 264_1068, classification = ItemClassification.useful, ), + "Royal Crown": KH1ItemData("Accessory", code = 264_1069, classification = ItemClassification.useful, ), + "Prime Cap": KH1ItemData("Accessory", code = 264_1070, classification = ItemClassification.useful, ), + "Obsidian Ring": KH1ItemData("Accessory", code = 264_1071, classification = ItemClassification.useful, ), + #"A56": KH1ItemData("Accessory", code = 264_1072, classification = ItemClassification.filler, ), + #"A57": KH1ItemData("Accessory", code = 264_1073, classification = ItemClassification.filler, ), + #"A58": KH1ItemData("Accessory", code = 264_1074, classification = ItemClassification.filler, ), + #"A59": KH1ItemData("Accessory", code = 264_1075, classification = ItemClassification.filler, ), + #"A60": KH1ItemData("Accessory", code = 264_1076, classification = ItemClassification.filler, ), + #"A61": KH1ItemData("Accessory", code = 264_1077, classification = ItemClassification.filler, ), + #"A62": KH1ItemData("Accessory", code = 264_1078, classification = ItemClassification.filler, ), + #"A63": KH1ItemData("Accessory", code = 264_1079, classification = ItemClassification.filler, ), + #"A64": KH1ItemData("Accessory", code = 264_1080, classification = ItemClassification.filler, ), + #"Kingdom Key": KH1ItemData("Keyblades", code = 264_1081, classification = ItemClassification.useful, ), + #"Dream Sword": KH1ItemData("Keyblades", code = 264_1082, classification = ItemClassification.useful, ), + #"Dream Shield": KH1ItemData("Keyblades", code = 264_1083, classification = ItemClassification.useful, ), + #"Dream Rod": KH1ItemData("Keyblades", code = 264_1084, classification = ItemClassification.useful, ), + "Wooden Sword": KH1ItemData("Keyblades", code = 264_1085, classification = ItemClassification.useful, ), + "Jungle King": KH1ItemData("Keyblades", code = 264_1086, classification = ItemClassification.progression, ), + "Three Wishes": KH1ItemData("Keyblades", code = 264_1087, classification = ItemClassification.progression, ), + "Fairy Harp": KH1ItemData("Keyblades", code = 264_1088, classification = ItemClassification.progression, ), + "Pumpkinhead": KH1ItemData("Keyblades", code = 264_1089, classification = ItemClassification.progression, ), + "Crabclaw": KH1ItemData("Keyblades", code = 264_1090, classification = ItemClassification.useful, ), + "Divine Rose": KH1ItemData("Keyblades", code = 264_1091, classification = ItemClassification.progression, ), + "Spellbinder": KH1ItemData("Keyblades", code = 264_1092, classification = ItemClassification.useful, ), + "Olympia": KH1ItemData("Keyblades", code = 264_1093, classification = ItemClassification.progression, ), + "Lionheart": KH1ItemData("Keyblades", code = 264_1094, classification = ItemClassification.progression, ), + "Metal Chocobo": KH1ItemData("Keyblades", code = 264_1095, classification = ItemClassification.useful, ), + "Oathkeeper": KH1ItemData("Keyblades", code = 264_1096, classification = ItemClassification.progression, ), + "Oblivion": KH1ItemData("Keyblades", code = 264_1097, classification = ItemClassification.progression, ), + "Lady Luck": KH1ItemData("Keyblades", code = 264_1098, classification = ItemClassification.progression, ), + "Wishing Star": KH1ItemData("Keyblades", code = 264_1099, classification = ItemClassification.progression, ), + "Ultima Weapon": KH1ItemData("Keyblades", code = 264_1100, classification = ItemClassification.useful, ), + "Diamond Dust": KH1ItemData("Keyblades", code = 264_1101, classification = ItemClassification.useful, ), + "One-Winged Angel": KH1ItemData("Keyblades", code = 264_1102, classification = ItemClassification.useful, ), + #"Mage's Staff": KH1ItemData("Weapons", code = 264_1103, classification = ItemClassification.filler, ), + "Morning Star": KH1ItemData("Weapons", code = 264_1104, classification = ItemClassification.useful, ), + "Shooting Star": KH1ItemData("Weapons", code = 264_1105, classification = ItemClassification.useful, ), + "Magus Staff": KH1ItemData("Weapons", code = 264_1106, classification = ItemClassification.useful, ), + "Wisdom Staff": KH1ItemData("Weapons", code = 264_1107, classification = ItemClassification.useful, ), + "Warhammer": KH1ItemData("Weapons", code = 264_1108, classification = ItemClassification.useful, ), + "Silver Mallet": KH1ItemData("Weapons", code = 264_1109, classification = ItemClassification.useful, ), + "Grand Mallet": KH1ItemData("Weapons", code = 264_1110, classification = ItemClassification.useful, ), + "Lord Fortune": KH1ItemData("Weapons", code = 264_1111, classification = ItemClassification.useful, ), + "Violetta": KH1ItemData("Weapons", code = 264_1112, classification = ItemClassification.useful, ), + "Dream Rod (Donald)": KH1ItemData("Weapons", code = 264_1113, classification = ItemClassification.useful, ), + "Save the Queen": KH1ItemData("Weapons", code = 264_1114, classification = ItemClassification.useful, ), + "Wizard's Relic": KH1ItemData("Weapons", code = 264_1115, classification = ItemClassification.useful, ), + "Meteor Strike": KH1ItemData("Weapons", code = 264_1116, classification = ItemClassification.useful, ), + "Fantasista": KH1ItemData("Weapons", code = 264_1117, classification = ItemClassification.useful, ), + #"Unused (Donald)": KH1ItemData("Weapons", code = 264_1118, classification = ItemClassification.filler, ), + #"Knight's Shield": KH1ItemData("Weapons", code = 264_1119, classification = ItemClassification.filler, ), + "Mythril Shield": KH1ItemData("Weapons", code = 264_1120, classification = ItemClassification.useful, ), + "Onyx Shield": KH1ItemData("Weapons", code = 264_1121, classification = ItemClassification.useful, ), + "Stout Shield": KH1ItemData("Weapons", code = 264_1122, classification = ItemClassification.useful, ), + "Golem Shield": KH1ItemData("Weapons", code = 264_1123, classification = ItemClassification.useful, ), + "Adamant Shield": KH1ItemData("Weapons", code = 264_1124, classification = ItemClassification.useful, ), + "Smasher": KH1ItemData("Weapons", code = 264_1125, classification = ItemClassification.useful, ), + "Gigas Fist": KH1ItemData("Weapons", code = 264_1126, classification = ItemClassification.useful, ), + "Genji Shield": KH1ItemData("Weapons", code = 264_1127, classification = ItemClassification.useful, ), + "Herc's Shield": KH1ItemData("Weapons", code = 264_1128, classification = ItemClassification.useful, ), + "Dream Shield (Goofy)": KH1ItemData("Weapons", code = 264_1129, classification = ItemClassification.useful, ), + "Save the King": KH1ItemData("Weapons", code = 264_1130, classification = ItemClassification.useful, ), + "Defender": KH1ItemData("Weapons", code = 264_1131, classification = ItemClassification.useful, ), + "Mighty Shield": KH1ItemData("Weapons", code = 264_1132, classification = ItemClassification.useful, ), + "Seven Elements": KH1ItemData("Weapons", code = 264_1133, classification = ItemClassification.useful, ), + #"Unused (Goofy)": KH1ItemData("Weapons", code = 264_1134, classification = ItemClassification.filler, ), + #"Spear": KH1ItemData("Weapons", code = 264_1135, classification = ItemClassification.filler, ), + #"No Weapon": KH1ItemData("Weapons", code = 264_1136, classification = ItemClassification.filler, ), + #"Genie": KH1ItemData("Weapons", code = 264_1137, classification = ItemClassification.filler, ), + #"No Weapon": KH1ItemData("Weapons", code = 264_1138, classification = ItemClassification.filler, ), + #"No Weapon": KH1ItemData("Weapons", code = 264_1139, classification = ItemClassification.filler, ), + #"Tinker Bell": KH1ItemData("Weapons", code = 264_1140, classification = ItemClassification.filler, ), + #"Claws": KH1ItemData("Weapons", code = 264_1141, classification = ItemClassification.filler, ), + "Tent": KH1ItemData("Camping", code = 264_1142, classification = ItemClassification.filler, ), + "Camping Set": KH1ItemData("Camping", code = 264_1143, classification = ItemClassification.filler, ), + "Cottage": KH1ItemData("Camping", code = 264_1144, classification = ItemClassification.filler, ), + #"C04": KH1ItemData("Camping", code = 264_1145, classification = ItemClassification.filler, ), + #"C05": KH1ItemData("Camping", code = 264_1146, classification = ItemClassification.filler, ), + #"C06": KH1ItemData("Camping", code = 264_1147, classification = ItemClassification.filler, ), + #"C07": KH1ItemData("Camping", code = 264_1148, classification = ItemClassification.filler, ), + "Ansem's Report 11": KH1ItemData("Reports", code = 264_1149, classification = ItemClassification.progression, ), + "Ansem's Report 12": KH1ItemData("Reports", code = 264_1150, classification = ItemClassification.progression, ), + "Ansem's Report 13": KH1ItemData("Reports", code = 264_1151, classification = ItemClassification.progression, ), + "Power Up": KH1ItemData("Stat Ups", code = 264_1152, classification = ItemClassification.filler, ), + "Defense Up": KH1ItemData("Stat Ups", code = 264_1153, classification = ItemClassification.filler, ), + "AP Up": KH1ItemData("Stat Ups", code = 264_1154, classification = ItemClassification.filler, ), + #"Serenity Power": KH1ItemData("Synthesis", code = 264_1155, classification = ItemClassification.filler, ), + #"Dark Matter": KH1ItemData("Synthesis", code = 264_1156, classification = ItemClassification.filler, ), + #"Mythril Stone": KH1ItemData("Synthesis", code = 264_1157, classification = ItemClassification.filler, ), + "Fire Arts": KH1ItemData("Key", code = 264_1158, classification = ItemClassification.progression, ), + "Blizzard Arts": KH1ItemData("Key", code = 264_1159, classification = ItemClassification.progression, ), + "Thunder Arts": KH1ItemData("Key", code = 264_1160, classification = ItemClassification.progression, ), + "Cure Arts": KH1ItemData("Key", code = 264_1161, classification = ItemClassification.progression, ), + "Gravity Arts": KH1ItemData("Key", code = 264_1162, classification = ItemClassification.progression, ), + "Stop Arts": KH1ItemData("Key", code = 264_1163, classification = ItemClassification.progression, ), + "Aero Arts": KH1ItemData("Key", code = 264_1164, classification = ItemClassification.progression, ), + #"Shiitank Rank": KH1ItemData("Synthesis", code = 264_1165, classification = ItemClassification.filler, ), + #"Matsutake Rank": KH1ItemData("Synthesis", code = 264_1166, classification = ItemClassification.filler, ), + #"Mystery Mold": KH1ItemData("Synthesis", code = 264_1167, classification = ItemClassification.filler, ), + "Ansem's Report 1": KH1ItemData("Reports", code = 264_1168, classification = ItemClassification.progression, ), + "Ansem's Report 2": KH1ItemData("Reports", code = 264_1169, classification = ItemClassification.progression, ), + "Ansem's Report 3": KH1ItemData("Reports", code = 264_1170, classification = ItemClassification.progression, ), + "Ansem's Report 4": KH1ItemData("Reports", code = 264_1171, classification = ItemClassification.progression, ), + "Ansem's Report 5": KH1ItemData("Reports", code = 264_1172, classification = ItemClassification.progression, ), + "Ansem's Report 6": KH1ItemData("Reports", code = 264_1173, classification = ItemClassification.progression, ), + "Ansem's Report 7": KH1ItemData("Reports", code = 264_1174, classification = ItemClassification.progression, ), + "Ansem's Report 8": KH1ItemData("Reports", code = 264_1175, classification = ItemClassification.progression, ), + "Ansem's Report 9": KH1ItemData("Reports", code = 264_1176, classification = ItemClassification.progression, ), + "Ansem's Report 10": KH1ItemData("Reports", code = 264_1177, classification = ItemClassification.progression, ), + #"Khama Vol. 8": KH1ItemData("Key", code = 264_1178, classification = ItemClassification.progression, ), + #"Salegg Vol. 6": KH1ItemData("Key", code = 264_1179, classification = ItemClassification.progression, ), + #"Azal Vol. 3": KH1ItemData("Key", code = 264_1180, classification = ItemClassification.progression, ), + #"Mava Vol. 3": KH1ItemData("Key", code = 264_1181, classification = ItemClassification.progression, ), + #"Mava Vol. 6": KH1ItemData("Key", code = 264_1182, classification = ItemClassification.progression, ), + "Theon Vol. 6": KH1ItemData("Key", code = 264_1183, classification = ItemClassification.progression, ), + #"Nahara Vol. 5": KH1ItemData("Key", code = 264_1184, classification = ItemClassification.progression, ), + #"Hafet Vol. 4": KH1ItemData("Key", code = 264_1185, classification = ItemClassification.progression, ), + "Empty Bottle": KH1ItemData("Key", code = 264_1186, classification = ItemClassification.progression, max_quantity = 6 ), + #"Old Book": KH1ItemData("Key", code = 264_1187, classification = ItemClassification.progression, ), + "Emblem Piece (Flame)": KH1ItemData("Key", code = 264_1188, classification = ItemClassification.progression, ), + "Emblem Piece (Chest)": KH1ItemData("Key", code = 264_1189, classification = ItemClassification.progression, ), + "Emblem Piece (Statue)": KH1ItemData("Key", code = 264_1190, classification = ItemClassification.progression, ), + "Emblem Piece (Fountain)": KH1ItemData("Key", code = 264_1191, classification = ItemClassification.progression, ), + #"Log": KH1ItemData("Key", code = 264_1192, classification = ItemClassification.progression, ), + #"Cloth": KH1ItemData("Key", code = 264_1193, classification = ItemClassification.progression, ), + #"Rope": KH1ItemData("Key", code = 264_1194, classification = ItemClassification.progression, ), + #"Seagull Egg": KH1ItemData("Key", code = 264_1195, classification = ItemClassification.progression, ), + #"Fish": KH1ItemData("Key", code = 264_1196, classification = ItemClassification.progression, ), + #"Mushroom": KH1ItemData("Key", code = 264_1197, classification = ItemClassification.progression, ), + #"Coconut": KH1ItemData("Key", code = 264_1198, classification = ItemClassification.progression, ), + #"Drinking Water": KH1ItemData("Key", code = 264_1199, classification = ItemClassification.progression, ), + #"Navi-G Piece 1": KH1ItemData("Key", code = 264_1200, classification = ItemClassification.progression, ), + #"Navi-G Piece 2": KH1ItemData("Key", code = 264_1201, classification = ItemClassification.progression, ), + #"Navi-Gummi Unused": KH1ItemData("Key", code = 264_1202, classification = ItemClassification.progression, ), + #"Navi-G Piece 3": KH1ItemData("Key", code = 264_1203, classification = ItemClassification.progression, ), + #"Navi-G Piece 4": KH1ItemData("Key", code = 264_1204, classification = ItemClassification.progression, ), + #"Navi-Gummi": KH1ItemData("Key", code = 264_1205, classification = ItemClassification.progression, ), + #"Watergleam": KH1ItemData("Key", code = 264_1206, classification = ItemClassification.progression, ), + #"Naturespark": KH1ItemData("Key", code = 264_1207, classification = ItemClassification.progression, ), + #"Fireglow": KH1ItemData("Key", code = 264_1208, classification = ItemClassification.progression, ), + #"Earthshine": KH1ItemData("Key", code = 264_1209, classification = ItemClassification.progression, ), + "Crystal Trident": KH1ItemData("Key", code = 264_1210, classification = ItemClassification.progression, ), + "Postcard": KH1ItemData("Key", code = 264_1211, classification = ItemClassification.progression, max_quantity = 10), + "Torn Page 1": KH1ItemData("Torn Pages", code = 264_1212, classification = ItemClassification.progression, ), + "Torn Page 2": KH1ItemData("Torn Pages", code = 264_1213, classification = ItemClassification.progression, ), + "Torn Page 3": KH1ItemData("Torn Pages", code = 264_1214, classification = ItemClassification.progression, ), + "Torn Page 4": KH1ItemData("Torn Pages", code = 264_1215, classification = ItemClassification.progression, ), + "Torn Page 5": KH1ItemData("Torn Pages", code = 264_1216, classification = ItemClassification.progression, ), + "Slides": KH1ItemData("Key", code = 264_1217, classification = ItemClassification.progression, ), + #"Slide 2": KH1ItemData("Key", code = 264_1218, classification = ItemClassification.progression, ), + #"Slide 3": KH1ItemData("Key", code = 264_1219, classification = ItemClassification.progression, ), + #"Slide 4": KH1ItemData("Key", code = 264_1220, classification = ItemClassification.progression, ), + #"Slide 5": KH1ItemData("Key", code = 264_1221, classification = ItemClassification.progression, ), + #"Slide 6": KH1ItemData("Key", code = 264_1222, classification = ItemClassification.progression, ), + "Footprints": KH1ItemData("Key", code = 264_1223, classification = ItemClassification.progression, ), + #"Claw Marks": KH1ItemData("Key", code = 264_1224, classification = ItemClassification.progression, ), + #"Stench": KH1ItemData("Key", code = 264_1225, classification = ItemClassification.progression, ), + #"Antenna": KH1ItemData("Key", code = 264_1226, classification = ItemClassification.progression, ), + "Forget-Me-Not": KH1ItemData("Key", code = 264_1227, classification = ItemClassification.progression, ), + "Jack-In-The-Box": KH1ItemData("Key", code = 264_1228, classification = ItemClassification.progression, ), + "Entry Pass": KH1ItemData("Key", code = 264_1229, classification = ItemClassification.progression, ), + #"Hero License": KH1ItemData("Key", code = 264_1230, classification = ItemClassification.progression, ), + #"Pretty Stone": KH1ItemData("Synthesis", code = 264_1231, classification = ItemClassification.filler, ), + #"N41": KH1ItemData("Synthesis", code = 264_1232, classification = ItemClassification.filler, ), + #"Lucid Shard": KH1ItemData("Synthesis", code = 264_1233, classification = ItemClassification.filler, ), + #"Lucid Gem": KH1ItemData("Synthesis", code = 264_1234, classification = ItemClassification.filler, ), + #"Lucid Crystal": KH1ItemData("Synthesis", code = 264_1235, classification = ItemClassification.filler, ), + #"Spirit Shard": KH1ItemData("Synthesis", code = 264_1236, classification = ItemClassification.filler, ), + #"Spirit Gem": KH1ItemData("Synthesis", code = 264_1237, classification = ItemClassification.filler, ), + #"Power Shard": KH1ItemData("Synthesis", code = 264_1238, classification = ItemClassification.filler, ), + #"Power Gem": KH1ItemData("Synthesis", code = 264_1239, classification = ItemClassification.filler, ), + #"Power Crystal": KH1ItemData("Synthesis", code = 264_1240, classification = ItemClassification.filler, ), + #"Blaze Shard": KH1ItemData("Synthesis", code = 264_1241, classification = ItemClassification.filler, ), + #"Blaze Gem": KH1ItemData("Synthesis", code = 264_1242, classification = ItemClassification.filler, ), + #"Frost Shard": KH1ItemData("Synthesis", code = 264_1243, classification = ItemClassification.filler, ), + #"Frost Gem": KH1ItemData("Synthesis", code = 264_1244, classification = ItemClassification.filler, ), + #"Thunder Shard": KH1ItemData("Synthesis", code = 264_1245, classification = ItemClassification.filler, ), + #"Thunder Gem": KH1ItemData("Synthesis", code = 264_1246, classification = ItemClassification.filler, ), + #"Shiny Crystal": KH1ItemData("Synthesis", code = 264_1247, classification = ItemClassification.filler, ), + #"Bright Shard": KH1ItemData("Synthesis", code = 264_1248, classification = ItemClassification.filler, ), + #"Bright Gem": KH1ItemData("Synthesis", code = 264_1249, classification = ItemClassification.filler, ), + #"Bright Crystal": KH1ItemData("Synthesis", code = 264_1250, classification = ItemClassification.filler, ), + #"Mystery Goo": KH1ItemData("Synthesis", code = 264_1251, classification = ItemClassification.filler, ), + #"Gale": KH1ItemData("Synthesis", code = 264_1252, classification = ItemClassification.filler, ), + #"Mythril Shard": KH1ItemData("Synthesis", code = 264_1253, classification = ItemClassification.filler, ), + #"Mythril": KH1ItemData("Synthesis", code = 264_1254, classification = ItemClassification.filler, ), + #"Orichalcum": KH1ItemData("Synthesis", code = 264_1255, classification = ItemClassification.filler, ), + "High Jump": KH1ItemData("Shared Abilities", code = 264_2001, classification = ItemClassification.progression, ), + "Mermaid Kick": KH1ItemData("Shared Abilities", code = 264_2002, classification = ItemClassification.progression, ), + "Progressive Glide": KH1ItemData("Shared Abilities", code = 264_2003, classification = ItemClassification.progression, max_quantity = 2 ), + #"Superglide": KH1ItemData("Shared Abilities", code = 264_2004, classification = ItemClassification.progression, ), + "Puppy 01": KH1ItemData("Puppies", code = 264_2101, classification = ItemClassification.progression, ), + "Puppy 02": KH1ItemData("Puppies", code = 264_2102, classification = ItemClassification.progression, ), + "Puppy 03": KH1ItemData("Puppies", code = 264_2103, classification = ItemClassification.progression, ), + "Puppy 04": KH1ItemData("Puppies", code = 264_2104, classification = ItemClassification.progression, ), + "Puppy 05": KH1ItemData("Puppies", code = 264_2105, classification = ItemClassification.progression, ), + "Puppy 06": KH1ItemData("Puppies", code = 264_2106, classification = ItemClassification.progression, ), + "Puppy 07": KH1ItemData("Puppies", code = 264_2107, classification = ItemClassification.progression, ), + "Puppy 08": KH1ItemData("Puppies", code = 264_2108, classification = ItemClassification.progression, ), + "Puppy 09": KH1ItemData("Puppies", code = 264_2109, classification = ItemClassification.progression, ), + "Puppy 10": KH1ItemData("Puppies", code = 264_2110, classification = ItemClassification.progression, ), + "Puppy 11": KH1ItemData("Puppies", code = 264_2111, classification = ItemClassification.progression, ), + "Puppy 12": KH1ItemData("Puppies", code = 264_2112, classification = ItemClassification.progression, ), + "Puppy 13": KH1ItemData("Puppies", code = 264_2113, classification = ItemClassification.progression, ), + "Puppy 14": KH1ItemData("Puppies", code = 264_2114, classification = ItemClassification.progression, ), + "Puppy 15": KH1ItemData("Puppies", code = 264_2115, classification = ItemClassification.progression, ), + "Puppy 16": KH1ItemData("Puppies", code = 264_2116, classification = ItemClassification.progression, ), + "Puppy 17": KH1ItemData("Puppies", code = 264_2117, classification = ItemClassification.progression, ), + "Puppy 18": KH1ItemData("Puppies", code = 264_2118, classification = ItemClassification.progression, ), + "Puppy 19": KH1ItemData("Puppies", code = 264_2119, classification = ItemClassification.progression, ), + "Puppy 20": KH1ItemData("Puppies", code = 264_2120, classification = ItemClassification.progression, ), + "Puppy 21": KH1ItemData("Puppies", code = 264_2121, classification = ItemClassification.progression, ), + "Puppy 22": KH1ItemData("Puppies", code = 264_2122, classification = ItemClassification.progression, ), + "Puppy 23": KH1ItemData("Puppies", code = 264_2123, classification = ItemClassification.progression, ), + "Puppy 24": KH1ItemData("Puppies", code = 264_2124, classification = ItemClassification.progression, ), + "Puppy 25": KH1ItemData("Puppies", code = 264_2125, classification = ItemClassification.progression, ), + "Puppy 26": KH1ItemData("Puppies", code = 264_2126, classification = ItemClassification.progression, ), + "Puppy 27": KH1ItemData("Puppies", code = 264_2127, classification = ItemClassification.progression, ), + "Puppy 28": KH1ItemData("Puppies", code = 264_2128, classification = ItemClassification.progression, ), + "Puppy 29": KH1ItemData("Puppies", code = 264_2129, classification = ItemClassification.progression, ), + "Puppy 30": KH1ItemData("Puppies", code = 264_2130, classification = ItemClassification.progression, ), + "Puppy 31": KH1ItemData("Puppies", code = 264_2131, classification = ItemClassification.progression, ), + "Puppy 32": KH1ItemData("Puppies", code = 264_2132, classification = ItemClassification.progression, ), + "Puppy 33": KH1ItemData("Puppies", code = 264_2133, classification = ItemClassification.progression, ), + "Puppy 34": KH1ItemData("Puppies", code = 264_2134, classification = ItemClassification.progression, ), + "Puppy 35": KH1ItemData("Puppies", code = 264_2135, classification = ItemClassification.progression, ), + "Puppy 36": KH1ItemData("Puppies", code = 264_2136, classification = ItemClassification.progression, ), + "Puppy 37": KH1ItemData("Puppies", code = 264_2137, classification = ItemClassification.progression, ), + "Puppy 38": KH1ItemData("Puppies", code = 264_2138, classification = ItemClassification.progression, ), + "Puppy 39": KH1ItemData("Puppies", code = 264_2139, classification = ItemClassification.progression, ), + "Puppy 40": KH1ItemData("Puppies", code = 264_2140, classification = ItemClassification.progression, ), + "Puppy 41": KH1ItemData("Puppies", code = 264_2141, classification = ItemClassification.progression, ), + "Puppy 42": KH1ItemData("Puppies", code = 264_2142, classification = ItemClassification.progression, ), + "Puppy 43": KH1ItemData("Puppies", code = 264_2143, classification = ItemClassification.progression, ), + "Puppy 44": KH1ItemData("Puppies", code = 264_2144, classification = ItemClassification.progression, ), + "Puppy 45": KH1ItemData("Puppies", code = 264_2145, classification = ItemClassification.progression, ), + "Puppy 46": KH1ItemData("Puppies", code = 264_2146, classification = ItemClassification.progression, ), + "Puppy 47": KH1ItemData("Puppies", code = 264_2147, classification = ItemClassification.progression, ), + "Puppy 48": KH1ItemData("Puppies", code = 264_2148, classification = ItemClassification.progression, ), + "Puppy 49": KH1ItemData("Puppies", code = 264_2149, classification = ItemClassification.progression, ), + "Puppy 50": KH1ItemData("Puppies", code = 264_2150, classification = ItemClassification.progression, ), + "Puppy 51": KH1ItemData("Puppies", code = 264_2151, classification = ItemClassification.progression, ), + "Puppy 52": KH1ItemData("Puppies", code = 264_2152, classification = ItemClassification.progression, ), + "Puppy 53": KH1ItemData("Puppies", code = 264_2153, classification = ItemClassification.progression, ), + "Puppy 54": KH1ItemData("Puppies", code = 264_2154, classification = ItemClassification.progression, ), + "Puppy 55": KH1ItemData("Puppies", code = 264_2155, classification = ItemClassification.progression, ), + "Puppy 56": KH1ItemData("Puppies", code = 264_2156, classification = ItemClassification.progression, ), + "Puppy 57": KH1ItemData("Puppies", code = 264_2157, classification = ItemClassification.progression, ), + "Puppy 58": KH1ItemData("Puppies", code = 264_2158, classification = ItemClassification.progression, ), + "Puppy 59": KH1ItemData("Puppies", code = 264_2159, classification = ItemClassification.progression, ), + "Puppy 60": KH1ItemData("Puppies", code = 264_2160, classification = ItemClassification.progression, ), + "Puppy 61": KH1ItemData("Puppies", code = 264_2161, classification = ItemClassification.progression, ), + "Puppy 62": KH1ItemData("Puppies", code = 264_2162, classification = ItemClassification.progression, ), + "Puppy 63": KH1ItemData("Puppies", code = 264_2163, classification = ItemClassification.progression, ), + "Puppy 64": KH1ItemData("Puppies", code = 264_2164, classification = ItemClassification.progression, ), + "Puppy 65": KH1ItemData("Puppies", code = 264_2165, classification = ItemClassification.progression, ), + "Puppy 66": KH1ItemData("Puppies", code = 264_2166, classification = ItemClassification.progression, ), + "Puppy 67": KH1ItemData("Puppies", code = 264_2167, classification = ItemClassification.progression, ), + "Puppy 68": KH1ItemData("Puppies", code = 264_2168, classification = ItemClassification.progression, ), + "Puppy 69": KH1ItemData("Puppies", code = 264_2169, classification = ItemClassification.progression, ), + "Puppy 70": KH1ItemData("Puppies", code = 264_2170, classification = ItemClassification.progression, ), + "Puppy 71": KH1ItemData("Puppies", code = 264_2171, classification = ItemClassification.progression, ), + "Puppy 72": KH1ItemData("Puppies", code = 264_2172, classification = ItemClassification.progression, ), + "Puppy 73": KH1ItemData("Puppies", code = 264_2173, classification = ItemClassification.progression, ), + "Puppy 74": KH1ItemData("Puppies", code = 264_2174, classification = ItemClassification.progression, ), + "Puppy 75": KH1ItemData("Puppies", code = 264_2175, classification = ItemClassification.progression, ), + "Puppy 76": KH1ItemData("Puppies", code = 264_2176, classification = ItemClassification.progression, ), + "Puppy 77": KH1ItemData("Puppies", code = 264_2177, classification = ItemClassification.progression, ), + "Puppy 78": KH1ItemData("Puppies", code = 264_2178, classification = ItemClassification.progression, ), + "Puppy 79": KH1ItemData("Puppies", code = 264_2179, classification = ItemClassification.progression, ), + "Puppy 80": KH1ItemData("Puppies", code = 264_2180, classification = ItemClassification.progression, ), + "Puppy 81": KH1ItemData("Puppies", code = 264_2181, classification = ItemClassification.progression, ), + "Puppy 82": KH1ItemData("Puppies", code = 264_2182, classification = ItemClassification.progression, ), + "Puppy 83": KH1ItemData("Puppies", code = 264_2183, classification = ItemClassification.progression, ), + "Puppy 84": KH1ItemData("Puppies", code = 264_2184, classification = ItemClassification.progression, ), + "Puppy 85": KH1ItemData("Puppies", code = 264_2185, classification = ItemClassification.progression, ), + "Puppy 86": KH1ItemData("Puppies", code = 264_2186, classification = ItemClassification.progression, ), + "Puppy 87": KH1ItemData("Puppies", code = 264_2187, classification = ItemClassification.progression, ), + "Puppy 88": KH1ItemData("Puppies", code = 264_2188, classification = ItemClassification.progression, ), + "Puppy 89": KH1ItemData("Puppies", code = 264_2189, classification = ItemClassification.progression, ), + "Puppy 90": KH1ItemData("Puppies", code = 264_2190, classification = ItemClassification.progression, ), + "Puppy 91": KH1ItemData("Puppies", code = 264_2191, classification = ItemClassification.progression, ), + "Puppy 92": KH1ItemData("Puppies", code = 264_2192, classification = ItemClassification.progression, ), + "Puppy 93": KH1ItemData("Puppies", code = 264_2193, classification = ItemClassification.progression, ), + "Puppy 94": KH1ItemData("Puppies", code = 264_2194, classification = ItemClassification.progression, ), + "Puppy 95": KH1ItemData("Puppies", code = 264_2195, classification = ItemClassification.progression, ), + "Puppy 96": KH1ItemData("Puppies", code = 264_2196, classification = ItemClassification.progression, ), + "Puppy 97": KH1ItemData("Puppies", code = 264_2197, classification = ItemClassification.progression, ), + "Puppy 98": KH1ItemData("Puppies", code = 264_2198, classification = ItemClassification.progression, ), + "Puppy 99": KH1ItemData("Puppies", code = 264_2199, classification = ItemClassification.progression, ), + "Puppies 01-03": KH1ItemData("Puppies", code = 264_2201, classification = ItemClassification.progression, ), + "Puppies 04-06": KH1ItemData("Puppies", code = 264_2202, classification = ItemClassification.progression, ), + "Puppies 07-09": KH1ItemData("Puppies", code = 264_2203, classification = ItemClassification.progression, ), + "Puppies 10-12": KH1ItemData("Puppies", code = 264_2204, classification = ItemClassification.progression, ), + "Puppies 13-15": KH1ItemData("Puppies", code = 264_2205, classification = ItemClassification.progression, ), + "Puppies 16-18": KH1ItemData("Puppies", code = 264_2206, classification = ItemClassification.progression, ), + "Puppies 19-21": KH1ItemData("Puppies", code = 264_2207, classification = ItemClassification.progression, ), + "Puppies 22-24": KH1ItemData("Puppies", code = 264_2208, classification = ItemClassification.progression, ), + "Puppies 25-27": KH1ItemData("Puppies", code = 264_2209, classification = ItemClassification.progression, ), + "Puppies 28-30": KH1ItemData("Puppies", code = 264_2210, classification = ItemClassification.progression, ), + "Puppies 31-33": KH1ItemData("Puppies", code = 264_2211, classification = ItemClassification.progression, ), + "Puppies 34-36": KH1ItemData("Puppies", code = 264_2212, classification = ItemClassification.progression, ), + "Puppies 37-39": KH1ItemData("Puppies", code = 264_2213, classification = ItemClassification.progression, ), + "Puppies 40-42": KH1ItemData("Puppies", code = 264_2214, classification = ItemClassification.progression, ), + "Puppies 43-45": KH1ItemData("Puppies", code = 264_2215, classification = ItemClassification.progression, ), + "Puppies 46-48": KH1ItemData("Puppies", code = 264_2216, classification = ItemClassification.progression, ), + "Puppies 49-51": KH1ItemData("Puppies", code = 264_2217, classification = ItemClassification.progression, ), + "Puppies 52-54": KH1ItemData("Puppies", code = 264_2218, classification = ItemClassification.progression, ), + "Puppies 55-57": KH1ItemData("Puppies", code = 264_2219, classification = ItemClassification.progression, ), + "Puppies 58-60": KH1ItemData("Puppies", code = 264_2220, classification = ItemClassification.progression, ), + "Puppies 61-63": KH1ItemData("Puppies", code = 264_2221, classification = ItemClassification.progression, ), + "Puppies 64-66": KH1ItemData("Puppies", code = 264_2222, classification = ItemClassification.progression, ), + "Puppies 67-69": KH1ItemData("Puppies", code = 264_2223, classification = ItemClassification.progression, ), + "Puppies 70-72": KH1ItemData("Puppies", code = 264_2224, classification = ItemClassification.progression, ), + "Puppies 73-75": KH1ItemData("Puppies", code = 264_2225, classification = ItemClassification.progression, ), + "Puppies 76-78": KH1ItemData("Puppies", code = 264_2226, classification = ItemClassification.progression, ), + "Puppies 79-81": KH1ItemData("Puppies", code = 264_2227, classification = ItemClassification.progression, ), + "Puppies 82-84": KH1ItemData("Puppies", code = 264_2228, classification = ItemClassification.progression, ), + "Puppies 85-87": KH1ItemData("Puppies", code = 264_2229, classification = ItemClassification.progression, ), + "Puppies 88-90": KH1ItemData("Puppies", code = 264_2230, classification = ItemClassification.progression, ), + "Puppies 91-93": KH1ItemData("Puppies", code = 264_2231, classification = ItemClassification.progression, ), + "Puppies 94-96": KH1ItemData("Puppies", code = 264_2232, classification = ItemClassification.progression, ), + "Puppies 97-99": KH1ItemData("Puppies", code = 264_2233, classification = ItemClassification.progression, ), + "All Puppies": KH1ItemData("Puppies", code = 264_2240, classification = ItemClassification.progression, ), + "Treasure Magnet": KH1ItemData("Abilities", code = 264_3005, classification = ItemClassification.useful, max_quantity = 2 ), + "Combo Plus": KH1ItemData("Abilities", code = 264_3006, classification = ItemClassification.useful, max_quantity = 4 ), + "Air Combo Plus": KH1ItemData("Abilities", code = 264_3007, classification = ItemClassification.useful, max_quantity = 2 ), + "Critical Plus": KH1ItemData("Abilities", code = 264_3008, classification = ItemClassification.useful, max_quantity = 3 ), + #"Second Wind": KH1ItemData("Abilities", code = 264_3009, classification = ItemClassification.useful, ), + "Scan": KH1ItemData("Abilities", code = 264_3010, classification = ItemClassification.useful, ), + "Sonic Blade": KH1ItemData("Abilities", code = 264_3011, classification = ItemClassification.useful, ), + "Ars Arcanum": KH1ItemData("Abilities", code = 264_3012, classification = ItemClassification.useful, ), + "Strike Raid": KH1ItemData("Abilities", code = 264_3013, classification = ItemClassification.useful, ), + "Ragnarok": KH1ItemData("Abilities", code = 264_3014, classification = ItemClassification.useful, ), + "Trinity Limit": KH1ItemData("Abilities", code = 264_3015, classification = ItemClassification.useful, ), + "Cheer": KH1ItemData("Abilities", code = 264_3016, classification = ItemClassification.useful, ), + "Vortex": KH1ItemData("Abilities", code = 264_3017, classification = ItemClassification.useful, ), + "Aerial Sweep": KH1ItemData("Abilities", code = 264_3018, classification = ItemClassification.useful, ), + "Counterattack": KH1ItemData("Abilities", code = 264_3019, classification = ItemClassification.useful, ), + "Blitz": KH1ItemData("Abilities", code = 264_3020, classification = ItemClassification.useful, ), + "Guard": KH1ItemData("Abilities", code = 264_3021, classification = ItemClassification.progression, ), + "Dodge Roll": KH1ItemData("Abilities", code = 264_3022, classification = ItemClassification.progression, ), + "MP Haste": KH1ItemData("Abilities", code = 264_3023, classification = ItemClassification.useful, ), + "MP Rage": KH1ItemData("Abilities", code = 264_3024, classification = ItemClassification.progression, ), + "Second Chance": KH1ItemData("Abilities", code = 264_3025, classification = ItemClassification.progression, ), + "Berserk": KH1ItemData("Abilities", code = 264_3026, classification = ItemClassification.useful, ), + "Jackpot": KH1ItemData("Abilities", code = 264_3027, classification = ItemClassification.useful, ), + "Lucky Strike": KH1ItemData("Abilities", code = 264_3028, classification = ItemClassification.useful, ), + #"Charge": KH1ItemData("Abilities", code = 264_3029, classification = ItemClassification.useful, ), + #"Rocket": KH1ItemData("Abilities", code = 264_3030, classification = ItemClassification.useful, ), + #"Tornado": KH1ItemData("Abilities", code = 264_3031, classification = ItemClassification.useful, ), + #"MP Gift": KH1ItemData("Abilities", code = 264_3032, classification = ItemClassification.useful, ), + #"Raging Boar": KH1ItemData("Abilities", code = 264_3033, classification = ItemClassification.useful, ), + #"Asp's Bite": KH1ItemData("Abilities", code = 264_3034, classification = ItemClassification.useful, ), + #"Healing Herb": KH1ItemData("Abilities", code = 264_3035, classification = ItemClassification.useful, ), + #"Wind Armor": KH1ItemData("Abilities", code = 264_3036, classification = ItemClassification.useful, ), + #"Crescent": KH1ItemData("Abilities", code = 264_3037, classification = ItemClassification.useful, ), + #"Sandstorm": KH1ItemData("Abilities", code = 264_3038, classification = ItemClassification.useful, ), + #"Applause!": KH1ItemData("Abilities", code = 264_3039, classification = ItemClassification.useful, ), + #"Blazing Fury": KH1ItemData("Abilities", code = 264_3040, classification = ItemClassification.useful, ), + #"Icy Terror": KH1ItemData("Abilities", code = 264_3041, classification = ItemClassification.useful, ), + #"Bolts of Sorrow": KH1ItemData("Abilities", code = 264_3042, classification = ItemClassification.useful, ), + #"Ghostly Scream": KH1ItemData("Abilities", code = 264_3043, classification = ItemClassification.useful, ), + #"Humming Bird": KH1ItemData("Abilities", code = 264_3044, classification = ItemClassification.useful, ), + #"Time-Out": KH1ItemData("Abilities", code = 264_3045, classification = ItemClassification.useful, ), + #"Storm's Eye": KH1ItemData("Abilities", code = 264_3046, classification = ItemClassification.useful, ), + #"Ferocious Lunge": KH1ItemData("Abilities", code = 264_3047, classification = ItemClassification.useful, ), + #"Furious Bellow": KH1ItemData("Abilities", code = 264_3048, classification = ItemClassification.useful, ), + #"Spiral Wave": KH1ItemData("Abilities", code = 264_3049, classification = ItemClassification.useful, ), + #"Thunder Potion": KH1ItemData("Abilities", code = 264_3050, classification = ItemClassification.useful, ), + #"Cure Potion": KH1ItemData("Abilities", code = 264_3051, classification = ItemClassification.useful, ), + #"Aero Potion": KH1ItemData("Abilities", code = 264_3052, classification = ItemClassification.useful, ), + "Slapshot": KH1ItemData("Abilities", code = 264_3053, classification = ItemClassification.useful, ), + "Sliding Dash": KH1ItemData("Abilities", code = 264_3054, classification = ItemClassification.useful, ), + "Hurricane Blast": KH1ItemData("Abilities", code = 264_3055, classification = ItemClassification.useful, ), + "Ripple Drive": KH1ItemData("Abilities", code = 264_3056, classification = ItemClassification.useful, ), + "Stun Impact": KH1ItemData("Abilities", code = 264_3057, classification = ItemClassification.useful, ), + "Gravity Break": KH1ItemData("Abilities", code = 264_3058, classification = ItemClassification.useful, ), + "Zantetsuken": KH1ItemData("Abilities", code = 264_3059, classification = ItemClassification.useful, ), + "Tech Boost": KH1ItemData("Abilities", code = 264_3060, classification = ItemClassification.useful, max_quantity = 4 ), + "Encounter Plus": KH1ItemData("Abilities", code = 264_3061, classification = ItemClassification.useful, ), + "Leaf Bracer": KH1ItemData("Abilities", code = 264_3062, classification = ItemClassification.progression, ), + #"Evolution": KH1ItemData("Abilities", code = 264_3063, classification = ItemClassification.useful, ), + "EXP Zero": KH1ItemData("Abilities", code = 264_3064, classification = ItemClassification.useful, ), + "Combo Master": KH1ItemData("Abilities", code = 264_3065, classification = ItemClassification.progression, ), + "Max HP Increase": KH1ItemData("Level Up", code = 264_4001, classification = ItemClassification.useful, max_quantity = 15), + "Max MP Increase": KH1ItemData("Level Up", code = 264_4002, classification = ItemClassification.useful, max_quantity = 15), + "Max AP Increase": KH1ItemData("Level Up", code = 264_4003, classification = ItemClassification.useful, max_quantity = 15), + "Strength Increase": KH1ItemData("Level Up", code = 264_4004, classification = ItemClassification.useful, max_quantity = 15), + "Defense Increase": KH1ItemData("Level Up", code = 264_4005, classification = ItemClassification.useful, max_quantity = 15), + "Accessory Slot Increase": KH1ItemData("Limited Level Up", code = 264_4006, classification = ItemClassification.useful, max_quantity = 15), + "Item Slot Increase": KH1ItemData("Limited Level Up", code = 264_4007, classification = ItemClassification.useful, max_quantity = 15), + "Dumbo": KH1ItemData("Summons", code = 264_5000, classification = ItemClassification.progression, ), + "Bambi": KH1ItemData("Summons", code = 264_5001, classification = ItemClassification.progression, ), + "Genie": KH1ItemData("Summons", code = 264_5002, classification = ItemClassification.progression, ), + "Tinker Bell": KH1ItemData("Summons", code = 264_5003, classification = ItemClassification.progression, ), + "Mushu": KH1ItemData("Summons", code = 264_5004, classification = ItemClassification.progression, ), + "Simba": KH1ItemData("Summons", code = 264_5005, classification = ItemClassification.progression, ), + "Progressive Fire": KH1ItemData("Magic", code = 264_6001, classification = ItemClassification.progression, max_quantity = 3 ), + "Progressive Blizzard": KH1ItemData("Magic", code = 264_6002, classification = ItemClassification.progression, max_quantity = 3 ), + "Progressive Thunder": KH1ItemData("Magic", code = 264_6003, classification = ItemClassification.progression, max_quantity = 3 ), + "Progressive Cure": KH1ItemData("Magic", code = 264_6004, classification = ItemClassification.progression, max_quantity = 3 ), + "Progressive Gravity": KH1ItemData("Magic", code = 264_6005, classification = ItemClassification.progression, max_quantity = 3 ), + "Progressive Stop": KH1ItemData("Magic", code = 264_6006, classification = ItemClassification.progression, max_quantity = 3 ), + "Progressive Aero": KH1ItemData("Magic", code = 264_6007, classification = ItemClassification.progression, max_quantity = 3 ), + #"Traverse Town": KH1ItemData("Worlds", code = 264_7001, classification = ItemClassification.progression, ), + "Wonderland": KH1ItemData("Worlds", code = 264_7002, classification = ItemClassification.progression, ), + "Olympus Coliseum": KH1ItemData("Worlds", code = 264_7003, classification = ItemClassification.progression, ), + "Deep Jungle": KH1ItemData("Worlds", code = 264_7004, classification = ItemClassification.progression, ), + "Agrabah": KH1ItemData("Worlds", code = 264_7005, classification = ItemClassification.progression, ), + "Halloween Town": KH1ItemData("Worlds", code = 264_7006, classification = ItemClassification.progression, ), + "Atlantica": KH1ItemData("Worlds", code = 264_7007, classification = ItemClassification.progression, ), + "Neverland": KH1ItemData("Worlds", code = 264_7008, classification = ItemClassification.progression, ), + "Hollow Bastion": KH1ItemData("Worlds", code = 264_7009, classification = ItemClassification.progression, ), + "End of the World": KH1ItemData("Worlds", code = 264_7010, classification = ItemClassification.progression, ), + "Monstro": KH1ItemData("Worlds", code = 264_7011, classification = ItemClassification.progression, ), + "Blue Trinity": KH1ItemData("Trinities", code = 264_8001, classification = ItemClassification.progression, ), + "Red Trinity": KH1ItemData("Trinities", code = 264_8002, classification = ItemClassification.progression, ), + "Green Trinity": KH1ItemData("Trinities", code = 264_8003, classification = ItemClassification.progression, ), + "Yellow Trinity": KH1ItemData("Trinities", code = 264_8004, classification = ItemClassification.progression, ), + "White Trinity": KH1ItemData("Trinities", code = 264_8005, classification = ItemClassification.progression, ), + "Phil Cup": KH1ItemData("Cups", code = 264_9001, classification = ItemClassification.progression, ), + "Pegasus Cup": KH1ItemData("Cups", code = 264_9002, classification = ItemClassification.progression, ), + "Hercules Cup": KH1ItemData("Cups", code = 264_9003, classification = ItemClassification.progression, ), + #"Hades Cup": KH1ItemData("Cups", code = 264_9004, classification = ItemClassification.progression, ), +} + +event_item_table: Dict[str, KH1ItemData] = {} + +#Make item categories +item_name_groups: Dict[str, Set[str]] = {} +for item in item_table.keys(): + category = item_table[item].category + if category not in item_name_groups.keys(): + item_name_groups[category] = set() + item_name_groups[category].add(item) diff --git a/worlds/kh1/Locations.py b/worlds/kh1/Locations.py new file mode 100644 index 000000000000..a82be70f090b --- /dev/null +++ b/worlds/kh1/Locations.py @@ -0,0 +1,590 @@ +from typing import Dict, NamedTuple, Optional, Set +import typing + + +from BaseClasses import Location + + +class KH1Location(Location): + game: str = "Kingdom Hearts" + + +class KH1LocationData(NamedTuple): + category: str + code: int + + +def get_locations_by_category(category: str) -> Dict[str, KH1LocationData]: + location_dict: Dict[str, KH1LocationData] = {} + for name, data in location_table.items(): + if data.category == category: + location_dict.setdefault(name, data) + + return location_dict + + +location_table: Dict[str, KH1LocationData] = { + #"Destiny Islands Chest": KH1LocationData("Destiny Islands", 265_0011), missable + "Traverse Town 1st District Candle Puzzle Chest": KH1LocationData("Traverse Town", 265_0211), + "Traverse Town 1st District Accessory Shop Roof Chest": KH1LocationData("Traverse Town", 265_0212), + "Traverse Town 2nd District Boots and Shoes Awning Chest": KH1LocationData("Traverse Town", 265_0213), + "Traverse Town 2nd District Rooftop Chest": KH1LocationData("Traverse Town", 265_0214), + "Traverse Town 2nd District Gizmo Shop Facade Chest": KH1LocationData("Traverse Town", 265_0251), + "Traverse Town Alleyway Balcony Chest": KH1LocationData("Traverse Town", 265_0252), + "Traverse Town Alleyway Blue Room Awning Chest": KH1LocationData("Traverse Town", 265_0253), + "Traverse Town Alleyway Corner Chest": KH1LocationData("Traverse Town", 265_0254), + "Traverse Town Green Room Clock Puzzle Chest": KH1LocationData("Traverse Town", 265_0292), + "Traverse Town Green Room Table Chest": KH1LocationData("Traverse Town", 265_0293), + "Traverse Town Red Room Chest": KH1LocationData("Traverse Town", 265_0294), + "Traverse Town Mystical House Yellow Trinity Chest": KH1LocationData("Traverse Town", 265_0331), + "Traverse Town Accessory Shop Chest": KH1LocationData("Traverse Town", 265_0332), + "Traverse Town Secret Waterway White Trinity Chest": KH1LocationData("Traverse Town", 265_0333), + "Traverse Town Geppetto's House Chest": KH1LocationData("Traverse Town", 265_0334), + "Traverse Town Item Workshop Right Chest": KH1LocationData("Traverse Town", 265_0371), + "Traverse Town 1st District Blue Trinity Balcony Chest": KH1LocationData("Traverse Town", 265_0411), + "Traverse Town Mystical House Glide Chest": KH1LocationData("Traverse Town", 265_0891), + "Traverse Town Alleyway Behind Crates Chest": KH1LocationData("Traverse Town", 265_0892), + "Traverse Town Item Workshop Left Chest": KH1LocationData("Traverse Town", 265_0893), + "Traverse Town Secret Waterway Near Stairs Chest": KH1LocationData("Traverse Town", 265_0894), + "Wonderland Rabbit Hole Green Trinity Chest": KH1LocationData("Wonderland", 265_0931), + "Wonderland Rabbit Hole Defeat Heartless 1 Chest": KH1LocationData("Wonderland", 265_0932), + "Wonderland Rabbit Hole Defeat Heartless 2 Chest": KH1LocationData("Wonderland", 265_0933), + "Wonderland Rabbit Hole Defeat Heartless 3 Chest": KH1LocationData("Wonderland", 265_0934), + "Wonderland Bizarre Room Green Trinity Chest": KH1LocationData("Wonderland", 265_0971), + "Wonderland Queen's Castle Hedge Left Red Chest": KH1LocationData("Wonderland", 265_1011), + "Wonderland Queen's Castle Hedge Right Blue Chest": KH1LocationData("Wonderland", 265_1012), + "Wonderland Queen's Castle Hedge Right Red Chest": KH1LocationData("Wonderland", 265_1013), + "Wonderland Lotus Forest Thunder Plant Chest": KH1LocationData("Wonderland", 265_1014), + "Wonderland Lotus Forest Through the Painting Thunder Plant Chest": KH1LocationData("Wonderland", 265_1051), + "Wonderland Lotus Forest Glide Chest": KH1LocationData("Wonderland", 265_1052), + "Wonderland Lotus Forest Nut Chest": KH1LocationData("Wonderland", 265_1053), + "Wonderland Lotus Forest Corner Chest": KH1LocationData("Wonderland", 265_1054), + "Wonderland Bizarre Room Lamp Chest": KH1LocationData("Wonderland", 265_1091), + "Wonderland Tea Party Garden Above Lotus Forest Entrance 2nd Chest": KH1LocationData("Wonderland", 265_1093), + "Wonderland Tea Party Garden Above Lotus Forest Entrance 1st Chest": KH1LocationData("Wonderland", 265_1094), + "Wonderland Tea Party Garden Bear and Clock Puzzle Chest": KH1LocationData("Wonderland", 265_1131), + "Wonderland Tea Party Garden Across From Bizarre Room Entrance Chest": KH1LocationData("Wonderland", 265_1132), + "Wonderland Lotus Forest Through the Painting White Trinity Chest": KH1LocationData("Wonderland", 265_1133), + "Deep Jungle Tree House Beneath Tree House Chest": KH1LocationData("Deep Jungle", 265_1213), + "Deep Jungle Tree House Rooftop Chest": KH1LocationData("Deep Jungle", 265_1214), + "Deep Jungle Hippo's Lagoon Center Chest": KH1LocationData("Deep Jungle", 265_1251), + "Deep Jungle Hippo's Lagoon Left Chest": KH1LocationData("Deep Jungle", 265_1252), + "Deep Jungle Hippo's Lagoon Right Chest": KH1LocationData("Deep Jungle", 265_1253), + "Deep Jungle Vines Chest": KH1LocationData("Deep Jungle", 265_1291), + "Deep Jungle Vines 2 Chest": KH1LocationData("Deep Jungle", 265_1292), + "Deep Jungle Climbing Trees Blue Trinity Chest": KH1LocationData("Deep Jungle", 265_1293), + "Deep Jungle Tunnel Chest": KH1LocationData("Deep Jungle", 265_1331), + "Deep Jungle Cavern of Hearts White Trinity Chest": KH1LocationData("Deep Jungle", 265_1332), + "Deep Jungle Camp Blue Trinity Chest": KH1LocationData("Deep Jungle", 265_1333), + "Deep Jungle Tent Chest": KH1LocationData("Deep Jungle", 265_1334), + "Deep Jungle Waterfall Cavern Low Chest": KH1LocationData("Deep Jungle", 265_1371), + "Deep Jungle Waterfall Cavern Middle Chest": KH1LocationData("Deep Jungle", 265_1372), + "Deep Jungle Waterfall Cavern High Wall Chest": KH1LocationData("Deep Jungle", 265_1373), + "Deep Jungle Waterfall Cavern High Middle Chest": KH1LocationData("Deep Jungle", 265_1374), + "Deep Jungle Cliff Right Cliff Left Chest": KH1LocationData("Deep Jungle", 265_1411), + "Deep Jungle Cliff Right Cliff Right Chest": KH1LocationData("Deep Jungle", 265_1412), + "Deep Jungle Tree House Suspended Boat Chest": KH1LocationData("Deep Jungle", 265_1413), + "100 Acre Wood Meadow Inside Log Chest": KH1LocationData("100 Acre Wood", 265_1654), + "100 Acre Wood Bouncing Spot Left Cliff Chest": KH1LocationData("100 Acre Wood", 265_1691), + "100 Acre Wood Bouncing Spot Right Tree Alcove Chest": KH1LocationData("100 Acre Wood", 265_1692), + "100 Acre Wood Bouncing Spot Under Giant Pot Chest": KH1LocationData("100 Acre Wood", 265_1693), + "Agrabah Plaza By Storage Chest": KH1LocationData("Agrabah", 265_1972), + "Agrabah Plaza Raised Terrace Chest": KH1LocationData("Agrabah", 265_1973), + "Agrabah Plaza Top Corner Chest": KH1LocationData("Agrabah", 265_1974), + "Agrabah Alley Chest": KH1LocationData("Agrabah", 265_2011), + "Agrabah Bazaar Across Windows Chest": KH1LocationData("Agrabah", 265_2012), + "Agrabah Bazaar High Corner Chest": KH1LocationData("Agrabah", 265_2013), + "Agrabah Main Street Right Palace Entrance Chest": KH1LocationData("Agrabah", 265_2014), + "Agrabah Main Street High Above Alley Entrance Chest": KH1LocationData("Agrabah", 265_2051), + "Agrabah Main Street High Above Palace Gates Entrance Chest": KH1LocationData("Agrabah", 265_2052), + "Agrabah Palace Gates Low Chest": KH1LocationData("Agrabah", 265_2053), + "Agrabah Palace Gates High Opposite Palace Chest": KH1LocationData("Agrabah", 265_2054), + "Agrabah Palace Gates High Close to Palace Chest": KH1LocationData("Agrabah", 265_2091), + "Agrabah Storage Green Trinity Chest": KH1LocationData("Agrabah", 265_2092), + "Agrabah Storage Behind Barrel Chest": KH1LocationData("Agrabah", 265_2093), + "Agrabah Cave of Wonders Entrance Left Chest": KH1LocationData("Agrabah", 265_2094), + "Agrabah Cave of Wonders Entrance Tall Tower Chest": KH1LocationData("Agrabah", 265_2131), + "Agrabah Cave of Wonders Hall High Left Chest": KH1LocationData("Agrabah", 265_2132), + "Agrabah Cave of Wonders Hall Near Bottomless Hall Chest": KH1LocationData("Agrabah", 265_2133), + "Agrabah Cave of Wonders Bottomless Hall Raised Platform Chest": KH1LocationData("Agrabah", 265_2134), + "Agrabah Cave of Wonders Bottomless Hall Pillar Chest": KH1LocationData("Agrabah", 265_2171), + "Agrabah Cave of Wonders Bottomless Hall Across Chasm Chest": KH1LocationData("Agrabah", 265_2172), + "Agrabah Cave of Wonders Treasure Room Across Platforms Chest": KH1LocationData("Agrabah", 265_2173), + "Agrabah Cave of Wonders Treasure Room Small Treasure Pile Chest": KH1LocationData("Agrabah", 265_2174), + "Agrabah Cave of Wonders Treasure Room Large Treasure Pile Chest": KH1LocationData("Agrabah", 265_2211), + "Agrabah Cave of Wonders Treasure Room Above Fire Chest": KH1LocationData("Agrabah", 265_2212), + "Agrabah Cave of Wonders Relic Chamber Jump from Stairs Chest": KH1LocationData("Agrabah", 265_2213), + "Agrabah Cave of Wonders Relic Chamber Stairs Chest": KH1LocationData("Agrabah", 265_2214), + "Agrabah Cave of Wonders Dark Chamber Abu Gem Chest": KH1LocationData("Agrabah", 265_2251), + "Agrabah Cave of Wonders Dark Chamber Across from Relic Chamber Entrance Chest": KH1LocationData("Agrabah", 265_2252), + "Agrabah Cave of Wonders Dark Chamber Bridge Chest": KH1LocationData("Agrabah", 265_2253), + "Agrabah Cave of Wonders Dark Chamber Near Save Chest": KH1LocationData("Agrabah", 265_2254), + "Agrabah Cave of Wonders Silent Chamber Blue Trinity Chest": KH1LocationData("Agrabah", 265_2291), + "Agrabah Cave of Wonders Hidden Room Right Chest": KH1LocationData("Agrabah", 265_2292), + "Agrabah Cave of Wonders Hidden Room Left Chest": KH1LocationData("Agrabah", 265_2293), + "Agrabah Aladdin's House Main Street Entrance Chest": KH1LocationData("Agrabah", 265_2294), + "Agrabah Aladdin's House Plaza Entrance Chest": KH1LocationData("Agrabah", 265_2331), + "Agrabah Cave of Wonders Entrance White Trinity Chest": KH1LocationData("Agrabah", 265_2332), + "Monstro Chamber 6 Other Platform Chest": KH1LocationData("Monstro", 265_2413), + "Monstro Chamber 6 Platform Near Chamber 5 Entrance Chest": KH1LocationData("Monstro", 265_2414), + "Monstro Chamber 6 Raised Area Near Chamber 1 Entrance Chest": KH1LocationData("Monstro", 265_2451), + "Monstro Chamber 6 Low Chest": KH1LocationData("Monstro", 265_2452), + "Atlantica Sunken Ship In Flipped Boat Chest": KH1LocationData("Atlantica", 265_2531), + "Atlantica Sunken Ship Seabed Chest": KH1LocationData("Atlantica", 265_2532), + "Atlantica Sunken Ship Inside Ship Chest": KH1LocationData("Atlantica", 265_2533), + "Atlantica Ariel's Grotto High Chest": KH1LocationData("Atlantica", 265_2534), + "Atlantica Ariel's Grotto Middle Chest": KH1LocationData("Atlantica", 265_2571), + "Atlantica Ariel's Grotto Low Chest": KH1LocationData("Atlantica", 265_2572), + "Atlantica Ursula's Lair Use Fire on Urchin Chest": KH1LocationData("Atlantica", 265_2573), + "Atlantica Undersea Gorge Jammed by Ariel's Grotto Chest": KH1LocationData("Atlantica", 265_2574), + "Atlantica Triton's Palace White Trinity Chest": KH1LocationData("Atlantica", 265_2611), + "Halloween Town Moonlight Hill White Trinity Chest": KH1LocationData("Halloween Town", 265_3014), + "Halloween Town Bridge Under Bridge": KH1LocationData("Halloween Town", 265_3051), + "Halloween Town Boneyard Tombstone Puzzle Chest": KH1LocationData("Halloween Town", 265_3052), + "Halloween Town Bridge Right of Gate Chest": KH1LocationData("Halloween Town", 265_3053), + "Halloween Town Cemetery Behind Grave Chest": KH1LocationData("Halloween Town", 265_3054), + "Halloween Town Cemetery By Cat Shape Chest": KH1LocationData("Halloween Town", 265_3091), + "Halloween Town Cemetery Between Graves Chest": KH1LocationData("Halloween Town", 265_3092), + "Halloween Town Oogie's Manor Lower Iron Cage Chest": KH1LocationData("Halloween Town", 265_3093), + "Halloween Town Oogie's Manor Upper Iron Cage Chest": KH1LocationData("Halloween Town", 265_3094), + "Halloween Town Oogie's Manor Hollow Chest": KH1LocationData("Halloween Town", 265_3131), + "Halloween Town Oogie's Manor Grounds Red Trinity Chest": KH1LocationData("Halloween Town", 265_3132), + "Halloween Town Guillotine Square High Tower Chest": KH1LocationData("Halloween Town", 265_3133), + "Halloween Town Guillotine Square Pumpkin Structure Left Chest": KH1LocationData("Halloween Town", 265_3134), + "Halloween Town Oogie's Manor Entrance Steps Chest": KH1LocationData("Halloween Town", 265_3171), + "Halloween Town Oogie's Manor Inside Entrance Chest": KH1LocationData("Halloween Town", 265_3172), + "Halloween Town Bridge Left of Gate Chest": KH1LocationData("Halloween Town", 265_3291), + "Halloween Town Cemetery By Striped Grave Chest": KH1LocationData("Halloween Town", 265_3292), + "Halloween Town Guillotine Square Under Jack's House Stairs Chest": KH1LocationData("Halloween Town", 265_3293), + "Halloween Town Guillotine Square Pumpkin Structure Right Chest": KH1LocationData("Halloween Town", 265_3294), + "Olympus Coliseum Coliseum Gates Left Behind Columns Chest": KH1LocationData("Olympus Coliseum", 265_3332), + "Olympus Coliseum Coliseum Gates Right Blue Trinity Chest": KH1LocationData("Olympus Coliseum", 265_3333), + "Olympus Coliseum Coliseum Gates Left Blue Trinity Chest": KH1LocationData("Olympus Coliseum", 265_3334), + "Olympus Coliseum Coliseum Gates White Trinity Chest": KH1LocationData("Olympus Coliseum", 265_3371), + "Olympus Coliseum Coliseum Gates Blizzara Chest": KH1LocationData("Olympus Coliseum", 265_3372), + "Olympus Coliseum Coliseum Gates Blizzaga Chest": KH1LocationData("Olympus Coliseum", 265_3373), + "Monstro Mouth Boat Deck Chest": KH1LocationData("Monstro", 265_3454), + "Monstro Mouth High Platform Boat Side Chest": KH1LocationData("Monstro", 265_3491), + "Monstro Mouth High Platform Across from Boat Chest": KH1LocationData("Monstro", 265_3492), + "Monstro Mouth Near Ship Chest": KH1LocationData("Monstro", 265_3493), + "Monstro Mouth Green Trinity Top of Boat Chest": KH1LocationData("Monstro", 265_3494), + "Monstro Chamber 2 Ground Chest": KH1LocationData("Monstro", 265_3534), + "Monstro Chamber 2 Platform Chest": KH1LocationData("Monstro", 265_3571), + "Monstro Chamber 5 Platform Chest": KH1LocationData("Monstro", 265_3613), + "Monstro Chamber 3 Ground Chest": KH1LocationData("Monstro", 265_3614), + "Monstro Chamber 3 Platform Above Chamber 2 Entrance Chest": KH1LocationData("Monstro", 265_3651), + "Monstro Chamber 3 Near Chamber 6 Entrance Chest": KH1LocationData("Monstro", 265_3652), + "Monstro Chamber 3 Platform Near Chamber 6 Entrance Chest": KH1LocationData("Monstro", 265_3653), + "Monstro Mouth High Platform Near Teeth Chest": KH1LocationData("Monstro", 265_3732), + "Monstro Chamber 5 Atop Barrel Chest": KH1LocationData("Monstro", 265_3733), + "Monstro Chamber 5 Low 2nd Chest": KH1LocationData("Monstro", 265_3734), + "Monstro Chamber 5 Low 1st Chest": KH1LocationData("Monstro", 265_3771), + "Neverland Pirate Ship Deck White Trinity Chest": KH1LocationData("Neverland", 265_3772), + "Neverland Pirate Ship Crows Nest Chest": KH1LocationData("Neverland", 265_3773), + "Neverland Hold Yellow Trinity Right Blue Chest": KH1LocationData("Neverland", 265_3774), + "Neverland Hold Yellow Trinity Left Blue Chest": KH1LocationData("Neverland", 265_3811), + "Neverland Galley Chest": KH1LocationData("Neverland", 265_3812), + "Neverland Cabin Chest": KH1LocationData("Neverland", 265_3813), + "Neverland Hold Flight 1st Chest": KH1LocationData("Neverland", 265_3814), + "Neverland Clock Tower Chest": KH1LocationData("Neverland", 265_4014), + "Neverland Hold Flight 2nd Chest": KH1LocationData("Neverland", 265_4051), + "Neverland Hold Yellow Trinity Green Chest": KH1LocationData("Neverland", 265_4052), + "Neverland Captain's Cabin Chest": KH1LocationData("Neverland", 265_4053), + "Hollow Bastion Rising Falls Water's Surface Chest": KH1LocationData("Hollow Bastion", 265_4054), + "Hollow Bastion Rising Falls Under Water 1st Chest": KH1LocationData("Hollow Bastion", 265_4091), + "Hollow Bastion Rising Falls Under Water 2nd Chest": KH1LocationData("Hollow Bastion", 265_4092), + "Hollow Bastion Rising Falls Floating Platform Near Save Chest": KH1LocationData("Hollow Bastion", 265_4093), + "Hollow Bastion Rising Falls Floating Platform Near Bubble Chest": KH1LocationData("Hollow Bastion", 265_4094), + "Hollow Bastion Rising Falls High Platform Chest": KH1LocationData("Hollow Bastion", 265_4131), + "Hollow Bastion Castle Gates Gravity Chest": KH1LocationData("Hollow Bastion", 265_4132), + "Hollow Bastion Castle Gates Freestanding Pillar Chest": KH1LocationData("Hollow Bastion", 265_4133), + "Hollow Bastion Castle Gates High Pillar Chest": KH1LocationData("Hollow Bastion", 265_4134), + "Hollow Bastion Great Crest Lower Chest": KH1LocationData("Hollow Bastion", 265_4171), + "Hollow Bastion Great Crest After Battle Platform Chest": KH1LocationData("Hollow Bastion", 265_4172), + "Hollow Bastion High Tower 2nd Gravity Chest": KH1LocationData("Hollow Bastion", 265_4173), + "Hollow Bastion High Tower 1st Gravity Chest": KH1LocationData("Hollow Bastion", 265_4174), + "Hollow Bastion High Tower Above Sliding Blocks Chest": KH1LocationData("Hollow Bastion", 265_4211), + "Hollow Bastion Library Top of Bookshelf Chest": KH1LocationData("Hollow Bastion", 265_4213), + "Hollow Bastion Library 1st Floor Turn the Carousel Chest": KH1LocationData("Hollow Bastion", 265_4214), + "Hollow Bastion Library Top of Bookshelf Turn the Carousel Chest": KH1LocationData("Hollow Bastion", 265_4251), + "Hollow Bastion Library 2nd Floor Turn the Carousel 1st Chest": KH1LocationData("Hollow Bastion", 265_4252), + "Hollow Bastion Library 2nd Floor Turn the Carousel 2nd Chest": KH1LocationData("Hollow Bastion", 265_4253), + "Hollow Bastion Lift Stop Library Node After High Tower Switch Gravity Chest": KH1LocationData("Hollow Bastion", 265_4254), + "Hollow Bastion Lift Stop Library Node Gravity Chest": KH1LocationData("Hollow Bastion", 265_4291), + "Hollow Bastion Lift Stop Under High Tower Sliding Blocks Chest": KH1LocationData("Hollow Bastion", 265_4292), + "Hollow Bastion Lift Stop Outside Library Gravity Chest": KH1LocationData("Hollow Bastion", 265_4293), + "Hollow Bastion Lift Stop Heartless Sigil Door Gravity Chest": KH1LocationData("Hollow Bastion", 265_4294), + "Hollow Bastion Base Level Bubble Under the Wall Platform Chest": KH1LocationData("Hollow Bastion", 265_4331), + "Hollow Bastion Base Level Platform Near Entrance Chest": KH1LocationData("Hollow Bastion", 265_4332), + "Hollow Bastion Base Level Near Crystal Switch Chest": KH1LocationData("Hollow Bastion", 265_4333), + "Hollow Bastion Waterway Near Save Chest": KH1LocationData("Hollow Bastion", 265_4334), + "Hollow Bastion Waterway Blizzard on Bubble Chest": KH1LocationData("Hollow Bastion", 265_4371), + "Hollow Bastion Waterway Unlock Passage from Base Level Chest": KH1LocationData("Hollow Bastion", 265_4372), + "Hollow Bastion Dungeon By Candles Chest": KH1LocationData("Hollow Bastion", 265_4373), + "Hollow Bastion Dungeon Corner Chest": KH1LocationData("Hollow Bastion", 265_4374), + "Hollow Bastion Grand Hall Steps Right Side Chest": KH1LocationData("Hollow Bastion", 265_4454), + "Hollow Bastion Grand Hall Oblivion Chest": KH1LocationData("Hollow Bastion", 265_4491), + "Hollow Bastion Grand Hall Left of Gate Chest": KH1LocationData("Hollow Bastion", 265_4492), + #"Hollow Bastion Entrance Hall Push the Statue Chest": KH1LocationData("Hollow Bastion", 265_4493), --handled later + "Hollow Bastion Entrance Hall Left of Emblem Door Chest": KH1LocationData("Hollow Bastion", 265_4212), + "Hollow Bastion Rising Falls White Trinity Chest": KH1LocationData("Hollow Bastion", 265_4494), + "End of the World Final Dimension 1st Chest": KH1LocationData("End of the World", 265_4531), + "End of the World Final Dimension 2nd Chest": KH1LocationData("End of the World", 265_4532), + "End of the World Final Dimension 3rd Chest": KH1LocationData("End of the World", 265_4533), + "End of the World Final Dimension 4th Chest": KH1LocationData("End of the World", 265_4534), + "End of the World Final Dimension 5th Chest": KH1LocationData("End of the World", 265_4571), + "End of the World Final Dimension 6th Chest": KH1LocationData("End of the World", 265_4572), + "End of the World Final Dimension 10th Chest": KH1LocationData("End of the World", 265_4573), + "End of the World Final Dimension 9th Chest": KH1LocationData("End of the World", 265_4574), + "End of the World Final Dimension 8th Chest": KH1LocationData("End of the World", 265_4611), + "End of the World Final Dimension 7th Chest": KH1LocationData("End of the World", 265_4612), + "End of the World Giant Crevasse 3rd Chest": KH1LocationData("End of the World", 265_4613), + "End of the World Giant Crevasse 5th Chest": KH1LocationData("End of the World", 265_4614), + "End of the World Giant Crevasse 1st Chest": KH1LocationData("End of the World", 265_4651), + "End of the World Giant Crevasse 4th Chest": KH1LocationData("End of the World", 265_4652), + "End of the World Giant Crevasse 2nd Chest": KH1LocationData("End of the World", 265_4653), + "End of the World World Terminus Traverse Town Chest": KH1LocationData("End of the World", 265_4654), + "End of the World World Terminus Wonderland Chest": KH1LocationData("End of the World", 265_4691), + "End of the World World Terminus Olympus Coliseum Chest": KH1LocationData("End of the World", 265_4692), + "End of the World World Terminus Deep Jungle Chest": KH1LocationData("End of the World", 265_4693), + "End of the World World Terminus Agrabah Chest": KH1LocationData("End of the World", 265_4694), + "End of the World World Terminus Atlantica Chest": KH1LocationData("End of the World", 265_4731), + "End of the World World Terminus Halloween Town Chest": KH1LocationData("End of the World", 265_4732), + "End of the World World Terminus Neverland Chest": KH1LocationData("End of the World", 265_4733), + "End of the World World Terminus 100 Acre Wood Chest": KH1LocationData("End of the World", 265_4734), + #"End of the World World Terminus Hollow Bastion Chest": KH1LocationData("End of the World", 265_4771), + "End of the World Final Rest Chest": KH1LocationData("End of the World", 265_4772), + "Monstro Chamber 6 White Trinity Chest": KH1LocationData("End of the World", 265_5092), + #"Awakening Chest": KH1LocationData("Awakening", 265_5093), missable + + "Traverse Town Defeat Guard Armor Dodge Roll Event": KH1LocationData("Traverse Town", 265_6011), + "Traverse Town Defeat Guard Armor Fire Event": KH1LocationData("Traverse Town", 265_6012), + "Traverse Town Defeat Guard Armor Blue Trinity Event": KH1LocationData("Traverse Town", 265_6013), + "Traverse Town Leon Secret Waterway Earthshine Event": KH1LocationData("Traverse Town", 265_6014), + "Traverse Town Kairi Secret Waterway Oathkeeper Event": KH1LocationData("Traverse Town", 265_6015), + "Traverse Town Defeat Guard Armor Brave Warrior Event": KH1LocationData("Traverse Town", 265_6016), + "Deep Jungle Defeat Sabor White Fang Event": KH1LocationData("Deep Jungle", 265_6021), + "Deep Jungle Defeat Clayton Cure Event": KH1LocationData("Deep Jungle", 265_6022), + "Deep Jungle Seal Keyhole Jungle King Event": KH1LocationData("Deep Jungle", 265_6023), + "Deep Jungle Seal Keyhole Red Trinity Event": KH1LocationData("Deep Jungle", 265_6024), + "Olympus Coliseum Clear Phil's Training Thunder Event": KH1LocationData("Olympus Coliseum", 265_6031), + "Olympus Coliseum Defeat Cerberus Inferno Band Event": KH1LocationData("Olympus Coliseum", 265_6033), + "Wonderland Defeat Trickmaster Blizzard Event": KH1LocationData("Wonderland", 265_6041), + "Wonderland Defeat Trickmaster Ifrit's Horn Event": KH1LocationData("Wonderland", 265_6042), + "Agrabah Defeat Pot Centipede Ray of Light Event": KH1LocationData("Agrabah", 265_6051), + "Agrabah Defeat Jafar Blizzard Event": KH1LocationData("Agrabah", 265_6052), + "Agrabah Defeat Jafar Genie Fire Event": KH1LocationData("Agrabah", 265_6053), + "Agrabah Seal Keyhole Genie Event": KH1LocationData("Agrabah", 265_6054), + "Agrabah Seal Keyhole Three Wishes Event": KH1LocationData("Agrabah", 265_6055), + "Agrabah Seal Keyhole Green Trinity Event": KH1LocationData("Agrabah", 265_6056), + "Monstro Defeat Parasite Cage I Goofy Cheer Event": KH1LocationData("Monstro", 265_6061), + "Monstro Defeat Parasite Cage II Stop Event": KH1LocationData("Monstro", 265_6062), + "Atlantica Defeat Ursula I Mermaid Kick Event": KH1LocationData("Atlantica", 265_6071), + "Atlantica Defeat Ursula II Thunder Event": KH1LocationData("Atlantica", 265_6072), + "Atlantica Seal Keyhole Crabclaw Event": KH1LocationData("Atlantica", 265_6073), + "Halloween Town Defeat Oogie Boogie Holy Circlet Event": KH1LocationData("Halloween Town", 265_6081), + "Halloween Town Defeat Oogie's Manor Gravity Event": KH1LocationData("Halloween Town", 265_6082), + "Halloween Town Seal Keyhole Pumpkinhead Event": KH1LocationData("Halloween Town", 265_6083), + "Neverland Defeat Anti Sora Raven's Claw Event": KH1LocationData("Neverland", 265_6091), + "Neverland Encounter Hook Cure Event": KH1LocationData("Neverland", 265_6092), + "Neverland Seal Keyhole Fairy Harp Event": KH1LocationData("Neverland", 265_6093), + "Neverland Seal Keyhole Tinker Bell Event": KH1LocationData("Neverland", 265_6094), + "Neverland Seal Keyhole Glide Event": KH1LocationData("Neverland", 265_6095), + "Neverland Defeat Phantom Stop Event": KH1LocationData("Neverland", 265_6096), + "Neverland Defeat Captain Hook Ars Arcanum Event": KH1LocationData("Neverland", 265_6097), + "Hollow Bastion Defeat Riku I White Trinity Event": KH1LocationData("Hollow Bastion", 265_6101), + "Hollow Bastion Defeat Maleficent Donald Cheer Event": KH1LocationData("Hollow Bastion", 265_6102), + "Hollow Bastion Defeat Dragon Maleficent Fireglow Event": KH1LocationData("Hollow Bastion", 265_6103), + "Hollow Bastion Defeat Riku II Ragnarok Event": KH1LocationData("Hollow Bastion", 265_6104), + "Hollow Bastion Defeat Behemoth Omega Arts Event": KH1LocationData("Hollow Bastion", 265_6105), + "Hollow Bastion Speak to Princesses Fire Event": KH1LocationData("Hollow Bastion", 265_6106), + "End of the World Defeat Chernabog Superglide Event": KH1LocationData("End of the World", 265_6111), + + "Traverse Town Mail Postcard 01 Event": KH1LocationData("Traverse Town", 265_6120), + "Traverse Town Mail Postcard 02 Event": KH1LocationData("Traverse Town", 265_6121), + "Traverse Town Mail Postcard 03 Event": KH1LocationData("Traverse Town", 265_6122), + "Traverse Town Mail Postcard 04 Event": KH1LocationData("Traverse Town", 265_6123), + "Traverse Town Mail Postcard 05 Event": KH1LocationData("Traverse Town", 265_6124), + "Traverse Town Mail Postcard 06 Event": KH1LocationData("Traverse Town", 265_6125), + "Traverse Town Mail Postcard 07 Event": KH1LocationData("Traverse Town", 265_6126), + "Traverse Town Mail Postcard 08 Event": KH1LocationData("Traverse Town", 265_6127), + "Traverse Town Mail Postcard 09 Event": KH1LocationData("Traverse Town", 265_6128), + "Traverse Town Mail Postcard 10 Event": KH1LocationData("Traverse Town", 265_6129), + + "Traverse Town Defeat Opposite Armor Aero Event": KH1LocationData("Traverse Town", 265_6131), + + "Atlantica Undersea Gorge Blizzard Clam": KH1LocationData("Atlantica", 265_6201), + "Atlantica Undersea Gorge Ocean Floor Clam": KH1LocationData("Atlantica", 265_6202), + "Atlantica Undersea Valley Higher Cave Clam": KH1LocationData("Atlantica", 265_6203), + "Atlantica Undersea Valley Lower Cave Clam": KH1LocationData("Atlantica", 265_6204), + "Atlantica Undersea Valley Fire Clam": KH1LocationData("Atlantica", 265_6205), + "Atlantica Undersea Valley Wall Clam": KH1LocationData("Atlantica", 265_6206), + "Atlantica Undersea Valley Pillar Clam": KH1LocationData("Atlantica", 265_6207), + "Atlantica Undersea Valley Ocean Floor Clam": KH1LocationData("Atlantica", 265_6208), + "Atlantica Triton's Palace Thunder Clam": KH1LocationData("Atlantica", 265_6209), + "Atlantica Triton's Palace Wall Right Clam": KH1LocationData("Atlantica", 265_6210), + "Atlantica Triton's Palace Near Path Clam": KH1LocationData("Atlantica", 265_6211), + "Atlantica Triton's Palace Wall Left Clam": KH1LocationData("Atlantica", 265_6212), + "Atlantica Cavern Nook Clam": KH1LocationData("Atlantica", 265_6213), + "Atlantica Below Deck Clam": KH1LocationData("Atlantica", 265_6214), + "Atlantica Undersea Garden Clam": KH1LocationData("Atlantica", 265_6215), + "Atlantica Undersea Cave Clam": KH1LocationData("Atlantica", 265_6216), + + #"Traverse Town Magician's Study Turn in Naturespark": KH1LocationData("Traverse Town", 265_6300), + #"Traverse Town Magician's Study Turn in Watergleam": KH1LocationData("Traverse Town", 265_6301), + #"Traverse Town Magician's Study Turn in Fireglow": KH1LocationData("Traverse Town", 265_6302), + #"Traverse Town Magician's Study Turn in all Summon Gems": KH1LocationData("Traverse Town", 265_6303), + "Traverse Town Geppetto's House Geppetto Reward 1": KH1LocationData("Traverse Town", 265_6304), + "Traverse Town Geppetto's House Geppetto Reward 2": KH1LocationData("Traverse Town", 265_6305), + "Traverse Town Geppetto's House Geppetto Reward 3": KH1LocationData("Traverse Town", 265_6306), + "Traverse Town Geppetto's House Geppetto Reward 4": KH1LocationData("Traverse Town", 265_6307), + "Traverse Town Geppetto's House Geppetto Reward 5": KH1LocationData("Traverse Town", 265_6308), + "Traverse Town Geppetto's House Geppetto All Summons Reward": KH1LocationData("Traverse Town", 265_6309), + "Traverse Town Geppetto's House Talk to Pinocchio": KH1LocationData("Traverse Town", 265_6310), + "Traverse Town Magician's Study Obtained All Arts Items": KH1LocationData("Traverse Town", 265_6311), + "Traverse Town Magician's Study Obtained All LV1 Magic": KH1LocationData("Traverse Town", 265_6312), + "Traverse Town Magician's Study Obtained All LV3 Magic": KH1LocationData("Traverse Town", 265_6313), + "Traverse Town Piano Room Return 10 Puppies": KH1LocationData("Traverse Town", 265_6314), + "Traverse Town Piano Room Return 20 Puppies": KH1LocationData("Traverse Town", 265_6315), + "Traverse Town Piano Room Return 30 Puppies": KH1LocationData("Traverse Town", 265_6316), + "Traverse Town Piano Room Return 40 Puppies": KH1LocationData("Traverse Town", 265_6317), + "Traverse Town Piano Room Return 50 Puppies Reward 1": KH1LocationData("Traverse Town", 265_6318), + "Traverse Town Piano Room Return 50 Puppies Reward 2": KH1LocationData("Traverse Town", 265_6319), + "Traverse Town Piano Room Return 60 Puppies": KH1LocationData("Traverse Town", 265_6320), + "Traverse Town Piano Room Return 70 Puppies": KH1LocationData("Traverse Town", 265_6321), + "Traverse Town Piano Room Return 80 Puppies": KH1LocationData("Traverse Town", 265_6322), + "Traverse Town Piano Room Return 90 Puppies": KH1LocationData("Traverse Town", 265_6324), + "Traverse Town Piano Room Return 99 Puppies Reward 1": KH1LocationData("Traverse Town", 265_6326), + "Traverse Town Piano Room Return 99 Puppies Reward 2": KH1LocationData("Traverse Town", 265_6327), + "Olympus Coliseum Cloud Sonic Blade Event": KH1LocationData("Olympus Coliseum", 265_6032), #Had to change the way we send this check, not changing location_id + "Olympus Coliseum Defeat Sephiroth One-Winged Angel Event": KH1LocationData("Olympus Coliseum", 265_6328), + "Olympus Coliseum Defeat Ice Titan Diamond Dust Event": KH1LocationData("Olympus Coliseum", 265_6329), + "Olympus Coliseum Gates Purple Jar After Defeating Hades": KH1LocationData("Olympus Coliseum", 265_6330), + "Halloween Town Guillotine Square Ring Jack's Doorbell 3 Times": KH1LocationData("Halloween Town", 265_6331), + #"Neverland Clock Tower 01:00 Door": KH1LocationData("Neverland", 265_6332), + #"Neverland Clock Tower 02:00 Door": KH1LocationData("Neverland", 265_6333), + #"Neverland Clock Tower 03:00 Door": KH1LocationData("Neverland", 265_6334), + #"Neverland Clock Tower 04:00 Door": KH1LocationData("Neverland", 265_6335), + #"Neverland Clock Tower 05:00 Door": KH1LocationData("Neverland", 265_6336), + #"Neverland Clock Tower 06:00 Door": KH1LocationData("Neverland", 265_6337), + #"Neverland Clock Tower 07:00 Door": KH1LocationData("Neverland", 265_6338), + #"Neverland Clock Tower 08:00 Door": KH1LocationData("Neverland", 265_6339), + #"Neverland Clock Tower 09:00 Door": KH1LocationData("Neverland", 265_6340), + #"Neverland Clock Tower 10:00 Door": KH1LocationData("Neverland", 265_6341), + #"Neverland Clock Tower 11:00 Door": KH1LocationData("Neverland", 265_6342), + #"Neverland Clock Tower 12:00 Door": KH1LocationData("Neverland", 265_6343), + "Neverland Hold Aero Chest": KH1LocationData("Neverland", 265_6344), + "100 Acre Wood Bouncing Spot Turn in Rare Nut 1": KH1LocationData("100 Acre Wood", 265_6345), + "100 Acre Wood Bouncing Spot Turn in Rare Nut 2": KH1LocationData("100 Acre Wood", 265_6346), + "100 Acre Wood Bouncing Spot Turn in Rare Nut 3": KH1LocationData("100 Acre Wood", 265_6347), + "100 Acre Wood Bouncing Spot Turn in Rare Nut 4": KH1LocationData("100 Acre Wood", 265_6348), + "100 Acre Wood Bouncing Spot Turn in Rare Nut 5": KH1LocationData("100 Acre Wood", 265_6349), + "100 Acre Wood Pooh's House Owl Cheer": KH1LocationData("100 Acre Wood", 265_6350), + "100 Acre Wood Convert Torn Page 1": KH1LocationData("100 Acre Wood", 265_6351), + "100 Acre Wood Convert Torn Page 2": KH1LocationData("100 Acre Wood", 265_6352), + "100 Acre Wood Convert Torn Page 3": KH1LocationData("100 Acre Wood", 265_6353), + "100 Acre Wood Convert Torn Page 4": KH1LocationData("100 Acre Wood", 265_6354), + "100 Acre Wood Convert Torn Page 5": KH1LocationData("100 Acre Wood", 265_6355), + "100 Acre Wood Pooh's House Start Fire": KH1LocationData("100 Acre Wood", 265_6356), + "100 Acre Wood Pooh's Room Cabinet": KH1LocationData("100 Acre Wood", 265_6357), + "100 Acre Wood Pooh's Room Chimney": KH1LocationData("100 Acre Wood", 265_6358), + "100 Acre Wood Bouncing Spot Break Log": KH1LocationData("100 Acre Wood", 265_6359), + "100 Acre Wood Bouncing Spot Fall Through Top of Tree Next to Pooh": KH1LocationData("100 Acre Wood", 265_6360), + "Deep Jungle Camp Hi-Potion Experiment": KH1LocationData("Deep Jungle", 265_6361), + "Deep Jungle Camp Ether Experiment": KH1LocationData("Deep Jungle", 265_6362), + "Deep Jungle Camp Replication Experiment": KH1LocationData("Deep Jungle", 265_6363), + "Deep Jungle Cliff Save Gorillas": KH1LocationData("Deep Jungle", 265_6364), + "Deep Jungle Tree House Save Gorillas": KH1LocationData("Deep Jungle", 265_6365), + "Deep Jungle Camp Save Gorillas": KH1LocationData("Deep Jungle", 265_6366), + "Deep Jungle Bamboo Thicket Save Gorillas": KH1LocationData("Deep Jungle", 265_6367), + "Deep Jungle Climbing Trees Save Gorillas": KH1LocationData("Deep Jungle", 265_6368), + "Olympus Coliseum Olympia Chest": KH1LocationData("Olympus Coliseum", 265_6369), + "Deep Jungle Jungle Slider 10 Fruits": KH1LocationData("Deep Jungle", 265_6370), + "Deep Jungle Jungle Slider 20 Fruits": KH1LocationData("Deep Jungle", 265_6371), + "Deep Jungle Jungle Slider 30 Fruits": KH1LocationData("Deep Jungle", 265_6372), + "Deep Jungle Jungle Slider 40 Fruits": KH1LocationData("Deep Jungle", 265_6373), + "Deep Jungle Jungle Slider 50 Fruits": KH1LocationData("Deep Jungle", 265_6374), + "Traverse Town 1st District Speak with Cid Event": KH1LocationData("Traverse Town", 265_6375), + "Wonderland Bizarre Room Read Book": KH1LocationData("Wonderland", 265_6376), + "Olympus Coliseum Coliseum Gates Green Trinity": KH1LocationData("Olympus Coliseum", 265_6377), + "Agrabah Defeat Kurt Zisa Zantetsuken Event": KH1LocationData("Agrabah", 265_6378), + "Hollow Bastion Defeat Unknown EXP Necklace Event": KH1LocationData("Hollow Bastion", 265_6379), + "Olympus Coliseum Coliseum Gates Hero's License Event": KH1LocationData("Olympus Coliseum", 265_6380), + "Atlantica Sunken Ship Crystal Trident Event": KH1LocationData("Atlantica", 265_6381), + "Halloween Town Graveyard Forget-Me-Not Event": KH1LocationData("Halloween Town", 265_6382), + "Deep Jungle Tent Protect-G Event": KH1LocationData("Deep Jungle", 265_6383), + "Deep Jungle Cavern of Hearts Navi-G Piece Event": KH1LocationData("Deep Jungle", 265_6384), + "Wonderland Bizarre Room Navi-G Piece Event": KH1LocationData("Wonderland", 265_6385), + "Olympus Coliseum Coliseum Gates Entry Pass Event": KH1LocationData("Olympus Coliseum", 265_6386), + + "Traverse Town Synth Log": KH1LocationData("Traverse Town", 265_6401), + "Traverse Town Synth Cloth": KH1LocationData("Traverse Town", 265_6402), + "Traverse Town Synth Rope": KH1LocationData("Traverse Town", 265_6403), + "Traverse Town Synth Seagull Egg": KH1LocationData("Traverse Town", 265_6404), + "Traverse Town Synth Fish": KH1LocationData("Traverse Town", 265_6405), + "Traverse Town Synth Mushroom": KH1LocationData("Traverse Town", 265_6406), + + "Traverse Town Item Shop Postcard": KH1LocationData("Traverse Town", 265_6500), + "Traverse Town 1st District Safe Postcard": KH1LocationData("Traverse Town", 265_6501), + "Traverse Town Gizmo Shop Postcard 1": KH1LocationData("Traverse Town", 265_6502), + "Traverse Town Gizmo Shop Postcard 2": KH1LocationData("Traverse Town", 265_6503), + "Traverse Town Item Workshop Postcard": KH1LocationData("Traverse Town", 265_6504), + "Traverse Town 3rd District Balcony Postcard": KH1LocationData("Traverse Town", 265_6505), + "Traverse Town Geppetto's House Postcard": KH1LocationData("Traverse Town", 265_6506), + "Halloween Town Lab Torn Page": KH1LocationData("Halloween Town", 265_6508), + "Hollow Bastion Entrance Hall Emblem Piece (Flame)": KH1LocationData("Hollow Bastion", 265_6516), + "Hollow Bastion Entrance Hall Emblem Piece (Chest)": KH1LocationData("Hollow Bastion", 265_6517), + "Hollow Bastion Entrance Hall Emblem Piece (Statue)": KH1LocationData("Hollow Bastion", 265_6518), + "Hollow Bastion Entrance Hall Emblem Piece (Fountain)": KH1LocationData("Hollow Bastion", 265_6519), + #"Traverse Town 1st District Leon Gift": KH1LocationData("Traverse Town", 265_6520), + #"Traverse Town 1st District Aerith Gift": KH1LocationData("Traverse Town", 265_6521), + "Hollow Bastion Library Speak to Belle Divine Rose": KH1LocationData("Hollow Bastion", 265_6522), + "Hollow Bastion Library Speak to Aerith Cure": KH1LocationData("Hollow Bastion", 265_6523), + + "Agrabah Defeat Jafar Genie Ansem's Report 1": KH1LocationData("Agrabah", 265_7018), + "Hollow Bastion Speak with Aerith Ansem's Report 2": KH1LocationData("Hollow Bastion", 265_7017), + "Atlantica Defeat Ursula II Ansem's Report 3": KH1LocationData("Atlantica", 265_7016), + "Hollow Bastion Speak with Aerith Ansem's Report 4": KH1LocationData("Hollow Bastion", 265_7015), + "Hollow Bastion Defeat Maleficent Ansem's Report 5": KH1LocationData("Hollow Bastion", 265_7014), + "Hollow Bastion Speak with Aerith Ansem's Report 6": KH1LocationData("Hollow Bastion", 265_7013), + "Halloween Town Defeat Oogie Boogie Ansem's Report 7": KH1LocationData("Halloween Town", 265_7012), + "Olympus Coliseum Defeat Hades Ansem's Report 8": KH1LocationData("Olympus Coliseum", 265_7011), + "Neverland Defeat Hook Ansem's Report 9": KH1LocationData("Neverland", 265_7028), + "Hollow Bastion Speak with Aerith Ansem's Report 10": KH1LocationData("Hollow Bastion", 265_7027), + "Agrabah Defeat Kurt Zisa Ansem's Report 11": KH1LocationData("Agrabah", 265_7026), + "Olympus Coliseum Defeat Sephiroth Ansem's Report 12": KH1LocationData("Olympus Coliseum", 265_7025), + "Hollow Bastion Defeat Unknown Ansem's Report 13": KH1LocationData("Hollow Bastion", 265_7024), + "Level 001": KH1LocationData("Levels", 265_8001), + "Level 002": KH1LocationData("Levels", 265_8002), + "Level 003": KH1LocationData("Levels", 265_8003), + "Level 004": KH1LocationData("Levels", 265_8004), + "Level 005": KH1LocationData("Levels", 265_8005), + "Level 006": KH1LocationData("Levels", 265_8006), + "Level 007": KH1LocationData("Levels", 265_8007), + "Level 008": KH1LocationData("Levels", 265_8008), + "Level 009": KH1LocationData("Levels", 265_8009), + "Level 010": KH1LocationData("Levels", 265_8010), + "Level 011": KH1LocationData("Levels", 265_8011), + "Level 012": KH1LocationData("Levels", 265_8012), + "Level 013": KH1LocationData("Levels", 265_8013), + "Level 014": KH1LocationData("Levels", 265_8014), + "Level 015": KH1LocationData("Levels", 265_8015), + "Level 016": KH1LocationData("Levels", 265_8016), + "Level 017": KH1LocationData("Levels", 265_8017), + "Level 018": KH1LocationData("Levels", 265_8018), + "Level 019": KH1LocationData("Levels", 265_8019), + "Level 020": KH1LocationData("Levels", 265_8020), + "Level 021": KH1LocationData("Levels", 265_8021), + "Level 022": KH1LocationData("Levels", 265_8022), + "Level 023": KH1LocationData("Levels", 265_8023), + "Level 024": KH1LocationData("Levels", 265_8024), + "Level 025": KH1LocationData("Levels", 265_8025), + "Level 026": KH1LocationData("Levels", 265_8026), + "Level 027": KH1LocationData("Levels", 265_8027), + "Level 028": KH1LocationData("Levels", 265_8028), + "Level 029": KH1LocationData("Levels", 265_8029), + "Level 030": KH1LocationData("Levels", 265_8030), + "Level 031": KH1LocationData("Levels", 265_8031), + "Level 032": KH1LocationData("Levels", 265_8032), + "Level 033": KH1LocationData("Levels", 265_8033), + "Level 034": KH1LocationData("Levels", 265_8034), + "Level 035": KH1LocationData("Levels", 265_8035), + "Level 036": KH1LocationData("Levels", 265_8036), + "Level 037": KH1LocationData("Levels", 265_8037), + "Level 038": KH1LocationData("Levels", 265_8038), + "Level 039": KH1LocationData("Levels", 265_8039), + "Level 040": KH1LocationData("Levels", 265_8040), + "Level 041": KH1LocationData("Levels", 265_8041), + "Level 042": KH1LocationData("Levels", 265_8042), + "Level 043": KH1LocationData("Levels", 265_8043), + "Level 044": KH1LocationData("Levels", 265_8044), + "Level 045": KH1LocationData("Levels", 265_8045), + "Level 046": KH1LocationData("Levels", 265_8046), + "Level 047": KH1LocationData("Levels", 265_8047), + "Level 048": KH1LocationData("Levels", 265_8048), + "Level 049": KH1LocationData("Levels", 265_8049), + "Level 050": KH1LocationData("Levels", 265_8050), + "Level 051": KH1LocationData("Levels", 265_8051), + "Level 052": KH1LocationData("Levels", 265_8052), + "Level 053": KH1LocationData("Levels", 265_8053), + "Level 054": KH1LocationData("Levels", 265_8054), + "Level 055": KH1LocationData("Levels", 265_8055), + "Level 056": KH1LocationData("Levels", 265_8056), + "Level 057": KH1LocationData("Levels", 265_8057), + "Level 058": KH1LocationData("Levels", 265_8058), + "Level 059": KH1LocationData("Levels", 265_8059), + "Level 060": KH1LocationData("Levels", 265_8060), + "Level 061": KH1LocationData("Levels", 265_8061), + "Level 062": KH1LocationData("Levels", 265_8062), + "Level 063": KH1LocationData("Levels", 265_8063), + "Level 064": KH1LocationData("Levels", 265_8064), + "Level 065": KH1LocationData("Levels", 265_8065), + "Level 066": KH1LocationData("Levels", 265_8066), + "Level 067": KH1LocationData("Levels", 265_8067), + "Level 068": KH1LocationData("Levels", 265_8068), + "Level 069": KH1LocationData("Levels", 265_8069), + "Level 070": KH1LocationData("Levels", 265_8070), + "Level 071": KH1LocationData("Levels", 265_8071), + "Level 072": KH1LocationData("Levels", 265_8072), + "Level 073": KH1LocationData("Levels", 265_8073), + "Level 074": KH1LocationData("Levels", 265_8074), + "Level 075": KH1LocationData("Levels", 265_8075), + "Level 076": KH1LocationData("Levels", 265_8076), + "Level 077": KH1LocationData("Levels", 265_8077), + "Level 078": KH1LocationData("Levels", 265_8078), + "Level 079": KH1LocationData("Levels", 265_8079), + "Level 080": KH1LocationData("Levels", 265_8080), + "Level 081": KH1LocationData("Levels", 265_8081), + "Level 082": KH1LocationData("Levels", 265_8082), + "Level 083": KH1LocationData("Levels", 265_8083), + "Level 084": KH1LocationData("Levels", 265_8084), + "Level 085": KH1LocationData("Levels", 265_8085), + "Level 086": KH1LocationData("Levels", 265_8086), + "Level 087": KH1LocationData("Levels", 265_8087), + "Level 088": KH1LocationData("Levels", 265_8088), + "Level 089": KH1LocationData("Levels", 265_8089), + "Level 090": KH1LocationData("Levels", 265_8090), + "Level 091": KH1LocationData("Levels", 265_8091), + "Level 092": KH1LocationData("Levels", 265_8092), + "Level 093": KH1LocationData("Levels", 265_8093), + "Level 094": KH1LocationData("Levels", 265_8094), + "Level 095": KH1LocationData("Levels", 265_8095), + "Level 096": KH1LocationData("Levels", 265_8096), + "Level 097": KH1LocationData("Levels", 265_8097), + "Level 098": KH1LocationData("Levels", 265_8098), + "Level 099": KH1LocationData("Levels", 265_8099), + "Level 100": KH1LocationData("Levels", 265_8100), + "Complete Phil Cup": KH1LocationData("Olympus Coliseum", 265_9001), + "Complete Phil Cup Solo": KH1LocationData("Olympus Coliseum", 265_9002), + "Complete Phil Cup Time Trial": KH1LocationData("Olympus Coliseum", 265_9003), + "Complete Pegasus Cup": KH1LocationData("Olympus Coliseum", 265_9004), + "Complete Pegasus Cup Solo": KH1LocationData("Olympus Coliseum", 265_9005), + "Complete Pegasus Cup Time Trial": KH1LocationData("Olympus Coliseum", 265_9006), + "Complete Hercules Cup": KH1LocationData("Olympus Coliseum", 265_9007), + "Complete Hercules Cup Solo": KH1LocationData("Olympus Coliseum", 265_9008), + "Complete Hercules Cup Time Trial": KH1LocationData("Olympus Coliseum", 265_9009), + "Complete Hades Cup": KH1LocationData("Olympus Coliseum", 265_9010), + "Complete Hades Cup Solo": KH1LocationData("Olympus Coliseum", 265_9011), + "Complete Hades Cup Time Trial": KH1LocationData("Olympus Coliseum", 265_9012), + "Hades Cup Defeat Cloud and Leon Event": KH1LocationData("Olympus Coliseum", 265_9013), + "Hades Cup Defeat Yuffie Event": KH1LocationData("Olympus Coliseum", 265_9014), + "Hades Cup Defeat Cerberus Event": KH1LocationData("Olympus Coliseum", 265_9015), + "Hades Cup Defeat Behemoth Event": KH1LocationData("Olympus Coliseum", 265_9016), + "Hades Cup Defeat Hades Event": KH1LocationData("Olympus Coliseum", 265_9017), + "Hercules Cup Defeat Cloud Event": KH1LocationData("Olympus Coliseum", 265_9018), + "Hercules Cup Yellow Trinity Event": KH1LocationData("Olympus Coliseum", 265_9019), + "Final Ansem": KH1LocationData("Final", 265_9999) +} + +event_location_table: Dict[str, KH1LocationData] = {} + +lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in location_table.items() if data.code} + + +#Make location categories +location_name_groups: Dict[str, Set[str]] = {} +for location in location_table.keys(): + category = location_table[location].category + if category not in location_name_groups.keys(): + location_name_groups[category] = set() + location_name_groups[category].add(location) diff --git a/worlds/kh1/Options.py b/worlds/kh1/Options.py new file mode 100644 index 000000000000..63732f61b2d0 --- /dev/null +++ b/worlds/kh1/Options.py @@ -0,0 +1,445 @@ +from dataclasses import dataclass + +from Options import NamedRange, Choice, Range, Toggle, DefaultOnToggle, PerGameCommonOptions, StartInventoryPool, OptionGroup + +class StrengthIncrease(Range): + """ + Determines the number of Strength Increases to add to the multiworld. + + The randomizer will add all stat ups defined here into a pool and choose up to 100 to add to the multiworld. + Accessory Slot Increases and Item Slot Increases are prioritized first, then the remaining items (up to 100 total) are chosen at random. + """ + display_name = "STR Increases" + range_start = 0 + range_end = 100 + default = 24 + +class DefenseIncrease(Range): + """ + Determines the number of Defense Increases to add to the multiworld. + + The randomizer will add all stat ups defined here into a pool and choose up to 100 to add to the multiworld. + Accessory Slot Increases and Item Slot Increases are prioritized first, then the remaining items (up to 100 total) are chosen at random. + """ + display_name = "DEF Increases" + range_start = 0 + range_end = 100 + default = 24 + +class HPIncrease(Range): + """ + Determines the number of HP Increases to add to the multiworld. + + The randomizer will add all stat ups defined here into a pool and choose up to 100 to add to the multiworld. + Accessory Slot Increases and Item Slot Increases are prioritized first, then the remaining items (up to 100 total) are chosen at random. + """ + display_name = "HP Increases" + range_start = 0 + range_end = 100 + default = 23 + +class APIncrease(Range): + """ + Determines the number of AP Increases to add to the multiworld. + + The randomizer will add all stat ups defined here into a pool and choose up to 100 to add to the multiworld. + Accessory Slot Increases and Item Slot Increases are prioritized first, then the remaining items (up to 100 total) are chosen at random. + """ + display_name = "AP Increases" + range_start = 0 + range_end = 100 + default = 18 + +class MPIncrease(Range): + """ + Determines the number of MP Increases to add to the multiworld. + + The randomizer will add all stat ups defined here into a pool and choose up to 100 to add to the multiworld. + Accessory Slot Increases and Item Slot Increases are prioritized first, then the remaining items (up to 100 total) are chosen at random. + """ + display_name = "MP Increases" + range_start = 0 + range_end = 20 + default = 7 + +class AccessorySlotIncrease(Range): + """ + Determines the number of Accessory Slot Increases to add to the multiworld. + + The randomizer will add all stat ups defined here into a pool and choose up to 100 to add to the multiworld. + Accessory Slot Increases and Item Slot Increases are prioritized first, then the remaining items (up to 100 total) are chosen at random. + """ + display_name = "Accessory Slot Increases" + range_start = 0 + range_end = 6 + default = 1 + +class ItemSlotIncrease(Range): + """ + Determines the number of Item Slot Increases to add to the multiworld. + + The randomizer will add all stat ups defined here into a pool and choose up to 100 to add to the multiworld. + Accessory Slot Increases and Item Slot Increases are prioritized first, then the remaining items (up to 100 total) are chosen at random. + """ + display_name = "Item Slot Increases" + range_start = 0 + range_end = 5 + default = 3 + +class Atlantica(Toggle): + """ + Toggle whether to include checks in Atlantica. + """ + display_name = "Atlantica" + +class HundredAcreWood(Toggle): + """ + Toggle whether to include checks in the 100 Acre Wood. + """ + display_name = "100 Acre Wood" + +class SuperBosses(Toggle): + """ + Toggle whether to include checks behind Super Bosses. + """ + display_name = "Super Bosses" + +class Cups(Toggle): + """ + Toggle whether to include checks behind completing Phil, Pegasus, Hercules, or Hades cups. + Please note that the cup items will still appear in the multiworld even if toggled off, as they are required to challenge Sephiroth. + """ + display_name = "Cups" + +class Goal(Choice): + """ + Determines when victory is achieved in your playthrough. + + Sephiroth: Defeat Sephiroth + Unknown: Defeat Unknown + Postcards: Turn in all 10 postcards in Traverse Town + Final Ansem: Enter End of the World and defeat Ansem as normal + Puppies: Rescue and return all 99 puppies in Traverse Town + Final Rest: Open the chest in End of the World Final Rest + """ + display_name = "Goal" + option_sephiroth = 0 + option_unknown = 1 + option_postcards = 2 + option_final_ansem = 3 + option_puppies = 4 + option_final_rest = 5 + default = 3 + +class EndoftheWorldUnlock(Choice): + """Determines how End of the World is unlocked. + + Item: You can receive an item called "End of the World" which unlocks the world + Reports: A certain amount of reports are required to unlock End of the World, which is defined in your options""" + display_name = "End of the World Unlock" + option_item = 0 + option_reports = 1 + default = 1 + +class FinalRestDoor(Choice): + """Determines what conditions need to be met to manifest the door in Final Rest, allowing the player to challenge Ansem. + + Reports: A certain number of Ansem's Reports are required, determined by the "Reports to Open Final Rest Door" option + Puppies: Having all 99 puppies is required + Postcards: Turning in all 10 postcards is required + Superbosses: Defeating Sephiroth, Unknown, Kurt Zisa, and Phantom are required + """ + display_name = "Final Rest Door" + option_reports = 0 + option_puppies = 1 + option_postcards = 2 + option_superbosses = 3 + +class Puppies(Choice): + """ + Determines how dalmatian puppies are shuffled into the pool. + Full: All puppies are in one location + Triplets: Puppies are found in triplets just as they are in the base game + Individual: One puppy can be found per location + """ + display_name = "Puppies" + option_full = 0 + option_triplets = 1 + option_individual = 2 + default = 1 + +class EXPMultiplier(NamedRange): + """ + Determines the multiplier to apply to EXP gained. + """ + display_name = "EXP Multiplier" + default = 16 + range_start = default // 4 + range_end = 128 + special_range_names = { + "0.25x": int(default // 4), + "0.5x": int(default // 2), + "1x": default, + "2x": default * 2, + "3x": default * 3, + "4x": default * 4, + "8x": default * 8, + } + +class RequiredReportsEotW(Range): + """ + If End of the World Unlock is set to "Reports", determines the number of Ansem's Reports required to open End of the World. + """ + display_name = "Reports to Open End of the World" + default = 4 + range_start = 0 + range_end = 13 + +class RequiredReportsDoor(Range): + """ + If Final Rest Door is set to "Reports", determines the number of Ansem's Reports required to manifest the door in Final Rest to challenge Ansem. + """ + display_name = "Reports to Open Final Rest Door" + default = 4 + range_start = 0 + range_end = 13 + +class ReportsInPool(Range): + """ + Determines the number of Ansem's Reports in the item pool. + """ + display_name = "Reports in Pool" + default = 4 + range_start = 0 + range_end = 13 + +class RandomizeKeybladeStats(DefaultOnToggle): + """ + Determines whether Keyblade stats should be randomized. + """ + display_name = "Randomize Keyblade Stats" + +class KeybladeMinStrength(Range): + """ + Determines the minimum STR bonus a keyblade can have. + """ + display_name = "Keyblade Minimum STR Bonus" + default = 3 + range_start = 0 + range_end = 20 + +class KeybladeMaxStrength(Range): + """ + Determines the maximum STR bonus a keyblade can have. + """ + display_name = "Keyblade Maximum STR Bonus" + default = 14 + range_start = 0 + range_end = 20 + +class KeybladeMinMP(Range): + """ + Determines the minimum MP bonus a keyblade can have. + """ + display_name = "Keyblade Minimum MP Bonus" + default = -2 + range_start = -2 + range_end = 5 + +class KeybladeMaxMP(Range): + """ + Determines the maximum MP bonus a keyblade can have. + """ + display_name = "Keyblade Maximum MP Bonus" + default = 3 + range_start = -2 + range_end = 5 + +class LevelChecks(Range): + """ + Determines the maximum level for which checks can be obtained. + """ + display_name = "Level Checks" + default = 100 + range_start = 0 + range_end = 100 + +class ForceStatsOnLevels(NamedRange): + """ + If this value is less than the value for Level Checks, this determines the minimum level from which only stat ups are obtained at level up locations. + For example, if you want to be able to find any multiworld item from levels 1-50, then just stat ups for levels 51-100, set this value to 51. + """ + display_name = "Force Stats on Level Starting From" + default = 1 + range_start = 1 + range_end = 101 + special_range_names = { + "none": 101, + "multiworld-to-level-50": 51, + "all": 1 + } + +class BadStartingWeapons(Toggle): + """ + Forces Kingdom Key, Dream Sword, Dream Shield, and Dream Staff to have bad stats. + """ + display_name = "Bad Starting Weapons" + +class DonaldDeathLink(Toggle): + """ + If Donald is KO'ed, so is Sora. If Death Link is toggled on in your client, this will send a death to everyone. + """ + display_name = "Donald Death Link" + +class GoofyDeathLink(Toggle): + """ + If Goofy is KO'ed, so is Sora. If Death Link is toggled on in your client, this will send a death to everyone. + """ + display_name = "Goofy Death Link" + +class KeybladesUnlockChests(Toggle): + """ + If toggled on, the player is required to have a certain keyblade to open chests in certain worlds. + TT - Lionheart + WL - Lady Luck + OC - Olympia + DJ - Jungle King + AG - Three Wishes + MS - Wishing Star + HT - Pumpkinhead + NL - Fairy Harp + HB - Divine Rose + EotW - Oblivion + HAW - Oathkeeper + + Note: Does not apply to Atlantica, the emblem and carousel chests in Hollow Bastion, or the Aero chest in Neverland currently. + """ + display_name = "Keyblades Unlock Chests" + +class InteractInBattle(Toggle): + """ + Allow Sora to talk to people, examine objects, and open chests in battle. + """ + display_name = "Interact in Battle" + +class AdvancedLogic(Toggle): + """ + If on, logic may expect you to do advanced skips like using Combo Master, Dumbo, and other unusual methods to reach locations. + """ + display_name = "Advanced Logic" + +class ExtraSharedAbilities(Toggle): + """ + If on, adds extra shared abilities to the pool. These can stack, so multiple high jumps make you jump higher and multiple glides make you superglide faster. + """ + display_name = "Extra Shared Abilities" + +class EXPZeroInPool(Toggle): + """ + If on, adds EXP Zero ability to the item pool. This is redundant if you are planning on playing on Proud. + """ + display_name = "EXP Zero in Pool" + +class VanillaEmblemPieces(DefaultOnToggle): + """ + If on, the Hollow Bastion emblem pieces are in their vanilla locations. + """ + display_name = "Vanilla Emblem Pieces" + +class StartingWorlds(Range): + """ + Number of random worlds to start with in addition to Traverse Town, which is always available. Will only consider Atlantica if toggled, and will only consider End of the World if its unlock is set to "Item". + """ + display_name = "Starting Worlds" + default = 0 + range_start = 0 + range_end = 10 + +@dataclass +class KH1Options(PerGameCommonOptions): + goal: Goal + end_of_the_world_unlock: EndoftheWorldUnlock + final_rest_door: FinalRestDoor + required_reports_eotw: RequiredReportsEotW + required_reports_door: RequiredReportsDoor + reports_in_pool: ReportsInPool + super_bosses: SuperBosses + atlantica: Atlantica + hundred_acre_wood: HundredAcreWood + cups: Cups + puppies: Puppies + starting_worlds: StartingWorlds + keyblades_unlock_chests: KeybladesUnlockChests + interact_in_battle: InteractInBattle + exp_multiplier: EXPMultiplier + advanced_logic: AdvancedLogic + extra_shared_abilities: ExtraSharedAbilities + exp_zero_in_pool: EXPZeroInPool + vanilla_emblem_pieces: VanillaEmblemPieces + donald_death_link: DonaldDeathLink + goofy_death_link: GoofyDeathLink + randomize_keyblade_stats: RandomizeKeybladeStats + bad_starting_weapons: BadStartingWeapons + keyblade_min_str: KeybladeMinStrength + keyblade_max_str: KeybladeMaxStrength + keyblade_min_mp: KeybladeMinMP + keyblade_max_mp: KeybladeMaxMP + level_checks: LevelChecks + force_stats_on_levels: ForceStatsOnLevels + strength_increase: StrengthIncrease + defense_increase: DefenseIncrease + hp_increase: HPIncrease + ap_increase: APIncrease + mp_increase: MPIncrease + accessory_slot_increase: AccessorySlotIncrease + item_slot_increase: ItemSlotIncrease + start_inventory_from_pool: StartInventoryPool + +kh1_option_groups = [ + OptionGroup("Goal", [ + Goal, + EndoftheWorldUnlock, + FinalRestDoor, + RequiredReportsDoor, + RequiredReportsEotW, + ReportsInPool, + ]), + OptionGroup("Locations", [ + SuperBosses, + Atlantica, + Cups, + HundredAcreWood, + VanillaEmblemPieces, + ]), + OptionGroup("Levels", [ + EXPMultiplier, + LevelChecks, + ForceStatsOnLevels, + StrengthIncrease, + DefenseIncrease, + HPIncrease, + APIncrease, + MPIncrease, + AccessorySlotIncrease, + ItemSlotIncrease, + ]), + OptionGroup("Keyblades", [ + KeybladesUnlockChests, + RandomizeKeybladeStats, + BadStartingWeapons, + KeybladeMaxStrength, + KeybladeMinStrength, + KeybladeMaxMP, + KeybladeMinMP, + ]), + OptionGroup("Misc", [ + StartingWorlds, + Puppies, + InteractInBattle, + AdvancedLogic, + ExtraSharedAbilities, + EXPZeroInPool, + DonaldDeathLink, + GoofyDeathLink, + ]) +] diff --git a/worlds/kh1/Presets.py b/worlds/kh1/Presets.py new file mode 100644 index 000000000000..77b43b7624b9 --- /dev/null +++ b/worlds/kh1/Presets.py @@ -0,0 +1,177 @@ +from typing import Any, Dict + +from .Options import * + +kh1_option_presets: Dict[str, Dict[str, Any]] = { + # Standard playthrough where your goal is to defeat Ansem, reaching him by acquiring enough reports. + "Final Ansem": { + "goal": Goal.option_final_ansem, + "end_of_the_world_unlock": EndoftheWorldUnlock.option_reports, + "final_rest_door": FinalRestDoor.option_reports, + "required_reports_eotw": 7, + "required_reports_door": 10, + "reports_in_pool": 13, + + "super_bosses": False, + "atlantica": False, + "hundred_acre_wood": False, + "cups": False, + "vanilla_emblem_pieces": True, + + "exp_multiplier": 48, + "level_checks": 100, + "force_stats_on_levels": 1, + "strength_increase": 24, + "defense_increase": 24, + "hp_increase": 23, + "ap_increase": 18, + "mp_increase": 7, + "accessory_slot_increase": 1, + "item_slot_increase": 3, + + "keyblades_unlock_chests": False, + "randomize_keyblade_stats": True, + "bad_starting_weapons": False, + "keyblade_max_str": 14, + "keyblade_min_str": 3, + "keyblade_max_mp": 3, + "keyblade_min_mp": -2, + + "puppies": Puppies.option_triplets, + "starting_worlds": 0, + "interact_in_battle": False, + "advanced_logic": False, + "extra_shared_abilities": False, + "exp_zero_in_pool": False, + "donald_death_link": False, + "goofy_death_link": False + }, + # Puppies are found individually, and the goal is to return them all. + "Puppy Hunt": { + "goal": Goal.option_puppies, + "end_of_the_world_unlock": EndoftheWorldUnlock.option_item, + "final_rest_door": FinalRestDoor.option_puppies, + "required_reports_eotw": 13, + "required_reports_door": 13, + "reports_in_pool": 13, + + "super_bosses": False, + "atlantica": False, + "hundred_acre_wood": False, + "cups": False, + "vanilla_emblem_pieces": True, + + "exp_multiplier": 48, + "level_checks": 100, + "force_stats_on_levels": 1, + "strength_increase": 24, + "defense_increase": 24, + "hp_increase": 23, + "ap_increase": 18, + "mp_increase": 7, + "accessory_slot_increase": 1, + "item_slot_increase": 3, + + "keyblades_unlock_chests": False, + "randomize_keyblade_stats": True, + "bad_starting_weapons": False, + "keyblade_max_str": 14, + "keyblade_min_str": 3, + "keyblade_max_mp": 3, + "keyblade_min_mp": -2, + + "puppies": Puppies.option_individual, + "starting_worlds": 0, + "interact_in_battle": False, + "advanced_logic": False, + "extra_shared_abilities": False, + "exp_zero_in_pool": False, + "donald_death_link": False, + "goofy_death_link": False + }, + # Advanced playthrough with most settings on. + "Advanced": { + "goal": Goal.option_final_ansem, + "end_of_the_world_unlock": EndoftheWorldUnlock.option_reports, + "final_rest_door": FinalRestDoor.option_reports, + "required_reports_eotw": 7, + "required_reports_door": 10, + "reports_in_pool": 13, + + "super_bosses": True, + "atlantica": True, + "hundred_acre_wood": True, + "cups": True, + "vanilla_emblem_pieces": False, + + "exp_multiplier": 48, + "level_checks": 100, + "force_stats_on_levels": 1, + "strength_increase": 24, + "defense_increase": 24, + "hp_increase": 23, + "ap_increase": 18, + "mp_increase": 7, + "accessory_slot_increase": 1, + "item_slot_increase": 3, + + "keyblades_unlock_chests": True, + "randomize_keyblade_stats": True, + "bad_starting_weapons": True, + "keyblade_max_str": 14, + "keyblade_min_str": 3, + "keyblade_max_mp": 3, + "keyblade_min_mp": -2, + + "puppies": Puppies.option_triplets, + "starting_worlds": 0, + "interact_in_battle": True, + "advanced_logic": True, + "extra_shared_abilities": True, + "exp_zero_in_pool": True, + "donald_death_link": False, + "goofy_death_link": False + }, + # Playthrough meant to enhance the level 1 experience. + "Level 1": { + "goal": Goal.option_final_ansem, + "end_of_the_world_unlock": EndoftheWorldUnlock.option_reports, + "final_rest_door": FinalRestDoor.option_reports, + "required_reports_eotw": 7, + "required_reports_door": 10, + "reports_in_pool": 13, + + "super_bosses": False, + "atlantica": False, + "hundred_acre_wood": False, + "cups": False, + "vanilla_emblem_pieces": True, + + "exp_multiplier": 16, + "level_checks": 0, + "force_stats_on_levels": 101, + "strength_increase": 0, + "defense_increase": 0, + "hp_increase": 0, + "mp_increase": 0, + "accessory_slot_increase": 6, + "item_slot_increase": 5, + + "keyblades_unlock_chests": False, + "randomize_keyblade_stats": True, + "bad_starting_weapons": False, + "keyblade_max_str": 14, + "keyblade_min_str": 3, + "keyblade_max_mp": 3, + "keyblade_min_mp": -2, + + "puppies": Puppies.option_triplets, + "starting_worlds": 0, + "interact_in_battle": False, + "advanced_logic": False, + "extra_shared_abilities": False, + "exp_zero_in_pool": False, + "donald_death_link": False, + "goofy_death_link": False + } +} diff --git a/worlds/kh1/Regions.py b/worlds/kh1/Regions.py new file mode 100644 index 000000000000..a6f85fe617cb --- /dev/null +++ b/worlds/kh1/Regions.py @@ -0,0 +1,516 @@ +from typing import Dict, List, NamedTuple, Optional + +from BaseClasses import MultiWorld, Region, Entrance +from .Locations import KH1Location, location_table + + +class KH1RegionData(NamedTuple): + locations: List[str] + region_exits: Optional[List[str]] + + +def create_regions(multiworld: MultiWorld, player: int, options): + regions: Dict[str, KH1RegionData] = { + "Menu": KH1RegionData([], ["Awakening", "Levels"]), + "Awakening": KH1RegionData([], ["Destiny Islands"]), + "Destiny Islands": KH1RegionData([], ["Traverse Town"]), + "Traverse Town": KH1RegionData([], ["World Map"]), + "Wonderland": KH1RegionData([], []), + "Olympus Coliseum": KH1RegionData([], []), + "Deep Jungle": KH1RegionData([], []), + "Agrabah": KH1RegionData([], []), + "Monstro": KH1RegionData([], []), + "Atlantica": KH1RegionData([], []), + "Halloween Town": KH1RegionData([], []), + "Neverland": KH1RegionData([], []), + "Hollow Bastion": KH1RegionData([], []), + "End of the World": KH1RegionData([], []), + "100 Acre Wood": KH1RegionData([], []), + "Levels": KH1RegionData([], []), + "World Map": KH1RegionData([], ["Wonderland", "Olympus Coliseum", "Deep Jungle", + "Agrabah", "Monstro", "Atlantica", + "Halloween Town", "Neverland", "Hollow Bastion", + "End of the World", "100 Acre Wood"]) + } + + # Set up locations + regions["Agrabah"].locations.append("Agrabah Aladdin's House Main Street Entrance Chest") + regions["Agrabah"].locations.append("Agrabah Aladdin's House Plaza Entrance Chest") + regions["Agrabah"].locations.append("Agrabah Alley Chest") + regions["Agrabah"].locations.append("Agrabah Bazaar Across Windows Chest") + regions["Agrabah"].locations.append("Agrabah Bazaar High Corner Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Bottomless Hall Across Chasm Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Bottomless Hall Pillar Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Bottomless Hall Raised Platform Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Dark Chamber Abu Gem Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Dark Chamber Across from Relic Chamber Entrance Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Dark Chamber Bridge Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Dark Chamber Near Save Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Entrance Left Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Entrance Tall Tower Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Entrance White Trinity Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Hall High Left Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Hall Near Bottomless Hall Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Hidden Room Left Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Hidden Room Right Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Relic Chamber Jump from Stairs Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Relic Chamber Stairs Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Silent Chamber Blue Trinity Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Treasure Room Above Fire Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Treasure Room Across Platforms Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Treasure Room Large Treasure Pile Chest") + regions["Agrabah"].locations.append("Agrabah Cave of Wonders Treasure Room Small Treasure Pile Chest") + regions["Agrabah"].locations.append("Agrabah Defeat Jafar Blizzard Event") + regions["Agrabah"].locations.append("Agrabah Defeat Jafar Genie Ansem's Report 1") + regions["Agrabah"].locations.append("Agrabah Defeat Jafar Genie Fire Event") + regions["Agrabah"].locations.append("Agrabah Defeat Pot Centipede Ray of Light Event") + regions["Agrabah"].locations.append("Agrabah Main Street High Above Alley Entrance Chest") + regions["Agrabah"].locations.append("Agrabah Main Street High Above Palace Gates Entrance Chest") + regions["Agrabah"].locations.append("Agrabah Main Street Right Palace Entrance Chest") + regions["Agrabah"].locations.append("Agrabah Palace Gates High Close to Palace Chest") + regions["Agrabah"].locations.append("Agrabah Palace Gates High Opposite Palace Chest") + regions["Agrabah"].locations.append("Agrabah Palace Gates Low Chest") + regions["Agrabah"].locations.append("Agrabah Plaza By Storage Chest") + regions["Agrabah"].locations.append("Agrabah Plaza Raised Terrace Chest") + regions["Agrabah"].locations.append("Agrabah Plaza Top Corner Chest") + regions["Agrabah"].locations.append("Agrabah Seal Keyhole Genie Event") + regions["Agrabah"].locations.append("Agrabah Seal Keyhole Green Trinity Event") + regions["Agrabah"].locations.append("Agrabah Seal Keyhole Three Wishes Event") + regions["Agrabah"].locations.append("Agrabah Storage Behind Barrel Chest") + regions["Agrabah"].locations.append("Agrabah Storage Green Trinity Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Bamboo Thicket Save Gorillas") + regions["Deep Jungle"].locations.append("Deep Jungle Camp Blue Trinity Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Camp Ether Experiment") + regions["Deep Jungle"].locations.append("Deep Jungle Camp Hi-Potion Experiment") + regions["Deep Jungle"].locations.append("Deep Jungle Camp Replication Experiment") + regions["Deep Jungle"].locations.append("Deep Jungle Camp Save Gorillas") + regions["Deep Jungle"].locations.append("Deep Jungle Cavern of Hearts Navi-G Piece Event") + regions["Deep Jungle"].locations.append("Deep Jungle Cavern of Hearts White Trinity Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Cliff Right Cliff Left Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Cliff Right Cliff Right Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Cliff Save Gorillas") + regions["Deep Jungle"].locations.append("Deep Jungle Climbing Trees Blue Trinity Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Climbing Trees Save Gorillas") + regions["Deep Jungle"].locations.append("Deep Jungle Defeat Clayton Cure Event") + regions["Deep Jungle"].locations.append("Deep Jungle Defeat Sabor White Fang Event") + regions["Deep Jungle"].locations.append("Deep Jungle Hippo's Lagoon Center Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Hippo's Lagoon Left Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Hippo's Lagoon Right Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Jungle Slider 10 Fruits") + regions["Deep Jungle"].locations.append("Deep Jungle Jungle Slider 20 Fruits") + regions["Deep Jungle"].locations.append("Deep Jungle Jungle Slider 30 Fruits") + regions["Deep Jungle"].locations.append("Deep Jungle Jungle Slider 40 Fruits") + regions["Deep Jungle"].locations.append("Deep Jungle Jungle Slider 50 Fruits") + regions["Deep Jungle"].locations.append("Deep Jungle Seal Keyhole Jungle King Event") + regions["Deep Jungle"].locations.append("Deep Jungle Seal Keyhole Red Trinity Event") + regions["Deep Jungle"].locations.append("Deep Jungle Tent Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Tent Protect-G Event") + regions["Deep Jungle"].locations.append("Deep Jungle Tree House Beneath Tree House Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Tree House Rooftop Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Tree House Save Gorillas") + regions["Deep Jungle"].locations.append("Deep Jungle Tree House Suspended Boat Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Tunnel Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Vines 2 Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Vines Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Waterfall Cavern High Middle Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Waterfall Cavern High Wall Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Waterfall Cavern Low Chest") + regions["Deep Jungle"].locations.append("Deep Jungle Waterfall Cavern Middle Chest") + regions["End of the World"].locations.append("End of the World Defeat Chernabog Superglide Event") + regions["End of the World"].locations.append("End of the World Final Dimension 10th Chest") + regions["End of the World"].locations.append("End of the World Final Dimension 1st Chest") + regions["End of the World"].locations.append("End of the World Final Dimension 2nd Chest") + regions["End of the World"].locations.append("End of the World Final Dimension 3rd Chest") + regions["End of the World"].locations.append("End of the World Final Dimension 4th Chest") + regions["End of the World"].locations.append("End of the World Final Dimension 5th Chest") + regions["End of the World"].locations.append("End of the World Final Dimension 6th Chest") + regions["End of the World"].locations.append("End of the World Final Dimension 7th Chest") + regions["End of the World"].locations.append("End of the World Final Dimension 8th Chest") + regions["End of the World"].locations.append("End of the World Final Dimension 9th Chest") + regions["End of the World"].locations.append("End of the World Final Rest Chest") + regions["End of the World"].locations.append("End of the World Giant Crevasse 1st Chest") + regions["End of the World"].locations.append("End of the World Giant Crevasse 2nd Chest") + regions["End of the World"].locations.append("End of the World Giant Crevasse 3rd Chest") + regions["End of the World"].locations.append("End of the World Giant Crevasse 4th Chest") + regions["End of the World"].locations.append("End of the World Giant Crevasse 5th Chest") + regions["End of the World"].locations.append("End of the World World Terminus 100 Acre Wood Chest") + regions["End of the World"].locations.append("End of the World World Terminus Agrabah Chest") + regions["End of the World"].locations.append("End of the World World Terminus Atlantica Chest") + regions["End of the World"].locations.append("End of the World World Terminus Deep Jungle Chest") + regions["End of the World"].locations.append("End of the World World Terminus Halloween Town Chest") + #regions["End of the World"].locations.append("End of the World World Terminus Hollow Bastion Chest") + regions["End of the World"].locations.append("End of the World World Terminus Neverland Chest") + regions["End of the World"].locations.append("End of the World World Terminus Olympus Coliseum Chest") + regions["End of the World"].locations.append("End of the World World Terminus Traverse Town Chest") + regions["End of the World"].locations.append("End of the World World Terminus Wonderland Chest") + regions["Halloween Town"].locations.append("Halloween Town Boneyard Tombstone Puzzle Chest") + regions["Halloween Town"].locations.append("Halloween Town Bridge Left of Gate Chest") + regions["Halloween Town"].locations.append("Halloween Town Bridge Right of Gate Chest") + regions["Halloween Town"].locations.append("Halloween Town Bridge Under Bridge") + regions["Halloween Town"].locations.append("Halloween Town Cemetery Behind Grave Chest") + regions["Halloween Town"].locations.append("Halloween Town Cemetery Between Graves Chest") + regions["Halloween Town"].locations.append("Halloween Town Cemetery By Cat Shape Chest") + regions["Halloween Town"].locations.append("Halloween Town Cemetery By Striped Grave Chest") + regions["Halloween Town"].locations.append("Halloween Town Defeat Oogie Boogie Ansem's Report 7") + regions["Halloween Town"].locations.append("Halloween Town Defeat Oogie Boogie Holy Circlet Event") + regions["Halloween Town"].locations.append("Halloween Town Defeat Oogie's Manor Gravity Event") + regions["Halloween Town"].locations.append("Halloween Town Graveyard Forget-Me-Not Event") + regions["Halloween Town"].locations.append("Halloween Town Guillotine Square High Tower Chest") + regions["Halloween Town"].locations.append("Halloween Town Guillotine Square Pumpkin Structure Left Chest") + regions["Halloween Town"].locations.append("Halloween Town Guillotine Square Pumpkin Structure Right Chest") + regions["Halloween Town"].locations.append("Halloween Town Guillotine Square Ring Jack's Doorbell 3 Times") + regions["Halloween Town"].locations.append("Halloween Town Guillotine Square Under Jack's House Stairs Chest") + regions["Halloween Town"].locations.append("Halloween Town Lab Torn Page") + regions["Halloween Town"].locations.append("Halloween Town Moonlight Hill White Trinity Chest") + regions["Halloween Town"].locations.append("Halloween Town Oogie's Manor Entrance Steps Chest") + regions["Halloween Town"].locations.append("Halloween Town Oogie's Manor Grounds Red Trinity Chest") + regions["Halloween Town"].locations.append("Halloween Town Oogie's Manor Hollow Chest") + regions["Halloween Town"].locations.append("Halloween Town Oogie's Manor Inside Entrance Chest") + regions["Halloween Town"].locations.append("Halloween Town Oogie's Manor Lower Iron Cage Chest") + regions["Halloween Town"].locations.append("Halloween Town Oogie's Manor Upper Iron Cage Chest") + regions["Halloween Town"].locations.append("Halloween Town Seal Keyhole Pumpkinhead Event") + regions["Hollow Bastion"].locations.append("Hollow Bastion Base Level Bubble Under the Wall Platform Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Base Level Near Crystal Switch Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Base Level Platform Near Entrance Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Castle Gates Freestanding Pillar Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Castle Gates Gravity Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Castle Gates High Pillar Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Behemoth Omega Arts Event") + regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Dragon Maleficent Fireglow Event") + regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Maleficent Ansem's Report 5") + regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Maleficent Donald Cheer Event") + regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Riku I White Trinity Event") + regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Riku II Ragnarok Event") + regions["Hollow Bastion"].locations.append("Hollow Bastion Dungeon By Candles Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Dungeon Corner Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Entrance Hall Emblem Piece (Chest)") + regions["Hollow Bastion"].locations.append("Hollow Bastion Entrance Hall Emblem Piece (Flame)") + regions["Hollow Bastion"].locations.append("Hollow Bastion Entrance Hall Emblem Piece (Fountain)") + regions["Hollow Bastion"].locations.append("Hollow Bastion Entrance Hall Emblem Piece (Statue)") + regions["Hollow Bastion"].locations.append("Hollow Bastion Entrance Hall Left of Emblem Door Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Grand Hall Left of Gate Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Grand Hall Oblivion Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Grand Hall Steps Right Side Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Great Crest After Battle Platform Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Great Crest Lower Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion High Tower 1st Gravity Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion High Tower 2nd Gravity Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion High Tower Above Sliding Blocks Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Library 1st Floor Turn the Carousel Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Library 2nd Floor Turn the Carousel 1st Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Library 2nd Floor Turn the Carousel 2nd Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Library Speak to Aerith Cure") + regions["Hollow Bastion"].locations.append("Hollow Bastion Library Speak to Belle Divine Rose") + regions["Hollow Bastion"].locations.append("Hollow Bastion Library Top of Bookshelf Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Library Top of Bookshelf Turn the Carousel Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Lift Stop Heartless Sigil Door Gravity Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Lift Stop Library Node After High Tower Switch Gravity Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Lift Stop Library Node Gravity Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Lift Stop Outside Library Gravity Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Lift Stop Under High Tower Sliding Blocks Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Rising Falls Floating Platform Near Bubble Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Rising Falls Floating Platform Near Save Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Rising Falls High Platform Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Rising Falls Under Water 1st Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Rising Falls Under Water 2nd Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Rising Falls Water's Surface Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Rising Falls White Trinity Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Speak to Princesses Fire Event") + regions["Hollow Bastion"].locations.append("Hollow Bastion Speak with Aerith Ansem's Report 10") + regions["Hollow Bastion"].locations.append("Hollow Bastion Speak with Aerith Ansem's Report 2") + regions["Hollow Bastion"].locations.append("Hollow Bastion Speak with Aerith Ansem's Report 4") + regions["Hollow Bastion"].locations.append("Hollow Bastion Speak with Aerith Ansem's Report 6") + regions["Hollow Bastion"].locations.append("Hollow Bastion Waterway Blizzard on Bubble Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Waterway Near Save Chest") + regions["Hollow Bastion"].locations.append("Hollow Bastion Waterway Unlock Passage from Base Level Chest") + regions["Monstro"].locations.append("Monstro Chamber 2 Ground Chest") + regions["Monstro"].locations.append("Monstro Chamber 2 Platform Chest") + regions["Monstro"].locations.append("Monstro Chamber 3 Ground Chest") + regions["Monstro"].locations.append("Monstro Chamber 3 Near Chamber 6 Entrance Chest") + regions["Monstro"].locations.append("Monstro Chamber 3 Platform Above Chamber 2 Entrance Chest") + regions["Monstro"].locations.append("Monstro Chamber 3 Platform Near Chamber 6 Entrance Chest") + regions["Monstro"].locations.append("Monstro Chamber 5 Atop Barrel Chest") + regions["Monstro"].locations.append("Monstro Chamber 5 Low 1st Chest") + regions["Monstro"].locations.append("Monstro Chamber 5 Low 2nd Chest") + regions["Monstro"].locations.append("Monstro Chamber 5 Platform Chest") + regions["Monstro"].locations.append("Monstro Chamber 6 Low Chest") + regions["Monstro"].locations.append("Monstro Chamber 6 Other Platform Chest") + regions["Monstro"].locations.append("Monstro Chamber 6 Platform Near Chamber 5 Entrance Chest") + regions["Monstro"].locations.append("Monstro Chamber 6 Raised Area Near Chamber 1 Entrance Chest") + regions["Monstro"].locations.append("Monstro Chamber 6 White Trinity Chest") + regions["Monstro"].locations.append("Monstro Defeat Parasite Cage I Goofy Cheer Event") + regions["Monstro"].locations.append("Monstro Defeat Parasite Cage II Stop Event") + regions["Monstro"].locations.append("Monstro Mouth Boat Deck Chest") + regions["Monstro"].locations.append("Monstro Mouth Green Trinity Top of Boat Chest") + regions["Monstro"].locations.append("Monstro Mouth High Platform Across from Boat Chest") + regions["Monstro"].locations.append("Monstro Mouth High Platform Boat Side Chest") + regions["Monstro"].locations.append("Monstro Mouth High Platform Near Teeth Chest") + regions["Monstro"].locations.append("Monstro Mouth Near Ship Chest") + regions["Neverland"].locations.append("Neverland Cabin Chest") + regions["Neverland"].locations.append("Neverland Captain's Cabin Chest") + #regions["Neverland"].locations.append("Neverland Clock Tower 01:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 02:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 03:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 04:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 05:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 06:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 07:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 08:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 09:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 10:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 11:00 Door") + #regions["Neverland"].locations.append("Neverland Clock Tower 12:00 Door") + regions["Neverland"].locations.append("Neverland Clock Tower Chest") + regions["Neverland"].locations.append("Neverland Defeat Anti Sora Raven's Claw Event") + regions["Neverland"].locations.append("Neverland Defeat Captain Hook Ars Arcanum Event") + regions["Neverland"].locations.append("Neverland Defeat Hook Ansem's Report 9") + regions["Neverland"].locations.append("Neverland Encounter Hook Cure Event") + regions["Neverland"].locations.append("Neverland Galley Chest") + regions["Neverland"].locations.append("Neverland Hold Aero Chest") + regions["Neverland"].locations.append("Neverland Hold Flight 1st Chest") + regions["Neverland"].locations.append("Neverland Hold Flight 2nd Chest") + regions["Neverland"].locations.append("Neverland Hold Yellow Trinity Green Chest") + regions["Neverland"].locations.append("Neverland Hold Yellow Trinity Left Blue Chest") + regions["Neverland"].locations.append("Neverland Hold Yellow Trinity Right Blue Chest") + regions["Neverland"].locations.append("Neverland Pirate Ship Crows Nest Chest") + regions["Neverland"].locations.append("Neverland Pirate Ship Deck White Trinity Chest") + regions["Neverland"].locations.append("Neverland Seal Keyhole Fairy Harp Event") + regions["Neverland"].locations.append("Neverland Seal Keyhole Glide Event") + regions["Neverland"].locations.append("Neverland Seal Keyhole Tinker Bell Event") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Clear Phil's Training Thunder Event") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Cloud Sonic Blade Event") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Coliseum Gates Blizzaga Chest") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Coliseum Gates Blizzara Chest") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Coliseum Gates Entry Pass Event") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Coliseum Gates Green Trinity") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Coliseum Gates Hero's License Event") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Coliseum Gates Left Behind Columns Chest") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Coliseum Gates Left Blue Trinity Chest") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Coliseum Gates Right Blue Trinity Chest") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Coliseum Gates White Trinity Chest") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Defeat Cerberus Inferno Band Event") + regions["Traverse Town"].locations.append("Traverse Town 1st District Accessory Shop Roof Chest") + #regions["Traverse Town"].locations.append("Traverse Town 1st District Aerith Gift") + regions["Traverse Town"].locations.append("Traverse Town 1st District Blue Trinity Balcony Chest") + regions["Traverse Town"].locations.append("Traverse Town 1st District Candle Puzzle Chest") + #regions["Traverse Town"].locations.append("Traverse Town 1st District Leon Gift") + regions["Traverse Town"].locations.append("Traverse Town 1st District Safe Postcard") + regions["Traverse Town"].locations.append("Traverse Town 1st District Speak with Cid Event") + regions["Traverse Town"].locations.append("Traverse Town 2nd District Boots and Shoes Awning Chest") + regions["Traverse Town"].locations.append("Traverse Town 2nd District Gizmo Shop Facade Chest") + regions["Traverse Town"].locations.append("Traverse Town 2nd District Rooftop Chest") + regions["Traverse Town"].locations.append("Traverse Town 3rd District Balcony Postcard") + regions["Traverse Town"].locations.append("Traverse Town Accessory Shop Chest") + regions["Traverse Town"].locations.append("Traverse Town Alleyway Balcony Chest") + regions["Traverse Town"].locations.append("Traverse Town Alleyway Behind Crates Chest") + regions["Traverse Town"].locations.append("Traverse Town Alleyway Blue Room Awning Chest") + regions["Traverse Town"].locations.append("Traverse Town Alleyway Corner Chest") + regions["Traverse Town"].locations.append("Traverse Town Defeat Guard Armor Blue Trinity Event") + regions["Traverse Town"].locations.append("Traverse Town Defeat Guard Armor Brave Warrior Event") + regions["Traverse Town"].locations.append("Traverse Town Defeat Guard Armor Dodge Roll Event") + regions["Traverse Town"].locations.append("Traverse Town Defeat Guard Armor Fire Event") + regions["Traverse Town"].locations.append("Traverse Town Defeat Opposite Armor Aero Event") + regions["Traverse Town"].locations.append("Traverse Town Geppetto's House Chest") + regions["Traverse Town"].locations.append("Traverse Town Geppetto's House Geppetto All Summons Reward") + regions["Traverse Town"].locations.append("Traverse Town Geppetto's House Geppetto Reward 1") + regions["Traverse Town"].locations.append("Traverse Town Geppetto's House Geppetto Reward 2") + regions["Traverse Town"].locations.append("Traverse Town Geppetto's House Geppetto Reward 3") + regions["Traverse Town"].locations.append("Traverse Town Geppetto's House Geppetto Reward 4") + regions["Traverse Town"].locations.append("Traverse Town Geppetto's House Geppetto Reward 5") + regions["Traverse Town"].locations.append("Traverse Town Geppetto's House Postcard") + regions["Traverse Town"].locations.append("Traverse Town Geppetto's House Talk to Pinocchio") + regions["Traverse Town"].locations.append("Traverse Town Gizmo Shop Postcard 1") + regions["Traverse Town"].locations.append("Traverse Town Gizmo Shop Postcard 2") + regions["Traverse Town"].locations.append("Traverse Town Green Room Clock Puzzle Chest") + regions["Traverse Town"].locations.append("Traverse Town Green Room Table Chest") + regions["Traverse Town"].locations.append("Traverse Town Item Shop Postcard") + regions["Traverse Town"].locations.append("Traverse Town Item Workshop Left Chest") + regions["Traverse Town"].locations.append("Traverse Town Item Workshop Postcard") + regions["Traverse Town"].locations.append("Traverse Town Item Workshop Right Chest") + regions["Traverse Town"].locations.append("Traverse Town Kairi Secret Waterway Oathkeeper Event") + regions["Traverse Town"].locations.append("Traverse Town Leon Secret Waterway Earthshine Event") + regions["Traverse Town"].locations.append("Traverse Town Magician's Study Obtained All Arts Items") + regions["Traverse Town"].locations.append("Traverse Town Magician's Study Obtained All LV1 Magic") + regions["Traverse Town"].locations.append("Traverse Town Magician's Study Obtained All LV3 Magic") + regions["Traverse Town"].locations.append("Traverse Town Mail Postcard 01 Event") + regions["Traverse Town"].locations.append("Traverse Town Mail Postcard 02 Event") + regions["Traverse Town"].locations.append("Traverse Town Mail Postcard 03 Event") + regions["Traverse Town"].locations.append("Traverse Town Mail Postcard 04 Event") + regions["Traverse Town"].locations.append("Traverse Town Mail Postcard 05 Event") + regions["Traverse Town"].locations.append("Traverse Town Mail Postcard 06 Event") + regions["Traverse Town"].locations.append("Traverse Town Mail Postcard 07 Event") + regions["Traverse Town"].locations.append("Traverse Town Mail Postcard 08 Event") + regions["Traverse Town"].locations.append("Traverse Town Mail Postcard 09 Event") + regions["Traverse Town"].locations.append("Traverse Town Mail Postcard 10 Event") + regions["Traverse Town"].locations.append("Traverse Town Mystical House Glide Chest") + regions["Traverse Town"].locations.append("Traverse Town Mystical House Yellow Trinity Chest") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 10 Puppies") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 20 Puppies") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 30 Puppies") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 40 Puppies") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 50 Puppies Reward 1") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 50 Puppies Reward 2") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 60 Puppies") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 70 Puppies") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 80 Puppies") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 90 Puppies") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 99 Puppies Reward 1") + regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 99 Puppies Reward 2") + regions["Traverse Town"].locations.append("Traverse Town Red Room Chest") + regions["Traverse Town"].locations.append("Traverse Town Secret Waterway Near Stairs Chest") + regions["Traverse Town"].locations.append("Traverse Town Secret Waterway White Trinity Chest") + regions["Traverse Town"].locations.append("Traverse Town Synth Cloth") + regions["Traverse Town"].locations.append("Traverse Town Synth Fish") + regions["Traverse Town"].locations.append("Traverse Town Synth Log") + regions["Traverse Town"].locations.append("Traverse Town Synth Mushroom") + regions["Traverse Town"].locations.append("Traverse Town Synth Rope") + regions["Traverse Town"].locations.append("Traverse Town Synth Seagull Egg") + regions["Wonderland"].locations.append("Wonderland Bizarre Room Green Trinity Chest") + regions["Wonderland"].locations.append("Wonderland Bizarre Room Lamp Chest") + regions["Wonderland"].locations.append("Wonderland Bizarre Room Navi-G Piece Event") + regions["Wonderland"].locations.append("Wonderland Bizarre Room Read Book") + regions["Wonderland"].locations.append("Wonderland Defeat Trickmaster Blizzard Event") + regions["Wonderland"].locations.append("Wonderland Defeat Trickmaster Ifrit's Horn Event") + regions["Wonderland"].locations.append("Wonderland Lotus Forest Corner Chest") + regions["Wonderland"].locations.append("Wonderland Lotus Forest Glide Chest") + regions["Wonderland"].locations.append("Wonderland Lotus Forest Nut Chest") + regions["Wonderland"].locations.append("Wonderland Lotus Forest Through the Painting Thunder Plant Chest") + regions["Wonderland"].locations.append("Wonderland Lotus Forest Through the Painting White Trinity Chest") + regions["Wonderland"].locations.append("Wonderland Lotus Forest Thunder Plant Chest") + regions["Wonderland"].locations.append("Wonderland Queen's Castle Hedge Left Red Chest") + regions["Wonderland"].locations.append("Wonderland Queen's Castle Hedge Right Blue Chest") + regions["Wonderland"].locations.append("Wonderland Queen's Castle Hedge Right Red Chest") + regions["Wonderland"].locations.append("Wonderland Rabbit Hole Defeat Heartless 1 Chest") + regions["Wonderland"].locations.append("Wonderland Rabbit Hole Defeat Heartless 2 Chest") + regions["Wonderland"].locations.append("Wonderland Rabbit Hole Defeat Heartless 3 Chest") + regions["Wonderland"].locations.append("Wonderland Rabbit Hole Green Trinity Chest") + regions["Wonderland"].locations.append("Wonderland Tea Party Garden Above Lotus Forest Entrance 1st Chest") + regions["Wonderland"].locations.append("Wonderland Tea Party Garden Above Lotus Forest Entrance 2nd Chest") + regions["Wonderland"].locations.append("Wonderland Tea Party Garden Across From Bizarre Room Entrance Chest") + regions["Wonderland"].locations.append("Wonderland Tea Party Garden Bear and Clock Puzzle Chest") + if options.hundred_acre_wood: + regions["100 Acre Wood"].locations.append("100 Acre Wood Meadow Inside Log Chest") + regions["100 Acre Wood"].locations.append("100 Acre Wood Bouncing Spot Left Cliff Chest") + regions["100 Acre Wood"].locations.append("100 Acre Wood Bouncing Spot Right Tree Alcove Chest") + regions["100 Acre Wood"].locations.append("100 Acre Wood Bouncing Spot Under Giant Pot Chest") + regions["100 Acre Wood"].locations.append("100 Acre Wood Bouncing Spot Turn in Rare Nut 1") + regions["100 Acre Wood"].locations.append("100 Acre Wood Bouncing Spot Turn in Rare Nut 2") + regions["100 Acre Wood"].locations.append("100 Acre Wood Bouncing Spot Turn in Rare Nut 3") + regions["100 Acre Wood"].locations.append("100 Acre Wood Bouncing Spot Turn in Rare Nut 4") + regions["100 Acre Wood"].locations.append("100 Acre Wood Bouncing Spot Turn in Rare Nut 5") + regions["100 Acre Wood"].locations.append("100 Acre Wood Pooh's House Owl Cheer") + regions["100 Acre Wood"].locations.append("100 Acre Wood Convert Torn Page 1") + regions["100 Acre Wood"].locations.append("100 Acre Wood Convert Torn Page 2") + regions["100 Acre Wood"].locations.append("100 Acre Wood Convert Torn Page 3") + regions["100 Acre Wood"].locations.append("100 Acre Wood Convert Torn Page 4") + regions["100 Acre Wood"].locations.append("100 Acre Wood Convert Torn Page 5") + regions["100 Acre Wood"].locations.append("100 Acre Wood Pooh's House Start Fire") + regions["100 Acre Wood"].locations.append("100 Acre Wood Pooh's Room Cabinet") + regions["100 Acre Wood"].locations.append("100 Acre Wood Pooh's Room Chimney") + regions["100 Acre Wood"].locations.append("100 Acre Wood Bouncing Spot Break Log") + regions["100 Acre Wood"].locations.append("100 Acre Wood Bouncing Spot Fall Through Top of Tree Next to Pooh") + if options.atlantica: + regions["Atlantica"].locations.append("Atlantica Sunken Ship In Flipped Boat Chest") + regions["Atlantica"].locations.append("Atlantica Sunken Ship Seabed Chest") + regions["Atlantica"].locations.append("Atlantica Sunken Ship Inside Ship Chest") + regions["Atlantica"].locations.append("Atlantica Ariel's Grotto High Chest") + regions["Atlantica"].locations.append("Atlantica Ariel's Grotto Middle Chest") + regions["Atlantica"].locations.append("Atlantica Ariel's Grotto Low Chest") + regions["Atlantica"].locations.append("Atlantica Ursula's Lair Use Fire on Urchin Chest") + regions["Atlantica"].locations.append("Atlantica Undersea Gorge Jammed by Ariel's Grotto Chest") + regions["Atlantica"].locations.append("Atlantica Triton's Palace White Trinity Chest") + regions["Atlantica"].locations.append("Atlantica Defeat Ursula I Mermaid Kick Event") + regions["Atlantica"].locations.append("Atlantica Defeat Ursula II Thunder Event") + regions["Atlantica"].locations.append("Atlantica Seal Keyhole Crabclaw Event") + regions["Atlantica"].locations.append("Atlantica Undersea Gorge Blizzard Clam") + regions["Atlantica"].locations.append("Atlantica Undersea Gorge Ocean Floor Clam") + regions["Atlantica"].locations.append("Atlantica Undersea Valley Higher Cave Clam") + regions["Atlantica"].locations.append("Atlantica Undersea Valley Lower Cave Clam") + regions["Atlantica"].locations.append("Atlantica Undersea Valley Fire Clam") + regions["Atlantica"].locations.append("Atlantica Undersea Valley Wall Clam") + regions["Atlantica"].locations.append("Atlantica Undersea Valley Pillar Clam") + regions["Atlantica"].locations.append("Atlantica Undersea Valley Ocean Floor Clam") + regions["Atlantica"].locations.append("Atlantica Triton's Palace Thunder Clam") + regions["Atlantica"].locations.append("Atlantica Triton's Palace Wall Right Clam") + regions["Atlantica"].locations.append("Atlantica Triton's Palace Near Path Clam") + regions["Atlantica"].locations.append("Atlantica Triton's Palace Wall Left Clam") + regions["Atlantica"].locations.append("Atlantica Cavern Nook Clam") + regions["Atlantica"].locations.append("Atlantica Below Deck Clam") + regions["Atlantica"].locations.append("Atlantica Undersea Garden Clam") + regions["Atlantica"].locations.append("Atlantica Undersea Cave Clam") + regions["Atlantica"].locations.append("Atlantica Sunken Ship Crystal Trident Event") + regions["Atlantica"].locations.append("Atlantica Defeat Ursula II Ansem's Report 3") + if options.cups: + regions["Olympus Coliseum"].locations.append("Complete Phil Cup") + regions["Olympus Coliseum"].locations.append("Complete Phil Cup Solo") + regions["Olympus Coliseum"].locations.append("Complete Phil Cup Time Trial") + regions["Olympus Coliseum"].locations.append("Complete Pegasus Cup") + regions["Olympus Coliseum"].locations.append("Complete Pegasus Cup Solo") + regions["Olympus Coliseum"].locations.append("Complete Pegasus Cup Time Trial") + regions["Olympus Coliseum"].locations.append("Complete Hercules Cup") + regions["Olympus Coliseum"].locations.append("Complete Hercules Cup Solo") + regions["Olympus Coliseum"].locations.append("Complete Hercules Cup Time Trial") + regions["Olympus Coliseum"].locations.append("Complete Hades Cup") + regions["Olympus Coliseum"].locations.append("Complete Hades Cup Solo") + regions["Olympus Coliseum"].locations.append("Complete Hades Cup Time Trial") + regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Cloud and Leon Event") + regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Yuffie Event") + regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Cerberus Event") + regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Behemoth Event") + regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Hades Event") + regions["Olympus Coliseum"].locations.append("Hercules Cup Defeat Cloud Event") + regions["Olympus Coliseum"].locations.append("Hercules Cup Yellow Trinity Event") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Defeat Hades Ansem's Report 8") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Olympia Chest") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Defeat Ice Titan Diamond Dust Event") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Gates Purple Jar After Defeating Hades") + if options.super_bosses: + regions["Neverland"].locations.append("Neverland Defeat Phantom Stop Event") + regions["Agrabah"].locations.append("Agrabah Defeat Kurt Zisa Zantetsuken Event") + regions["Agrabah"].locations.append("Agrabah Defeat Kurt Zisa Ansem's Report 11") + if options.super_bosses or options.goal.current_key == "sephiroth": + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Defeat Sephiroth Ansem's Report 12") + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Defeat Sephiroth One-Winged Angel Event") + if options.super_bosses or options.goal.current_key == "unknown": + regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Unknown Ansem's Report 13") + regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Unknown EXP Necklace Event") + for i in range(options.level_checks): + regions["Levels"].locations.append("Level " + str(i+1).rjust(3, '0')) + if options.goal.current_key == "final_ansem": + regions["End of the World"].locations.append("Final Ansem") + + # Set up the regions correctly. + for name, data in regions.items(): + multiworld.regions.append(create_region(multiworld, player, name, data)) + + multiworld.get_entrance("Awakening", player).connect(multiworld.get_region("Awakening", player)) + multiworld.get_entrance("Destiny Islands", player).connect(multiworld.get_region("Destiny Islands", player)) + multiworld.get_entrance("Traverse Town", player).connect(multiworld.get_region("Traverse Town", player)) + multiworld.get_entrance("Wonderland", player).connect(multiworld.get_region("Wonderland", player)) + multiworld.get_entrance("Olympus Coliseum", player).connect(multiworld.get_region("Olympus Coliseum", player)) + multiworld.get_entrance("Deep Jungle", player).connect(multiworld.get_region("Deep Jungle", player)) + multiworld.get_entrance("Agrabah", player).connect(multiworld.get_region("Agrabah", player)) + multiworld.get_entrance("Monstro", player).connect(multiworld.get_region("Monstro", player)) + multiworld.get_entrance("Atlantica", player).connect(multiworld.get_region("Atlantica", player)) + multiworld.get_entrance("Halloween Town", player).connect(multiworld.get_region("Halloween Town", player)) + multiworld.get_entrance("Neverland", player).connect(multiworld.get_region("Neverland", player)) + multiworld.get_entrance("Hollow Bastion", player).connect(multiworld.get_region("Hollow Bastion", player)) + multiworld.get_entrance("End of the World", player).connect(multiworld.get_region("End of the World", player)) + multiworld.get_entrance("100 Acre Wood", player).connect(multiworld.get_region("100 Acre Wood", player)) + multiworld.get_entrance("World Map", player).connect(multiworld.get_region("World Map", player)) + multiworld.get_entrance("Levels", player).connect(multiworld.get_region("Levels", player)) + +def create_region(multiworld: MultiWorld, player: int, name: str, data: KH1RegionData): + region = Region(name, player, multiworld) + if data.locations: + for loc_name in data.locations: + loc_data = location_table.get(loc_name) + location = KH1Location(player, loc_name, loc_data.code if loc_data else None, region) + region.locations.append(location) + + if data.region_exits: + for exit in data.region_exits: + entrance = Entrance(player, exit, region) + region.exits.append(entrance) + + return region diff --git a/worlds/kh1/Rules.py b/worlds/kh1/Rules.py new file mode 100644 index 000000000000..c8cb71ffd636 --- /dev/null +++ b/worlds/kh1/Rules.py @@ -0,0 +1,1947 @@ +from BaseClasses import CollectionState +from worlds.generic.Rules import add_rule + +SINGLE_PUPPIES = ["Puppy " + str(i).rjust(2,"0") for i in range(1,100)] +TRIPLE_PUPPIES = ["Puppies " + str(3*(i-1)+1).rjust(2, "0") + "-" + str(3*(i-1)+3).rjust(2, "0") for i in range(1,34)] +TORN_PAGES = ["Torn Page " + str(i) for i in range(1,6)] +WORLDS = ["Wonderland", "Olympus Coliseum", "Deep Jungle", "Agrabah", "Monstro", "Atlantica", "Halloween Town", "Neverland", "Hollow Bastion", "End of the World"] +KEYBLADES = ["Lady Luck", "Olympia", "Jungle King", "Three Wishes", "Wishing Star", "Crabclaw", "Pumpkinhead", "Fairy Harp", "Divine Rose", "Oblivion"] + +def has_x_worlds(state: CollectionState, player: int, num_of_worlds: int, keyblades_unlock_chests: bool) -> bool: + worlds_acquired = 0.0 + for i in range(len(WORLDS)): + if state.has(WORLDS[i], player): + worlds_acquired = worlds_acquired + 0.5 + if (state.has(WORLDS[i], player) and (not keyblades_unlock_chests or state.has(KEYBLADES[i], player))) or (state.has(WORLDS[i], player) and WORLDS[i] == "Atlantica"): + worlds_acquired = worlds_acquired + 0.5 + return worlds_acquired >= num_of_worlds + +def has_emblems(state: CollectionState, player: int, keyblades_unlock_chests: bool) -> bool: + return state.has_all({ + "Emblem Piece (Flame)", + "Emblem Piece (Chest)", + "Emblem Piece (Statue)", + "Emblem Piece (Fountain)", + "Hollow Bastion"}, player) and has_x_worlds(state, player, 5, keyblades_unlock_chests) + +def has_puppies_all(state: CollectionState, player: int, puppies_required: int) -> bool: + return state.has("All Puppies", player) + +def has_puppies_triplets(state: CollectionState, player: int, puppies_required: int) -> bool: + return state.has_from_list_unique(TRIPLE_PUPPIES, player, -(puppies_required / -3)) + +def has_puppies_individual(state: CollectionState, player: int, puppies_required: int) -> bool: + return state.has_from_list_unique(SINGLE_PUPPIES, player, puppies_required) + +def has_torn_pages(state: CollectionState, player: int, pages_required: int) -> bool: + return state.count_from_list_unique(TORN_PAGES, player) >= pages_required + +def has_all_arts(state: CollectionState, player: int) -> bool: + return state.has_all({"Fire Arts", "Blizzard Arts", "Thunder Arts", "Cure Arts", "Gravity Arts", "Stop Arts", "Aero Arts"}, player) + +def has_all_summons(state: CollectionState, player: int) -> bool: + return state.has_all({"Simba", "Bambi", "Genie", "Dumbo", "Mushu", "Tinker Bell"}, player) + +def has_all_magic_lvx(state: CollectionState, player: int, level) -> bool: + return state.has_all_counts({ + "Progressive Fire": level, + "Progressive Blizzard": level, + "Progressive Thunder": level, + "Progressive Cure": level, + "Progressive Gravity": level, + "Progressive Aero": level, + "Progressive Stop": level}, player) + +def has_offensive_magic(state: CollectionState, player: int) -> bool: + return state.has_any({"Progressive Fire", "Progressive Blizzard", "Progressive Thunder", "Progressive Gravity", "Progressive Stop"}, player) + +def has_reports(state: CollectionState, player: int, eotw_required_reports: int) -> bool: + return state.has_group_unique("Reports", player, eotw_required_reports) + +def has_final_rest_door(state: CollectionState, player: int, final_rest_door_requirement: str, final_rest_door_required_reports: int, keyblades_unlock_chests: bool, puppies_choice: str): + if final_rest_door_requirement == "reports": + return state.has_group_unique("Reports", player, final_rest_door_required_reports) + if final_rest_door_requirement == "puppies": + if puppies_choice == "individual": + return has_puppies_individual(state, player, 99) + if puppies_choice == "triplets": + return has_puppies_triplets(state, player, 99) + return has_puppies_all(state, player, 99) + if final_rest_door_requirement == "postcards": + return state.has("Postcard", player, 10) + if final_rest_door_requirement == "superbosses": + return ( + state.has_all({"Olympus Coliseum", "Neverland", "Agrabah", "Hollow Bastion", "Green Trinity", "Phil Cup", "Pegasus Cup", "Hercules Cup", "Entry Pass"}, player) + and has_emblems(state, player, keyblades_unlock_chests) + and has_all_magic_lvx(state, player, 2) + and has_defensive_tools(state, player) + and has_x_worlds(state, player, 7, keyblades_unlock_chests) + ) + +def has_defensive_tools(state: CollectionState, player: int) -> bool: + return ( + state.has_all_counts({"Progressive Cure": 2, "Leaf Bracer": 1, "Dodge Roll": 1}, player) + and state.has_any_count({"Second Chance": 1, "MP Rage": 1, "Progressive Aero": 2}, player) + ) + +def can_dumbo_skip(state: CollectionState, player: int) -> bool: + return ( + state.has("Dumbo", player) + and state.has_group("Magic", player) + ) + +def has_oogie_manor(state: CollectionState, player: int, advanced_logic: bool) -> bool: + return ( + state.has("Progressive Fire", player) + or (advanced_logic and state.has("High Jump", player, 2)) + or (advanced_logic and state.has("High Jump", player) and state.has("Progressive Glide", player)) + ) + +def set_rules(kh1world): + multiworld = kh1world.multiworld + player = kh1world.player + options = kh1world.options + eotw_required_reports = kh1world.determine_reports_required_to_open_end_of_the_world() + final_rest_door_required_reports = kh1world.determine_reports_required_to_open_final_rest_door() + final_rest_door_requirement = kh1world.options.final_rest_door.current_key + + has_puppies = has_puppies_individual + if kh1world.options.puppies == "triplets": + has_puppies = has_puppies_triplets + elif kh1world.options.puppies == "full": + has_puppies = has_puppies_all + + add_rule(kh1world.get_location("Traverse Town 1st District Candle Puzzle Chest"), + lambda state: state.has("Progressive Blizzard", player)) + add_rule(kh1world.get_location("Traverse Town Mystical House Yellow Trinity Chest"), + lambda state: ( + state.has("Progressive Fire", player) + and + ( + state.has("Yellow Trinity", player) + or (options.advanced_logic and state.has("High Jump", player)) + or state.has("High Jump", player, 2) + ) + )) + add_rule(kh1world.get_location("Traverse Town Secret Waterway White Trinity Chest"), + lambda state: state.has("White Trinity", player)) + add_rule(kh1world.get_location("Traverse Town Geppetto's House Chest"), + lambda state: ( + state.has("Monstro", player) + and + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and has_x_worlds(state, player, 2, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Traverse Town Item Workshop Right Chest"), + lambda state: ( + state.has("Green Trinity", player) + or state.has("High Jump", player, 3) + )) + add_rule(kh1world.get_location("Traverse Town 1st District Blue Trinity Balcony Chest"), + lambda state: ( + (state.has("Blue Trinity", player) and state.has("Progressive Glide", player)) + or (options.advanced_logic and state.has("Progressive Glide", player)) + )) + add_rule(kh1world.get_location("Traverse Town Mystical House Glide Chest"), + lambda state: ( + ( + state.has("Progressive Glide", player) + or + ( + options.advanced_logic + and + ( + (state.has("High Jump", player) and state.has("Yellow Trinity", player)) + or state.has("High Jump", player, 2) + ) + and state.has("Combo Master", player) + ) + or + ( + options.advanced_logic + and state.has("Mermaid Kick", player) + ) + ) + and state.has("Progressive Fire", player) + )) + add_rule(kh1world.get_location("Traverse Town Alleyway Behind Crates Chest"), + lambda state: state.has("Red Trinity", player)) + add_rule(kh1world.get_location("Traverse Town Item Workshop Left Chest"), + lambda state: ( + state.has("Green Trinity", player) + or state.has("High Jump", player, 3) + )) + add_rule(kh1world.get_location("Wonderland Rabbit Hole Green Trinity Chest"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Wonderland Rabbit Hole Defeat Heartless 3 Chest"), + lambda state: has_x_worlds(state, player, 5, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Wonderland Bizarre Room Green Trinity Chest"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Wonderland Queen's Castle Hedge Left Red Chest"), + lambda state: ( + state.has("Footprints", player) + or state.has("High Jump", player) + or state.has("Progressive Glide", player) + )) + add_rule(kh1world.get_location("Wonderland Queen's Castle Hedge Right Blue Chest"), + lambda state: ( + state.has("Footprints", player) + or state.has("High Jump", player) + or state.has("Progressive Glide", player) + )) + add_rule(kh1world.get_location("Wonderland Queen's Castle Hedge Right Red Chest"), + lambda state: ( + state.has("Footprints", player) + or state.has("High Jump", player) + or state.has("Progressive Glide", player) + )) + add_rule(kh1world.get_location("Wonderland Lotus Forest Thunder Plant Chest"), + lambda state: ( + state.has_all({ + "Progressive Thunder", + "Footprints"}, player) + )) + add_rule(kh1world.get_location("Wonderland Lotus Forest Through the Painting Thunder Plant Chest"), + lambda state: ( + state.has_all({ + "Progressive Thunder", + "Footprints"}, player) + )) + add_rule(kh1world.get_location("Wonderland Lotus Forest Glide Chest"), + lambda state: ( + state.has("Progressive Glide", player) + or + ( + options.advanced_logic + and (state.has("High Jump", player) or can_dumbo_skip(state, player)) + and state.has("Footprints", player) + ) + )) + add_rule(kh1world.get_location("Wonderland Lotus Forest Corner Chest"), + lambda state: ( + ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + ) + or options.advanced_logic + )) + add_rule(kh1world.get_location("Wonderland Bizarre Room Lamp Chest"), + lambda state: state.has("Footprints", player)) + add_rule(kh1world.get_location("Wonderland Tea Party Garden Above Lotus Forest Entrance 2nd Chest"), + lambda state: ( + state.has("Progressive Glide", player) + or + ( + options.advanced_logic + and state.has_all({ + "High Jump", + "Footprints"}, player) + ) + )) + add_rule(kh1world.get_location("Wonderland Tea Party Garden Above Lotus Forest Entrance 1st Chest"), + lambda state: ( + state.has("Progressive Glide", player) + or + ( + options.advanced_logic + and state.has_all({ + "High Jump", + "Footprints"}, player) + ) + )) + add_rule(kh1world.get_location("Wonderland Tea Party Garden Bear and Clock Puzzle Chest"), + lambda state: ( + + state.has("Footprints", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + or state.has("High Jump", player, 2) + )) + add_rule(kh1world.get_location("Wonderland Tea Party Garden Across From Bizarre Room Entrance Chest"), + lambda state: ( + state.has("Progressive Glide", player) + or + ( + state.has("High Jump", player, 3) + and state.has("Footprints", player) + ) + or + ( + options.advanced_logic + and state.has_all({ + "High Jump", + "Footprints", + "Combo Master"}, player) + ) + )) + add_rule(kh1world.get_location("Wonderland Lotus Forest Through the Painting White Trinity Chest"), + lambda state: ( + state.has_all({ + "White Trinity", + "Footprints"}, player) + )) + add_rule(kh1world.get_location("Deep Jungle Hippo's Lagoon Right Chest"), + lambda state: ( + + state.has("High Jump", player) + or state.has("Progressive Glide", player) + or options.advanced_logic + )) + add_rule(kh1world.get_location("Deep Jungle Climbing Trees Blue Trinity Chest"), + lambda state: state.has("Blue Trinity", player)) + add_rule(kh1world.get_location("Deep Jungle Cavern of Hearts White Trinity Chest"), + lambda state: ( + state.has_all({ + "White Trinity", + "Slides"}, player) + )) + add_rule(kh1world.get_location("Deep Jungle Camp Blue Trinity Chest"), + lambda state: state.has("Blue Trinity", player)) + add_rule(kh1world.get_location("Deep Jungle Waterfall Cavern Low Chest"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Waterfall Cavern Middle Chest"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Waterfall Cavern High Wall Chest"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Waterfall Cavern High Middle Chest"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Tree House Suspended Boat Chest"), + lambda state: ( + state.has("Progressive Glide", player) + or options.advanced_logic + )) + add_rule(kh1world.get_location("Agrabah Main Street High Above Palace Gates Entrance Chest"), + lambda state: ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + or (options.advanced_logic and can_dumbo_skip(state, player)) + )) + add_rule(kh1world.get_location("Agrabah Palace Gates High Opposite Palace Chest"), + lambda state: ( + state.has("High Jump", player) + or options.advanced_logic + )) + add_rule(kh1world.get_location("Agrabah Palace Gates High Close to Palace Chest"), + lambda state: ( + ( + state.has_all({ + "High Jump", + "Progressive Glide"}, player) + or + ( + options.advanced_logic + and + ( + state.has("Combo Master", player) + or can_dumbo_skip(state, player) + ) + ) + ) + or state.has("High Jump", player, 3) + or (options.advanced_logic and state.has("Progressive Glide", player)) + )) + add_rule(kh1world.get_location("Agrabah Storage Green Trinity Chest"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Entrance Tall Tower Chest"), + lambda state: ( + state.has("Progressive Glide", player) + or (options.advanced_logic and state.has("Combo Master", player)) + or (options.advanced_logic and can_dumbo_skip(state, player)) + or state.has("High Jump", player, 2) + )) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Bottomless Hall Pillar Chest"), + lambda state: ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + or options.advanced_logic + )) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Silent Chamber Blue Trinity Chest"), + lambda state: state.has("Blue Trinity", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Hidden Room Right Chest"), + lambda state: ( + state.has("Yellow Trinity", player) + or state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + )) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Hidden Room Left Chest"), + lambda state: ( + state.has("Yellow Trinity", player) + or state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + )) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Entrance White Trinity Chest"), + lambda state: state.has("White Trinity", player)) + add_rule(kh1world.get_location("Monstro Chamber 6 Other Platform Chest"), + lambda state: ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Combo Master", player)) + )) + add_rule(kh1world.get_location("Monstro Chamber 6 Platform Near Chamber 5 Entrance Chest"), + lambda state: ( + state.has("High Jump", player) + or options.advanced_logic + )) + add_rule(kh1world.get_location("Monstro Chamber 6 Raised Area Near Chamber 1 Entrance Chest"), + lambda state: ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Combo Master", player)) + )) + add_rule(kh1world.get_location("Halloween Town Moonlight Hill White Trinity Chest"), + lambda state: ( + state.has_all({ + "White Trinity", + "Forget-Me-Not"}, player) + )) + add_rule(kh1world.get_location("Halloween Town Bridge Under Bridge"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + )) + add_rule(kh1world.get_location("Halloween Town Boneyard Tombstone Puzzle Chest"), + lambda state: state.has("Forget-Me-Not", player)) + add_rule(kh1world.get_location("Halloween Town Bridge Right of Gate Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and + ( + state.has("Progressive Glide", player) + or options.advanced_logic + ) + )) + add_rule(kh1world.get_location("Halloween Town Cemetery Behind Grave Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and has_oogie_manor(state, player, options.advanced_logic) + )) + add_rule(kh1world.get_location("Halloween Town Cemetery By Cat Shape Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and has_oogie_manor(state, player, options.advanced_logic) + )) + add_rule(kh1world.get_location("Halloween Town Cemetery Between Graves Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and has_oogie_manor(state, player, options.advanced_logic) + )) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Lower Iron Cage Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and has_oogie_manor(state, player, options.advanced_logic) + )) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Upper Iron Cage Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and has_oogie_manor(state, player, options.advanced_logic) + )) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Hollow Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and has_oogie_manor(state, player, options.advanced_logic) + )) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Grounds Red Trinity Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not", + "Red Trinity"}, player) + )) + add_rule(kh1world.get_location("Halloween Town Guillotine Square High Tower Chest"), + lambda state: ( + state.has("High Jump", player) + or (options.advanced_logic and can_dumbo_skip(state, player)) + or (options.advanced_logic and state.has("Progressive Glide", player)) + )) + add_rule(kh1world.get_location("Halloween Town Guillotine Square Pumpkin Structure Left Chest"), + lambda state: ( + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and + ( + state.has("Progressive Glide", player) + or (options.advanced_logic and state.has("Combo Master", player)) + or state.has("High Jump", player, 2) + ) + )) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Entrance Steps Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + )) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Inside Entrance Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + )) + add_rule(kh1world.get_location("Halloween Town Bridge Left of Gate Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and + ( + state.has("Progressive Glide", player) + or state.has("High Jump", player) + or options.advanced_logic + ) + )) + add_rule(kh1world.get_location("Halloween Town Cemetery By Striped Grave Chest"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and has_oogie_manor(state, player, options.advanced_logic) + )) + add_rule(kh1world.get_location("Halloween Town Guillotine Square Pumpkin Structure Right Chest"), + lambda state: ( + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and + ( + state.has("Progressive Glide", player) + or (options.advanced_logic and state.has("Combo Master", player)) + or state.has("High Jump", player, 2) + ) + )) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Right Blue Trinity Chest"), + lambda state: state.has("Blue Trinity", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Left Blue Trinity Chest"), + lambda state: state.has("Blue Trinity", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates White Trinity Chest"), + lambda state: state.has("White Trinity", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Blizzara Chest"), + lambda state: state.has("Progressive Blizzard", player, 2)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Blizzaga Chest"), + lambda state: state.has("Progressive Blizzard", player, 3)) + add_rule(kh1world.get_location("Monstro Mouth High Platform Boat Side Chest"), + lambda state: ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + )) + add_rule(kh1world.get_location("Monstro Mouth High Platform Across from Boat Chest"), + lambda state: ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + )) + add_rule(kh1world.get_location("Monstro Mouth Green Trinity Top of Boat Chest"), + lambda state: ( + ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + ) + and state.has("Green Trinity", player) + )) + add_rule(kh1world.get_location("Monstro Chamber 5 Platform Chest"), + lambda state: state.has("High Jump", player)) + add_rule(kh1world.get_location("Monstro Chamber 3 Platform Above Chamber 2 Entrance Chest"), + lambda state: ( + state.has("High Jump", player) + or options.advanced_logic + )) + add_rule(kh1world.get_location("Monstro Chamber 3 Platform Near Chamber 6 Entrance Chest"), + lambda state: ( + state.has("High Jump", player) + or options.advanced_logic + )) + add_rule(kh1world.get_location("Monstro Chamber 5 Atop Barrel Chest"), + lambda state: ( + state.has("High Jump", player) + or options.advanced_logic + )) + add_rule(kh1world.get_location("Neverland Pirate Ship Deck White Trinity Chest"), + lambda state: ( + state.has_all({ + "White Trinity", + "Green Trinity"}, player) + )) + add_rule(kh1world.get_location("Neverland Pirate Ship Crows Nest Chest"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Neverland Hold Yellow Trinity Right Blue Chest"), + lambda state: state.has("Yellow Trinity", player)) + add_rule(kh1world.get_location("Neverland Hold Yellow Trinity Left Blue Chest"), + lambda state: state.has("Yellow Trinity", player)) + add_rule(kh1world.get_location("Neverland Cabin Chest"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Neverland Hold Flight 1st Chest"), + lambda state: ( + state.has("Green Trinity", player) + or state.has("Progressive Glide", player) + or state.has("High Jump", player, 3) + )) + add_rule(kh1world.get_location("Neverland Clock Tower Chest"), + lambda state: ( + state.has("Green Trinity", player) + and has_all_magic_lvx(state, player, 2) + )) + add_rule(kh1world.get_location("Neverland Hold Flight 2nd Chest"), + lambda state: ( + state.has("Green Trinity", player) + or state.has("Progressive Glide", player) + or state.has("High Jump", player, 3) + )) + add_rule(kh1world.get_location("Neverland Hold Yellow Trinity Green Chest"), + lambda state: state.has("Yellow Trinity", player)) + add_rule(kh1world.get_location("Neverland Captain's Cabin Chest"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls Under Water 2nd Chest"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls Floating Platform Near Save Chest"), + lambda state: ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + or state.has("Progressive Blizzard", player) + )) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls Floating Platform Near Bubble Chest"), + lambda state: ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + or state.has("Progressive Blizzard", player) + )) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls High Platform Chest"), + lambda state: ( + state.has("Progressive Glide", player) + or (state.has("Progressive Blizzard", player) and has_emblems(state, player, options.keyblades_unlock_chests)) + or (options.advanced_logic and state.has("Combo Master", player)) + )) + add_rule(kh1world.get_location("Hollow Bastion Castle Gates Gravity Chest"), + lambda state: ( + state.has("Progressive Gravity", player) + and + ( + has_emblems(state, player, options.keyblades_unlock_chests) + or (options.advanced_logic and state.has("High Jump", player, 2) and state.has("Progressive Glide", player)) + or (options.advanced_logic and can_dumbo_skip(state, player) and state.has("Progressive Glide", player)) + ) + )) + add_rule(kh1world.get_location("Hollow Bastion Castle Gates Freestanding Pillar Chest"), + lambda state: ( + has_emblems(state, player, options.keyblades_unlock_chests) + or state.has("High Jump", player, 2) + or (options.advanced_logic and can_dumbo_skip(state, player)) + )) + add_rule(kh1world.get_location("Hollow Bastion Castle Gates High Pillar Chest"), + lambda state: ( + has_emblems(state, player, options.keyblades_unlock_chests) + or state.has("High Jump", player, 2) + or (options.advanced_logic and can_dumbo_skip(state, player)) + )) + add_rule(kh1world.get_location("Hollow Bastion Great Crest Lower Chest"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Great Crest After Battle Platform Chest"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion High Tower 2nd Gravity Chest"), + lambda state: ( + state.has("Progressive Gravity", player) + and has_emblems(state, player, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Hollow Bastion High Tower 1st Gravity Chest"), + lambda state: ( + state.has("Progressive Gravity", player) + and has_emblems(state, player, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Hollow Bastion High Tower Above Sliding Blocks Chest"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Lift Stop Library Node After High Tower Switch Gravity Chest"), + lambda state: ( + state.has("Progressive Gravity", player) + and has_emblems(state, player, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Hollow Bastion Lift Stop Library Node Gravity Chest"), + lambda state: state.has("Progressive Gravity", player)) + add_rule(kh1world.get_location("Hollow Bastion Lift Stop Under High Tower Sliding Blocks Chest"), + lambda state: ( + has_emblems(state, player, options.keyblades_unlock_chests) + and state.has_all({ + "Progressive Glide", + "Progressive Gravity"}, player) + )) + add_rule(kh1world.get_location("Hollow Bastion Lift Stop Outside Library Gravity Chest"), + lambda state: state.has("Progressive Gravity", player)) + add_rule(kh1world.get_location("Hollow Bastion Lift Stop Heartless Sigil Door Gravity Chest"), + lambda state: ( + state.has("Progressive Gravity", player) + and has_emblems(state, player, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Hollow Bastion Waterway Blizzard on Bubble Chest"), + lambda state: ( + (state.has("Progressive Blizzard", player) and state.has("High Jump", player)) + or state.has("High Jump", player, 3) + )) + add_rule(kh1world.get_location("Hollow Bastion Grand Hall Steps Right Side Chest"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Grand Hall Oblivion Chest"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Grand Hall Left of Gate Chest"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Entrance Hall Left of Emblem Door Chest"), + lambda state: ( + state.has("High Jump", player) + or + ( + options.advanced_logic + and can_dumbo_skip(state, player) + and has_emblems(state, player, options.keyblades_unlock_chests) + ) + )) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls White Trinity Chest"), + lambda state: state.has("White Trinity", player)) + add_rule(kh1world.get_location("End of the World Giant Crevasse 5th Chest"), + lambda state: ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + )) + add_rule(kh1world.get_location("End of the World Giant Crevasse 1st Chest"), + lambda state: ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + )) + add_rule(kh1world.get_location("End of the World Giant Crevasse 4th Chest"), + lambda state: ( + ( + options.advanced_logic + and state.has("High Jump", player) + and state.has("Combo Master", player) + ) + or state.has("Progressive Glide", player) + )) + add_rule(kh1world.get_location("End of the World World Terminus Agrabah Chest"), + lambda state: ( + state.has("High Jump", player) + or + ( + options.advanced_logic + and can_dumbo_skip(state, player) + and state.has("Progressive Glide", player) + ) + )) + add_rule(kh1world.get_location("Monstro Chamber 6 White Trinity Chest"), + lambda state: state.has("White Trinity", player)) + add_rule(kh1world.get_location("Traverse Town Kairi Secret Waterway Oathkeeper Event"), + lambda state: ( + has_emblems(state, player, options.keyblades_unlock_chests) + and state.has("Hollow Bastion", player) + and has_x_worlds(state, player, 5, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Deep Jungle Defeat Sabor White Fang Event"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Defeat Clayton Cure Event"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Seal Keyhole Jungle King Event"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Seal Keyhole Red Trinity Event"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Olympus Coliseum Defeat Cerberus Inferno Band Event"), + lambda state: state.has("Entry Pass", player)) + add_rule(kh1world.get_location("Olympus Coliseum Cloud Sonic Blade Event"), + lambda state: state.has("Entry Pass", player)) + add_rule(kh1world.get_location("Wonderland Defeat Trickmaster Blizzard Event"), + lambda state: state.has("Footprints", player)) + add_rule(kh1world.get_location("Wonderland Defeat Trickmaster Ifrit's Horn Event"), + lambda state: state.has("Footprints", player)) + add_rule(kh1world.get_location("Monstro Defeat Parasite Cage II Stop Event"), + lambda state: ( + state.has("High Jump", player) + or + ( + options.advanced_logic + and state.has("Progressive Glide", player) + ) + )) + add_rule(kh1world.get_location("Halloween Town Defeat Oogie Boogie Holy Circlet Event"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and has_oogie_manor(state, player, options.advanced_logic) + )) + add_rule(kh1world.get_location("Halloween Town Defeat Oogie's Manor Gravity Event"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and has_oogie_manor(state, player, options.advanced_logic) + )) + add_rule(kh1world.get_location("Halloween Town Seal Keyhole Pumpkinhead Event"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not"}, player) + and has_oogie_manor(state, player, options.advanced_logic) + )) + add_rule(kh1world.get_location("Neverland Defeat Anti Sora Raven's Claw Event"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Neverland Encounter Hook Cure Event"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Neverland Seal Keyhole Fairy Harp Event"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Neverland Seal Keyhole Tinker Bell Event"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Neverland Seal Keyhole Glide Event"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Neverland Defeat Captain Hook Ars Arcanum Event"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Hollow Bastion Defeat Maleficent Donald Cheer Event"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Defeat Dragon Maleficent Fireglow Event"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Defeat Riku II Ragnarok Event"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Defeat Behemoth Omega Arts Event"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Speak to Princesses Fire Event"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Traverse Town Mail Postcard 01 Event"), + lambda state: state.has("Postcard", player)) + add_rule(kh1world.get_location("Traverse Town Mail Postcard 02 Event"), + lambda state: state.has("Postcard", player, 2)) + add_rule(kh1world.get_location("Traverse Town Mail Postcard 03 Event"), + lambda state: state.has("Postcard", player, 3)) + add_rule(kh1world.get_location("Traverse Town Mail Postcard 04 Event"), + lambda state: state.has("Postcard", player, 4)) + add_rule(kh1world.get_location("Traverse Town Mail Postcard 05 Event"), + lambda state: state.has("Postcard", player, 5)) + add_rule(kh1world.get_location("Traverse Town Mail Postcard 06 Event"), + lambda state: state.has("Postcard", player, 6)) + add_rule(kh1world.get_location("Traverse Town Mail Postcard 07 Event"), + lambda state: state.has("Postcard", player, 7)) + add_rule(kh1world.get_location("Traverse Town Mail Postcard 08 Event"), + lambda state: state.has("Postcard", player, 8)) + add_rule(kh1world.get_location("Traverse Town Mail Postcard 09 Event"), + lambda state: state.has("Postcard", player, 9)) + add_rule(kh1world.get_location("Traverse Town Mail Postcard 10 Event"), + lambda state: state.has("Postcard", player, 10)) + add_rule(kh1world.get_location("Traverse Town Defeat Opposite Armor Aero Event"), + lambda state: state.has("Red Trinity", player)) + add_rule(kh1world.get_location("Hollow Bastion Speak with Aerith Ansem's Report 2"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Speak with Aerith Ansem's Report 4"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Defeat Maleficent Ansem's Report 5"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Speak with Aerith Ansem's Report 6"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Halloween Town Defeat Oogie Boogie Ansem's Report 7"), + lambda state: ( + state.has_all({ + "Jack-In-The-Box", + "Forget-Me-Not", + "Progressive Fire"}, player) + )) + add_rule(kh1world.get_location("Neverland Defeat Hook Ansem's Report 9"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Hollow Bastion Speak with Aerith Ansem's Report 10"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Traverse Town Geppetto's House Geppetto Reward 1"), + lambda state: ( + state.has("Monstro", player) + and + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and has_x_worlds(state, player, 2, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Traverse Town Geppetto's House Geppetto Reward 2"), + lambda state: ( + state.has("Monstro", player) + and + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and has_x_worlds(state, player, 2, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Traverse Town Geppetto's House Geppetto Reward 3"), + lambda state: ( + state.has("Monstro", player) + and + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and has_x_worlds(state, player, 2, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Traverse Town Geppetto's House Geppetto Reward 4"), + lambda state: ( + state.has("Monstro", player) + and + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and has_x_worlds(state, player, 2, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Traverse Town Geppetto's House Geppetto Reward 5"), + lambda state: ( + state.has("Monstro", player) + and + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and has_x_worlds(state, player, 2, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Traverse Town Geppetto's House Geppetto All Summons Reward"), + lambda state: ( + state.has("Monstro", player) + and + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and has_all_summons(state, player) + and has_x_worlds(state, player, 2, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Traverse Town Geppetto's House Talk to Pinocchio"), + lambda state: ( + state.has("Monstro", player) + and + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and has_x_worlds(state, player, 2, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Traverse Town Magician's Study Obtained All Arts Items"), + lambda state: ( + has_all_magic_lvx(state, player, 1) + and has_all_arts(state, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Traverse Town Magician's Study Obtained All LV1 Magic"), + lambda state: has_all_magic_lvx(state, player, 1)) + add_rule(kh1world.get_location("Traverse Town Magician's Study Obtained All LV3 Magic"), + lambda state: has_all_magic_lvx(state, player, 3)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 10 Puppies"), + lambda state: has_puppies(state, player, 10)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 20 Puppies"), + lambda state: has_puppies(state, player, 20)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 30 Puppies"), + lambda state: has_puppies(state, player, 30)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 40 Puppies"), + lambda state: has_puppies(state, player, 40)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 50 Puppies Reward 1"), + lambda state: has_puppies(state, player, 50)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 50 Puppies Reward 2"), + lambda state: has_puppies(state, player, 50)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 60 Puppies"), + lambda state: has_puppies(state, player, 60)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 70 Puppies"), + lambda state: has_puppies(state, player, 70)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 80 Puppies"), + lambda state: has_puppies(state, player, 80)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 90 Puppies"), + lambda state: has_puppies(state, player, 90)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 99 Puppies Reward 1"), + lambda state: has_puppies(state, player, 99)) + add_rule(kh1world.get_location("Traverse Town Piano Room Return 99 Puppies Reward 2"), + lambda state: has_puppies(state, player, 99)) + add_rule(kh1world.get_location("Neverland Hold Aero Chest"), + lambda state: state.has("Yellow Trinity", player)) + add_rule(kh1world.get_location("Deep Jungle Camp Hi-Potion Experiment"), + lambda state: state.has("Progressive Fire", player)) + add_rule(kh1world.get_location("Deep Jungle Camp Ether Experiment"), + lambda state: state.has("Progressive Blizzard", player)) + add_rule(kh1world.get_location("Deep Jungle Camp Replication Experiment"), + lambda state: state.has("Progressive Blizzard", player)) + add_rule(kh1world.get_location("Deep Jungle Cliff Save Gorillas"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Tree House Save Gorillas"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Camp Save Gorillas"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Bamboo Thicket Save Gorillas"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Climbing Trees Save Gorillas"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Jungle Slider 10 Fruits"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Jungle Slider 20 Fruits"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Jungle Slider 30 Fruits"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Jungle Slider 40 Fruits"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Deep Jungle Jungle Slider 50 Fruits"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Wonderland Bizarre Room Read Book"), + lambda state: state.has("Footprints", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Green Trinity"), + lambda state: state.has("Green Trinity", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Hero's License Event"), + lambda state: state.has("Entry Pass", player)) + add_rule(kh1world.get_location("Deep Jungle Cavern of Hearts Navi-G Piece Event"), + lambda state: state.has("Slides", player)) + add_rule(kh1world.get_location("Wonderland Bizarre Room Navi-G Piece Event"), + lambda state: state.has("Footprints", player)) + add_rule(kh1world.get_location("Traverse Town Synth Log"), + lambda state: ( + state.has("Empty Bottle", player, 6) + and + ( + state.has("Green Trinity", player) + or state.has("High Jump", player, 3) + ) + )) + add_rule(kh1world.get_location("Traverse Town Synth Cloth"), + lambda state: ( + state.has("Empty Bottle", player, 6) + and + ( + state.has("Green Trinity", player) + or state.has("High Jump", player, 3) + ) + )) + add_rule(kh1world.get_location("Traverse Town Synth Rope"), + lambda state: ( + state.has("Empty Bottle", player, 6) + and + ( + state.has("Green Trinity", player) + or state.has("High Jump", player, 3) + ) + )) + add_rule(kh1world.get_location("Traverse Town Synth Seagull Egg"), + lambda state: ( + state.has("Empty Bottle", player, 6) + and + ( + state.has("Green Trinity", player) + or state.has("High Jump", player, 3) + ) + )) + add_rule(kh1world.get_location("Traverse Town Synth Fish"), + lambda state: ( + state.has("Empty Bottle", player, 6) + and + ( + state.has("Green Trinity", player) + or state.has("High Jump", player, 3) + ) + )) + add_rule(kh1world.get_location("Traverse Town Synth Mushroom"), + lambda state: ( + state.has("Empty Bottle", player, 6) + and + ( + state.has("Green Trinity", player) + or state.has("High Jump", player, 3) + ) + )) + add_rule(kh1world.get_location("Traverse Town Gizmo Shop Postcard 1"), + lambda state: state.has("Progressive Thunder", player)) + add_rule(kh1world.get_location("Traverse Town Gizmo Shop Postcard 2"), + lambda state: state.has("Progressive Thunder", player)) + add_rule(kh1world.get_location("Traverse Town Item Workshop Postcard"), + lambda state: ( + state.has("Green Trinity", player) + or state.has("High Jump", player, 3) + )) + add_rule(kh1world.get_location("Traverse Town Geppetto's House Postcard"), + lambda state: ( + state.has("Monstro", player) + and + ( + state.has("High Jump", player) + or (options.advanced_logic and state.has("Progressive Glide", player)) + ) + and has_x_worlds(state, player, 2, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Hollow Bastion Entrance Hall Emblem Piece (Flame)"), + lambda state: ( + ( + state.has("Theon Vol. 6", player) + or state.has("High Jump", player, 3) + or has_emblems(state, player, options.keyblades_unlock_chests) + ) + and state.has("Progressive Fire", player) + and + ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + or state.has("Progressive Thunder", player) + or options.advanced_logic + ) + )) + add_rule(kh1world.get_location("Hollow Bastion Entrance Hall Emblem Piece (Chest)"), + lambda state: ( + state.has("Theon Vol. 6", player) + or state.has("High Jump", player, 3) + or has_emblems(state, player, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Hollow Bastion Entrance Hall Emblem Piece (Statue)"), + lambda state: ( + ( + state.has("Theon Vol. 6", player) + or state.has("High Jump", player, 3) + or has_emblems(state, player, options.keyblades_unlock_chests) + ) + and state.has("Red Trinity", player) + )) + add_rule(kh1world.get_location("Hollow Bastion Entrance Hall Emblem Piece (Fountain)"), + lambda state: ( + state.has("Theon Vol. 6", player) + or state.has("High Jump", player, 3) + or has_emblems(state, player, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Hollow Bastion Library Speak to Belle Divine Rose"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + add_rule(kh1world.get_location("Hollow Bastion Library Speak to Aerith Cure"), + lambda state: has_emblems(state, player, options.keyblades_unlock_chests)) + if options.hundred_acre_wood: + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Left Cliff Chest"), + lambda state: ( + has_torn_pages(state, player, 4) + and + ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + ) + )) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Right Tree Alcove Chest"), + lambda state: ( + has_torn_pages(state, player, 4) + and + ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + ) + )) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Under Giant Pot Chest"), + lambda state: has_torn_pages(state, player, 4)) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Turn in Rare Nut 1"), + lambda state: has_torn_pages(state, player, 4)) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Turn in Rare Nut 2"), + lambda state: ( + has_torn_pages(state, player, 4) + and + ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + ) + )) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Turn in Rare Nut 3"), + lambda state: ( + has_torn_pages(state, player, 4) + and + ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + ) + )) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Turn in Rare Nut 4"), + lambda state: ( + has_torn_pages(state, player, 4) + and + ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + ) + )) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Turn in Rare Nut 5"), + lambda state: ( + has_torn_pages(state, player, 4) + and + ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + ) + )) + add_rule(kh1world.get_location("100 Acre Wood Pooh's House Owl Cheer"), + lambda state: has_torn_pages(state, player, 5)) + add_rule(kh1world.get_location("100 Acre Wood Convert Torn Page 1"), + lambda state: has_torn_pages(state, player, 1)) + add_rule(kh1world.get_location("100 Acre Wood Convert Torn Page 2"), + lambda state: has_torn_pages(state, player, 2)) + add_rule(kh1world.get_location("100 Acre Wood Convert Torn Page 3"), + lambda state: has_torn_pages(state, player, 3)) + add_rule(kh1world.get_location("100 Acre Wood Convert Torn Page 4"), + lambda state: has_torn_pages(state, player, 4)) + add_rule(kh1world.get_location("100 Acre Wood Convert Torn Page 5"), + lambda state: has_torn_pages(state, player, 5)) + add_rule(kh1world.get_location("100 Acre Wood Pooh's House Start Fire"), + lambda state: has_torn_pages(state, player, 3)) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Break Log"), + lambda state: has_torn_pages(state, player, 4)) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Fall Through Top of Tree Next to Pooh"), + lambda state: ( + has_torn_pages(state, player, 4) + and + ( + state.has("High Jump", player) + or state.has("Progressive Glide", player) + ) + )) + if options.atlantica: + add_rule(kh1world.get_location("Atlantica Ursula's Lair Use Fire on Urchin Chest"), + lambda state: ( + state.has_all({ + "Progressive Fire", + "Crystal Trident"}, player) + )) + add_rule(kh1world.get_location("Atlantica Triton's Palace White Trinity Chest"), + lambda state: state.has("White Trinity", player)) + add_rule(kh1world.get_location("Atlantica Defeat Ursula I Mermaid Kick Event"), + lambda state: ( + has_offensive_magic(state, player) + and state.has("Crystal Trident", player) + )) + add_rule(kh1world.get_location("Atlantica Defeat Ursula II Thunder Event"), + lambda state: ( + state.has("Mermaid Kick", player) + and has_offensive_magic(state, player) + and state.has("Crystal Trident", player) + )) + add_rule(kh1world.get_location("Atlantica Seal Keyhole Crabclaw Event"), + lambda state: ( + state.has("Mermaid Kick", player) + and has_offensive_magic(state, player) + and state.has("Crystal Trident", player) + )) + add_rule(kh1world.get_location("Atlantica Undersea Gorge Blizzard Clam"), + lambda state: state.has("Progressive Blizzard", player)) + add_rule(kh1world.get_location("Atlantica Undersea Valley Fire Clam"), + lambda state: state.has("Progressive Fire", player)) + add_rule(kh1world.get_location("Atlantica Triton's Palace Thunder Clam"), + lambda state: state.has("Progressive Thunder", player)) + add_rule(kh1world.get_location("Atlantica Cavern Nook Clam"), + lambda state: state.has("Crystal Trident", player)) + add_rule(kh1world.get_location("Atlantica Defeat Ursula II Ansem's Report 3"), + lambda state: ( + state.has_all({ + "Mermaid Kick", + "Crystal Trident"}, player) + and has_offensive_magic(state, player) + )) + if options.cups: + add_rule(kh1world.get_location("Olympus Coliseum Defeat Hades Ansem's Report 8"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Complete Phil Cup"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Entry Pass"}, player) + )) + add_rule(kh1world.get_location("Complete Phil Cup Solo"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Entry Pass"}, player) + )) + add_rule(kh1world.get_location("Complete Phil Cup Time Trial"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Entry Pass"}, player) + )) + add_rule(kh1world.get_location("Complete Pegasus Cup"), + lambda state: ( + state.has_all({ + "Pegasus Cup", + "Entry Pass"}, player) + )) + add_rule(kh1world.get_location("Complete Pegasus Cup Solo"), + lambda state: ( + state.has_all({ + "Pegasus Cup", + "Entry Pass"}, player) + )) + add_rule(kh1world.get_location("Complete Pegasus Cup Time Trial"), + lambda state: ( + state.has_all({ + "Pegasus Cup", + "Entry Pass"}, player) + )) + add_rule(kh1world.get_location("Complete Hercules Cup"), + lambda state: ( + state.has_all({ + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 4, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Complete Hercules Cup Solo"), + lambda state: ( + state.has_all({ + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 4, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Complete Hercules Cup Time Trial"), + lambda state: ( + state.has_all({ + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 4, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Complete Hades Cup"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Complete Hades Cup Solo"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Complete Hades Cup Time Trial"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Hades Cup Defeat Cloud and Leon Event"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Hades Cup Defeat Yuffie Event"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Hades Cup Defeat Cerberus Event"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Hades Cup Defeat Behemoth Event"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Hades Cup Defeat Hades Event"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Hercules Cup Defeat Cloud Event"), + lambda state: ( + state.has_all({ + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 4, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Hercules Cup Yellow Trinity Event"), + lambda state: ( + state.has_all({ + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 4, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Olympus Coliseum Defeat Ice Titan Diamond Dust Event"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass", + "Guard"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Olympus Coliseum Gates Purple Jar After Defeating Hades"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Olympus Coliseum Olympia Chest"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 4, options.keyblades_unlock_chests) + )) + if options.super_bosses: + add_rule(kh1world.get_location("Neverland Defeat Phantom Stop Event"), + lambda state: ( + state.has("Green Trinity", player) + and has_all_magic_lvx(state, player, 2) + and has_defensive_tools(state, player) + and has_emblems(state, player, options.keyblades_unlock_chests) + )) + add_rule(kh1world.get_location("Agrabah Defeat Kurt Zisa Ansem's Report 11"), + lambda state: ( + has_emblems(state, player, options.keyblades_unlock_chests) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Agrabah Defeat Kurt Zisa Zantetsuken Event"), + lambda state: ( + has_emblems(state, player, options.keyblades_unlock_chests) and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) and has_defensive_tools(state, player) + )) + if options.super_bosses or options.goal.current_key == "sephiroth": + add_rule(kh1world.get_location("Olympus Coliseum Defeat Sephiroth Ansem's Report 12"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Olympus Coliseum Defeat Sephiroth One-Winged Angel Event"), + lambda state: ( + state.has_all({ + "Phil Cup", + "Pegasus Cup", + "Hercules Cup", + "Entry Pass"}, player) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + if options.super_bosses or options.goal.current_key == "unknown": + add_rule(kh1world.get_location("Hollow Bastion Defeat Unknown Ansem's Report 13"), + lambda state: ( + has_emblems(state, player, options.keyblades_unlock_chests) + and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + add_rule(kh1world.get_location("Hollow Bastion Defeat Unknown EXP Necklace Event"), + lambda state: ( + has_emblems(state, player, options.keyblades_unlock_chests) and has_x_worlds(state, player, 7, options.keyblades_unlock_chests) + and has_defensive_tools(state, player) + )) + for i in range(options.level_checks): + add_rule(kh1world.get_location("Level " + str(i+1).rjust(3,'0')), + lambda state, level_num=i: ( + has_x_worlds(state, player, min(((level_num//10)*2), 8), options.keyblades_unlock_chests) + )) + if options.goal.current_key == "final_ansem": + add_rule(kh1world.get_location("Final Ansem"), + lambda state: ( + has_final_rest_door(state, player, final_rest_door_requirement, final_rest_door_required_reports, options.keyblades_unlock_chests, options.puppies) + )) + if options.keyblades_unlock_chests: + add_rule(kh1world.get_location("Traverse Town 1st District Candle Puzzle Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town 1st District Accessory Shop Roof Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town 2nd District Boots and Shoes Awning Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town 2nd District Rooftop Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town 2nd District Gizmo Shop Facade Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Alleyway Balcony Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Alleyway Blue Room Awning Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Alleyway Corner Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Green Room Clock Puzzle Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Green Room Table Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Red Room Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Mystical House Yellow Trinity Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Accessory Shop Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Secret Waterway White Trinity Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Geppetto's House Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Item Workshop Right Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town 1st District Blue Trinity Balcony Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Mystical House Glide Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Alleyway Behind Crates Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Item Workshop Left Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Traverse Town Secret Waterway Near Stairs Chest"), + lambda state: state.has("Lionheart", player)) + add_rule(kh1world.get_location("Wonderland Rabbit Hole Green Trinity Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Rabbit Hole Defeat Heartless 1 Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Rabbit Hole Defeat Heartless 2 Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Rabbit Hole Defeat Heartless 3 Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Bizarre Room Green Trinity Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Queen's Castle Hedge Left Red Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Queen's Castle Hedge Right Blue Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Queen's Castle Hedge Right Red Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Lotus Forest Thunder Plant Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Lotus Forest Through the Painting Thunder Plant Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Lotus Forest Glide Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Lotus Forest Nut Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Lotus Forest Corner Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Bizarre Room Lamp Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Tea Party Garden Above Lotus Forest Entrance 2nd Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Tea Party Garden Above Lotus Forest Entrance 1st Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Tea Party Garden Bear and Clock Puzzle Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Tea Party Garden Across From Bizarre Room Entrance Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Wonderland Lotus Forest Through the Painting White Trinity Chest"), + lambda state: state.has("Lady Luck", player)) + add_rule(kh1world.get_location("Deep Jungle Tree House Beneath Tree House Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Tree House Rooftop Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Hippo's Lagoon Center Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Hippo's Lagoon Left Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Hippo's Lagoon Right Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Vines Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Vines 2 Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Climbing Trees Blue Trinity Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Tunnel Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Cavern of Hearts White Trinity Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Camp Blue Trinity Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Tent Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Waterfall Cavern Low Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Waterfall Cavern Middle Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Waterfall Cavern High Wall Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Waterfall Cavern High Middle Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Cliff Right Cliff Left Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Cliff Right Cliff Right Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Deep Jungle Tree House Suspended Boat Chest"), + lambda state: state.has("Jungle King", player)) + add_rule(kh1world.get_location("Agrabah Plaza By Storage Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Plaza Raised Terrace Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Plaza Top Corner Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Alley Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Bazaar Across Windows Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Bazaar High Corner Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Main Street Right Palace Entrance Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Main Street High Above Alley Entrance Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Main Street High Above Palace Gates Entrance Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Palace Gates Low Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Palace Gates High Opposite Palace Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Palace Gates High Close to Palace Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Storage Green Trinity Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Storage Behind Barrel Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Entrance Left Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Entrance Tall Tower Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Hall High Left Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Hall Near Bottomless Hall Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Bottomless Hall Raised Platform Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Bottomless Hall Pillar Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Bottomless Hall Across Chasm Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Treasure Room Across Platforms Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Treasure Room Small Treasure Pile Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Treasure Room Large Treasure Pile Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Treasure Room Above Fire Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Relic Chamber Jump from Stairs Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Relic Chamber Stairs Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Dark Chamber Abu Gem Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Dark Chamber Across from Relic Chamber Entrance Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Dark Chamber Bridge Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Dark Chamber Near Save Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Silent Chamber Blue Trinity Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Hidden Room Right Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Hidden Room Left Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Aladdin's House Main Street Entrance Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Aladdin's House Plaza Entrance Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Agrabah Cave of Wonders Entrance White Trinity Chest"), + lambda state: state.has("Three Wishes", player)) + add_rule(kh1world.get_location("Monstro Chamber 6 Other Platform Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 6 Platform Near Chamber 5 Entrance Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 6 Raised Area Near Chamber 1 Entrance Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 6 Low Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Halloween Town Moonlight Hill White Trinity Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Bridge Under Bridge"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Boneyard Tombstone Puzzle Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Bridge Right of Gate Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Cemetery Behind Grave Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Cemetery By Cat Shape Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Cemetery Between Graves Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Lower Iron Cage Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Upper Iron Cage Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Hollow Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Grounds Red Trinity Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Guillotine Square High Tower Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Guillotine Square Pumpkin Structure Left Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Entrance Steps Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Oogie's Manor Inside Entrance Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Bridge Left of Gate Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Cemetery By Striped Grave Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Guillotine Square Under Jack's House Stairs Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Halloween Town Guillotine Square Pumpkin Structure Right Chest"), + lambda state: state.has("Pumpkinhead", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Left Behind Columns Chest"), + lambda state: state.has("Olympia", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Right Blue Trinity Chest"), + lambda state: state.has("Olympia", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Left Blue Trinity Chest"), + lambda state: state.has("Olympia", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates White Trinity Chest"), + lambda state: state.has("Olympia", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Blizzara Chest"), + lambda state: state.has("Olympia", player)) + add_rule(kh1world.get_location("Olympus Coliseum Coliseum Gates Blizzaga Chest"), + lambda state: state.has("Olympia", player)) + add_rule(kh1world.get_location("Monstro Mouth Boat Deck Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Mouth High Platform Boat Side Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Mouth High Platform Across from Boat Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Mouth Near Ship Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Mouth Green Trinity Top of Boat Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 2 Ground Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 2 Platform Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 5 Platform Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 3 Ground Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 3 Platform Above Chamber 2 Entrance Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 3 Near Chamber 6 Entrance Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 3 Platform Near Chamber 6 Entrance Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Mouth High Platform Near Teeth Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 5 Atop Barrel Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 5 Low 2nd Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Monstro Chamber 5 Low 1st Chest"), + lambda state: state.has("Wishing Star", player)) + add_rule(kh1world.get_location("Neverland Pirate Ship Deck White Trinity Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Neverland Pirate Ship Crows Nest Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Neverland Hold Yellow Trinity Right Blue Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Neverland Hold Yellow Trinity Left Blue Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Neverland Galley Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Neverland Cabin Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Neverland Hold Flight 1st Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Neverland Clock Tower Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Neverland Hold Flight 2nd Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Neverland Hold Yellow Trinity Green Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Neverland Captain's Cabin Chest"), + lambda state: state.has("Fairy Harp", player)) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls Water's Surface Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls Under Water 1st Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls Under Water 2nd Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls Floating Platform Near Save Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls Floating Platform Near Bubble Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls High Platform Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Castle Gates Gravity Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Castle Gates Freestanding Pillar Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Castle Gates High Pillar Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Great Crest Lower Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Great Crest After Battle Platform Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion High Tower 2nd Gravity Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion High Tower 1st Gravity Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion High Tower Above Sliding Blocks Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Library Top of Bookshelf Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Lift Stop Library Node After High Tower Switch Gravity Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Lift Stop Library Node Gravity Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Lift Stop Under High Tower Sliding Blocks Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Lift Stop Outside Library Gravity Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Lift Stop Heartless Sigil Door Gravity Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Base Level Bubble Under the Wall Platform Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Base Level Platform Near Entrance Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Base Level Near Crystal Switch Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Waterway Near Save Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Waterway Blizzard on Bubble Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Waterway Unlock Passage from Base Level Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Dungeon By Candles Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Dungeon Corner Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Grand Hall Steps Right Side Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Grand Hall Oblivion Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Grand Hall Left of Gate Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Entrance Hall Left of Emblem Door Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("Hollow Bastion Rising Falls White Trinity Chest"), + lambda state: state.has("Divine Rose", player)) + add_rule(kh1world.get_location("End of the World Final Dimension 1st Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Final Dimension 2nd Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Final Dimension 3rd Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Final Dimension 4th Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Final Dimension 5th Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Final Dimension 6th Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Final Dimension 10th Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Final Dimension 9th Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Final Dimension 8th Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Final Dimension 7th Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Giant Crevasse 3rd Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Giant Crevasse 5th Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Giant Crevasse 1st Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Giant Crevasse 4th Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Giant Crevasse 2nd Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World World Terminus Traverse Town Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World World Terminus Wonderland Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World World Terminus Olympus Coliseum Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World World Terminus Deep Jungle Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World World Terminus Agrabah Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World World Terminus Halloween Town Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World World Terminus Neverland Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World World Terminus 100 Acre Wood Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("End of the World Final Rest Chest"), + lambda state: state.has("Oblivion", player)) + add_rule(kh1world.get_location("Monstro Chamber 6 White Trinity Chest"), + lambda state: state.has("Oblivion", player)) + if options.hundred_acre_wood: + add_rule(kh1world.get_location("100 Acre Wood Meadow Inside Log Chest"), + lambda state: state.has("Oathkeeper", player)) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Left Cliff Chest"), + lambda state: state.has("Oathkeeper", player)) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Right Tree Alcove Chest"), + lambda state: state.has("Oathkeeper", player)) + add_rule(kh1world.get_location("100 Acre Wood Bouncing Spot Under Giant Pot Chest"), + lambda state: state.has("Oathkeeper", player)) + + + add_rule(kh1world.get_entrance("Wonderland"), + lambda state: state.has("Wonderland", player) and has_x_worlds(state, player, 2, options.keyblades_unlock_chests)) + add_rule(kh1world.get_entrance("Olympus Coliseum"), + lambda state: state.has("Olympus Coliseum", player) and has_x_worlds(state, player, 2, options.keyblades_unlock_chests)) + add_rule(kh1world.get_entrance("Deep Jungle"), + lambda state: state.has("Deep Jungle", player) and has_x_worlds(state, player, 2, options.keyblades_unlock_chests)) + add_rule(kh1world.get_entrance("Agrabah"), + lambda state: state.has("Agrabah", player) and has_x_worlds(state, player, 2, options.keyblades_unlock_chests)) + add_rule(kh1world.get_entrance("Monstro"), + lambda state: state.has("Monstro", player) and has_x_worlds(state, player, 2, options.keyblades_unlock_chests)) + if options.atlantica: + add_rule(kh1world.get_entrance("Atlantica"), + lambda state: state.has("Atlantica", player) and has_x_worlds(state, player, 2, options.keyblades_unlock_chests)) + add_rule(kh1world.get_entrance("Halloween Town"), + lambda state: state.has("Halloween Town", player) and has_x_worlds(state, player, 2, options.keyblades_unlock_chests)) + add_rule(kh1world.get_entrance("Neverland"), + lambda state: state.has("Neverland", player) and has_x_worlds(state, player, 3, options.keyblades_unlock_chests)) + add_rule(kh1world.get_entrance("Hollow Bastion"), + lambda state: state.has("Hollow Bastion", player) and has_x_worlds(state, player, 5, options.keyblades_unlock_chests)) + add_rule(kh1world.get_entrance("End of the World"), + lambda state: has_x_worlds(state, player, 7, options.keyblades_unlock_chests) and (has_reports(state, player, eotw_required_reports) or state.has("End of the World", player))) + add_rule(kh1world.get_entrance("100 Acre Wood"), + lambda state: state.has("Progressive Fire", player)) + + multiworld.completion_condition[player] = lambda state: state.has("Victory", player) diff --git a/worlds/kh1/__init__.py b/worlds/kh1/__init__.py new file mode 100644 index 000000000000..63b457556894 --- /dev/null +++ b/worlds/kh1/__init__.py @@ -0,0 +1,282 @@ +import logging +from typing import List + +from BaseClasses import Tutorial +from worlds.AutoWorld import WebWorld, World +from .Items import KH1Item, KH1ItemData, event_item_table, get_items_by_category, item_table, item_name_groups +from .Locations import KH1Location, location_table, get_locations_by_category, location_name_groups +from .Options import KH1Options, kh1_option_groups +from .Regions import create_regions +from .Rules import set_rules +from .Presets import kh1_option_presets +from worlds.LauncherComponents import Component, components, Type, launch_subprocess + + +def launch_client(): + from .Client import launch + launch_subprocess(launch, name="KH1 Client") + + +components.append(Component("KH1 Client", "KH1Client", func=launch_client, component_type=Type.CLIENT)) + + +class KH1Web(WebWorld): + theme = "ocean" + tutorials = [Tutorial( + "Multiworld Setup Guide", + "A guide to setting up the Kingdom Hearts Randomizer software on your computer." + "This guide covers single-player, multiworld, and related software.", + "English", + "kh1_en.md", + "kh1/en", + ["Gicu"] + )] + option_groups = kh1_option_groups + options_presets = kh1_option_presets + + +class KH1World(World): + """ + Kingdom Hearts is an action RPG following Sora on his journey + through many worlds to find Riku and Kairi. + """ + game = "Kingdom Hearts" + options_dataclass = KH1Options + options: KH1Options + topology_present = True + web = KH1Web() + + item_name_to_id = {name: data.code for name, data in item_table.items()} + location_name_to_id = {name: data.code for name, data in location_table.items()} + item_name_groups = item_name_groups + location_name_groups = location_name_groups + fillers = {} + fillers.update(get_items_by_category("Item")) + fillers.update(get_items_by_category("Camping")) + fillers.update(get_items_by_category("Stat Ups")) + + def create_items(self): + self.place_predetermined_items() + # Handle starting worlds + starting_worlds = [] + if self.options.starting_worlds > 0: + possible_starting_worlds = ["Wonderland", "Olympus Coliseum", "Deep Jungle", "Agrabah", "Monstro", "Halloween Town", "Neverland", "Hollow Bastion"] + if self.options.atlantica: + possible_starting_worlds.append("Atlantica") + if self.options.end_of_the_world_unlock == "item": + possible_starting_worlds.append("End of the World") + starting_worlds = self.random.sample(possible_starting_worlds, min(self.options.starting_worlds.value, len(possible_starting_worlds))) + for starting_world in starting_worlds: + self.multiworld.push_precollected(self.create_item(starting_world)) + + item_pool: List[KH1Item] = [] + possible_level_up_item_pool = [] + level_up_item_pool = [] + + # Calculate Level Up Items + # Fill pool with mandatory items + for _ in range(self.options.item_slot_increase): + level_up_item_pool.append("Item Slot Increase") + for _ in range(self.options.accessory_slot_increase): + level_up_item_pool.append("Accessory Slot Increase") + + # Create other pool + for _ in range(self.options.strength_increase): + possible_level_up_item_pool.append("Strength Increase") + for _ in range(self.options.defense_increase): + possible_level_up_item_pool.append("Defense Increase") + for _ in range(self.options.hp_increase): + possible_level_up_item_pool.append("Max HP Increase") + for _ in range(self.options.mp_increase): + possible_level_up_item_pool.append("Max MP Increase") + for _ in range(self.options.ap_increase): + possible_level_up_item_pool.append("Max AP Increase") + + # Fill remaining pool with items from other pool + self.random.shuffle(possible_level_up_item_pool) + level_up_item_pool = level_up_item_pool + possible_level_up_item_pool[:(100 - len(level_up_item_pool))] + + level_up_locations = list(get_locations_by_category("Levels").keys()) + self.random.shuffle(level_up_item_pool) + current_level_for_placing_stats = self.options.force_stats_on_levels.value + while len(level_up_item_pool) > 0 and current_level_for_placing_stats <= self.options.level_checks: + self.get_location(level_up_locations[current_level_for_placing_stats - 1]).place_locked_item(self.create_item(level_up_item_pool.pop())) + current_level_for_placing_stats += 1 + + # Calculate prefilled locations and items + prefilled_items = [] + if self.options.vanilla_emblem_pieces: + prefilled_items = prefilled_items + ["Emblem Piece (Flame)", "Emblem Piece (Chest)", "Emblem Piece (Fountain)", "Emblem Piece (Statue)"] + + total_locations = len(self.multiworld.get_unfilled_locations(self.player)) + + non_filler_item_categories = ["Key", "Magic", "Worlds", "Trinities", "Cups", "Summons", "Abilities", "Shared Abilities", "Keyblades", "Accessory", "Weapons", "Puppies"] + if self.options.hundred_acre_wood: + non_filler_item_categories.append("Torn Pages") + for name, data in item_table.items(): + quantity = data.max_quantity + if data.category not in non_filler_item_categories: + continue + if name in starting_worlds: + continue + if data.category == "Puppies": + if self.options.puppies == "triplets" and "-" in name: + item_pool += [self.create_item(name) for _ in range(quantity)] + if self.options.puppies == "individual" and "Puppy" in name: + item_pool += [self.create_item(name) for _ in range(0, quantity)] + if self.options.puppies == "full" and name == "All Puppies": + item_pool += [self.create_item(name) for _ in range(0, quantity)] + elif name == "Atlantica": + if self.options.atlantica: + item_pool += [self.create_item(name) for _ in range(0, quantity)] + elif name == "Mermaid Kick": + if self.options.atlantica: + if self.options.extra_shared_abilities: + item_pool += [self.create_item(name) for _ in range(0, 2)] + else: + item_pool += [self.create_item(name) for _ in range(0, quantity)] + elif name == "Crystal Trident": + if self.options.atlantica: + item_pool += [self.create_item(name) for _ in range(0, quantity)] + elif name == "High Jump": + if self.options.extra_shared_abilities: + item_pool += [self.create_item(name) for _ in range(0, 3)] + else: + item_pool += [self.create_item(name) for _ in range(0, quantity)] + elif name == "Progressive Glide": + if self.options.extra_shared_abilities: + item_pool += [self.create_item(name) for _ in range(0, 4)] + else: + item_pool += [self.create_item(name) for _ in range(0, quantity)] + elif name == "End of the World": + if self.options.end_of_the_world_unlock.current_key == "item": + item_pool += [self.create_item(name) for _ in range(0, quantity)] + elif name == "EXP Zero": + if self.options.exp_zero_in_pool: + item_pool += [self.create_item(name) for _ in range(0, quantity)] + elif name not in prefilled_items: + item_pool += [self.create_item(name) for _ in range(0, quantity)] + + for i in range(self.determine_reports_in_pool()): + item_pool += [self.create_item("Ansem's Report " + str(i+1))] + + while len(item_pool) < total_locations and len(level_up_item_pool) > 0: + item_pool += [self.create_item(level_up_item_pool.pop())] + + # Fill any empty locations with filler items. + while len(item_pool) < total_locations: + item_pool.append(self.create_item(self.get_filler_item_name())) + + self.multiworld.itempool += item_pool + + def place_predetermined_items(self) -> None: + goal_dict = { + "sephiroth": "Olympus Coliseum Defeat Sephiroth Ansem's Report 12", + "unknown": "Hollow Bastion Defeat Unknown Ansem's Report 13", + "postcards": "Traverse Town Mail Postcard 10 Event", + "final_ansem": "Final Ansem", + "puppies": "Traverse Town Piano Room Return 99 Puppies Reward 2", + "final_rest": "End of the World Final Rest Chest" + } + self.get_location(goal_dict[self.options.goal.current_key]).place_locked_item(self.create_item("Victory")) + if self.options.vanilla_emblem_pieces: + self.get_location("Hollow Bastion Entrance Hall Emblem Piece (Flame)").place_locked_item(self.create_item("Emblem Piece (Flame)")) + self.get_location("Hollow Bastion Entrance Hall Emblem Piece (Statue)").place_locked_item(self.create_item("Emblem Piece (Statue)")) + self.get_location("Hollow Bastion Entrance Hall Emblem Piece (Fountain)").place_locked_item(self.create_item("Emblem Piece (Fountain)")) + self.get_location("Hollow Bastion Entrance Hall Emblem Piece (Chest)").place_locked_item(self.create_item("Emblem Piece (Chest)")) + + def get_filler_item_name(self) -> str: + weights = [data.weight for data in self.fillers.values()] + return self.random.choices([filler for filler in self.fillers.keys()], weights)[0] + + def fill_slot_data(self) -> dict: + slot_data = {"xpmult": int(self.options.exp_multiplier)/16, + "required_reports_eotw": self.determine_reports_required_to_open_end_of_the_world(), + "required_reports_door": self.determine_reports_required_to_open_final_rest_door(), + "door": self.options.final_rest_door.current_key, + "seed": self.multiworld.seed_name, + "advanced_logic": bool(self.options.advanced_logic), + "hundred_acre_wood": bool(self.options.hundred_acre_wood), + "atlantica": bool(self.options.atlantica), + "goal": str(self.options.goal.current_key)} + if self.options.randomize_keyblade_stats: + min_str_bonus = min(self.options.keyblade_min_str.value, self.options.keyblade_max_str.value) + max_str_bonus = max(self.options.keyblade_min_str.value, self.options.keyblade_max_str.value) + self.options.keyblade_min_str.value = min_str_bonus + self.options.keyblade_max_str.value = max_str_bonus + min_mp_bonus = min(self.options.keyblade_min_mp.value, self.options.keyblade_max_mp.value) + max_mp_bonus = max(self.options.keyblade_min_mp.value, self.options.keyblade_max_mp.value) + self.options.keyblade_min_mp.value = min_mp_bonus + self.options.keyblade_max_mp.value = max_mp_bonus + slot_data["keyblade_stats"] = "" + for i in range(22): + if i < 4 and self.options.bad_starting_weapons: + slot_data["keyblade_stats"] = slot_data["keyblade_stats"] + "1,0," + else: + str_bonus = int(self.random.randint(min_str_bonus, max_str_bonus)) + mp_bonus = int(self.random.randint(min_mp_bonus, max_mp_bonus)) + slot_data["keyblade_stats"] = slot_data["keyblade_stats"] + str(str_bonus) + "," + str(mp_bonus) + "," + slot_data["keyblade_stats"] = slot_data["keyblade_stats"][:-1] + if self.options.donald_death_link: + slot_data["donalddl"] = "" + if self.options.goofy_death_link: + slot_data["goofydl"] = "" + if self.options.keyblades_unlock_chests: + slot_data["chestslocked"] = "" + else: + slot_data["chestsunlocked"] = "" + if self.options.interact_in_battle: + slot_data["interactinbattle"] = "" + return slot_data + + def create_item(self, name: str) -> KH1Item: + data = item_table[name] + return KH1Item(name, data.classification, data.code, self.player) + + def create_event(self, name: str) -> KH1Item: + data = event_item_table[name] + return KH1Item(name, data.classification, data.code, self.player) + + def set_rules(self): + set_rules(self) + + def create_regions(self): + create_regions(self.multiworld, self.player, self.options) + + def generate_early(self): + value_names = ["Reports to Open End of the World", "Reports to Open Final Rest Door", "Reports in Pool"] + initial_report_settings = [self.options.required_reports_eotw.value, self.options.required_reports_door.value, self.options.reports_in_pool.value] + self.change_numbers_of_reports_to_consider() + new_report_settings = [self.options.required_reports_eotw.value, self.options.required_reports_door.value, self.options.reports_in_pool.value] + for i in range(3): + if initial_report_settings[i] != new_report_settings[i]: + logging.info(f"{self.player_name}'s value {initial_report_settings[i]} for \"{value_names[i]}\" was invalid\n" + f"Setting \"{value_names[i]}\" value to {new_report_settings[i]}") + + def change_numbers_of_reports_to_consider(self) -> None: + if self.options.end_of_the_world_unlock == "reports" and self.options.final_rest_door == "reports": + self.options.required_reports_eotw.value, self.options.required_reports_door.value, self.options.reports_in_pool.value = sorted( + [self.options.required_reports_eotw.value, self.options.required_reports_door.value, self.options.reports_in_pool.value]) + + elif self.options.end_of_the_world_unlock == "reports": + self.options.required_reports_eotw.value, self.options.reports_in_pool.value = sorted( + [self.options.required_reports_eotw.value, self.options.reports_in_pool.value]) + + elif self.options.final_rest_door == "reports": + self.options.required_reports_door.value, self.options.reports_in_pool.value = sorted( + [self.options.required_reports_door.value, self.options.reports_in_pool.value]) + + def determine_reports_in_pool(self) -> int: + if self.options.end_of_the_world_unlock == "reports" or self.options.final_rest_door == "reports": + return self.options.reports_in_pool.value + return 0 + + def determine_reports_required_to_open_end_of_the_world(self) -> int: + if self.options.end_of_the_world_unlock == "reports": + return self.options.required_reports_eotw.value + return 14 + + def determine_reports_required_to_open_final_rest_door(self) -> int: + if self.options.final_rest_door == "reports": + return self.options.required_reports_door.value + return 14 diff --git a/worlds/kh1/docs/en_Kingdom Hearts.md b/worlds/kh1/docs/en_Kingdom Hearts.md new file mode 100644 index 000000000000..5167505efbbd --- /dev/null +++ b/worlds/kh1/docs/en_Kingdom Hearts.md @@ -0,0 +1,88 @@ +# Kingdom Hearts (PC) + +## Where is the options page? + +The [player options page for this game](../player-options) contains most of the options you need to +configure and export a config file. + +## What does randomization do to this game? + +The Kingdom Hearts AP Randomizer randomizes most rewards in the game and adds several items which are used to unlock worlds, Olympus Coliseum cups, and world progression. + +Worlds can only be accessed by finding the corresponding item. For example, you need to find the `Monstro` item to enter Monstro. + +The default goal is to enter End of the World and defeat Final Ansem. + +## What items and locations get shuffled? + +### Items + +Any weapon, accessory, spell, trinity, summon, world, key item, stat up, consumable, or ability can be found in any location. + +### Locations + +Locations the player can find items include chests, event rewards, Atlantica clams, level up rewards, 101 Dalmatian rewards, and postcard rewards. + +## Which items can be in another player's world? + +Any of the items which can be shuffled may also be placed into another player's world. It is possible to choose to limit +certain items to your own world. +## When the player receives an item, what happens? + +When the player receives an item, your client will display a message displaying the item you have obtained. You will also see a notification in the "LEVEL UP" box. + +## What do I do if I encounter a bug with the game? + +Please reach out to Gicu#7034 on Discord. + +## How do I progress in a certain world? + +### The evidence boxes aren't spawning in Wonderland. + +Find `Footprints` in the multiworld. + +### I can't enter any cups in Olympus Coliseum. + +Firstly, find `Entry Pass` in the multiworld. Additionally, `Phil Cup`, `Pegasus Cup`, and `Hercules Cup` are all multiworld items. Finding all 3 grant you access to the Hades Cup and the Platinum Match. Clearing all cups lets you challenge Ice Titan. + +### The slides aren't spawning in Deep Jungle. + +Find `Slides` in the multiworld. + +### I can't progress in Atlantica. +Find `Crystal Trident` in the multiworld. + +### I can't progress in Halloween Town. + +Find `Forget-Me-Not` and `Jack-in-the-Box` in the multiworld. + +### The Hollow Bastion Library is missing a book. + +Find `Theon Vol. 6` in the multiworld. + +## How do I enter the End of the World? + +You can enter End of the World by obtaining a number of Ansem's Reports or by finding `End of the World` in the multiworld, depending on your options. + +## Credits +This is a collaborative effort from several individuals in the Kingdom Hearts community, but most of all, denhonator. + +Denho's original KH rando laid the foundation for the work here and makes everything here possible, so thank you Denho for such a blast of a randomizer. + +Other credits include: + +Sonicshadowsilver2 for their work finding many memory addresses, working to identify and resolve bugs, and converting the code base to the latest EGS update. + +Shananas and the rest of the OpenKH team for providing such an amazing tool for us to utilize on this project. + +TopazTK for their work on the `Show Prompt` method and Krujo for their implementation of the method in AP. + +JaredWeakStrike for helping clean up my mess of code. + +KSX for their `Interact in Battle` code. + +RavSpect for their title screen image edit. + +SunCatMC for their work on ChecksFinder, which I used as a basis for game-to-client communication. + +ThePhar for their work on Rogue Legacy AP, which I used as a basis for the apworld creation. diff --git a/worlds/kh1/docs/kh1_en.md b/worlds/kh1/docs/kh1_en.md new file mode 100644 index 000000000000..522da20b0dc9 --- /dev/null +++ b/worlds/kh1/docs/kh1_en.md @@ -0,0 +1,54 @@ +# Kingdom Hearts Randomizer Setup Guide + +## Setting up the required mods + +BEFORE MODDING, PLEASE INSTALL AND RUN KH1 AT LEAST ONCE. + +1. Install OpenKH and the LUA Backend + + Download the [latest release of OpenKH](https://github.com/OpenKH/OpenKh/releases/tag/latest) + + Extract the files to a directory of your choosing. + + Open `OpenKh.Tools.ModsManager.exe` and run first time set up + + When prompted for game edition, choose `PC Release`, select which platform you're using (EGS or Steam), navigate to your `Kingdom Hearts I.5 + II.5` installation folder in the path box and click `Next` + + When prompted, install Panacea, then click `Next` + + When prompted, check KH1 plus any other AP game you play and click `Install and configure LUA backend`, then click `Next` + + Extracting game data for KH1 is unnecessary, but you may want to extract data for KH2 if you plan on playing KH2 AP + + Click `Finish` + +2. Open `OpenKh.Tools.ModsManager.exe` + +3. Click the drop-down menu at the top-right and choose `Kingdom Hearts 1` + +4. Click `Mods>Install a New Mod` + +5. In `Add a new mod from GitHub` paste `gaithern/KH-1FM-AP-LUA` + +6. Click `Install` + +7. Navigate to Mod Loader and click `Build and Run` + + +## Configuring your YAML file + +### What is a YAML file and why do I need one? + +Your YAML file contains a set of configuration options which provide the generator with information about how it should +generate your game. Each player of a multiworld will provide their own YAML file. This setup allows each player to enjoy +an experience customized for their taste, and different players in the same multiworld can all have different options. + +### Where do I get a YAML file? + +you can customize your settings by visiting the [Kingdom Hearts Options Page](/games/Kingdom%20Hearts/player-options). + +## Connect to the MultiWorld + +For first-time players, it is recommended to open your KH1 Client first before opening the game. + +On the title screen, open your KH1 Client and connect to your multiworld. diff --git a/worlds/kh1/test/__init__.py b/worlds/kh1/test/__init__.py new file mode 100644 index 000000000000..960b527f8b8a --- /dev/null +++ b/worlds/kh1/test/__init__.py @@ -0,0 +1,5 @@ +from test.bases import WorldTestBase + + +class KH1TestBase(WorldTestBase): + game = "Kingdom Hearts" diff --git a/worlds/kh1/test/test_goal.py b/worlds/kh1/test/test_goal.py new file mode 100644 index 000000000000..6b501404feee --- /dev/null +++ b/worlds/kh1/test/test_goal.py @@ -0,0 +1,33 @@ +from . import KH1TestBase + +class TestDefault(KH1TestBase): + options = {} + +class TestSephiroth(KH1TestBase): + options = { + "Goal": 0, + } + +class TestUnknown(KH1TestBase): + options = { + "Goal": 1, + } + +class TestPostcards(KH1TestBase): + options = { + "Goal": 2, + } + +class TestFinalAnsem(KH1TestBase): + options = { + "Goal": 3, + } + +class TestPuppies(KH1TestBase): + options = { + "Goal": 4, + } +class TestFinalRest(KH1TestBase): + options = { + "Goal": 5, + } diff --git a/worlds/lingo/data/LL1.yaml b/worlds/lingo/data/LL1.yaml index 950fd326743a..16a1573b1d56 100644 --- a/worlds/lingo/data/LL1.yaml +++ b/worlds/lingo/data/LL1.yaml @@ -2049,6 +2049,18 @@ panel: I - room: Elements Area panel: A + Eight Door (Outside The Initiated): + id: Red Blue Purple Room Area Doors/Door_a_strands2 + item_name: Outside The Initiated - Eight Door + item_group: Achievement Room Entrances + skip_location: True + panels: + - room: The Incomparable + panel: I (Seven) + - room: Courtyard + panel: I + - room: Elements Area + panel: A panel_doors: Giant Sevens: item_name: Giant Seven Panels @@ -2067,8 +2079,8 @@ room: The Incomparable door: Eight Door Outside The Initiated: - room: Outside The Initiated - door: Eight Door + room: The Incomparable + door: Eight Door (Outside The Initiated) paintings: - id: eight_painting2 orientation: north @@ -3310,7 +3322,8 @@ room: Art Gallery door: Exit Eight Alcove: - door: Eight Door + room: The Incomparable + door: Eight Door (Outside The Initiated) The Optimistic: True panels: SEVEN (1): @@ -3463,17 +3476,6 @@ panel: GREEN - room: Outside The Agreeable panel: PURPLE - Eight Door: - id: Red Blue Purple Room Area Doors/Door_a_strands2 - item_group: Achievement Room Entrances - skip_location: True - panels: - - room: The Incomparable - panel: I (Seven) - - room: Courtyard - panel: I - - room: Elements Area - panel: A panel_doors: UNCOVER: panels: diff --git a/worlds/lingo/data/generated.dat b/worlds/lingo/data/generated.dat index 9a49d3d9d4b9..e2d3d06bec96 100644 Binary files a/worlds/lingo/data/generated.dat and b/worlds/lingo/data/generated.dat differ diff --git a/worlds/lingo/data/ids.yaml b/worlds/lingo/data/ids.yaml index b46f1d36ec1a..13b77145ea2c 100644 --- a/worlds/lingo/data/ids.yaml +++ b/worlds/lingo/data/ids.yaml @@ -1124,6 +1124,8 @@ doors: Eight Door: item: 444475 location: 445219 + Eight Door (Outside The Initiated): + item: 444578 Orange Tower: Second Floor: item: 444476 @@ -1242,8 +1244,6 @@ doors: Entrance: item: 444516 location: 445237 - Eight Door: - item: 444578 The Traveled: Color Hallways Entrance: item: 444517 diff --git a/worlds/minecraft/ItemPool.py b/worlds/minecraft/ItemPool.py index 78eeffca80f5..19bb70ed6402 100644 --- a/worlds/minecraft/ItemPool.py +++ b/worlds/minecraft/ItemPool.py @@ -1,10 +1,14 @@ from math import ceil from typing import List -from BaseClasses import MultiWorld, Item -from worlds.AutoWorld import World +from BaseClasses import Item from . import Constants +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from . import MinecraftWorld + def get_junk_item_names(rand, k: int) -> str: junk_weights = Constants.item_info["junk_weights"] @@ -14,39 +18,38 @@ def get_junk_item_names(rand, k: int) -> str: k=k) return junk -def build_item_pool(mc_world: World) -> List[Item]: - multiworld = mc_world.multiworld - player = mc_world.player +def build_item_pool(world: "MinecraftWorld") -> List[Item]: + multiworld = world.multiworld + player = world.player itempool = [] total_location_count = len(multiworld.get_unfilled_locations(player)) required_pool = Constants.item_info["required_pool"] - junk_weights = Constants.item_info["junk_weights"] # Add required progression items for item_name, num in required_pool.items(): - itempool += [mc_world.create_item(item_name) for _ in range(num)] + itempool += [world.create_item(item_name) for _ in range(num)] # Add structure compasses - if multiworld.structure_compasses[player]: - compasses = [name for name in mc_world.item_name_to_id if "Structure Compass" in name] + if world.options.structure_compasses: + compasses = [name for name in world.item_name_to_id if "Structure Compass" in name] for item_name in compasses: - itempool.append(mc_world.create_item(item_name)) + itempool.append(world.create_item(item_name)) # Dragon egg shards - if multiworld.egg_shards_required[player] > 0: - num = multiworld.egg_shards_available[player] - itempool += [mc_world.create_item("Dragon Egg Shard") for _ in range(num)] + if world.options.egg_shards_required > 0: + num = world.options.egg_shards_available + itempool += [world.create_item("Dragon Egg Shard") for _ in range(num)] # Bee traps - bee_trap_percentage = multiworld.bee_traps[player] * 0.01 + bee_trap_percentage = world.options.bee_traps * 0.01 if bee_trap_percentage > 0: bee_trap_qty = ceil(bee_trap_percentage * (total_location_count - len(itempool))) - itempool += [mc_world.create_item("Bee Trap") for _ in range(bee_trap_qty)] + itempool += [world.create_item("Bee Trap") for _ in range(bee_trap_qty)] # Fill remaining itempool with randomly generated junk - junk = get_junk_item_names(multiworld.random, total_location_count - len(itempool)) - itempool += [mc_world.create_item(name) for name in junk] + junk = get_junk_item_names(world.random, total_location_count - len(itempool)) + itempool += [world.create_item(name) for name in junk] return itempool diff --git a/worlds/minecraft/Options.py b/worlds/minecraft/Options.py index 9407097b4638..7d1377233e4c 100644 --- a/worlds/minecraft/Options.py +++ b/worlds/minecraft/Options.py @@ -1,6 +1,7 @@ -import typing -from Options import Choice, Option, Toggle, DefaultOnToggle, Range, OptionList, DeathLink, PlandoConnections +from Options import Choice, Toggle, DefaultOnToggle, Range, OptionList, DeathLink, PlandoConnections, \ + PerGameCommonOptions from .Constants import region_info +from dataclasses import dataclass class AdvancementGoal(Range): @@ -55,7 +56,7 @@ class StructureCompasses(DefaultOnToggle): display_name = "Structure Compasses" -class BeeTraps(Range): +class BeeTraps(Range): """Replaces a percentage of junk items with bee traps, which spawn multiple angered bees around every player when received.""" display_name = "Bee Trap Percentage" @@ -94,7 +95,20 @@ class SendDefeatedMobs(Toggle): class StartingItems(OptionList): - """Start with these items. Each entry should be of this format: {item: "item_name", amount: #, nbt: "nbt_string"}""" + """Start with these items. Each entry should be of this format: {item: "item_name", amount: #} + `item` can include components, and should be in an identical format to a `/give` command with + `"` escaped for json reasons. + + `amount` is optional and will default to 1 if omitted. + + example: + ``` + starting_items: [ + { "item": "minecraft:stick[minecraft:custom_name=\"{'text':'pointy stick'}\"]" }, + { "item": "minecraft:arrow[minecraft:rarity=epic]", amount: 64 } + ] + ``` + """ display_name = "Starting Items" @@ -109,22 +123,21 @@ def can_connect(cls, entrance, exit): return True -minecraft_options: typing.Dict[str, type(Option)] = { - "plando_connections": MCPlandoConnections, - "advancement_goal": AdvancementGoal, - "egg_shards_required": EggShardsRequired, - "egg_shards_available": EggShardsAvailable, - "required_bosses": BossGoal, - - "shuffle_structures": ShuffleStructures, - "structure_compasses": StructureCompasses, - - "combat_difficulty": CombatDifficulty, - "include_hard_advancements": HardAdvancements, - "include_unreasonable_advancements": UnreasonableAdvancements, - "include_postgame_advancements": PostgameAdvancements, - "bee_traps": BeeTraps, - "send_defeated_mobs": SendDefeatedMobs, - "death_link": DeathLink, - "starting_items": StartingItems, -} +@dataclass +class MinecraftOptions(PerGameCommonOptions): + plando_connections: MCPlandoConnections + advancement_goal: AdvancementGoal + egg_shards_required: EggShardsRequired + egg_shards_available: EggShardsAvailable + required_bosses: BossGoal + shuffle_structures: ShuffleStructures + structure_compasses: StructureCompasses + + combat_difficulty: CombatDifficulty + include_hard_advancements: HardAdvancements + include_unreasonable_advancements: UnreasonableAdvancements + include_postgame_advancements: PostgameAdvancements + bee_traps: BeeTraps + send_defeated_mobs: SendDefeatedMobs + death_link: DeathLink + starting_items: StartingItems diff --git a/worlds/minecraft/Rules.py b/worlds/minecraft/Rules.py index dae4241b992c..9a7be09a4a84 100644 --- a/worlds/minecraft/Rules.py +++ b/worlds/minecraft/Rules.py @@ -1,276 +1,471 @@ -import typing -from collections.abc import Callable - from BaseClasses import CollectionState from worlds.generic.Rules import exclusion_rules -from worlds.AutoWorld import World from . import Constants +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from . import MinecraftWorld + # Helper functions # moved from logicmixin -def has_iron_ingots(state: CollectionState, player: int) -> bool: +def has_iron_ingots(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: return state.has('Progressive Tools', player) and state.has('Progressive Resource Crafting', player) -def has_copper_ingots(state: CollectionState, player: int) -> bool: + +def has_copper_ingots(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: return state.has('Progressive Tools', player) and state.has('Progressive Resource Crafting', player) -def has_gold_ingots(state: CollectionState, player: int) -> bool: - return state.has('Progressive Resource Crafting', player) and (state.has('Progressive Tools', player, 2) or state.can_reach('The Nether', 'Region', player)) -def has_diamond_pickaxe(state: CollectionState, player: int) -> bool: - return state.has('Progressive Tools', player, 3) and has_iron_ingots(state, player) +def has_gold_ingots(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + return (state.has('Progressive Resource Crafting', player) + and ( + state.has('Progressive Tools', player, 2) + or state.can_reach_region('The Nether', player) + ) + ) + -def craft_crossbow(state: CollectionState, player: int) -> bool: - return state.has('Archery', player) and has_iron_ingots(state, player) +def has_diamond_pickaxe(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + return state.has('Progressive Tools', player, 3) and has_iron_ingots(world, state, player) -def has_bottle(state: CollectionState, player: int) -> bool: + +def craft_crossbow(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + return state.has('Archery', player) and has_iron_ingots(world, state, player) + + +def has_bottle(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: return state.has('Bottles', player) and state.has('Progressive Resource Crafting', player) -def has_spyglass(state: CollectionState, player: int) -> bool: - return has_copper_ingots(state, player) and state.has('Spyglass', player) and can_adventure(state, player) -def can_enchant(state: CollectionState, player: int) -> bool: - return state.has('Enchanting', player) and has_diamond_pickaxe(state, player) # mine obsidian and lapis +def has_spyglass(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + return (has_copper_ingots(world, state, player) + and state.has('Spyglass', player) + and can_adventure(world, state, player) + ) + + +def can_enchant(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + return state.has('Enchanting', player) and has_diamond_pickaxe(world, state, player) # mine obsidian and lapis -def can_use_anvil(state: CollectionState, player: int) -> bool: - return state.has('Enchanting', player) and state.has('Progressive Resource Crafting', player, 2) and has_iron_ingots(state, player) -def fortress_loot(state: CollectionState, player: int) -> bool: # saddles, blaze rods, wither skulls - return state.can_reach('Nether Fortress', 'Region', player) and basic_combat(state, player) +def can_use_anvil(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + return (state.has('Enchanting', player) + and state.has('Progressive Resource Crafting', player,2) + and has_iron_ingots(world, state, player) + ) -def can_brew_potions(state: CollectionState, player: int) -> bool: - return state.has('Blaze Rods', player) and state.has('Brewing', player) and has_bottle(state, player) -def can_piglin_trade(state: CollectionState, player: int) -> bool: - return has_gold_ingots(state, player) and ( - state.can_reach('The Nether', 'Region', player) or - state.can_reach('Bastion Remnant', 'Region', player)) +def fortress_loot(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: # saddles, blaze rods, wither skulls + return state.can_reach_region('Nether Fortress', player) and basic_combat(world, state, player) -def overworld_villager(state: CollectionState, player: int) -> bool: + +def can_brew_potions(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + return state.has('Blaze Rods', player) and state.has('Brewing', player) and has_bottle(world, state, player) + + +def can_piglin_trade(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + return (has_gold_ingots(world, state, player) + and ( + state.can_reach_region('The Nether', player) + or state.can_reach_region('Bastion Remnant', player) + )) + + +def overworld_villager(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: village_region = state.multiworld.get_region('Village', player).entrances[0].parent_region.name - if village_region == 'The Nether': # 2 options: cure zombie villager or build portal in village - return (state.can_reach('Zombie Doctor', 'Location', player) or - (has_diamond_pickaxe(state, player) and state.can_reach('Village', 'Region', player))) + if village_region == 'The Nether': # 2 options: cure zombie villager or build portal in village + return (state.can_reach_location('Zombie Doctor', player) + or ( + has_diamond_pickaxe(world, state, player) + and state.can_reach_region('Village', player) + )) elif village_region == 'The End': - return state.can_reach('Zombie Doctor', 'Location', player) - return state.can_reach('Village', 'Region', player) + return state.can_reach_location('Zombie Doctor', player) + return state.can_reach_region('Village', player) -def enter_stronghold(state: CollectionState, player: int) -> bool: + +def enter_stronghold(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: return state.has('Blaze Rods', player) and state.has('Brewing', player) and state.has('3 Ender Pearls', player) + # Difficulty-dependent functions -def combat_difficulty(state: CollectionState, player: int) -> bool: - return state.multiworld.combat_difficulty[player].current_key - -def can_adventure(state: CollectionState, player: int) -> bool: - death_link_check = not state.multiworld.death_link[player] or state.has('Bed', player) - if combat_difficulty(state, player) == 'easy': - return state.has('Progressive Weapons', player, 2) and has_iron_ingots(state, player) and death_link_check - elif combat_difficulty(state, player) == 'hard': +def combat_difficulty(world: "MinecraftWorld", state: CollectionState, player: int) -> str: + return world.options.combat_difficulty.current_key + + +def can_adventure(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + death_link_check = not world.options.death_link or state.has('Bed', player) + if combat_difficulty(world, state, player) == 'easy': + return state.has('Progressive Weapons', player, 2) and has_iron_ingots(world, state, player) and death_link_check + elif combat_difficulty(world, state, player) == 'hard': return True - return (state.has('Progressive Weapons', player) and death_link_check and - (state.has('Progressive Resource Crafting', player) or state.has('Campfire', player))) - -def basic_combat(state: CollectionState, player: int) -> bool: - if combat_difficulty(state, player) == 'easy': - return state.has('Progressive Weapons', player, 2) and state.has('Progressive Armor', player) and \ - state.has('Shield', player) and has_iron_ingots(state, player) - elif combat_difficulty(state, player) == 'hard': + return (state.has('Progressive Weapons', player) and death_link_check and + (state.has('Progressive Resource Crafting', player) or state.has('Campfire', player))) + + +def basic_combat(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + if combat_difficulty(world, state, player) == 'easy': + return (state.has('Progressive Weapons', player, 2) + and state.has('Progressive Armor', player) + and state.has('Shield', player) + and has_iron_ingots(world, state, player) + ) + elif combat_difficulty(world, state, player) == 'hard': return True - return state.has('Progressive Weapons', player) and (state.has('Progressive Armor', player) or state.has('Shield', player)) and has_iron_ingots(state, player) - -def complete_raid(state: CollectionState, player: int) -> bool: - reach_regions = state.can_reach('Village', 'Region', player) and state.can_reach('Pillager Outpost', 'Region', player) - if combat_difficulty(state, player) == 'easy': - return reach_regions and \ - state.has('Progressive Weapons', player, 3) and state.has('Progressive Armor', player, 2) and \ - state.has('Shield', player) and state.has('Archery', player) and \ - state.has('Progressive Tools', player, 2) and has_iron_ingots(state, player) - elif combat_difficulty(state, player) == 'hard': # might be too hard? - return reach_regions and state.has('Progressive Weapons', player, 2) and has_iron_ingots(state, player) and \ - (state.has('Progressive Armor', player) or state.has('Shield', player)) - return reach_regions and state.has('Progressive Weapons', player, 2) and has_iron_ingots(state, player) and \ - state.has('Progressive Armor', player) and state.has('Shield', player) - -def can_kill_wither(state: CollectionState, player: int) -> bool: - normal_kill = state.has("Progressive Weapons", player, 3) and state.has("Progressive Armor", player, 2) and can_brew_potions(state, player) and can_enchant(state, player) - if combat_difficulty(state, player) == 'easy': - return fortress_loot(state, player) and normal_kill and state.has('Archery', player) - elif combat_difficulty(state, player) == 'hard': # cheese kill using bedrock ceilings - return fortress_loot(state, player) and (normal_kill or state.can_reach('The Nether', 'Region', player) or state.can_reach('The End', 'Region', player)) - return fortress_loot(state, player) and normal_kill - -def can_respawn_ender_dragon(state: CollectionState, player: int) -> bool: - return state.can_reach('The Nether', 'Region', player) and state.can_reach('The End', 'Region', player) and \ - state.has('Progressive Resource Crafting', player) # smelt sand into glass - -def can_kill_ender_dragon(state: CollectionState, player: int) -> bool: - if combat_difficulty(state, player) == 'easy': - return state.has("Progressive Weapons", player, 3) and state.has("Progressive Armor", player, 2) and \ - state.has('Archery', player) and can_brew_potions(state, player) and can_enchant(state, player) - if combat_difficulty(state, player) == 'hard': - return (state.has('Progressive Weapons', player, 2) and state.has('Progressive Armor', player)) or \ - (state.has('Progressive Weapons', player, 1) and state.has('Bed', player)) - return state.has('Progressive Weapons', player, 2) and state.has('Progressive Armor', player) and state.has('Archery', player) - -def has_structure_compass(state: CollectionState, entrance_name: str, player: int) -> bool: - if not state.multiworld.structure_compasses[player]: + return (state.has('Progressive Weapons', player) + and ( + state.has('Progressive Armor', player) + or state.has('Shield', player) + ) + and has_iron_ingots(world, state, player) + ) + + +def complete_raid(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + reach_regions = (state.can_reach_region('Village', player) + and state.can_reach_region('Pillager Outpost', player)) + if combat_difficulty(world, state, player) == 'easy': + return (reach_regions + and state.has('Progressive Weapons', player, 3) + and state.has('Progressive Armor', player, 2) + and state.has('Shield', player) + and state.has('Archery', player) + and state.has('Progressive Tools', player, 2) + and has_iron_ingots(world, state, player) + ) + elif combat_difficulty(world, state, player) == 'hard': # might be too hard? + return (reach_regions + and state.has('Progressive Weapons', player, 2) + and has_iron_ingots(world, state, player) + and ( + state.has('Progressive Armor', player) + or state.has('Shield', player) + ) + ) + return (reach_regions + and state.has('Progressive Weapons', player, 2) + and has_iron_ingots(world, state, player) + and state.has('Progressive Armor', player) + and state.has('Shield', player) + ) + + +def can_kill_wither(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + normal_kill = (state.has("Progressive Weapons", player, 3) + and state.has("Progressive Armor", player, 2) + and can_brew_potions(world, state, player) + and can_enchant(world, state, player) + ) + if combat_difficulty(world, state, player) == 'easy': + return (fortress_loot(world, state, player) + and normal_kill + and state.has('Archery', player) + ) + elif combat_difficulty(world, state, player) == 'hard': # cheese kill using bedrock ceilings + return (fortress_loot(world, state, player) + and ( + normal_kill + or state.can_reach_region('The Nether', player) + or state.can_reach_region('The End', player) + ) + ) + + return fortress_loot(world, state, player) and normal_kill + + +def can_respawn_ender_dragon(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + return (state.can_reach_region('The Nether', player) + and state.can_reach_region('The End', player) + and state.has('Progressive Resource Crafting', player) # smelt sand into glass + ) + + +def can_kill_ender_dragon(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: + if combat_difficulty(world, state, player) == 'easy': + return (state.has("Progressive Weapons", player, 3) + and state.has("Progressive Armor", player, 2) + and state.has('Archery', player) + and can_brew_potions(world, state, player) + and can_enchant(world, state, player) + ) + if combat_difficulty(world, state, player) == 'hard': + return ( + ( + state.has('Progressive Weapons', player, 2) + and state.has('Progressive Armor', player) + ) or ( + state.has('Progressive Weapons', player, 1) + and state.has('Bed', player) # who needs armor when you can respawn right outside the chamber + ) + ) + return (state.has('Progressive Weapons', player, 2) + and state.has('Progressive Armor', player) + and state.has('Archery', player) + ) + + +def has_structure_compass(world: "MinecraftWorld", state: CollectionState, entrance_name: str, player: int) -> bool: + if not world.options.structure_compasses: return True return state.has(f"Structure Compass ({state.multiworld.get_entrance(entrance_name, player).connected_region.name})", player) -def get_rules_lookup(player: int): - rules_lookup: typing.Dict[str, typing.List[Callable[[CollectionState], bool]]] = { +def get_rules_lookup(world, player: int): + rules_lookup = { "entrances": { - "Nether Portal": lambda state: (state.has('Flint and Steel', player) and - (state.has('Bucket', player) or state.has('Progressive Tools', player, 3)) and - has_iron_ingots(state, player)), - "End Portal": lambda state: enter_stronghold(state, player) and state.has('3 Ender Pearls', player, 4), - "Overworld Structure 1": lambda state: (can_adventure(state, player) and has_structure_compass(state, "Overworld Structure 1", player)), - "Overworld Structure 2": lambda state: (can_adventure(state, player) and has_structure_compass(state, "Overworld Structure 2", player)), - "Nether Structure 1": lambda state: (can_adventure(state, player) and has_structure_compass(state, "Nether Structure 1", player)), - "Nether Structure 2": lambda state: (can_adventure(state, player) and has_structure_compass(state, "Nether Structure 2", player)), - "The End Structure": lambda state: (can_adventure(state, player) and has_structure_compass(state, "The End Structure", player)), + "Nether Portal": lambda state: state.has('Flint and Steel', player) + and ( + state.has('Bucket', player) + or state.has('Progressive Tools', player, 3) + ) + and has_iron_ingots(world, state, player), + "End Portal": lambda state: enter_stronghold(world, state, player) + and state.has('3 Ender Pearls', player, 4), + "Overworld Structure 1": lambda state: can_adventure(world, state, player) + and has_structure_compass(world, state, "Overworld Structure 1", player), + "Overworld Structure 2": lambda state: can_adventure(world, state, player) + and has_structure_compass(world, state, "Overworld Structure 2", player), + "Nether Structure 1": lambda state: can_adventure(world, state, player) + and has_structure_compass(world, state, "Nether Structure 1", player), + "Nether Structure 2": lambda state: can_adventure(world, state, player) + and has_structure_compass(world, state, "Nether Structure 2", player), + "The End Structure": lambda state: can_adventure(world, state, player) + and has_structure_compass(world, state, "The End Structure", player), }, "locations": { - "Ender Dragon": lambda state: can_respawn_ender_dragon(state, player) and can_kill_ender_dragon(state, player), - "Wither": lambda state: can_kill_wither(state, player), - "Blaze Rods": lambda state: fortress_loot(state, player), - - "Who is Cutting Onions?": lambda state: can_piglin_trade(state, player), - "Oh Shiny": lambda state: can_piglin_trade(state, player), - "Suit Up": lambda state: state.has("Progressive Armor", player) and has_iron_ingots(state, player), - "Very Very Frightening": lambda state: (state.has("Channeling Book", player) and - can_use_anvil(state, player) and can_enchant(state, player) and overworld_villager(state, player)), - "Hot Stuff": lambda state: state.has("Bucket", player) and has_iron_ingots(state, player), - "Free the End": lambda state: can_respawn_ender_dragon(state, player) and can_kill_ender_dragon(state, player), - "A Furious Cocktail": lambda state: (can_brew_potions(state, player) and - state.has("Fishing Rod", player) and # Water Breathing - state.can_reach("The Nether", "Region", player) and # Regeneration, Fire Resistance, gold nuggets - state.can_reach("Village", "Region", player) and # Night Vision, Invisibility - state.can_reach("Bring Home the Beacon", "Location", player)), # Resistance - "Bring Home the Beacon": lambda state: (can_kill_wither(state, player) and - has_diamond_pickaxe(state, player) and state.has("Progressive Resource Crafting", player, 2)), - "Not Today, Thank You": lambda state: state.has("Shield", player) and has_iron_ingots(state, player), - "Isn't It Iron Pick": lambda state: state.has("Progressive Tools", player, 2) and has_iron_ingots(state, player), - "Local Brewery": lambda state: can_brew_potions(state, player), - "The Next Generation": lambda state: can_respawn_ender_dragon(state, player) and can_kill_ender_dragon(state, player), + "Ender Dragon": lambda state: can_respawn_ender_dragon(world, state, player) + and can_kill_ender_dragon(world, state, player), + "Wither": lambda state: can_kill_wither(world, state, player), + "Blaze Rods": lambda state: fortress_loot(world, state, player), + "Who is Cutting Onions?": lambda state: can_piglin_trade(world, state, player), + "Oh Shiny": lambda state: can_piglin_trade(world, state, player), + "Suit Up": lambda state: state.has("Progressive Armor", player) + and has_iron_ingots(world, state, player), + "Very Very Frightening": lambda state: state.has("Channeling Book", player) + and can_use_anvil(world, state, player) + and can_enchant(world, state, player) + and overworld_villager(world, state, player), + "Hot Stuff": lambda state: state.has("Bucket", player) + and has_iron_ingots(world, state, player), + "Free the End": lambda state: can_respawn_ender_dragon(world, state, player) + and can_kill_ender_dragon(world, state, player), + "A Furious Cocktail": lambda state: (can_brew_potions(world, state, player) + and state.has("Fishing Rod", player) # Water Breathing + and state.can_reach_region("The Nether", player) # Regeneration, Fire Resistance, gold nuggets + and state.can_reach_region("Village", player) # Night Vision, Invisibility + and state.can_reach_location("Bring Home the Beacon", player)), + # Resistance + "Bring Home the Beacon": lambda state: can_kill_wither(world, state, player) + and has_diamond_pickaxe(world, state, player) + and state.has("Progressive Resource Crafting", player, 2), + "Not Today, Thank You": lambda state: state.has("Shield", player) + and has_iron_ingots(world, state, player), + "Isn't It Iron Pick": lambda state: state.has("Progressive Tools", player, 2) + and has_iron_ingots(world, state, player), + "Local Brewery": lambda state: can_brew_potions(world, state, player), + "The Next Generation": lambda state: can_respawn_ender_dragon(world, state, player) + and can_kill_ender_dragon(world, state, player), "Fishy Business": lambda state: state.has("Fishing Rod", player), - "This Boat Has Legs": lambda state: ((fortress_loot(state, player) or complete_raid(state, player)) and - state.has("Saddle", player) and state.has("Fishing Rod", player)), + "This Boat Has Legs": lambda state: ( + fortress_loot(world, state, player) + or complete_raid(world, state, player) + ) + and state.has("Saddle", player) + and state.has("Fishing Rod", player), "Sniper Duel": lambda state: state.has("Archery", player), - "Great View From Up Here": lambda state: basic_combat(state, player), - "How Did We Get Here?": lambda state: (can_brew_potions(state, player) and - has_gold_ingots(state, player) and # Absorption - state.can_reach('End City', 'Region', player) and # Levitation - state.can_reach('The Nether', 'Region', player) and # potion ingredients - state.has("Fishing Rod", player) and state.has("Archery",player) and # Pufferfish, Nautilus Shells; spectral arrows - state.can_reach("Bring Home the Beacon", "Location", player) and # Haste - state.can_reach("Hero of the Village", "Location", player)), # Bad Omen, Hero of the Village - "Bullseye": lambda state: (state.has("Archery", player) and state.has("Progressive Tools", player, 2) and - has_iron_ingots(state, player)), - "Spooky Scary Skeleton": lambda state: basic_combat(state, player), - "Two by Two": lambda state: has_iron_ingots(state, player) and state.has("Bucket", player) and can_adventure(state, player), - "Two Birds, One Arrow": lambda state: craft_crossbow(state, player) and can_enchant(state, player), - "Who's the Pillager Now?": lambda state: craft_crossbow(state, player), + "Great View From Up Here": lambda state: basic_combat(world, state, player), + "How Did We Get Here?": lambda state: (can_brew_potions(world, state, player) + and has_gold_ingots(world, state, player) # Absorption + and state.can_reach_region('End City', player) # Levitation + and state.can_reach_region('The Nether', player) # potion ingredients + and state.has("Fishing Rod", player) # Pufferfish, Nautilus Shells; spectral arrows + and state.has("Archery", player) + and state.can_reach_location("Bring Home the Beacon", player) # Haste + and state.can_reach_location("Hero of the Village", player)), # Bad Omen, Hero of the Village + "Bullseye": lambda state: state.has("Archery", player) + and state.has("Progressive Tools", player, 2) + and has_iron_ingots(world, state, player), + "Spooky Scary Skeleton": lambda state: basic_combat(world, state, player), + "Two by Two": lambda state: has_iron_ingots(world, state, player) + and state.has("Bucket", player) + and can_adventure(world, state, player), + "Two Birds, One Arrow": lambda state: craft_crossbow(world, state, player) + and can_enchant(world, state, player), + "Who's the Pillager Now?": lambda state: craft_crossbow(world, state, player), "Getting an Upgrade": lambda state: state.has("Progressive Tools", player), - "Tactical Fishing": lambda state: state.has("Bucket", player) and has_iron_ingots(state, player), - "Zombie Doctor": lambda state: can_brew_potions(state, player) and has_gold_ingots(state, player), - "Ice Bucket Challenge": lambda state: has_diamond_pickaxe(state, player), - "Into Fire": lambda state: basic_combat(state, player), - "War Pigs": lambda state: basic_combat(state, player), + "Tactical Fishing": lambda state: state.has("Bucket", player) + and has_iron_ingots(world, state, player), + "Zombie Doctor": lambda state: can_brew_potions(world, state, player) + and has_gold_ingots(world, state, player), + "Ice Bucket Challenge": lambda state: has_diamond_pickaxe(world, state, player), + "Into Fire": lambda state: basic_combat(world, state, player), + "War Pigs": lambda state: basic_combat(world, state, player), "Take Aim": lambda state: state.has("Archery", player), - "Total Beelocation": lambda state: state.has("Silk Touch Book", player) and can_use_anvil(state, player) and can_enchant(state, player), - "Arbalistic": lambda state: (craft_crossbow(state, player) and state.has("Piercing IV Book", player) and - can_use_anvil(state, player) and can_enchant(state, player)), - "The End... Again...": lambda state: can_respawn_ender_dragon(state, player) and can_kill_ender_dragon(state, player), - "Acquire Hardware": lambda state: has_iron_ingots(state, player), - "Not Quite \"Nine\" Lives": lambda state: can_piglin_trade(state, player) and state.has("Progressive Resource Crafting", player, 2), - "Cover Me With Diamonds": lambda state: (state.has("Progressive Armor", player, 2) and - state.has("Progressive Tools", player, 2) and has_iron_ingots(state, player)), - "Sky's the Limit": lambda state: basic_combat(state, player), - "Hired Help": lambda state: state.has("Progressive Resource Crafting", player, 2) and has_iron_ingots(state, player), - "Sweet Dreams": lambda state: state.has("Bed", player) or state.can_reach('Village', 'Region', player), - "You Need a Mint": lambda state: can_respawn_ender_dragon(state, player) and has_bottle(state, player), - "Monsters Hunted": lambda state: (can_respawn_ender_dragon(state, player) and can_kill_ender_dragon(state, player) and - can_kill_wither(state, player) and state.has("Fishing Rod", player)), - "Enchanter": lambda state: can_enchant(state, player), - "Voluntary Exile": lambda state: basic_combat(state, player), - "Eye Spy": lambda state: enter_stronghold(state, player), - "Serious Dedication": lambda state: (can_brew_potions(state, player) and state.has("Bed", player) and - has_diamond_pickaxe(state, player) and has_gold_ingots(state, player)), - "Postmortal": lambda state: complete_raid(state, player), - "Adventuring Time": lambda state: can_adventure(state, player), - "Hero of the Village": lambda state: complete_raid(state, player), - "Hidden in the Depths": lambda state: can_brew_potions(state, player) and state.has("Bed", player) and has_diamond_pickaxe(state, player), - "Beaconator": lambda state: (can_kill_wither(state, player) and has_diamond_pickaxe(state, player) and - state.has("Progressive Resource Crafting", player, 2)), - "Withering Heights": lambda state: can_kill_wither(state, player), - "A Balanced Diet": lambda state: (has_bottle(state, player) and has_gold_ingots(state, player) and # honey bottle; gapple - state.has("Progressive Resource Crafting", player, 2) and state.can_reach('The End', 'Region', player)), # notch apple, chorus fruit - "Subspace Bubble": lambda state: has_diamond_pickaxe(state, player), - "Country Lode, Take Me Home": lambda state: state.can_reach("Hidden in the Depths", "Location", player) and has_gold_ingots(state, player), - "Bee Our Guest": lambda state: state.has("Campfire", player) and has_bottle(state, player), - "Uneasy Alliance": lambda state: has_diamond_pickaxe(state, player) and state.has('Fishing Rod', player), - "Diamonds!": lambda state: state.has("Progressive Tools", player, 2) and has_iron_ingots(state, player), - "A Throwaway Joke": lambda state: can_adventure(state, player), - "Sticky Situation": lambda state: state.has("Campfire", player) and has_bottle(state, player), - "Ol' Betsy": lambda state: craft_crossbow(state, player), - "Cover Me in Debris": lambda state: (state.has("Progressive Armor", player, 2) and - state.has("8 Netherite Scrap", player, 2) and state.has("Progressive Resource Crafting", player) and - has_diamond_pickaxe(state, player) and has_iron_ingots(state, player) and - can_brew_potions(state, player) and state.has("Bed", player)), + "Total Beelocation": lambda state: state.has("Silk Touch Book", player) + and can_use_anvil(world, state, player) + and can_enchant(world, state, player), + "Arbalistic": lambda state: (craft_crossbow(world, state, player) + and state.has("Piercing IV Book", player) + and can_use_anvil(world, state, player) + and can_enchant(world, state, player) + ), + "The End... Again...": lambda state: can_respawn_ender_dragon(world, state, player) + and can_kill_ender_dragon(world, state, player), + "Acquire Hardware": lambda state: has_iron_ingots(world, state, player), + "Not Quite \"Nine\" Lives": lambda state: can_piglin_trade(world, state, player) + and state.has("Progressive Resource Crafting", player, 2), + "Cover Me With Diamonds": lambda state: state.has("Progressive Armor", player, 2) + and state.has("Progressive Tools", player, 2) + and has_iron_ingots(world, state, player), + "Sky's the Limit": lambda state: basic_combat(world, state, player), + "Hired Help": lambda state: state.has("Progressive Resource Crafting", player, 2) + and has_iron_ingots(world, state, player), + "Sweet Dreams": lambda state: state.has("Bed", player) + or state.can_reach_region('Village', player), + "You Need a Mint": lambda state: can_respawn_ender_dragon(world, state, player) + and has_bottle(world, state, player), + "Monsters Hunted": lambda state: (can_respawn_ender_dragon(world, state, player) + and can_kill_ender_dragon(world, state, player) + and can_kill_wither(world, state, player) + and state.has("Fishing Rod", player)), + "Enchanter": lambda state: can_enchant(world, state, player), + "Voluntary Exile": lambda state: basic_combat(world, state, player), + "Eye Spy": lambda state: enter_stronghold(world, state, player), + "Serious Dedication": lambda state: (can_brew_potions(world, state, player) + and state.has("Bed", player) + and has_diamond_pickaxe(world, state, player) + and has_gold_ingots(world, state, player)), + "Postmortal": lambda state: complete_raid(world, state, player), + "Adventuring Time": lambda state: can_adventure(world, state, player), + "Hero of the Village": lambda state: complete_raid(world, state, player), + "Hidden in the Depths": lambda state: can_brew_potions(world, state, player) + and state.has("Bed", player) + and has_diamond_pickaxe(world, state, player), + "Beaconator": lambda state: (can_kill_wither(world, state, player) + and has_diamond_pickaxe(world, state, player) + and state.has("Progressive Resource Crafting", player, 2)), + "Withering Heights": lambda state: can_kill_wither(world, state, player), + "A Balanced Diet": lambda state: (has_bottle(world, state, player) + and has_gold_ingots(world, state, player) + and state.has("Progressive Resource Crafting", player, 2) + and state.can_reach_region('The End', player)), + # notch apple, chorus fruit + "Subspace Bubble": lambda state: has_diamond_pickaxe(world, state, player), + "Country Lode, Take Me Home": lambda state: state.can_reach_location("Hidden in the Depths", player) + and has_gold_ingots(world, state, player), + "Bee Our Guest": lambda state: state.has("Campfire", player) + and has_bottle(world, state, player), + "Uneasy Alliance": lambda state: has_diamond_pickaxe(world, state, player) + and state.has('Fishing Rod', player), + "Diamonds!": lambda state: state.has("Progressive Tools", player, 2) + and has_iron_ingots(world, state, player), + "A Throwaway Joke": lambda state: can_adventure(world, state, player), + "Sticky Situation": lambda state: state.has("Campfire", player) + and has_bottle(world, state, player), + "Ol' Betsy": lambda state: craft_crossbow(world, state, player), + "Cover Me in Debris": lambda state: state.has("Progressive Armor", player, 2) + and state.has("8 Netherite Scrap", player, 2) + and state.has("Progressive Resource Crafting", player) + and has_diamond_pickaxe(world, state, player) + and has_iron_ingots(world, state, player) + and can_brew_potions(world, state, player) + and state.has("Bed", player), "Hot Topic": lambda state: state.has("Progressive Resource Crafting", player), - "The Lie": lambda state: has_iron_ingots(state, player) and state.has("Bucket", player), - "On a Rail": lambda state: has_iron_ingots(state, player) and state.has('Progressive Tools', player, 2), - "When Pigs Fly": lambda state: ((fortress_loot(state, player) or complete_raid(state, player)) and - state.has("Saddle", player) and state.has("Fishing Rod", player) and can_adventure(state, player)), - "Overkill": lambda state: (can_brew_potions(state, player) and - (state.has("Progressive Weapons", player) or state.can_reach('The Nether', 'Region', player))), + "The Lie": lambda state: has_iron_ingots(world, state, player) + and state.has("Bucket", player), + "On a Rail": lambda state: has_iron_ingots(world, state, player) + and state.has('Progressive Tools', player, 2), + "When Pigs Fly": lambda state: ( + fortress_loot(world, state, player) + or complete_raid(world, state, player) + ) + and state.has("Saddle", player) + and state.has("Fishing Rod", player) + and can_adventure(world, state, player), + "Overkill": lambda state: can_brew_potions(world, state, player) + and ( + state.has("Progressive Weapons", player) + or state.can_reach_region('The Nether', player) + ), "Librarian": lambda state: state.has("Enchanting", player), - "Overpowered": lambda state: (has_iron_ingots(state, player) and - state.has('Progressive Tools', player, 2) and basic_combat(state, player)), - "Wax On": lambda state: (has_copper_ingots(state, player) and state.has('Campfire', player) and - state.has('Progressive Resource Crafting', player, 2)), - "Wax Off": lambda state: (has_copper_ingots(state, player) and state.has('Campfire', player) and - state.has('Progressive Resource Crafting', player, 2)), - "The Cutest Predator": lambda state: has_iron_ingots(state, player) and state.has('Bucket', player), - "The Healing Power of Friendship": lambda state: has_iron_ingots(state, player) and state.has('Bucket', player), - "Is It a Bird?": lambda state: has_spyglass(state, player) and can_adventure(state, player), - "Is It a Balloon?": lambda state: has_spyglass(state, player), - "Is It a Plane?": lambda state: has_spyglass(state, player) and can_respawn_ender_dragon(state, player), - "Surge Protector": lambda state: (state.has("Channeling Book", player) and - can_use_anvil(state, player) and can_enchant(state, player) and overworld_villager(state, player)), - "Light as a Rabbit": lambda state: can_adventure(state, player) and has_iron_ingots(state, player) and state.has('Bucket', player), - "Glow and Behold!": lambda state: can_adventure(state, player), - "Whatever Floats Your Goat!": lambda state: can_adventure(state, player), - "Caves & Cliffs": lambda state: has_iron_ingots(state, player) and state.has('Bucket', player) and state.has('Progressive Tools', player, 2), - "Feels like home": lambda state: (has_iron_ingots(state, player) and state.has('Bucket', player) and state.has('Fishing Rod', player) and - (fortress_loot(state, player) or complete_raid(state, player)) and state.has("Saddle", player)), - "Sound of Music": lambda state: state.has("Progressive Tools", player, 2) and has_iron_ingots(state, player) and basic_combat(state, player), - "Star Trader": lambda state: (has_iron_ingots(state, player) and state.has('Bucket', player) and - (state.can_reach("The Nether", 'Region', player) or - state.can_reach("Nether Fortress", 'Region', player) or # soul sand for water elevator - can_piglin_trade(state, player)) and - overworld_villager(state, player)), - "Birthday Song": lambda state: state.can_reach("The Lie", "Location", player) and state.has("Progressive Tools", player, 2) and has_iron_ingots(state, player), - "Bukkit Bukkit": lambda state: state.has("Bucket", player) and has_iron_ingots(state, player) and can_adventure(state, player), - "It Spreads": lambda state: can_adventure(state, player) and has_iron_ingots(state, player) and state.has("Progressive Tools", player, 2), - "Sneak 100": lambda state: can_adventure(state, player) and has_iron_ingots(state, player) and state.has("Progressive Tools", player, 2), - "When the Squad Hops into Town": lambda state: can_adventure(state, player) and state.has("Lead", player), - "With Our Powers Combined!": lambda state: can_adventure(state, player) and state.has("Lead", player), + "Overpowered": lambda state: has_iron_ingots(world, state, player) + and state.has('Progressive Tools', player, 2) + and basic_combat(world, state, player), + "Wax On": lambda state: has_copper_ingots(world, state, player) + and state.has('Campfire', player) + and state.has('Progressive Resource Crafting', player, 2), + "Wax Off": lambda state: has_copper_ingots(world, state, player) + and state.has('Campfire', player) + and state.has('Progressive Resource Crafting', player, 2), + "The Cutest Predator": lambda state: has_iron_ingots(world, state, player) + and state.has('Bucket', player), + "The Healing Power of Friendship": lambda state: has_iron_ingots(world, state, player) + and state.has('Bucket', player), + "Is It a Bird?": lambda state: has_spyglass(world, state, player) + and can_adventure(world, state, player), + "Is It a Balloon?": lambda state: has_spyglass(world, state, player), + "Is It a Plane?": lambda state: has_spyglass(world, state, player) + and can_respawn_ender_dragon(world, state, player), + "Surge Protector": lambda state: state.has("Channeling Book", player) + and can_use_anvil(world, state, player) + and can_enchant(world, state, player) + and overworld_villager(world, state, player), + "Light as a Rabbit": lambda state: can_adventure(world, state, player) + and has_iron_ingots(world, state, player) + and state.has('Bucket', player), + "Glow and Behold!": lambda state: can_adventure(world, state, player), + "Whatever Floats Your Goat!": lambda state: can_adventure(world, state, player), + "Caves & Cliffs": lambda state: has_iron_ingots(world, state, player) + and state.has('Bucket', player) + and state.has('Progressive Tools', player, 2), + "Feels like home": lambda state: has_iron_ingots(world, state, player) + and state.has('Bucket', player) + and state.has('Fishing Rod', player) + and ( + fortress_loot(world, state, player) + or complete_raid(world, state, player) + ) + and state.has("Saddle", player), + "Sound of Music": lambda state: state.has("Progressive Tools", player, 2) + and has_iron_ingots(world, state, player) + and basic_combat(world, state, player), + "Star Trader": lambda state: has_iron_ingots(world, state, player) + and state.has('Bucket', player) + and ( + state.can_reach_region("The Nether", player) # soul sand in nether + or state.can_reach_region("Nether Fortress", player) # soul sand in fortress if not in nether for water elevator + or can_piglin_trade(world, state, player) # piglins give soul sand + ) + and overworld_villager(world, state, player), + "Birthday Song": lambda state: state.can_reach_location("The Lie", player) + and state.has("Progressive Tools", player, 2) + and has_iron_ingots(world, state, player), + "Bukkit Bukkit": lambda state: state.has("Bucket", player) + and has_iron_ingots(world, state, player) + and can_adventure(world, state, player), + "It Spreads": lambda state: can_adventure(world, state, player) + and has_iron_ingots(world, state, player) + and state.has("Progressive Tools", player, 2), + "Sneak 100": lambda state: can_adventure(world, state, player) + and has_iron_ingots(world, state, player) + and state.has("Progressive Tools", player, 2), + "When the Squad Hops into Town": lambda state: can_adventure(world, state, player) + and state.has("Lead", player), + "With Our Powers Combined!": lambda state: can_adventure(world, state, player) + and state.has("Lead", player), } } return rules_lookup -def set_rules(mc_world: World) -> None: - multiworld = mc_world.multiworld - player = mc_world.player +def set_rules(self: "MinecraftWorld") -> None: + multiworld = self.multiworld + player = self.player - rules_lookup = get_rules_lookup(player) + rules_lookup = get_rules_lookup(self, player) # Set entrance rules for entrance_name, rule in rules_lookup["entrances"].items(): @@ -281,33 +476,33 @@ def set_rules(mc_world: World) -> None: multiworld.get_location(location_name, player).access_rule = rule # Set rules surrounding completion - bosses = multiworld.required_bosses[player] + bosses = self.options.required_bosses postgame_advancements = set() if bosses.dragon: postgame_advancements.update(Constants.exclusion_info["ender_dragon"]) if bosses.wither: postgame_advancements.update(Constants.exclusion_info["wither"]) - def location_count(state: CollectionState) -> bool: + def location_count(state: CollectionState) -> int: return len([location for location in multiworld.get_locations(player) if - location.address != None and - location.can_reach(state)]) + location.address is not None and + location.can_reach(state)]) def defeated_bosses(state: CollectionState) -> bool: return ((not bosses.dragon or state.has("Ender Dragon", player)) - and (not bosses.wither or state.has("Wither", player))) + and (not bosses.wither or state.has("Wither", player))) - egg_shards = min(multiworld.egg_shards_required[player], multiworld.egg_shards_available[player]) - completion_requirements = lambda state: (location_count(state) >= multiworld.advancement_goal[player] - and state.has("Dragon Egg Shard", player, egg_shards)) + egg_shards = min(self.options.egg_shards_required.value, self.options.egg_shards_available.value) + completion_requirements = lambda state: (location_count(state) >= self.options.advancement_goal + and state.has("Dragon Egg Shard", player, egg_shards)) multiworld.completion_condition[player] = lambda state: completion_requirements(state) and defeated_bosses(state) # Set exclusions on hard/unreasonable/postgame excluded_advancements = set() - if not multiworld.include_hard_advancements[player]: + if not self.options.include_hard_advancements: excluded_advancements.update(Constants.exclusion_info["hard"]) - if not multiworld.include_unreasonable_advancements[player]: + if not self.options.include_unreasonable_advancements: excluded_advancements.update(Constants.exclusion_info["unreasonable"]) - if not multiworld.include_postgame_advancements[player]: + if not self.options.include_postgame_advancements: excluded_advancements.update(postgame_advancements) exclusion_rules(multiworld, player, excluded_advancements) diff --git a/worlds/minecraft/Structures.py b/worlds/minecraft/Structures.py index 95bafc9efb5c..df3d944a6c65 100644 --- a/worlds/minecraft/Structures.py +++ b/worlds/minecraft/Structures.py @@ -1,17 +1,19 @@ -from worlds.AutoWorld import World - from . import Constants +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from . import MinecraftWorld + -def shuffle_structures(mc_world: World) -> None: - multiworld = mc_world.multiworld - player = mc_world.player +def shuffle_structures(self: "MinecraftWorld") -> None: + multiworld = self.multiworld + player = self.player default_connections = Constants.region_info["default_connections"] illegal_connections = Constants.region_info["illegal_connections"] # Get all unpaired exits and all regions without entrances (except the Menu) # This function is destructive on these lists. - exits = [exit.name for r in multiworld.regions if r.player == player for exit in r.exits if exit.connected_region == None] + exits = [exit.name for r in multiworld.regions if r.player == player for exit in r.exits if exit.connected_region is None] structs = [r.name for r in multiworld.regions if r.player == player and r.entrances == [] and r.name != 'Menu'] exits_spoiler = exits[:] # copy the original order for the spoiler log @@ -26,19 +28,19 @@ def set_pair(exit, struct): raise Exception(f"Invalid connection: {exit} => {struct} for player {player} ({multiworld.player_name[player]})") # Connect plando structures first - if multiworld.plando_connections[player]: - for conn in multiworld.plando_connections[player]: + if self.options.plando_connections: + for conn in self.plando_connections: set_pair(conn.entrance, conn.exit) # The algorithm tries to place the most restrictive structures first. This algorithm always works on the # relatively small set of restrictions here, but does not work on all possible inputs with valid configurations. - if multiworld.shuffle_structures[player]: + if self.options.shuffle_structures: structs.sort(reverse=True, key=lambda s: len(illegal_connections.get(s, []))) for struct in structs[:]: try: - exit = multiworld.random.choice([e for e in exits if e not in illegal_connections.get(struct, [])]) + exit = self.random.choice([e for e in exits if e not in illegal_connections.get(struct, [])]) except IndexError: - raise Exception(f"No valid structure placements remaining for player {player} ({multiworld.player_name[player]})") + raise Exception(f"No valid structure placements remaining for player {player} ({self.player_name})") set_pair(exit, struct) else: # write remaining default connections for (exit, struct) in default_connections: @@ -49,9 +51,9 @@ def set_pair(exit, struct): try: assert len(exits) == len(structs) == 0 except AssertionError: - raise Exception(f"Failed to connect all Minecraft structures for player {player} ({multiworld.player_name[player]})") + raise Exception(f"Failed to connect all Minecraft structures for player {player} ({self.player_name})") for exit in exits_spoiler: multiworld.get_entrance(exit, player).connect(multiworld.get_region(pairs[exit], player)) - if multiworld.shuffle_structures[player] or multiworld.plando_connections[player]: + if self.options.shuffle_structures or self.options.plando_connections: multiworld.spoiler.set_entrance(exit, pairs[exit], 'entrance', player) diff --git a/worlds/minecraft/__init__.py b/worlds/minecraft/__init__.py index 75e043d0cbaf..75539fcf2ea6 100644 --- a/worlds/minecraft/__init__.py +++ b/worlds/minecraft/__init__.py @@ -9,7 +9,7 @@ from worlds.AutoWorld import World, WebWorld from . import Constants -from .Options import minecraft_options +from .Options import MinecraftOptions from .Structures import shuffle_structures from .ItemPool import build_item_pool, get_junk_item_names from .Rules import set_rules @@ -83,8 +83,9 @@ class MinecraftWorld(World): structures, and materials to create a portal to another world. Defeat the Ender Dragon, and claim victory! """ - game: str = "Minecraft" - option_definitions = minecraft_options + game = "Minecraft" + options_dataclass = MinecraftOptions + options: MinecraftOptions settings: typing.ClassVar[MinecraftSettings] topology_present = True web = MinecraftWebWorld() @@ -95,20 +96,20 @@ class MinecraftWorld(World): def _get_mc_data(self) -> Dict[str, Any]: exits = [connection[0] for connection in Constants.region_info["default_connections"]] return { - 'world_seed': self.multiworld.per_slot_randoms[self.player].getrandbits(32), + 'world_seed': self.random.getrandbits(32), 'seed_name': self.multiworld.seed_name, - 'player_name': self.multiworld.get_player_name(self.player), + 'player_name': self.player_name, 'player_id': self.player, 'client_version': client_version, 'structures': {exit: self.multiworld.get_entrance(exit, self.player).connected_region.name for exit in exits}, - 'advancement_goal': self.multiworld.advancement_goal[self.player].value, - 'egg_shards_required': min(self.multiworld.egg_shards_required[self.player].value, - self.multiworld.egg_shards_available[self.player].value), - 'egg_shards_available': self.multiworld.egg_shards_available[self.player].value, - 'required_bosses': self.multiworld.required_bosses[self.player].current_key, - 'MC35': bool(self.multiworld.send_defeated_mobs[self.player].value), - 'death_link': bool(self.multiworld.death_link[self.player].value), - 'starting_items': str(self.multiworld.starting_items[self.player].value), + 'advancement_goal': self.options.advancement_goal.value, + 'egg_shards_required': min(self.options.egg_shards_required.value, + self.options.egg_shards_available.value), + 'egg_shards_available': self.options.egg_shards_available.value, + 'required_bosses': self.options.required_bosses.current_key, + 'MC35': bool(self.options.send_defeated_mobs.value), + 'death_link': bool(self.options.death_link.value), + 'starting_items': json.dumps(self.options.starting_items.value), 'race': self.multiworld.is_race, } @@ -129,7 +130,7 @@ def create_event(self, region_name: str, event_name: str) -> None: loc.place_locked_item(self.create_event_item(event_name)) region.locations.append(loc) - def create_event_item(self, name: str) -> None: + def create_event_item(self, name: str) -> Item: item = self.create_item(name) item.classification = ItemClassification.progression return item @@ -176,15 +177,10 @@ def generate_output(self, output_directory: str) -> None: f.write(b64encode(bytes(json.dumps(data), 'utf-8'))) def fill_slot_data(self) -> dict: - slot_data = self._get_mc_data() - for option_name in minecraft_options: - option = getattr(self.multiworld, option_name)[self.player] - if slot_data.get(option_name, None) is None and type(option.value) in {str, int}: - slot_data[option_name] = int(option.value) - return slot_data + return self._get_mc_data() def get_filler_item_name(self) -> str: - return get_junk_item_names(self.multiworld.random, 1)[0] + return get_junk_item_names(self.random, 1)[0] class MinecraftLocation(Location): diff --git a/worlds/minecraft/test/TestOptions.py b/worlds/minecraft/test/TestOptions.py index 668ed500e832..c04a07054c9c 100644 --- a/worlds/minecraft/test/TestOptions.py +++ b/worlds/minecraft/test/TestOptions.py @@ -1,19 +1,19 @@ from . import MCTestBase from ..Constants import region_info -from ..Options import minecraft_options +from .. import Options from BaseClasses import ItemClassification class AdvancementTestBase(MCTestBase): options = { - "advancement_goal": minecraft_options["advancement_goal"].range_end + "advancement_goal": Options.AdvancementGoal.range_end } # beatability test implicit class ShardTestBase(MCTestBase): options = { - "egg_shards_required": minecraft_options["egg_shards_required"].range_end, - "egg_shards_available": minecraft_options["egg_shards_available"].range_end + "egg_shards_required": Options.EggShardsRequired.range_end, + "egg_shards_available": Options.EggShardsAvailable.range_end } # check that itempool is not overfilled with shards @@ -29,7 +29,7 @@ def test_compasses_in_pool(self): class NoBeeTestBase(MCTestBase): options = { - "bee_traps": 0 + "bee_traps": Options.BeeTraps.range_start } # With no bees, there are no traps in the pool @@ -40,7 +40,7 @@ def test_bees(self): class AllBeeTestBase(MCTestBase): options = { - "bee_traps": 100 + "bee_traps": Options.BeeTraps.range_end } # With max bees, there are no filler items, only bee traps diff --git a/worlds/minecraft/test/__init__.py b/worlds/minecraft/test/__init__.py index acf9b7949137..3d936fe9cb6b 100644 --- a/worlds/minecraft/test/__init__.py +++ b/worlds/minecraft/test/__init__.py @@ -1,5 +1,5 @@ -from test.TestBase import TestBase, WorldTestBase -from .. import MinecraftWorld +from test.bases import TestBase, WorldTestBase +from .. import MinecraftWorld, MinecraftOptions class MCTestBase(WorldTestBase, TestBase): diff --git a/worlds/mm2/__init__.py b/worlds/mm2/__init__.py new file mode 100644 index 000000000000..07e1823f9387 --- /dev/null +++ b/worlds/mm2/__init__.py @@ -0,0 +1,290 @@ +import hashlib +import logging +from copy import deepcopy +from typing import Dict, Any, TYPE_CHECKING, Optional, Sequence, Tuple, ClassVar, List + +from BaseClasses import Tutorial, ItemClassification, MultiWorld, Item, Location +from worlds.AutoWorld import World, WebWorld +from .names import (dr_wily, heat_man_stage, air_man_stage, wood_man_stage, bubble_man_stage, quick_man_stage, + flash_man_stage, metal_man_stage, crash_man_stage) +from .items import (item_table, item_names, MM2Item, filler_item_weights, robot_master_weapon_table, + stage_access_table, item_item_table, lookup_item_to_id) +from .locations import (MM2Location, mm2_regions, MM2Region, energy_pickups, etank_1ups, lookup_location_to_id, + location_groups) +from .rom import patch_rom, MM2ProcedurePatch, MM2LCHASH, PROTEUSHASH, MM2VCHASH, MM2NESHASH +from .options import MM2Options, Consumables +from .client import MegaMan2Client +from .rules import set_rules, weapon_damage, robot_masters, weapons_to_name, minimum_weakness_requirement +import os +import threading +import base64 +import settings +logger = logging.getLogger("Mega Man 2") + +if TYPE_CHECKING: + from BaseClasses import CollectionState + + +class MM2Settings(settings.Group): + class RomFile(settings.UserFilePath): + """File name of the MM2 EN rom""" + description = "Mega Man 2 ROM File" + copy_to: Optional[str] = "Mega Man 2 (USA).nes" + md5s = [MM2NESHASH, MM2VCHASH, MM2LCHASH, PROTEUSHASH] + + def browse(self: settings.T, + filetypes: Optional[Sequence[Tuple[str, Sequence[str]]]] = None, + **kwargs: Any) -> Optional[settings.T]: + if not filetypes: + file_types = [("NES", [".nes"]), ("Program", [".exe"])] # LC1 is only a windows executable, no linux + return super().browse(file_types, **kwargs) + else: + return super().browse(filetypes, **kwargs) + + @classmethod + def validate(cls, path: str) -> None: + """Try to open and validate file against hashes""" + with open(path, "rb", buffering=0) as f: + try: + f.seek(0) + if f.read(4) == b"NES\x1A": + f.seek(16) + else: + f.seek(0) + cls._validate_stream_hashes(f) + base_rom_bytes = f.read() + basemd5 = hashlib.md5() + basemd5.update(base_rom_bytes) + if basemd5.hexdigest() == PROTEUSHASH: + # we need special behavior here + cls.copy_to = None + except ValueError: + raise ValueError(f"File hash does not match for {path}") + + rom_file: RomFile = RomFile(RomFile.copy_to) + + +class MM2WebWorld(WebWorld): + theme = "partyTime" + tutorials = [ + + Tutorial( + "Multiworld Setup Guide", + "A guide to setting up the Mega Man 2 randomizer connected to an Archipelago Multiworld.", + "English", + "setup_en.md", + "setup/en", + ["Silvris"] + ) + ] + + +class MM2World(World): + """ + In the year 200X, following his prior defeat by Mega Man, the evil Dr. Wily has returned to take over the world with + his own group of Robot Masters. Mega Man once again sets out to defeat the eight Robot Masters and stop Dr. Wily. + + """ + + game = "Mega Man 2" + settings: ClassVar[MM2Settings] + options_dataclass = MM2Options + options: MM2Options + item_name_to_id = lookup_item_to_id + location_name_to_id = lookup_location_to_id + item_name_groups = item_names + location_name_groups = location_groups + web = MM2WebWorld() + rom_name: bytearray + world_version: Tuple[int, int, int] = (0, 3, 1) + wily_5_weapons: Dict[int, List[int]] + + def __init__(self, world: MultiWorld, player: int): + self.rom_name = bytearray() + self.rom_name_available_event = threading.Event() + super().__init__(world, player) + self.weapon_damage = deepcopy(weapon_damage) + self.wily_5_weapons = {} + + def create_regions(self) -> None: + menu = MM2Region("Menu", self.player, self.multiworld) + self.multiworld.regions.append(menu) + for region in mm2_regions: + stage = MM2Region(region, self.player, self.multiworld) + required_items = mm2_regions[region][0] + locations = mm2_regions[region][1] + prev_stage = mm2_regions[region][2] + if prev_stage is None: + menu.connect(stage, f"To {region}", + lambda state, items=required_items: state.has_all(items, self.player)) + else: + old_stage = self.get_region(prev_stage) + old_stage.connect(stage, f"To {region}", + lambda state, items=required_items: state.has_all(items, self.player)) + stage.add_locations(locations, MM2Location) + for location in stage.get_locations(): + if location.address is None and location.name != dr_wily: + location.place_locked_item(MM2Item(location.name, ItemClassification.progression, + None, self.player)) + if region in etank_1ups and self.options.consumables in (Consumables.option_1up_etank, + Consumables.option_all): + stage.add_locations(etank_1ups[region], MM2Location) + if region in energy_pickups and self.options.consumables in (Consumables.option_weapon_health, + Consumables.option_all): + stage.add_locations(energy_pickups[region], MM2Location) + self.multiworld.regions.append(stage) + + def create_item(self, name: str) -> MM2Item: + item = item_table[name] + classification = ItemClassification.filler + if item.progression: + classification = ItemClassification.progression_skip_balancing \ + if item.skip_balancing else ItemClassification.progression + if item.useful: + classification |= ItemClassification.useful + return MM2Item(name, classification, item.code, self.player) + + def get_filler_item_name(self) -> str: + return self.random.choices(list(filler_item_weights.keys()), + weights=list(filler_item_weights.values()))[0] + + def create_items(self) -> None: + itempool = [] + # grab first robot master + robot_master = self.item_id_to_name[0x880101 + self.options.starting_robot_master.value] + self.multiworld.push_precollected(self.create_item(robot_master)) + itempool.extend([self.create_item(name) for name in stage_access_table.keys() + if name != robot_master]) + itempool.extend([self.create_item(name) for name in robot_master_weapon_table.keys()]) + itempool.extend([self.create_item(name) for name in item_item_table.keys()]) + total_checks = 24 + if self.options.consumables in (Consumables.option_1up_etank, + Consumables.option_all): + total_checks += 20 + if self.options.consumables in (Consumables.option_weapon_health, + Consumables.option_all): + total_checks += 27 + remaining = total_checks - len(itempool) + itempool.extend([self.create_item(name) + for name in self.random.choices(list(filler_item_weights.keys()), + weights=list(filler_item_weights.values()), + k=remaining)]) + self.multiworld.itempool += itempool + + set_rules = set_rules + + def generate_early(self) -> None: + if (not self.options.yoku_jumps + and self.options.starting_robot_master == "heat_man") or \ + (not self.options.enable_lasers + and self.options.starting_robot_master == "quick_man"): + robot_master_pool = [1, 2, 3, 5, 6, 7, ] + if self.options.yoku_jumps: + robot_master_pool.append(0) + if self.options.enable_lasers: + robot_master_pool.append(4) + self.options.starting_robot_master.value = self.random.choice(robot_master_pool) + logger.warning( + f"Mega Man 2 ({self.player_name}): " + f"Incompatible starting Robot Master, changing to " + f"{self.options.starting_robot_master.current_key.replace('_', ' ').title()}") + + def generate_basic(self) -> None: + goal_location = self.get_location(dr_wily) + goal_location.place_locked_item(MM2Item("Victory", ItemClassification.progression, None, self.player)) + self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player) + + def fill_hook(self, + progitempool: List["Item"], + usefulitempool: List["Item"], + filleritempool: List["Item"], + fill_locations: List["Location"]) -> None: + # on a solo gen, fill can try to force Wily into sphere 2, but for most generations this is impossible + # since MM2 can have a 2 item sphere 1, and 3 items are required for Wily + if self.multiworld.players > 1: + return # Don't need to change anything on a multi gen, fill should be able to solve it with a 4 sphere 1 + rbm_to_item = { + 0: heat_man_stage, + 1: air_man_stage, + 2: wood_man_stage, + 3: bubble_man_stage, + 4: quick_man_stage, + 5: flash_man_stage, + 6: metal_man_stage, + 7: crash_man_stage + } + affected_rbm = [2, 3] # Wood and Bubble will always have this happen + possible_rbm = [1, 5] # Air and Flash are always valid targets, due to Item 2/3 receive + if self.options.consumables: + possible_rbm.append(6) # Metal has 3 consumables + possible_rbm.append(7) # Crash has 3 consumables + if self.options.enable_lasers: + possible_rbm.append(4) # Quick has a lot of consumables, but needs logical time stopper if not enabled + else: + affected_rbm.extend([6, 7]) # only two checks on non consumables + if self.options.yoku_jumps: + possible_rbm.append(0) # Heat has 3 locations always, but might need 2 items logically + if self.options.starting_robot_master.value in affected_rbm: + rbm_names = list(map(lambda s: rbm_to_item[s], possible_rbm)) + valid_second = [item for item in progitempool + if item.name in rbm_names + and item.player == self.player] + placed_item = self.random.choice(valid_second) + rbm_defeated = (f"{robot_masters[self.options.starting_robot_master.value].replace(' Defeated', '')}" + f" - Defeated") + rbm_location = self.get_location(rbm_defeated) + rbm_location.place_locked_item(placed_item) + progitempool.remove(placed_item) + fill_locations.remove(rbm_location) + target_rbm = (placed_item.code & 0xF) - 1 + if self.options.strict_weakness or (self.options.random_weakness + and not (self.weapon_damage[0][target_rbm] > 0)): + # we need to find a weakness for this boss + weaknesses = [weapon for weapon in range(1, 9) + if self.weapon_damage[weapon][target_rbm] >= minimum_weakness_requirement[weapon]] + weapons = list(map(lambda s: weapons_to_name[s], weaknesses)) + valid_weapons = [item for item in progitempool + if item.name in weapons + and item.player == self.player] + placed_weapon = self.random.choice(valid_weapons) + weapon_name = next(name for name, idx in lookup_location_to_id.items() + if idx == 0x880101 + self.options.starting_robot_master.value) + weapon_location = self.get_location(weapon_name) + weapon_location.place_locked_item(placed_weapon) + progitempool.remove(placed_weapon) + fill_locations.remove(weapon_location) + + def generate_output(self, output_directory: str) -> None: + try: + patch = MM2ProcedurePatch(player=self.player, player_name=self.player_name) + patch_rom(self, patch) + + self.rom_name = patch.name + + patch.write(os.path.join(output_directory, + f"{self.multiworld.get_out_file_name_base(self.player)}{patch.patch_file_ending}")) + except Exception: + raise + finally: + self.rom_name_available_event.set() # make sure threading continues and errors are collected + + def fill_slot_data(self) -> Dict[str, Any]: + return { + "death_link": self.options.death_link.value, + "weapon_damage": self.weapon_damage, + "wily_5_weapons": self.wily_5_weapons, + } + + def interpret_slot_data(self, slot_data: Dict[str, Any]) -> Dict[str, Any]: + local_weapon = {int(key): value for key, value in slot_data["weapon_damage"].items()} + local_wily = {int(key): value for key, value in slot_data["wily_5_weapons"].items()} + return {"weapon_damage": local_weapon, "wily_5_weapons": local_wily} + + def modify_multidata(self, multidata: Dict[str, Any]) -> None: + # wait for self.rom_name to be available. + self.rom_name_available_event.wait() + rom_name = getattr(self, "rom_name", None) + # we skip in case of error, so that the original error in the output thread is the one that gets raised + if rom_name: + new_name = base64.b64encode(bytes(self.rom_name)).decode() + multidata["connect_names"][new_name] = multidata["connect_names"][self.player_name] diff --git a/worlds/mm2/client.py b/worlds/mm2/client.py new file mode 100644 index 000000000000..aaa0813c763a --- /dev/null +++ b/worlds/mm2/client.py @@ -0,0 +1,562 @@ +import logging +import time +from enum import IntEnum +from base64 import b64encode +from typing import TYPE_CHECKING, Dict, Tuple, List, Optional, Any +from NetUtils import ClientStatus, color, NetworkItem +from worlds._bizhawk.client import BizHawkClient + +if TYPE_CHECKING: + from worlds._bizhawk.context import BizHawkClientContext, BizHawkClientCommandProcessor + +nes_logger = logging.getLogger("NES") +logger = logging.getLogger("Client") + +MM2_ROBOT_MASTERS_UNLOCKED = 0x8A +MM2_ROBOT_MASTERS_DEFEATED = 0x8B +MM2_ITEMS_ACQUIRED = 0x8C +MM2_LAST_WILY = 0x8D +MM2_RECEIVED_ITEMS = 0x8E +MM2_DEATHLINK = 0x8F +MM2_ENERGYLINK = 0x90 +MM2_RBM_STROBE = 0x91 +MM2_WEAPONS_UNLOCKED = 0x9A +MM2_ITEMS_UNLOCKED = 0x9B +MM2_WEAPON_ENERGY = 0x9C +MM2_E_TANKS = 0xA7 +MM2_LIVES = 0xA8 +MM2_DIFFICULTY = 0xCB +MM2_HEALTH = 0x6C0 +MM2_COMPLETED_STAGES = 0x770 +MM2_CONSUMABLES = 0x780 + +MM2_SFX_QUEUE = 0x580 +MM2_SFX_STROBE = 0x66 + +MM2_CONSUMABLE_TABLE: Dict[int, Tuple[int, int]] = { + # Item: (byte offset, bit mask) + 0x880201: (0, 8), + 0x880202: (16, 1), + 0x880203: (16, 2), + 0x880204: (16, 4), + 0x880205: (16, 8), + 0x880206: (16, 16), + 0x880207: (16, 32), + 0x880208: (16, 64), + 0x880209: (16, 128), + 0x88020A: (20, 1), + 0x88020B: (20, 4), + 0x88020C: (20, 64), + 0x88020D: (21, 1), + 0x88020E: (21, 2), + 0x88020F: (21, 4), + 0x880210: (24, 1), + 0x880211: (24, 2), + 0x880212: (24, 4), + 0x880213: (28, 1), + 0x880214: (28, 2), + 0x880215: (28, 4), + 0x880216: (33, 4), + 0x880217: (33, 8), + 0x880218: (37, 8), + 0x880219: (37, 16), + 0x88021A: (38, 1), + 0x88021B: (38, 2), + 0x880227: (38, 4), + 0x880228: (38, 32), + 0x880229: (38, 128), + 0x88022A: (39, 4), + 0x88022B: (39, 2), + 0x88022C: (39, 1), + 0x88022D: (38, 64), + 0x88022E: (38, 16), + 0x88022F: (38, 8), + 0x88021C: (39, 32), + 0x88021D: (39, 64), + 0x88021E: (39, 128), + 0x88021F: (41, 16), + 0x880220: (42, 2), + 0x880221: (42, 4), + 0x880222: (42, 8), + 0x880223: (46, 1), + 0x880224: (46, 2), + 0x880225: (46, 4), + 0x880226: (46, 8), +} + + +class MM2EnergyLinkType(IntEnum): + Life = 0 + AtomicFire = 1 + AirShooter = 2 + LeafShield = 3 + BubbleLead = 4 + QuickBoomerang = 5 + TimeStopper = 6 + MetalBlade = 7 + CrashBomber = 8 + Item1 = 9 + Item2 = 10 + Item3 = 11 + OneUP = 12 + + +request_to_name: Dict[str, str] = { + "HP": "health", + "AF": "Atomic Fire energy", + "AS": "Air Shooter energy", + "LS": "Leaf Shield energy", + "BL": "Bubble Lead energy", + "QB": "Quick Boomerang energy", + "TS": "Time Stopper energy", + "MB": "Metal Blade energy", + "CB": "Crash Bomber energy", + "I1": "Item 1 energy", + "I2": "Item 2 energy", + "I3": "Item 3 energy", + "1U": "lives" +} + +HP_EXCHANGE_RATE = 500000000 +WEAPON_EXCHANGE_RATE = 250000000 +ONEUP_EXCHANGE_RATE = 14000000000 + + +def cmd_pool(self: "BizHawkClientCommandProcessor") -> None: + """Check the current pool of EnergyLink, and requestable refills from it.""" + if self.ctx.game != "Mega Man 2": + logger.warning("This command can only be used when playing Mega Man 2.") + return + if not self.ctx.server or not self.ctx.slot: + logger.warning("You must be connected to a server to use this command.") + return + energylink = self.ctx.stored_data.get(f"EnergyLink{self.ctx.team}", 0) + health_points = energylink // HP_EXCHANGE_RATE + weapon_points = energylink // WEAPON_EXCHANGE_RATE + lives = energylink // ONEUP_EXCHANGE_RATE + logger.info(f"Healing available: {health_points}\n" + f"Weapon refill available: {weapon_points}\n" + f"Lives available: {lives}") + + +def cmd_request(self: "BizHawkClientCommandProcessor", amount: str, target: str) -> None: + from worlds._bizhawk.context import BizHawkClientContext + """Request a refill from EnergyLink.""" + if self.ctx.game != "Mega Man 2": + logger.warning("This command can only be used when playing Mega Man 2.") + return + if not self.ctx.server or not self.ctx.slot: + logger.warning("You must be connected to a server to use this command.") + return + valid_targets: Dict[str, MM2EnergyLinkType] = { + "HP": MM2EnergyLinkType.Life, + "AF": MM2EnergyLinkType.AtomicFire, + "AS": MM2EnergyLinkType.AirShooter, + "LS": MM2EnergyLinkType.LeafShield, + "BL": MM2EnergyLinkType.BubbleLead, + "QB": MM2EnergyLinkType.QuickBoomerang, + "TS": MM2EnergyLinkType.TimeStopper, + "MB": MM2EnergyLinkType.MetalBlade, + "CB": MM2EnergyLinkType.CrashBomber, + "I1": MM2EnergyLinkType.Item1, + "I2": MM2EnergyLinkType.Item2, + "I3": MM2EnergyLinkType.Item3, + "1U": MM2EnergyLinkType.OneUP + } + if target.upper() not in valid_targets: + logger.warning(f"Unrecognized target {target.upper()}. Available targets: {', '.join(valid_targets.keys())}") + return + ctx = self.ctx + assert isinstance(ctx, BizHawkClientContext) + client = ctx.client_handler + assert isinstance(client, MegaMan2Client) + client.refill_queue.append((valid_targets[target.upper()], int(amount))) + logger.info(f"Restoring {amount} {request_to_name[target.upper()]}.") + + +def cmd_autoheal(self) -> None: + """Enable auto heal from EnergyLink.""" + if self.ctx.game != "Mega Man 2": + logger.warning("This command can only be used when playing Mega Man 2.") + return + if not self.ctx.server or not self.ctx.slot: + logger.warning("You must be connected to a server to use this command.") + return + else: + assert isinstance(self.ctx.client_handler, MegaMan2Client) + if self.ctx.client_handler.auto_heal: + self.ctx.client_handler.auto_heal = False + logger.info(f"Auto healing disabled.") + else: + self.ctx.client_handler.auto_heal = True + logger.info(f"Auto healing enabled.") + + +def get_sfx_writes(sfx: int) -> Tuple[Tuple[int, bytes, str], ...]: + return (MM2_SFX_QUEUE, sfx.to_bytes(1, 'little'), "RAM"), (MM2_SFX_STROBE, 0x01.to_bytes(1, "little"), "RAM") + + +class MegaMan2Client(BizHawkClient): + game = "Mega Man 2" + system = "NES" + patch_suffix = ".apmm2" + item_queue: List[NetworkItem] = [] + pending_death_link: bool = False + # default to true, as we don't want to send a deathlink until Mega Man's HP is initialized once + sending_death_link: bool = True + death_link: bool = False + energy_link: bool = False + rom: Optional[bytes] = None + weapon_energy: int = 0 + health_energy: int = 0 + auto_heal: bool = False + refill_queue: List[Tuple[MM2EnergyLinkType, int]] = [] + last_wily: Optional[int] = None # default to wily 1 + + async def validate_rom(self, ctx: "BizHawkClientContext") -> bool: + from worlds._bizhawk import RequestFailedError, read + from . import MM2World + + try: + game_name, version = (await read(ctx.bizhawk_ctx, [(0x3FFB0, 21, "PRG ROM"), + (0x3FFC8, 3, "PRG ROM")])) + if game_name[:3] != b"MM2" or version != bytes(MM2World.world_version): + if game_name[:3] == b"MM2": + # I think this is an easier check than the other? + older_version = "0.2.1" if version == b"\xFF\xFF\xFF" else f"{version[0]}.{version[1]}.{version[2]}" + logger.warning(f"This Mega Man 2 patch was generated for an different version of the apworld. " + f"Please use that version to connect instead.\n" + f"Patch version: ({older_version})\n" + f"Client version: ({'.'.join([str(i) for i in MM2World.world_version])})") + if "pool" in ctx.command_processor.commands: + ctx.command_processor.commands.pop("pool") + if "request" in ctx.command_processor.commands: + ctx.command_processor.commands.pop("request") + if "autoheal" in ctx.command_processor.commands: + ctx.command_processor.commands.pop("autoheal") + return False + except UnicodeDecodeError: + return False + except RequestFailedError: + return False # Should verify on the next pass + + ctx.game = self.game + self.rom = game_name + ctx.items_handling = 0b111 + ctx.want_slot_data = False + deathlink = (await read(ctx.bizhawk_ctx, [(0x3FFC5, 1, "PRG ROM")]))[0][0] + if deathlink & 0x01: + self.death_link = True + if deathlink & 0x02: + self.energy_link = True + + if self.energy_link: + if "pool" not in ctx.command_processor.commands: + ctx.command_processor.commands["pool"] = cmd_pool + if "request" not in ctx.command_processor.commands: + ctx.command_processor.commands["request"] = cmd_request + if "autoheal" not in ctx.command_processor.commands: + ctx.command_processor.commands["autoheal"] = cmd_autoheal + + return True + + async def set_auth(self, ctx: "BizHawkClientContext") -> None: + if self.rom: + ctx.auth = b64encode(self.rom).decode() + + def on_package(self, ctx: "BizHawkClientContext", cmd: str, args: Dict[str, Any]) -> None: + if cmd == "Bounced": + if "tags" in args: + assert ctx.slot is not None + if "DeathLink" in args["tags"] and args["data"]["source"] != ctx.slot_info[ctx.slot].name: + self.on_deathlink(ctx) + elif cmd == "Retrieved": + if f"MM2_LAST_WILY_{ctx.team}_{ctx.slot}" in args["keys"]: + self.last_wily = args["keys"][f"MM2_LAST_WILY_{ctx.team}_{ctx.slot}"] + elif cmd == "Connected": + if self.energy_link: + ctx.set_notify(f"EnergyLink{ctx.team}") + if ctx.ui: + ctx.ui.enable_energy_link() + + async def send_deathlink(self, ctx: "BizHawkClientContext") -> None: + self.sending_death_link = True + ctx.last_death_link = time.time() + await ctx.send_death("Mega Man was defeated.") + + def on_deathlink(self, ctx: "BizHawkClientContext") -> None: + ctx.last_death_link = time.time() + self.pending_death_link = True + + async def game_watcher(self, ctx: "BizHawkClientContext") -> None: + from worlds._bizhawk import read, write + + if ctx.server is None: + return + + if ctx.slot is None: + return + + # get our relevant bytes + robot_masters_unlocked, robot_masters_defeated, items_acquired, \ + weapons_unlocked, items_unlocked, items_received, \ + completed_stages, consumable_checks, \ + e_tanks, lives, weapon_energy, health, difficulty, death_link_status, \ + energy_link_packet, last_wily = await read(ctx.bizhawk_ctx, [ + (MM2_ROBOT_MASTERS_UNLOCKED, 1, "RAM"), + (MM2_ROBOT_MASTERS_DEFEATED, 1, "RAM"), + (MM2_ITEMS_ACQUIRED, 1, "RAM"), + (MM2_WEAPONS_UNLOCKED, 1, "RAM"), + (MM2_ITEMS_UNLOCKED, 1, "RAM"), + (MM2_RECEIVED_ITEMS, 1, "RAM"), + (MM2_COMPLETED_STAGES, 0xE, "RAM"), + (MM2_CONSUMABLES, 52, "RAM"), + (MM2_E_TANKS, 1, "RAM"), + (MM2_LIVES, 1, "RAM"), + (MM2_WEAPON_ENERGY, 11, "RAM"), + (MM2_HEALTH, 1, "RAM"), + (MM2_DIFFICULTY, 1, "RAM"), + (MM2_DEATHLINK, 1, "RAM"), + (MM2_ENERGYLINK, 1, "RAM"), + (MM2_LAST_WILY, 1, "RAM"), + ]) + + if difficulty[0] not in (0, 1): + return # Game is not initialized + + if not ctx.finished_game and completed_stages[0xD] != 0: + # this sets on credits fade, no real better way to do this + await ctx.send_msgs([{ + "cmd": "StatusUpdate", + "status": ClientStatus.CLIENT_GOAL + }]) + writes = [] + + # deathlink + if self.death_link: + await ctx.update_death_link(self.death_link) + if self.pending_death_link: + writes.append((MM2_DEATHLINK, bytes([0x01]), "RAM")) + self.pending_death_link = False + self.sending_death_link = True + if "DeathLink" in ctx.tags and ctx.last_death_link + 1 < time.time(): + if health[0] == 0x00 and not self.sending_death_link: + await self.send_deathlink(ctx) + elif health[0] != 0x00 and not death_link_status[0]: + self.sending_death_link = False + + if self.last_wily != last_wily[0]: + if self.last_wily is None: + # revalidate last wily from data storage + await ctx.send_msgs([{"cmd": "Set", "key": f"MM2_LAST_WILY_{ctx.team}_{ctx.slot}", "operations": [ + {"operation": "default", "value": 8} + ]}]) + await ctx.send_msgs([{"cmd": "Get", "keys": [f"MM2_LAST_WILY_{ctx.team}_{ctx.slot}"]}]) + elif last_wily[0] == 0: + writes.append((MM2_LAST_WILY, self.last_wily.to_bytes(1, "little"), "RAM")) + else: + # correct our setting + self.last_wily = last_wily[0] + await ctx.send_msgs([{"cmd": "Set", "key": f"MM2_LAST_WILY_{ctx.team}_{ctx.slot}", "operations": [ + {"operation": "replace", "value": self.last_wily} + ]}]) + + # handle receiving items + recv_amount = items_received[0] + if recv_amount < len(ctx.items_received): + item = ctx.items_received[recv_amount] + logging.info('Received %s from %s (%s) (%d/%d in list)' % ( + color(ctx.item_names.lookup_in_game(item.item), 'red', 'bold'), + color(ctx.player_names[item.player], 'yellow'), + ctx.location_names.lookup_in_slot(item.location, item.player), recv_amount, len(ctx.items_received))) + + if item.item & 0x130 == 0: + # Robot Master Weapon + new_weapons = weapons_unlocked[0] | (1 << ((item.item & 0xF) - 1)) + writes.append((MM2_WEAPONS_UNLOCKED, new_weapons.to_bytes(1, 'little'), "RAM")) + writes.extend(get_sfx_writes(0x21)) + elif item.item & 0x30 == 0: + # Robot Master Stage Access + new_stages = robot_masters_unlocked[0] & ~(1 << ((item.item & 0xF) - 1)) + writes.append((MM2_ROBOT_MASTERS_UNLOCKED, new_stages.to_bytes(1, 'little'), "RAM")) + writes.extend(get_sfx_writes(0x3a)) + writes.append((MM2_RBM_STROBE, b"\x01", "RAM")) + elif item.item & 0x20 == 0: + # Items + new_items = items_unlocked[0] | (1 << ((item.item & 0xF) - 1)) + writes.append((MM2_ITEMS_UNLOCKED, new_items.to_bytes(1, 'little'), "RAM")) + writes.extend(get_sfx_writes(0x21)) + else: + # append to the queue, so we handle it later + self.item_queue.append(item) + recv_amount += 1 + writes.append((MM2_RECEIVED_ITEMS, recv_amount.to_bytes(1, 'little'), "RAM")) + + if energy_link_packet[0]: + pickup = energy_link_packet[0] + if pickup in (0x76, 0x77): + # Health pickups + if pickup == 0x77: + value = 2 + else: + value = 10 + exchange_rate = HP_EXCHANGE_RATE + elif pickup in (0x78, 0x79): + # Weapon Energy + if pickup == 0x79: + value = 2 + else: + value = 10 + exchange_rate = WEAPON_EXCHANGE_RATE + elif pickup == 0x7B: + # 1-Up + value = 1 + exchange_rate = ONEUP_EXCHANGE_RATE + else: + # if we managed to pickup something else, we should just fall through + value = 0 + exchange_rate = 0 + contribution = (value * exchange_rate) >> 1 + if contribution: + await ctx.send_msgs([{ + "cmd": "Set", "key": f"EnergyLink{ctx.team}", "slot": ctx.slot, "operations": + [{"operation": "add", "value": contribution}, + {"operation": "max", "value": 0}]}]) + logger.info(f"Deposited {contribution / HP_EXCHANGE_RATE} health into the pool.") + writes.append((MM2_ENERGYLINK, 0x00.to_bytes(1, "little"), "RAM")) + + if self.weapon_energy: + # Weapon Energy + # We parse the whole thing to spread it as thin as possible + current_energy = self.weapon_energy + weapon_energy = bytearray(weapon_energy) + for i, weapon in zip(range(len(weapon_energy)), weapon_energy): + if weapon < 0x1C: + missing = 0x1C - weapon + if missing > self.weapon_energy: + missing = self.weapon_energy + self.weapon_energy -= missing + weapon_energy[i] = weapon + missing + if not self.weapon_energy: + writes.append((MM2_WEAPON_ENERGY, weapon_energy, "RAM")) + break + else: + if current_energy != self.weapon_energy: + writes.append((MM2_WEAPON_ENERGY, weapon_energy, "RAM")) + + if self.health_energy or self.auto_heal: + # Health Energy + # We save this if the player has not taken any damage + current_health = health[0] + if 0 < current_health < 0x1C: + health_diff = 0x1C - current_health + if self.health_energy: + if health_diff > self.health_energy: + health_diff = self.health_energy + self.health_energy -= health_diff + else: + pool = ctx.stored_data.get(f"EnergyLink{ctx.team}", 0) + if health_diff * HP_EXCHANGE_RATE > pool: + health_diff = int(pool // HP_EXCHANGE_RATE) + await ctx.send_msgs([{ + "cmd": "Set", "key": f"EnergyLink{ctx.team}", "slot": ctx.slot, "operations": + [{"operation": "add", "value": -health_diff * HP_EXCHANGE_RATE}, + {"operation": "max", "value": 0}]}]) + current_health += health_diff + writes.append((MM2_HEALTH, current_health.to_bytes(1, 'little'), "RAM")) + + if self.refill_queue: + refill_type, refill_amount = self.refill_queue.pop() + if refill_type == MM2EnergyLinkType.Life: + exchange_rate = HP_EXCHANGE_RATE + elif refill_type == MM2EnergyLinkType.OneUP: + exchange_rate = ONEUP_EXCHANGE_RATE + else: + exchange_rate = WEAPON_EXCHANGE_RATE + pool = ctx.stored_data.get(f"EnergyLink{ctx.team}", 0) + request = exchange_rate * refill_amount + if request > pool: + logger.warning( + f"Not enough energy to fulfill the request. Maximum request: {pool // exchange_rate}") + else: + await ctx.send_msgs([{ + "cmd": "Set", "key": f"EnergyLink{ctx.team}", "slot": ctx.slot, "operations": + [{"operation": "add", "value": -request}, + {"operation": "max", "value": 0}]}]) + if refill_type == MM2EnergyLinkType.Life: + refill_ptr = MM2_HEALTH + elif refill_type == MM2EnergyLinkType.OneUP: + refill_ptr = MM2_LIVES + else: + refill_ptr = MM2_WEAPON_ENERGY - 1 + refill_type + current_value = (await read(ctx.bizhawk_ctx, [(refill_ptr, 1, "RAM")]))[0][0] + new_value = min(0x1C if refill_type != MM2EnergyLinkType.OneUP else 99, current_value + refill_amount) + writes.append((refill_ptr, new_value.to_bytes(1, "little"), "RAM")) + + if len(self.item_queue): + item = self.item_queue.pop(0) + idx = item.item & 0xF + if idx == 0: + # 1-Up + current_lives = lives[0] + if current_lives > 99: + self.item_queue.append(item) + else: + current_lives += 1 + writes.append((MM2_LIVES, current_lives.to_bytes(1, 'little'), "RAM")) + writes.extend(get_sfx_writes(0x42)) + elif idx == 1: + self.weapon_energy += 0xE + writes.extend(get_sfx_writes(0x28)) + elif idx == 2: + self.health_energy += 0xE + writes.extend(get_sfx_writes(0x28)) + elif idx == 3: + # E-Tank + # visuals only allow 4, but we're gonna go up to 9 anyway? May change + current_tanks = e_tanks[0] + if current_tanks < 9: + current_tanks += 1 + writes.append((MM2_E_TANKS, current_tanks.to_bytes(1, 'little'), "RAM")) + writes.extend(get_sfx_writes(0x42)) + else: + self.item_queue.append(item) + + await write(ctx.bizhawk_ctx, writes) + + new_checks = [] + # check for locations + for i in range(8): + flag = 1 << i + if robot_masters_defeated[0] & flag: + wep_id = 0x880101 + i + if wep_id not in ctx.checked_locations: + new_checks.append(wep_id) + + for i in range(3): + flag = 1 << i + if items_acquired[0] & flag: + itm_id = 0x880111 + i + if itm_id not in ctx.checked_locations: + new_checks.append(itm_id) + + for i in range(0xD): + rbm_id = 0x880001 + i + if completed_stages[i] != 0: + if rbm_id not in ctx.checked_locations: + new_checks.append(rbm_id) + + for consumable in MM2_CONSUMABLE_TABLE: + if consumable not in ctx.checked_locations: + is_checked = consumable_checks[MM2_CONSUMABLE_TABLE[consumable][0]] \ + & MM2_CONSUMABLE_TABLE[consumable][1] + if is_checked: + new_checks.append(consumable) + + for new_check_id in new_checks: + ctx.locations_checked.add(new_check_id) + location = ctx.location_names.lookup_in_game(new_check_id) + nes_logger.info( + f'New Check: {location} ({len(ctx.locations_checked)}/' + f'{len(ctx.missing_locations) + len(ctx.checked_locations)})') + await ctx.send_msgs([{"cmd": 'LocationChecks', "locations": [new_check_id]}]) diff --git a/worlds/mm2/color.py b/worlds/mm2/color.py new file mode 100644 index 000000000000..77b39caf3d4f --- /dev/null +++ b/worlds/mm2/color.py @@ -0,0 +1,276 @@ +from typing import Dict, Tuple, List, TYPE_CHECKING, Union +from . import names +from zlib import crc32 +import struct +import logging + +if TYPE_CHECKING: + from . import MM2World + from .rom import MM2ProcedurePatch + +HTML_TO_NES: Dict[str, int] = { + "SNOW": 0x20, + "LINEN": 0x36, + "SEASHELL": 0x36, + "AZURE": 0x3C, + "LAVENDER": 0x33, + "WHITE": 0x30, + "BLACK": 0x0F, + "GREY": 0x00, + "GRAY": 0x00, + "ROYALBLUE": 0x12, + "BLUE": 0x11, + "SKYBLUE": 0x21, + "LIGHTBLUE": 0x31, + "TURQUOISE": 0x2B, + "CYAN": 0x2C, + "AQUAMARINE": 0x3B, + "DARKGREEN": 0x0A, + "GREEN": 0x1A, + "YELLOW": 0x28, + "GOLD": 0x28, + "WHEAT": 0x37, + "TAN": 0x37, + "CHOCOLATE": 0x07, + "BROWN": 0x07, + "SALMON": 0x26, + "ORANGE": 0x27, + "CORAL": 0x36, + "TOMATO": 0x16, + "RED": 0x16, + "PINK": 0x25, + "MAROON": 0x06, + "MAGENTA": 0x24, + "FUSCHIA": 0x24, + "VIOLET": 0x24, + "PLUM": 0x33, + "PURPLE": 0x14, + "THISTLE": 0x34, + "DARKBLUE": 0x01, + "SILVER": 0x10, + "NAVY": 0x02, + "TEAL": 0x1C, + "OLIVE": 0x18, + "LIME": 0x2A, + "AQUA": 0x2C, + # can add more as needed +} + +MM2_COLORS: Dict[str, Tuple[int, int]] = { + names.atomic_fire: (0x28, 0x15), + names.air_shooter: (0x20, 0x11), + names.leaf_shield: (0x20, 0x19), + names.bubble_lead: (0x20, 0x00), + names.time_stopper: (0x34, 0x25), + names.quick_boomerang: (0x34, 0x14), + names.metal_blade: (0x37, 0x18), + names.crash_bomber: (0x20, 0x26), + names.item_1: (0x20, 0x16), + names.item_2: (0x20, 0x16), + names.item_3: (0x20, 0x16), + names.heat_man_stage: (0x28, 0x15), + names.air_man_stage: (0x28, 0x11), + names.wood_man_stage: (0x36, 0x17), + names.bubble_man_stage: (0x30, 0x19), + names.quick_man_stage: (0x28, 0x15), + names.flash_man_stage: (0x30, 0x12), + names.metal_man_stage: (0x28, 0x15), + names.crash_man_stage: (0x30, 0x16) +} + +MM2_KNOWN_COLORS: Dict[str, Tuple[int, int]] = { + **MM2_COLORS, + # Street Fighter, technically + "Hadouken": (0x3C, 0x11), + "Shoryuken": (0x38, 0x16), + # X Series + "Z-Saber": (0x20, 0x16), + # X1 + "Homing Torpedo": (0x3D, 0x37), + "Chameleon Sting": (0x3B, 0x1A), + "Rolling Shield": (0x3A, 0x25), + "Fire Wave": (0x37, 0x26), + "Storm Tornado": (0x34, 0x14), + "Electric Spark": (0x3D, 0x28), + "Boomerang Cutter": (0x3B, 0x2D), + "Shotgun Ice": (0x28, 0x2C), + # X2 + "Crystal Hunter": (0x33, 0x21), + "Bubble Splash": (0x35, 0x28), + "Spin Wheel": (0x34, 0x1B), + "Silk Shot": (0x3B, 0x27), + "Sonic Slicer": (0x27, 0x01), + "Strike Chain": (0x30, 0x23), + "Magnet Mine": (0x28, 0x2D), + "Speed Burner": (0x31, 0x16), + # X3 + "Acid Burst": (0x28, 0x2A), + "Tornado Fang": (0x28, 0x2C), + "Triad Thunder": (0x2B, 0x23), + "Spinning Blade": (0x20, 0x16), + "Ray Splasher": (0x28, 0x17), + "Gravity Well": (0x38, 0x14), + "Parasitic Bomb": (0x31, 0x28), + "Frost Shield": (0x23, 0x2C), +} + +palette_pointers: Dict[str, List[int]] = { + "Mega Buster": [0x3D314], + "Atomic Fire": [0x3D318], + "Air Shooter": [0x3D31C], + "Leaf Shield": [0x3D320], + "Bubble Lead": [0x3D324], + "Quick Boomerang": [0x3D328], + "Time Stopper": [0x3D32C], + "Metal Blade": [0x3D330], + "Crash Bomber": [0x3D334], + "Item 1": [0x3D338], + "Item 2": [0x3D33C], + "Item 3": [0x3D340], + "Heat Man": [0x34B6, 0x344F7], + "Air Man": [0x74B6, 0x344FF], + "Wood Man": [0xB4EC, 0x34507], + "Bubble Man": [0xF4B6, 0x3450F], + "Quick Man": [0x134C8, 0x34517], + "Flash Man": [0x174B6, 0x3451F], + "Metal Man": [0x1B4A4, 0x34527], + "Crash Man": [0x1F4EC, 0x3452F], +} + + +def add_color_to_mm2(name: str, color: Tuple[int, int]) -> None: + """ + Add a color combo for Mega Man 2 to recognize as the color to display for a given item. + For information on available colors: https://www.nesdev.org/wiki/PPU_palettes#2C02 + """ + MM2_KNOWN_COLORS[name] = validate_colors(*color) + + +def extrapolate_color(color: int) -> Tuple[int, int]: + if color > 0x1F: + color_1 = color + color_2 = color_1 - 0x10 + else: + color_2 = color + color_1 = color_2 + 0x10 + return color_1, color_2 + + +def validate_colors(color_1: int, color_2: int, allow_match: bool = False) -> Tuple[int, int]: + # Black should be reserved for outlines, a gray should suffice + if color_1 in [0x0D, 0x0E, 0x0F, 0x1E, 0x2E, 0x3E, 0x1F, 0x2F, 0x3F]: + color_1 = 0x10 + if color_2 in [0x0D, 0x0E, 0x0F, 0x1E, 0x2E, 0x3E, 0x1F, 0x2F, 0x3F]: + color_2 = 0x10 + + # one final check, make sure we don't have two matching + if not allow_match and color_1 == color_2: + color_1 = 0x30 # color 1 to white works with about any paired color + + return color_1, color_2 + + +def get_colors_for_item(name: str) -> Tuple[int, int]: + if name in MM2_KNOWN_COLORS: + return MM2_KNOWN_COLORS[name] + + check_colors = {color: color in name.upper().replace(" ", "") for color in HTML_TO_NES} + colors = [color for color in check_colors if check_colors[color]] + if colors: + # we have at least one color pattern matched + if len(colors) > 1: + # we have at least 2 + color_1 = HTML_TO_NES[colors[0]] + color_2 = HTML_TO_NES[colors[1]] + else: + color_1, color_2 = extrapolate_color(HTML_TO_NES[colors[0]]) + else: + # generate hash + crc_hash = crc32(name.encode("utf-8")) + hash_color = struct.pack("I", crc_hash) + color_1 = hash_color[0] % 0x3F + color_2 = hash_color[1] % 0x3F + + if color_1 < color_2: + temp = color_1 + color_1 = color_2 + color_2 = temp + + color_1, color_2 = validate_colors(color_1, color_2) + + return color_1, color_2 + + +def parse_color(colors: List[str]) -> Tuple[int, int]: + color_a = colors[0] + if color_a.startswith("$"): + color_1 = int(color_a[1:], 16) + else: + # assume it's in our list of colors + color_1 = HTML_TO_NES[color_a.upper()] + + if len(colors) == 1: + color_1, color_2 = extrapolate_color(color_1) + else: + color_b = colors[1] + if color_b.startswith("$"): + color_2 = int(color_b[1:], 16) + else: + color_2 = HTML_TO_NES[color_b.upper()] + return color_1, color_2 + + +def write_palette_shuffle(world: "MM2World", rom: "MM2ProcedurePatch") -> None: + palette_shuffle: Union[int, str] = world.options.palette_shuffle.value + palettes_to_write: Dict[str, Tuple[int, int]] = {} + if isinstance(palette_shuffle, str): + color_sets = palette_shuffle.split(";") + if len(color_sets) == 1: + palette_shuffle = world.options.palette_shuffle.option_none + # singularity is more correct, but this is faster + else: + palette_shuffle = world.options.palette_shuffle.options[color_sets.pop()] + for color_set in color_sets: + if "-" in color_set: + character, color = color_set.split("-") + if character.title() not in palette_pointers: + logging.warning(f"Player {world.multiworld.get_player_name(world.player)} " + f"attempted to set color for unrecognized option {character}") + colors = color.split("|") + real_colors = validate_colors(*parse_color(colors), allow_match=True) + palettes_to_write[character.title()] = real_colors + else: + # If color is provided with no character, assume singularity + colors = color_set.split("|") + real_colors = validate_colors(*parse_color(colors), allow_match=True) + for character in palette_pointers: + palettes_to_write[character] = real_colors + # Now we handle the real values + if palette_shuffle == 1: + shuffled_colors = list(MM2_COLORS.values()) + shuffled_colors.append((0x2C, 0x11)) # Mega Buster + world.random.shuffle(shuffled_colors) + for character in palette_pointers: + if character not in palettes_to_write: + palettes_to_write[character] = shuffled_colors.pop() + elif palette_shuffle > 1: + if palette_shuffle == 2: + for character in palette_pointers: + if character not in palettes_to_write: + real_colors = validate_colors(world.random.randint(0, 0x3F), world.random.randint(0, 0x3F)) + palettes_to_write[character] = real_colors + else: + # singularity + real_colors = validate_colors(world.random.randint(0, 0x3F), world.random.randint(0, 0x3F)) + for character in palette_pointers: + if character not in palettes_to_write: + palettes_to_write[character] = real_colors + + for character in palettes_to_write: + for pointer in palette_pointers[character]: + rom.write_bytes(pointer, bytes(palettes_to_write[character])) + + if character == "Atomic Fire": + # special case, we need to update Atomic Fire's flashing routine + rom.write_byte(0x3DE4A, palettes_to_write[character][1]) + rom.write_byte(0x3DE4C, palettes_to_write[character][1]) diff --git a/worlds/mm2/data/mm2_basepatch.bsdiff4 b/worlds/mm2/data/mm2_basepatch.bsdiff4 new file mode 100644 index 000000000000..8f3c17c3c7af Binary files /dev/null and b/worlds/mm2/data/mm2_basepatch.bsdiff4 differ diff --git a/worlds/mm2/docs/en_Mega Man 2.md b/worlds/mm2/docs/en_Mega Man 2.md new file mode 100644 index 000000000000..2c9504f5d00f --- /dev/null +++ b/worlds/mm2/docs/en_Mega Man 2.md @@ -0,0 +1,114 @@ +# Mega Man 2 + +## Where is the options page? + +The [player options page for this game](../player-options) contains all the options you need to configure and export a +config file. + +## What does randomization do to this game? + +Weapons received from Robot Masters, access to each individual stage, and Items from Dr. Light are randomized +into the multiworld. Access to the Wily Stages is locked behind receiving Item 1, 2, and 3. The game is completed when +viewing the ending sequence after defeating the Alien. + +## What Mega Man 2 items can appear in other players' worlds? +- Robot Master weapons +- Robot Master Access Codes (stage access) +- Items 1/2/3 +- 1-Ups +- E-Tanks +- Health Energy (L) +- Weapon Energy (L) + +## What is considered a location check in Mega Man 2? +- The defeat of a Robot Master or Wily Boss +- Receiving a weapon or item from Dr. Light +- Optionally, 1-Ups and E-Tanks present within stages +- Optionally, Weapon and Health Energy pickups present within stages + +## When the player receives an item, what happens? +A sound effect will play based on the type of item received, and the effects of the item will be immediately applied, +such as unlocking the use of a weapon mid-stage. If the effects of the item cannot be fully applied (such as receiving +Health Energy while at full health), the leftover amount is withheld until it can be applied. + +## What is EnergyLink? +EnergyLink is an energy storage supported by certain games that is shared across all worlds in a multiworld. In Mega Man + 2, when enabled, drops from enemies are not applied directly to Mega Man and are instead deposited into the EnergyLink. +Half of the energy that would be gained is lost upon transfer to the EnergyLink. + +Energy from the EnergyLink storage can be converted into health, weapon energy, and lives at different conversion rates. +You can find out how much of each type you can pull using the `/pool` command in the client. Additionally, you can have it +automatically pull from the EnergyLink storage to keep Mega Man healed using the `/autoheal` command in the client. +Finally, you can use the `/request` command to request a certain type of energy from the storage. + +## Plando Palettes +The palette shuffle option supports specifying a specific palette for a given weapon/Robot Master. The format for doing +so is `Character-Color1|Color2;Option`. Character is the individual that this should apply to, and can only be one of +the following: +- Mega Buster +- Atomic Fire +- Air Shooter +- Leaf Shield +- Bubble Lead +- Quick Boomerang +- Time Stopper +- Metal Blade +- Crash Bomber +- Item 1 +- Item 2 +- Item 3 +- Heat Man +- Air Man +- Wood Man +- Bubble Man +- Quick Man +- Flash Man +- Metal Man +- Crash Man + +Colors attempt to map a list of HTML-defined colors to what the NES can render. A full list of applicable colors can be +found [here](https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/mm2/color.py#L11). Alternatively, colors can +be supplied directly using `$xx` format. A full list of NES colors can be found [here](https://www.nesdev.org/wiki/PPU_palettes#2C02). + +You can also pass only one color (such as `Mega Buster-Red`) and it will interpret a second color based off of the color +given. Additionally, passing only colors (such as `Red|Blue`) and not any specific boss/weapon will apply that color to +all weapons/bosses that did not have a prior color specified. + +The option is the method to be used to set the palettes of the remaining bosses/weapons, and will not overwrite any +plando placements. + +## Plando Weaknesses +Plando Weaknesses allows you to override the amount of damage a boss should take from a given weapon, ignoring prior +weaknesses generated by strict/random weakness options. Formatting for this is as follows: +```yaml +plando_weakness: + Air Man: + Atomic Fire: 0 + Bubble Lead: 4 +``` +This would cause Air Man to take 4 damage from Bubble Lead, and 0 from Atomic Fire. + +Note: it is possible that plando weakness is not be respected should the plando create a situation in which the game +becomes impossible to complete. In this situation, the damage would be boosted to the minimum required to defeat the +Robot Master. + + +## Unique Local Commands +- `/pool` Only present with EnergyLink, prints the max amount of each type of request that could be fulfilled. +- `/autoheal` Only present with EnergyLink, will automatically drain energy from the EnergyLink in order to +restore Mega Man's health. +- `/request ` Only present with EnergyLink, sends a request of a certain type of energy to be pulled from +the EnergyLink. Types are as follows: + - `HP` Health + - `AF` Atomic Fire + - `AS` Air Shooter + - `LS` Leaf Shield + - `BL` Bubble Lead + - `QB` Quick Boomerang + - `TS` Time Stopper + - `MB` Metal Blade + - `CB` Crash Bomber + - `I1` Item 1 + - `I2` Item 2 + - `I3` Item 3 + - `1U` Lives \ No newline at end of file diff --git a/worlds/mm2/docs/setup_en.md b/worlds/mm2/docs/setup_en.md new file mode 100644 index 000000000000..3b8f833b9967 --- /dev/null +++ b/worlds/mm2/docs/setup_en.md @@ -0,0 +1,53 @@ +# Mega Man 2 Setup Guide + +## Required Software + +- [Archipelago](https://github.com/ArchipelagoMW/Archipelago/releases) +- An English Mega Man 2 ROM. Alternatively, the [Mega Man Legacy Collection](https://store.steampowered.com/app/363440/Mega_Man_Legacy_Collection/) on Steam. +- [BizHawk](https://tasvideos.org/BizHawk/ReleaseHistory) 2.7 or later + +### Configuring Bizhawk + +Once you have installed BizHawk, open `EmuHawk.exe` and change the following settings: + +- If you're using BizHawk 2.7 or 2.8, go to `Config > Customize`. On the Advanced tab, switch the Lua Core from +`NLua+KopiLua` to `Lua+LuaInterface`, then restart EmuHawk. (If you're using BizHawk 2.9, you can skip this step.) +- Under `Config > Customize`, check the "Run in background" option to prevent disconnecting from the client while you're +tabbed out of EmuHawk. +- Open a `.nes` file in EmuHawk and go to `Config > Controllers…` to configure your inputs. If you can't click +`Controllers…`, load any `.nes` ROM first. +- Consider clearing keybinds in `Config > Hotkeys…` if you don't intend to use them. Select the keybind and press Esc to +clear it. + +## Generating and Patching a Game + +1. Create your options file (YAML). You can make one on the +[Mega Man 2 options page](../../../games/Mega%20Man%202/player-options). +2. Follow the general Archipelago instructions for [generating a game](../../Archipelago/setup/en#generating-a-game). +This will generate an output file for you. Your patch file will have the `.apmm2` file extension. +3. Open `ArchipelagoLauncher.exe` +4. Select "Open Patch" on the left side and select your patch file. +5. If this is your first time patching, you will be prompted to locate your vanilla ROM. If you are using the Legacy +Collection, provide `Proteus.exe` in place of your rom. +6. A patched `.nes` file will be created in the same place as the patch file. +7. On your first time opening a patch with BizHawk Client, you will also be asked to locate `EmuHawk.exe` in your +BizHawk install. + +## Connecting to a Server + +By default, opening a patch file will do steps 1-5 below for you automatically. Even so, keep them in your memory just +in case you have to close and reopen a window mid-game for some reason. + +1. Mega Man 2 uses Archipelago's BizHawk Client. If the client isn't still open from when you patched your game, +you can re-open it from the launcher. +2. Ensure EmuHawk is running the patched ROM. +3. In EmuHawk, go to `Tools > Lua Console`. This window must stay open while playing. +4. In the Lua Console window, go to `Script > Open Script…`. +5. Navigate to your Archipelago install folder and open `data/lua/connector_bizhawk_generic.lua`. +6. The emulator and client will eventually connect to each other. The BizHawk Client window should indicate that it +connected and recognized Mega Man 2. +7. To connect the client to the server, enter your room's address and port (e.g. `archipelago.gg:38281`) into the +top text field of the client and click Connect. + +You should now be able to receive and send items. You'll need to do these steps every time you want to reconnect. It is +perfectly safe to make progress offline; everything will re-sync when you reconnect. diff --git a/worlds/mm2/items.py b/worlds/mm2/items.py new file mode 100644 index 000000000000..e644b171dded --- /dev/null +++ b/worlds/mm2/items.py @@ -0,0 +1,72 @@ +from BaseClasses import Item +from typing import NamedTuple, Dict +from . import names + + +class ItemData(NamedTuple): + code: int + progression: bool + useful: bool = False # primarily use this for incredibly useful items of their class, like Metal Blade + skip_balancing: bool = False + + +class MM2Item(Item): + game = "Mega Man 2" + + +robot_master_weapon_table = { + names.atomic_fire: ItemData(0x880001, True), + names.air_shooter: ItemData(0x880002, True), + names.leaf_shield: ItemData(0x880003, True), + names.bubble_lead: ItemData(0x880004, True), + names.quick_boomerang: ItemData(0x880005, True), + names.time_stopper: ItemData(0x880006, True, True), + names.metal_blade: ItemData(0x880007, True, True), + names.crash_bomber: ItemData(0x880008, True), +} + +stage_access_table = { + names.heat_man_stage: ItemData(0x880101, True), + names.air_man_stage: ItemData(0x880102, True), + names.wood_man_stage: ItemData(0x880103, True), + names.bubble_man_stage: ItemData(0x880104, True), + names.quick_man_stage: ItemData(0x880105, True), + names.flash_man_stage: ItemData(0x880106, True), + names.metal_man_stage: ItemData(0x880107, True), + names.crash_man_stage: ItemData(0x880108, True), +} + +item_item_table = { + names.item_1: ItemData(0x880011, True, True, True), + names.item_2: ItemData(0x880012, True, True, True), + names.item_3: ItemData(0x880013, True, True, True) +} + +filler_item_table = { + names.one_up: ItemData(0x880020, False), + names.weapon_energy: ItemData(0x880021, False), + names.health_energy: ItemData(0x880022, False), + names.e_tank: ItemData(0x880023, False, True), +} + +filler_item_weights = { + names.one_up: 1, + names.weapon_energy: 4, + names.health_energy: 1, + names.e_tank: 2, +} + +item_table = { + **robot_master_weapon_table, + **stage_access_table, + **item_item_table, + **filler_item_table, +} + +item_names = { + "Weapons": {name for name in robot_master_weapon_table.keys()}, + "Stages": {name for name in stage_access_table.keys()}, + "Items": {name for name in item_item_table.keys()} +} + +lookup_item_to_id: Dict[str, int] = {item_name: data.code for item_name, data in item_table.items()} diff --git a/worlds/mm2/locations.py b/worlds/mm2/locations.py new file mode 100644 index 000000000000..4807d25d6992 --- /dev/null +++ b/worlds/mm2/locations.py @@ -0,0 +1,239 @@ +from BaseClasses import Location, Region +from typing import Dict, Tuple, Optional +from . import names + + +class MM2Location(Location): + game = "Mega Man 2" + + +class MM2Region(Region): + game = "Mega Man 2" + + +heat_man_locations: Dict[str, Optional[int]] = { + names.heat_man: 0x880001, + names.atomic_fire_get: 0x880101, + names.item_1_get: 0x880111, +} + +air_man_locations: Dict[str, Optional[int]] = { + names.air_man: 0x880002, + names.air_shooter_get: 0x880102, + names.item_2_get: 0x880112 +} + +wood_man_locations: Dict[str, Optional[int]] = { + names.wood_man: 0x880003, + names.leaf_shield_get: 0x880103 +} + +bubble_man_locations: Dict[str, Optional[int]] = { + names.bubble_man: 0x880004, + names.bubble_lead_get: 0x880104 +} + +quick_man_locations: Dict[str, Optional[int]] = { + names.quick_man: 0x880005, + names.quick_boomerang_get: 0x880105, +} + +flash_man_locations: Dict[str, Optional[int]] = { + names.flash_man: 0x880006, + names.time_stopper_get: 0x880106, + names.item_3_get: 0x880113, +} + +metal_man_locations: Dict[str, Optional[int]] = { + names.metal_man: 0x880007, + names.metal_blade_get: 0x880107 +} + +crash_man_locations: Dict[str, Optional[int]] = { + names.crash_man: 0x880008, + names.crash_bomber_get: 0x880108 +} + +wily_1_locations: Dict[str, Optional[int]] = { + names.wily_1: 0x880009, + names.wily_stage_1: None +} + +wily_2_locations: Dict[str, Optional[int]] = { + names.wily_2: 0x88000A, + names.wily_stage_2: None +} + +wily_3_locations: Dict[str, Optional[int]] = { + names.wily_3: 0x88000B, + names.wily_stage_3: None +} + +wily_4_locations: Dict[str, Optional[int]] = { + names.wily_4: 0x88000C, + names.wily_stage_4: None +} + +wily_5_locations: Dict[str, Optional[int]] = { + names.wily_5: 0x88000D, + names.wily_stage_5: None +} + +wily_6_locations: Dict[str, Optional[int]] = { + names.dr_wily: None +} + +etank_1ups: Dict[str, Dict[str, Optional[int]]] = { + "Heat Man Stage": { + names.heat_man_c1: 0x880201, + }, + "Quick Man Stage": { + names.quick_man_c1: 0x880202, + names.quick_man_c2: 0x880203, + names.quick_man_c3: 0x880204, + names.quick_man_c7: 0x880208, + }, + "Flash Man Stage": { + names.flash_man_c2: 0x88020B, + names.flash_man_c6: 0x88020F, + }, + "Metal Man Stage": { + names.metal_man_c1: 0x880210, + names.metal_man_c2: 0x880211, + names.metal_man_c3: 0x880212, + }, + "Crash Man Stage": { + names.crash_man_c2: 0x880214, + names.crash_man_c3: 0x880215, + }, + "Wily Stage 1": { + names.wily_1_c1: 0x880216, + }, + "Wily Stage 2": { + names.wily_2_c3: 0x88021A, + names.wily_2_c4: 0x88021B, + names.wily_2_c5: 0x88021C, + names.wily_2_c6: 0x88021D, + }, + "Wily Stage 3": { + names.wily_3_c2: 0x880220, + }, + "Wily Stage 4": { + names.wily_4_c3: 0x880225, + names.wily_4_c4: 0x880226, + } +} + +energy_pickups: Dict[str, Dict[str, Optional[int]]] = { + "Quick Man Stage": { + names.quick_man_c4: 0x880205, + names.quick_man_c5: 0x880206, + names.quick_man_c6: 0x880207, + names.quick_man_c8: 0x880209, + }, + "Flash Man Stage": { + names.flash_man_c1: 0x88020A, + names.flash_man_c3: 0x88020C, + names.flash_man_c4: 0x88020D, + names.flash_man_c5: 0x88020E, + }, + "Crash Man Stage": { + names.crash_man_c1: 0x880213, + }, + "Wily Stage 1": { + names.wily_1_c2: 0x880217, + }, + "Wily Stage 2": { + names.wily_2_c1: 0x880218, + names.wily_2_c2: 0x880219, + names.wily_2_c7: 0x88021E, + names.wily_2_c8: 0x880227, + names.wily_2_c9: 0x880228, + names.wily_2_c10: 0x880229, + names.wily_2_c11: 0x88022A, + names.wily_2_c12: 0x88022B, + names.wily_2_c13: 0x88022C, + names.wily_2_c14: 0x88022D, + names.wily_2_c15: 0x88022E, + names.wily_2_c16: 0x88022F, + }, + "Wily Stage 3": { + names.wily_3_c1: 0x88021F, + names.wily_3_c3: 0x880221, + names.wily_3_c4: 0x880222, + }, + "Wily Stage 4": { + names.wily_4_c1: 0x880223, + names.wily_4_c2: 0x880224, + } +} + +mm2_regions: Dict[str, Tuple[Tuple[str, ...], Dict[str, Optional[int]], Optional[str]]] = { + "Heat Man Stage": ((names.heat_man_stage,), heat_man_locations, None), + "Air Man Stage": ((names.air_man_stage,), air_man_locations, None), + "Wood Man Stage": ((names.wood_man_stage,), wood_man_locations, None), + "Bubble Man Stage": ((names.bubble_man_stage,), bubble_man_locations, None), + "Quick Man Stage": ((names.quick_man_stage,), quick_man_locations, None), + "Flash Man Stage": ((names.flash_man_stage,), flash_man_locations, None), + "Metal Man Stage": ((names.metal_man_stage,), metal_man_locations, None), + "Crash Man Stage": ((names.crash_man_stage,), crash_man_locations, None), + "Wily Stage 1": ((names.item_1, names.item_2, names.item_3), wily_1_locations, None), + "Wily Stage 2": ((names.wily_stage_1,), wily_2_locations, "Wily Stage 1"), + "Wily Stage 3": ((names.wily_stage_2,), wily_3_locations, "Wily Stage 2"), + "Wily Stage 4": ((names.wily_stage_3,), wily_4_locations, "Wily Stage 3"), + "Wily Stage 5": ((names.wily_stage_4,), wily_5_locations, "Wily Stage 4"), + "Wily Stage 6": ((names.wily_stage_5,), wily_6_locations, "Wily Stage 5") +} + +location_table: Dict[str, Optional[int]] = { + **heat_man_locations, + **air_man_locations, + **wood_man_locations, + **bubble_man_locations, + **quick_man_locations, + **flash_man_locations, + **metal_man_locations, + **crash_man_locations, + **wily_1_locations, + **wily_2_locations, + **wily_3_locations, + **wily_4_locations, + **wily_5_locations, +} + +for table in etank_1ups: + location_table.update(etank_1ups[table]) + +for table in energy_pickups: + location_table.update(energy_pickups[table]) + +location_groups = { + "Get Equipped": { + names.atomic_fire_get, + names.air_shooter_get, + names.leaf_shield_get, + names.bubble_lead_get, + names.quick_boomerang_get, + names.time_stopper_get, + names.metal_blade_get, + names.crash_bomber_get, + names.item_1_get, + names.item_2_get, + names.item_3_get + }, + "Heat Man Stage": {*heat_man_locations.keys(), *etank_1ups["Heat Man Stage"].keys()}, + "Air Man Stage": {*air_man_locations.keys()}, + "Wood Man Stage": {*wood_man_locations.keys()}, + "Bubble Man Stage": {*bubble_man_locations.keys()}, + "Quick Man Stage": {*quick_man_locations.keys(), *etank_1ups["Quick Man Stage"].keys(), + *energy_pickups["Quick Man Stage"].keys()}, + "Flash Man Stage": {*flash_man_locations.keys(), *etank_1ups["Flash Man Stage"].keys(), + *energy_pickups["Flash Man Stage"].keys()}, + "Metal Man Stage": {*metal_man_locations.keys(), *etank_1ups["Metal Man Stage"].keys()}, + "Crash Man Stage": {*crash_man_locations.keys(), *etank_1ups["Crash Man Stage"].keys(), + *energy_pickups["Crash Man Stage"].keys()}, + "Wily 2 Weapon Energy": {names.wily_2_c8, names.wily_2_c9, names.wily_2_c10, names.wily_2_c11, names.wily_2_c12, + names.wily_2_c13, names.wily_2_c14, names.wily_2_c15, names.wily_2_c16} +} + +lookup_location_to_id: Dict[str, int] = {location: idx for location, idx in location_table.items() if idx is not None} diff --git a/worlds/mm2/names.py b/worlds/mm2/names.py new file mode 100644 index 000000000000..fbbea85f0317 --- /dev/null +++ b/worlds/mm2/names.py @@ -0,0 +1,114 @@ +# Robot Master Weapons +crash_bomber = "Crash Bomber" +metal_blade = "Metal Blade" +quick_boomerang = "Quick Boomerang" +bubble_lead = "Bubble Lead" +atomic_fire = "Atomic Fire" +leaf_shield = "Leaf Shield" +time_stopper = "Time Stopper" +air_shooter = "Air Shooter" + +# Stage Entry +crash_man_stage = "Crash Man Access Codes" +metal_man_stage = "Metal Man Access Codes" +quick_man_stage = "Quick Man Access Codes" +bubble_man_stage = "Bubble Man Access Codes" +heat_man_stage = "Heat Man Access Codes" +wood_man_stage = "Wood Man Access Codes" +flash_man_stage = "Flash Man Access Codes" +air_man_stage = "Air Man Access Codes" + +# The Items +item_1 = "Item 1 - Propeller" +item_2 = "Item 2 - Rocket" +item_3 = "Item 3 - Bouncy" + +# Misc. Items +one_up = "1-Up" +weapon_energy = "Weapon Energy (L)" +health_energy = "Health Energy (L)" +e_tank = "E-Tank" + +# Locations +crash_man = "Crash Man - Defeated" +metal_man = "Metal Man - Defeated" +quick_man = "Quick Man - Defeated" +bubble_man = "Bubble Man - Defeated" +heat_man = "Heat Man - Defeated" +wood_man = "Wood Man - Defeated" +flash_man = "Flash Man - Defeated" +air_man = "Air Man - Defeated" +crash_bomber_get = "Crash Bomber - Received" +metal_blade_get = "Metal Blade - Received" +quick_boomerang_get = "Quick Boomerang - Received" +bubble_lead_get = "Bubble Lead - Received" +atomic_fire_get = "Atomic Fire - Received" +leaf_shield_get = "Leaf Shield - Received" +time_stopper_get = "Time Stopper - Received" +air_shooter_get = "Air Shooter - Received" +item_1_get = "Item 1 - Received" +item_2_get = "Item 2 - Received" +item_3_get = "Item 3 - Received" +wily_1 = "Mecha Dragon - Defeated" +wily_2 = "Picopico-kun - Defeated" +wily_3 = "Guts Tank - Defeated" +wily_4 = "Boobeam Trap - Defeated" +wily_5 = "Wily Machine 2 - Defeated" +dr_wily = "Dr. Wily (Alien) - Defeated" + +# Wily Stage Event Items +wily_stage_1 = "Wily Stage 1 - Completed" +wily_stage_2 = "Wily Stage 2 - Completed" +wily_stage_3 = "Wily Stage 3 - Completed" +wily_stage_4 = "Wily Stage 4 - Completed" +wily_stage_5 = "Wily Stage 5 - Completed" + +# Consumable Locations +heat_man_c1 = "Heat Man Stage - 1-Up" # 3, requires Yoku jumps or Item 2 +flash_man_c1 = "Flash Man Stage - Health Energy 1" # 0 +flash_man_c2 = "Flash Man Stage - 1-Up" # 2, requires any Item +flash_man_c3 = "Flash Man Stage - Health Energy 2" # 6, requires Crash Bomber +flash_man_c4 = "Flash Man Stage - Weapon Energy 1" # 8, requires Crash Bomber +flash_man_c5 = "Flash Man Stage - Health Energy 3" # 9 +flash_man_c6 = "Flash Man Stage - E-Tank" # 10 +quick_man_c1 = "Quick Man Stage - 1-Up 1" # 0, needs any Item +quick_man_c2 = "Quick Man Stage - E-Tank" # 1, requires allow lasers or Time Stopper +quick_man_c3 = "Quick Man Stage - 1-Up 2" # 2, requires allow lasers or Time Stopper +quick_man_c4 = "Quick Man Stage - Weapon Energy 1" # 3, requires allow lasers or Time Stopper +quick_man_c5 = "Quick Man Stage - Weapon Energy 2" # 4, requires allow lasers or Time Stopper +quick_man_c6 = "Quick Man Stage - Health Energy" # 5, requires allow lasers or Time Stopper +quick_man_c7 = "Quick Man Stage - 1-Up 3" # 6, requires allow lasers or Time Stopper +quick_man_c8 = "Quick Man Stage - Weapon Energy 3" # 7, requires allow lasers or Time Stopper +metal_man_c1 = "Metal Man Stage - E-Tank 1" # 0 +metal_man_c2 = "Metal Man Stage - 1-Up" # 1, needs Item 1/2 +metal_man_c3 = "Metal Man Stage - E-Tank 2" # 2, needs Item 1/2 (without putting dying in logic at least) +crash_man_c1 = "Crash Man Stage - Health Energy" # 0 +crash_man_c2 = "Crash Man Stage - E-Tank" # 1 +crash_man_c3 = "Crash Man Stage - 1-Up" # 2, any Item +wily_1_c1 = "Wily Stage 1 - 1-Up" # 10 +wily_1_c2 = "Wily Stage 1 - Weapon Energy 1" # 11 +wily_2_c1 = "Wily Stage 2 - Weapon Energy 1" # 11 +wily_2_c2 = "Wily Stage 2 - Weapon Energy 2" # 12 +wily_2_c3 = "Wily Stage 2 - E-Tank 1" # 16 +wily_2_c4 = "Wily Stage 2 - 1-Up 1" # 17 +# 18 - 27 are all small weapon energies, might force these local junk? +wily_2_c8 = "Wily Stage 2 - Weapon Energy 3" # 18 +wily_2_c9 = "Wily Stage 2 - Weapon Energy 4" # 19 +wily_2_c10 = "Wily Stage 2 - Weapon Energy 5" # 20 +wily_2_c11 = "Wily Stage 2 - Weapon Energy 6" # 21 +wily_2_c12 = "Wily Stage 2 - Weapon Energy 7" # 22 +wily_2_c13 = "Wily Stage 2 - Weapon Energy 8" # 23 +wily_2_c14 = "Wily Stage 2 - Weapon Energy 9" # 24 +wily_2_c15 = "Wily Stage 2 - Weapon Energy 10" # 25 +wily_2_c16 = "Wily Stage 2 - Weapon Energy 11" # 26 +wily_2_c5 = "Wily Stage 2 - 1-Up 2" # 29, requires Crash Bomber +wily_2_c6 = "Wily Stage 2 - E-Tank 2" # 30, requires Crash Bomber +wily_2_c7 = "Wily Stage 2 - Health Energy" # 31, item 2 (already required to reach wily 2) +wily_3_c1 = "Wily Stage 3 - Weapon Energy 1" # 12, requires Crash Bomber +wily_3_c2 = "Wily Stage 3 - E-Tank" # 17, requires Crash Bomber +wily_3_c3 = "Wily Stage 3 - Weapon Energy 2" # 18 +wily_3_c4 = "Wily Stage 3 - Weapon Energy 3" # 19 +wily_4_c1 = "Wily Stage 4 - Weapon Energy 1" # 16 +wily_4_c2 = "Wily Stage 4 - Weapon Energy 2" # 17 +wily_4_c3 = "Wily Stage 4 - 1-Up 1" # 18 +wily_4_c4 = "Wily Stage 4 - E-Tank 1" # 19 diff --git a/worlds/mm2/options.py b/worlds/mm2/options.py new file mode 100644 index 000000000000..2d90395cacda --- /dev/null +++ b/worlds/mm2/options.py @@ -0,0 +1,229 @@ +from dataclasses import dataclass + +from Options import Choice, Toggle, DeathLink, DefaultOnToggle, TextChoice, Range, OptionDict, PerGameCommonOptions +from schema import Schema, And, Use, Optional + +bosses = { + "Heat Man": 0, + "Air Man": 1, + "Wood Man": 2, + "Bubble Man": 3, + "Quick Man": 4, + "Flash Man": 5, + "Metal Man": 6, + "Crash Man": 7, + "Mecha Dragon": 8, + "Picopico-kun": 9, + "Guts Tank": 10, + "Boobeam Trap": 11, + "Wily Machine 2": 12, + "Alien": 13 +} + +weapons_to_id = { + "Mega Buster": 0, + "Atomic Fire": 1, + "Air Shooter": 2, + "Leaf Shield": 3, + "Bubble Lead": 4, + "Quick Boomerang": 5, + "Metal Blade": 7, + "Crash Bomber": 6, + "Time Stopper": 8, +} + + +class EnergyLink(Toggle): + """ + Enables EnergyLink support. + When enabled, pickups dropped from enemies are sent to the EnergyLink pool, and healing/weapon energy/1-Ups can + be requested from the EnergyLink pool. + Some of the energy sent to the pool will be lost on transfer. + """ + display_name = "EnergyLink" + + +class StartingRobotMaster(Choice): + """ + The initial stage unlocked at the start. + """ + display_name = "Starting Robot Master" + option_heat_man = 0 + option_air_man = 1 + option_wood_man = 2 + option_bubble_man = 3 + option_quick_man = 4 + option_flash_man = 5 + option_metal_man = 6 + option_crash_man = 7 + default = "random" + + +class YokuJumps(Toggle): + """ + When enabled, the player is expected to be able to perform the yoku block sequence in Heat Man's + stage without Item 2. + """ + display_name = "Yoku Block Jumps" + + +class EnableLasers(Toggle): + """ + When enabled, the player is expected to complete (and acquire items within) the laser sections of Quick Man's + stage without the Time Stopper. + """ + display_name = "Enable Lasers" + + +class Consumables(Choice): + """ + When enabled, e-tanks/1-ups/health/weapon energy will be added to the pool of items and included as checks. + E-Tanks and 1-Ups add 20 checks to the pool. + Weapon/Health Energy add 27 checks to the pool. + """ + display_name = "Consumables" + option_none = 0 + option_1up_etank = 1 + option_weapon_health = 2 + option_all = 3 + default = 1 + alias_true = 3 + alias_false = 0 + + @classmethod + def get_option_name(cls, value: int) -> str: + if value == 1: + return "1-Ups/E-Tanks" + if value == 2: + return "Weapon/Health Energy" + return super().get_option_name(value) + + +class Quickswap(DefaultOnToggle): + """ + When enabled, the player can quickswap through all received weapons by pressing Select. + """ + display_name = "Quickswap" + + +class PaletteShuffle(TextChoice): + """ + Change the color of Mega Man and the Robot Masters. + None: The palettes are unchanged. + Shuffled: Palette colors are shuffled amongst the robot masters. + Randomized: Random (usually good) palettes are generated for each robot master. + Singularity: one palette is generated and used for all robot masters. + Supports custom palettes using HTML named colors in the + following format: Mega Buster-Lavender|Violet;randomized + The first value is the character whose palette you'd like to define, then separated by - is a set of 2 colors for + that character. separate every color with a pipe, and separate every character as well as the remaining shuffle with + a semicolon. + """ + display_name = "Palette Shuffle" + option_none = 0 + option_shuffled = 1 + option_randomized = 2 + option_singularity = 3 + + +class EnemyWeaknesses(Toggle): + """ + Randomizes the damage dealt to enemies by weapons. Friender will always take damage from the buster. + """ + display_name = "Random Enemy Weaknesses" + + +class StrictWeaknesses(Toggle): + """ + Only your starting Robot Master will take damage from the Mega Buster, the rest must be defeated with weapons. + Weapons that only do 1-3 damage to bosses no longer deal damage (aside from Alien). + """ + display_name = "Strict Boss Weaknesses" + + +class RandomWeaknesses(Choice): + """ + None: Bosses will have their regular weaknesses. + Shuffled: Weapon damage will be shuffled amongst the weapons, so Metal Blade may do Bubble Lead damage. + Time Stopper will deplete half of a random Robot Master's HP. + Randomized: Weapon damage will be fully randomized. + """ + display_name = "Random Boss Weaknesses" + option_none = 0 + option_shuffled = 1 + option_randomized = 2 + alias_false = 0 + alias_true = 2 + + +class Wily5Requirement(Range): + """Change the number of Robot Masters that are required to be defeated for + the teleporter to the Wily Machine to appear.""" + display_name = "Wily 5 Requirement" + default = 8 + range_start = 1 + range_end = 8 + + +class WeaknessPlando(OptionDict): + """ + Specify specific damage numbers for boss damage. Can be used even without strict/random weaknesses. + plando_weakness: + Robot Master: + Weapon: Damage + """ + display_name = "Plando Weaknesses" + schema = Schema({ + Optional(And(str, Use(str.title), lambda s: s in bosses)): { + And(str, Use(str.title), lambda s: s in weapons_to_id): And(int, lambda i: i in range(-1, 14)) + } + }) + default = {} + + +class ReduceFlashing(Choice): + """ + Reduce flashing seen in gameplay, such as the stage select and when defeating a Wily boss. + Virtual Console: increases length of most flashes, changes some flashes from white to a dark gray. + Minor: VC changes + decreasing the speed of Bubble/Metal Man stage animations. + Full: VC changes + further decreasing the brightness of most flashes and + disables stage animations for Metal/Bubble Man stages. + """ + display_name = "Reduce Flashing" + option_none = 0 + option_virtual_console = 1 + option_minor = 2 + option_full = 3 + default = 1 + + +class RandomMusic(Choice): + """ + Vanilla: music is unchanged + Shuffled: stage and certain menu music is shuffled. + Randomized: stage and certain menu music is randomly selected + None: no music will play + """ + display_name = "Random Music" + option_vanilla = 0 + option_shuffled = 1 + option_randomized = 2 + option_none = 3 + +@dataclass +class MM2Options(PerGameCommonOptions): + death_link: DeathLink + energy_link: EnergyLink + starting_robot_master: StartingRobotMaster + consumables: Consumables + yoku_jumps: YokuJumps + enable_lasers: EnableLasers + enemy_weakness: EnemyWeaknesses + strict_weakness: StrictWeaknesses + random_weakness: RandomWeaknesses + wily_5_requirement: Wily5Requirement + plando_weakness: WeaknessPlando + palette_shuffle: PaletteShuffle + quickswap: Quickswap + reduce_flashing: ReduceFlashing + random_music: RandomMusic diff --git a/worlds/mm2/rom.py b/worlds/mm2/rom.py new file mode 100644 index 000000000000..cac0a8706007 --- /dev/null +++ b/worlds/mm2/rom.py @@ -0,0 +1,415 @@ +import pkgutil +from typing import Optional, TYPE_CHECKING, Iterable, Dict, Sequence +import hashlib +import Utils +import os + +import settings +from worlds.Files import APProcedurePatch, APTokenMixin, APTokenTypes +from . import names +from .rules import minimum_weakness_requirement +from .text import MM2TextEntry +from .color import get_colors_for_item, write_palette_shuffle +from .options import Consumables, ReduceFlashing, RandomMusic + +if TYPE_CHECKING: + from . import MM2World + +MM2LCHASH = "37f2c36ce7592f1e16b3434b3985c497" +PROTEUSHASH = "9ff045a3ca30018b6e874c749abb3ec4" +MM2NESHASH = "0527a0ee512f69e08b8db6dc97964632" +MM2VCHASH = "0c78dfe8e90fb8f3eed022ff01126ad3" + +enemy_weakness_ptrs: Dict[int, int] = { + 0: 0x3E9A8, + 1: 0x3EA24, + 2: 0x3EA9C, + 3: 0x3EB14, + 4: 0x3EB8C, + 5: 0x3EC04, + 6: 0x3EC7C, + 7: 0x3ECF4, +} + +enemy_addresses: Dict[str, int] = { + "Shrink": 0x00, + "M-445": 0x04, + "Claw": 0x08, + "Tanishi": 0x0A, + "Kerog": 0x0C, + "Petit Kerog": 0x0D, + "Anko": 0x0F, + "Batton": 0x16, + "Robitto": 0x17, + "Friender": 0x1C, + "Monking": 0x1D, + "Kukku": 0x1F, + "Telly": 0x22, + "Changkey Maker": 0x23, + "Changkey": 0x24, + "Pierrobot": 0x29, + "Fly Boy": 0x2C, + # "Crash Wall": 0x2D + # "Friender Wall": 0x2E + "Blocky": 0x31, + "Neo Metall": 0x34, + "Matasaburo": 0x36, + "Pipi": 0x38, + "Pipi Egg": 0x3A, + "Copipi": 0x3C, + "Kaminari Goro": 0x3E, + "Petit Goblin": 0x45, + "Springer": 0x46, + "Mole (Up)": 0x48, + "Mole (Down)": 0x49, + "Shotman (Left)": 0x4B, + "Shotman (Right)": 0x4C, + "Sniper Armor": 0x4E, + "Sniper Joe": 0x4F, + "Scworm": 0x50, + "Scworm Worm": 0x51, + "Picopico-kun": 0x6A, + "Boobeam Trap": 0x6D, + "Big Fish": 0x71 +} + +# addresses printed when assembling basepatch +consumables_ptr: int = 0x3F2FE +quickswap_ptr: int = 0x3F363 +wily_5_ptr: int = 0x3F3A1 +energylink_ptr: int = 0x3F46B +get_equipped_sound_ptr: int = 0x3F384 + + +class RomData: + def __init__(self, file: bytes, name: str = "") -> None: + self.file = bytearray(file) + self.name = name + + def read_byte(self, offset: int) -> int: + return self.file[offset] + + def read_bytes(self, offset: int, length: int) -> bytearray: + return self.file[offset:offset + length] + + def write_byte(self, offset: int, value: int) -> None: + self.file[offset] = value + + def write_bytes(self, offset: int, values: Sequence[int]) -> None: + self.file[offset:offset + len(values)] = values + + def write_to_file(self, file: str) -> None: + with open(file, 'wb') as outfile: + outfile.write(self.file) + + +class MM2ProcedurePatch(APProcedurePatch, APTokenMixin): + hash = [MM2LCHASH, MM2NESHASH, MM2VCHASH] + game = "Mega Man 2" + patch_file_ending = ".apmm2" + result_file_ending = ".nes" + name: bytearray + procedure = [ + ("apply_bsdiff4", ["mm2_basepatch.bsdiff4"]), + ("apply_tokens", ["token_patch.bin"]), + ] + + @classmethod + def get_source_data(cls) -> bytes: + return get_base_rom_bytes() + + def write_byte(self, offset: int, value: int) -> None: + self.write_token(APTokenTypes.WRITE, offset, value.to_bytes(1, "little")) + + def write_bytes(self, offset: int, value: Iterable[int]) -> None: + self.write_token(APTokenTypes.WRITE, offset, bytes(value)) + + +def patch_rom(world: "MM2World", patch: MM2ProcedurePatch) -> None: + patch.write_file("mm2_basepatch.bsdiff4", pkgutil.get_data(__name__, os.path.join("data", "mm2_basepatch.bsdiff4"))) + # text writing + patch.write_bytes(0x37E2A, MM2TextEntry("FOR ", 0xCB).resolve()) + patch.write_bytes(0x37EAA, MM2TextEntry("GET EQUIPPED ", 0x0B).resolve()) + patch.write_bytes(0x37EBA, MM2TextEntry("WITH ", 0x2B).resolve()) + + base_address = 0x3F650 + color_address = 0x37F6C + for i, location in zip(range(11), [ + names.atomic_fire_get, + names.air_shooter_get, + names.leaf_shield_get, + names.bubble_lead_get, + names.quick_boomerang_get, + names.time_stopper_get, + names.metal_blade_get, + names.crash_bomber_get, + names.item_1_get, + names.item_2_get, + names.item_3_get + ]): + item = world.multiworld.get_location(location, world.player).item + if item: + if len(item.name) <= 14: + # we want to just place it in the center + first_str = "" + second_str = item.name + third_str = "" + elif len(item.name) <= 28: + # spread across second and third + first_str = "" + second_str = item.name[:14] + third_str = item.name[14:] + else: + # all three + first_str = item.name[:14] + second_str = item.name[14:28] + third_str = item.name[28:] + if len(third_str) > 16: + third_str = third_str[:16] + player_str = world.multiworld.get_player_name(item.player) + if len(player_str) > 14: + player_str = player_str[:14] + patch.write_bytes(base_address + (64 * i), MM2TextEntry(first_str, 0x4B).resolve()) + patch.write_bytes(base_address + (64 * i) + 16, MM2TextEntry(second_str, 0x6B).resolve()) + patch.write_bytes(base_address + (64 * i) + 32, MM2TextEntry(third_str, 0x8B).resolve()) + patch.write_bytes(base_address + (64 * i) + 48, MM2TextEntry(player_str, 0xEB).resolve()) + + colors = get_colors_for_item(item.name) + if i > 7: + patch.write_bytes(color_address + 27 + ((i - 8) * 2), colors) + else: + patch.write_bytes(color_address + (i * 2), colors) + + write_palette_shuffle(world, patch) + + enemy_weaknesses: Dict[str, Dict[int, int]] = {} + + if world.options.strict_weakness or world.options.random_weakness or world.options.plando_weakness: + # we need to write boss weaknesses + output = bytearray() + for weapon in world.weapon_damage: + if weapon == 8: + continue # Time Stopper is a special case + weapon_damage = [world.weapon_damage[weapon][i] + if world.weapon_damage[weapon][i] >= 0 + else 256 + world.weapon_damage[weapon][i] + for i in range(14)] + output.extend(weapon_damage) + patch.write_bytes(0x2E952, bytes(output)) + time_stopper_damage = world.weapon_damage[8] + time_offset = 0x2C03B + damage_table = { + 4: 0xF, + 3: 0x17, + 2: 0x1E, + 1: 0x25 + } + for boss, damage in enumerate(time_stopper_damage): + if damage > 4: + damage = 4 # 4 is a guaranteed kill, no need to exceed + if damage <= 0: + patch.write_byte(time_offset + 14 + boss, 0) + else: + patch.write_byte(time_offset + 14 + boss, 1) + patch.write_byte(time_offset + boss, damage_table[damage]) + if world.options.random_weakness: + wily_5_weaknesses = [i for i in range(8) if world.weapon_damage[i][12] > minimum_weakness_requirement[i]] + world.random.shuffle(wily_5_weaknesses) + if len(wily_5_weaknesses) >= 3: + weak1 = wily_5_weaknesses.pop() + weak2 = wily_5_weaknesses.pop() + weak3 = wily_5_weaknesses.pop() + elif len(wily_5_weaknesses) == 2: + weak1 = weak2 = wily_5_weaknesses.pop() + weak3 = wily_5_weaknesses.pop() + else: + weak1 = weak2 = weak3 = 0 + patch.write_byte(0x2DA2E, weak1) + patch.write_byte(0x2DA32, weak2) + patch.write_byte(0x2DA3A, weak3) + enemy_weaknesses["Picopico-kun"] = {weapon: world.weapon_damage[weapon][9] for weapon in range(8)} + enemy_weaknesses["Boobeam Trap"] = {weapon: world.weapon_damage[weapon][11] for weapon in range(8)} + + if world.options.enemy_weakness: + for enemy in enemy_addresses: + if enemy in ("Picopico-kun", "Boobeam Trap"): + continue + enemy_weaknesses[enemy] = {weapon: world.random.randint(-4, 4) for weapon in enemy_weakness_ptrs} + if enemy == "Friender": + # Friender has to be killed, need buster damage to not break logic + enemy_weaknesses[enemy][0] = max(enemy_weaknesses[enemy][0], 1) + + for enemy, damage_table in enemy_weaknesses.items(): + for weapon in enemy_weakness_ptrs: + if damage_table[weapon] < 0: + damage_table[weapon] = 256 + damage_table[weapon] + patch.write_byte(enemy_weakness_ptrs[weapon] + enemy_addresses[enemy], damage_table[weapon]) + + if world.options.quickswap: + patch.write_byte(quickswap_ptr + 1, 0x01) + + if world.options.consumables != Consumables.option_all: + value_a = 0x7C + value_b = 0x76 + if world.options.consumables == Consumables.option_1up_etank: + value_b = 0x7A + else: + value_a = 0x7A + patch.write_byte(consumables_ptr - 3, value_a) + patch.write_byte(consumables_ptr + 1, value_b) + + patch.write_byte(wily_5_ptr + 1, world.options.wily_5_requirement.value) + + if world.options.energy_link: + patch.write_byte(energylink_ptr + 1, 1) + + if world.options.reduce_flashing: + if world.options.reduce_flashing.value == ReduceFlashing.option_virtual_console: + color = 0x2D # Dark Gray + speed = -1 + elif world.options.reduce_flashing.value == ReduceFlashing.option_minor: + color = 0x2D + speed = 0x08 + else: + color = 0x0F + speed = 0x00 + patch.write_byte(0x2D1B0, color) # Change white to a dark gray, Mecha Dragon + patch.write_byte(0x2D397, 0x0F) # Longer flash time, Mecha Dragon kill + patch.write_byte(0x2D3A0, color) # Change white to a dark gray, Picopico-kun/Boobeam Trap + patch.write_byte(0x2D65F, color) # Change white to a dark gray, Guts Tank + patch.write_byte(0x2DA94, color) # Change white to a dark gray, Wily Machine + patch.write_byte(0x2DC97, color) # Change white to a dark gray, Alien + patch.write_byte(0x2DD68, 0x10) # Longer flash time, Alien kill + patch.write_bytes(0x2DF14, [0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA]) # Reduce final Alien flash to 1 big flash + patch.write_byte(0x34132, 0x08) # Longer flash time, Stage Select + + if world.options.reduce_flashing.value == ReduceFlashing.option_full: + # reduce color of stage flashing + patch.write_bytes(0x344C9, [0x2D, 0x10, 0x00, 0x2D, + 0x0F, 0x10, 0x2D, 0x00, + 0x0F, 0x10, 0x2D, 0x00, + 0x0F, 0x10, 0x2D, 0x00, + 0x2D, 0x10, 0x2D, 0x00, + 0x0F, 0x10, 0x2D, 0x00, + 0x0F, 0x10, 0x2D, 0x00, + 0x0F, 0x10, 0x2D, 0x00]) + # remove wily castle flash + patch.write_byte(0x3596D, 0x0F) + + if speed != -1: + patch.write_byte(0xFE01, speed) # Bubble Man Stage + patch.write_byte(0x1BE01, speed) # Metal Man Stage + + if world.options.random_music: + if world.options.random_music == RandomMusic.option_none: + pool = [0xFF] * 20 + # A couple of additional mutes we want here + patch.write_byte(0x37819, 0xFF) # Credits + patch.write_byte(0x378A4, 0xFF) # Credits #2 + patch.write_byte(0x37149, 0xFF) # Game Over Jingle + patch.write_byte(0x341BA, 0xFF) # Robot Master Jingle + patch.write_byte(0x2E0B4, 0xFF) # Robot Master Defeated + patch.write_byte(0x35B78, 0xFF) # Wily Castle + patch.write_byte(0x2DFA5, 0xFF) # Wily Defeated + + elif world.options.random_music == RandomMusic.option_shuffled: + pool = [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 9, 0x10, 0xC, 0xB, 0x17, 0x13, 0xE, 0xD] + world.random.shuffle(pool) + else: + pool = world.random.choices([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xB, 0xC, 0xD, 0xE, 0x10, 0x13, 0x17], k=20) + patch.write_bytes(0x381E0, pool[:13]) + patch.write_byte(0x36318, pool[13]) # Game Start + patch.write_byte(0x37181, pool[13]) # Game Over + patch.write_byte(0x340AE, pool[14]) # RBM Select + patch.write_byte(0x39005, pool[15]) # Robot Master Battle + patch.write_byte(get_equipped_sound_ptr + 1, pool[16]) # Get Equipped, we actually hook this already lmao + patch.write_byte(0x3775A, pool[17]) # Epilogue + patch.write_byte(0x36089, pool[18]) # Intro + patch.write_byte(0x361F1, pool[19]) # Title + + + + from Utils import __version__ + patch.name = bytearray(f'MM2{__version__.replace(".", "")[0:3]}_{world.player}_{world.multiworld.seed:11}\0', + 'utf8')[:21] + patch.name.extend([0] * (21 - len(patch.name))) + patch.write_bytes(0x3FFC0, patch.name) + deathlink_byte = world.options.death_link.value | (world.options.energy_link.value << 1) + patch.write_byte(0x3FFD5, deathlink_byte) + + patch.write_bytes(0x3FFD8, world.world_version) + + version_map = { + "0": 0x90, + "1": 0x91, + "2": 0x92, + "3": 0x93, + "4": 0x94, + "5": 0x95, + "6": 0x96, + "7": 0x97, + "8": 0x98, + "9": 0x99, + ".": 0xDC + } + patch.write_token(APTokenTypes.RLE, 0x36EE0, (11, 0)) + patch.write_token(APTokenTypes.RLE, 0x36EEE, (25, 0)) + + # BY SILVRIS + patch.write_bytes(0x36EE0, [0xC2, 0xD9, 0xC0, 0xD3, 0xC9, 0xCC, 0xD6, 0xD2, 0xC9, 0xD3]) + # ARCHIPELAGO x.x.x + patch.write_bytes(0x36EF2, [0xC1, 0xD2, 0xC3, 0xC8, 0xC9, 0xD0, 0xC5, 0xCC, 0xC1, 0xC7, 0xCF, 0xC0]) + patch.write_bytes(0x36EFE, list(map(lambda c: version_map[c], __version__))) + + patch.write_file("token_patch.bin", patch.get_token_binary()) + + +header = b"\x4E\x45\x53\x1A\x10\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + +def read_headerless_nes_rom(rom: bytes) -> bytes: + if rom[:4] == b"NES\x1A": + return rom[16:] + else: + return rom + + +def get_base_rom_bytes(file_name: str = "") -> bytes: + base_rom_bytes: Optional[bytes] = getattr(get_base_rom_bytes, "base_rom_bytes", None) + if not base_rom_bytes: + file_name = get_base_rom_path(file_name) + base_rom_bytes = read_headerless_nes_rom(bytes(open(file_name, "rb").read())) + + basemd5 = hashlib.md5() + basemd5.update(base_rom_bytes) + if basemd5.hexdigest() == PROTEUSHASH: + base_rom_bytes = extract_mm2(base_rom_bytes) + basemd5 = hashlib.md5() + basemd5.update(base_rom_bytes) + if basemd5.hexdigest() not in {MM2LCHASH, MM2NESHASH, MM2VCHASH}: + print(basemd5.hexdigest()) + raise Exception("Supplied Base Rom does not match known MD5 for US, LC, or US VC release. " + "Get the correct game and version, then dump it") + headered_rom = bytearray(base_rom_bytes) + headered_rom[0:0] = header + setattr(get_base_rom_bytes, "base_rom_bytes", bytes(headered_rom)) + return bytes(headered_rom) + return base_rom_bytes + + +def get_base_rom_path(file_name: str = "") -> str: + options: settings.Settings = settings.get_settings() + if not file_name: + file_name = options["mm2_options"]["rom_file"] + if not os.path.exists(file_name): + file_name = Utils.user_path(file_name) + return file_name + + +PRG_OFFSET = 0x8ED70 +PRG_SIZE = 0x40000 + + +def extract_mm2(proteus: bytes) -> bytes: + mm2 = bytearray(proteus[PRG_OFFSET:PRG_OFFSET + PRG_SIZE]) + return bytes(mm2) diff --git a/worlds/mm2/rules.py b/worlds/mm2/rules.py new file mode 100644 index 000000000000..c30688f2adbe --- /dev/null +++ b/worlds/mm2/rules.py @@ -0,0 +1,321 @@ +from math import ceil +from typing import TYPE_CHECKING, Dict, List +from . import names +from .locations import heat_man_locations, air_man_locations, wood_man_locations, bubble_man_locations, \ + quick_man_locations, flash_man_locations, metal_man_locations, crash_man_locations, wily_1_locations, \ + wily_2_locations, wily_3_locations, wily_4_locations, wily_5_locations, wily_6_locations +from .options import bosses, weapons_to_id, Consumables, RandomWeaknesses +from worlds.generic.Rules import add_rule + +if TYPE_CHECKING: + from . import MM2World + from BaseClasses import CollectionState + +weapon_damage: Dict[int, List[int]] = { + 0: [2, 2, 1, 1, 2, 2, 1, 1, 1, 7, 1, 0, 1, -1], # Mega Buster + 1: [-1, 6, 0xE, 0, 0xA, 6, 4, 6, 8, 13, 8, 0, 0xE, -1], # Atomic Fire + 2: [2, 0, 4, 0, 2, 0, 0, 0xA, 0, 0, 0, 0, 1, -1], # Air Shooter + 3: [0, 8, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1], # Leaf Shield + 4: [6, 0, 0, -1, 0, 2, 0, 1, 0, 14, 1, 0, 0, 1], # Bubble Lead + 5: [2, 2, 0, 2, 0, 0, 4, 1, 1, 7, 2, 0, 1, -1], # Quick Boomerang + 6: [-1, 0, 2, 2, 4, 3, 0, 0, 1, 0, 1, 0x14, 1, -1], # Crash Bomber + 7: [1, 0, 2, 4, 0, 4, 0xE, 0, 0, 7, 0, 0, 1, -1], # Metal Blade + 8: [0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0], # Time Stopper +} + +weapons_to_name: Dict[int, str] = { + 1: names.atomic_fire, + 2: names.air_shooter, + 3: names.leaf_shield, + 4: names.bubble_lead, + 5: names.quick_boomerang, + 6: names.crash_bomber, + 7: names.metal_blade, + 8: names.time_stopper +} + +minimum_weakness_requirement: Dict[int, int] = { + 0: 1, # Mega Buster is free + 1: 14, # 2 shots of Atomic Fire + 2: 1, # 14 shots of Air Shooter, although you likely hit more than one shot + 3: 4, # 9 uses of Leaf Shield, 3 ends up 1 damage off + 4: 1, # 56 uses of Bubble Lead + 5: 1, # 224 uses of Quick Boomerang + 6: 4, # 7 uses of Crash Bomber + 7: 1, # 112 uses of Metal Blade + 8: 4, # 1 use of Time Stopper, but setting to 4 means we shave the entire HP bar +} + +robot_masters: Dict[int, str] = { + 0: "Heat Man Defeated", + 1: "Air Man Defeated", + 2: "Wood Man Defeated", + 3: "Bubble Man Defeated", + 4: "Quick Man Defeated", + 5: "Flash Man Defeated", + 6: "Metal Man Defeated", + 7: "Crash Man Defeated" +} + +weapon_costs = { + 0: 0, + 1: 10, + 2: 2, + 3: 3, + 4: 0.5, + 5: 0.125, + 6: 4, + 7: 0.25, + 8: 7, +} + + +def can_defeat_enough_rbms(state: "CollectionState", player: int, + required: int, boss_requirements: Dict[int, List[int]]): + can_defeat = 0 + for boss, reqs in boss_requirements.items(): + if boss in robot_masters: + if state.has_all(map(lambda x: weapons_to_name[x], reqs), player): + can_defeat += 1 + if can_defeat >= required: + return True + return False + + +def set_rules(world: "MM2World") -> None: + # most rules are set on region, so we only worry about rules required within stage access + # or rules variable on settings + if (hasattr(world.multiworld, "re_gen_passthrough") + and "Mega Man 2" in getattr(world.multiworld, "re_gen_passthrough")): + slot_data = getattr(world.multiworld, "re_gen_passthrough")["Mega Man 2"] + world.weapon_damage = slot_data["weapon_damage"] + world.wily_5_weapons = slot_data["wily_5_weapons"] + else: + if world.options.random_weakness == RandomWeaknesses.option_shuffled: + weapon_tables = [table for weapon, table in weapon_damage.items() if weapon not in (0, 8)] + world.random.shuffle(weapon_tables) + for i in range(1, 8): + world.weapon_damage[i] = weapon_tables.pop() + # alien must take minimum required damage from his weakness + alien_weakness = next(weapon for weapon in range(8) if world.weapon_damage[weapon][13] != -1) + world.weapon_damage[alien_weakness][13] = minimum_weakness_requirement[alien_weakness] + world.weapon_damage[8] = [0 for _ in range(14)] + world.weapon_damage[8][world.random.choice(range(8))] = 2 + elif world.options.random_weakness == RandomWeaknesses.option_randomized: + world.weapon_damage = {i: [] for i in range(9)} + for boss in range(13): + for weapon in world.weapon_damage: + world.weapon_damage[weapon].append(min(14, max(-1, int(world.random.normalvariate(3, 3))))) + if not any([world.weapon_damage[weapon][boss] >= max(4, minimum_weakness_requirement[weapon]) + for weapon in range(1, 7)]): + # failsafe, there should be at least one defined non-Buster weakness + weapon = world.random.randint(1, 7) + world.weapon_damage[weapon][boss] = world.random.randint( + max(4, minimum_weakness_requirement[weapon]), 14) # Force weakness + # special case, if boobeam trap has a weakness to Crash, it needs to be max damage + if world.weapon_damage[6][11] > 4: + world.weapon_damage[6][11] = 14 + # handle the alien + boss = 13 + for weapon in world.weapon_damage: + world.weapon_damage[weapon].append(-1) + weapon = world.random.choice(list(world.weapon_damage.keys())) + world.weapon_damage[weapon][boss] = minimum_weakness_requirement[weapon] + + if world.options.strict_weakness: + for weapon in weapon_damage: + for i in range(13): + if weapon == 0: + world.weapon_damage[weapon][i] = 0 + elif i in (8, 12) and not world.options.random_weakness: + continue + # Mecha Dragon only has damage range of 0-1, so allow the 1 + # Wily Machine needs all three weaknesses present, so allow + elif 4 > world.weapon_damage[weapon][i] > 0: + world.weapon_damage[weapon][i] = 0 + # handle special cases + for boss in range(14): + for weapon in (1, 3, 6, 8): + if (0 < world.weapon_damage[weapon][boss] < minimum_weakness_requirement[weapon] and + not any(world.weapon_damage[i][boss] > 0 for i in range(1, 8) if i != weapon)): + # Weapon does not have enough possible ammo to kill the boss, raise the damage + if boss == 9: + if weapon != 3: + # Atomic Fire and Crash Bomber cannot be Picopico-kun's only weakness + world.weapon_damage[weapon][boss] = 0 + weakness = world.random.choice((2, 3, 4, 5, 7, 8)) + world.weapon_damage[weakness][boss] = minimum_weakness_requirement[weakness] + elif boss == 11: + if weapon == 1: + # Atomic Fire cannot be Boobeam Trap's only weakness + world.weapon_damage[weapon][boss] = 0 + weakness = world.random.choice((2, 3, 4, 5, 6, 7, 8)) + world.weapon_damage[weakness][boss] = minimum_weakness_requirement[weakness] + else: + world.weapon_damage[weapon][boss] = minimum_weakness_requirement[weapon] + starting = world.options.starting_robot_master.value + world.weapon_damage[0][starting] = 1 + + for p_boss in world.options.plando_weakness: + for p_weapon in world.options.plando_weakness[p_boss]: + if world.options.plando_weakness[p_boss][p_weapon] < minimum_weakness_requirement[p_weapon] \ + and not any(w != p_weapon + and world.weapon_damage[w][bosses[p_boss]] > minimum_weakness_requirement[w] + for w in world.weapon_damage): + # we need to replace this weakness + weakness = world.random.choice([key for key in world.weapon_damage if key != p_weapon]) + world.weapon_damage[weakness][bosses[p_boss]] = minimum_weakness_requirement[weakness] + world.weapon_damage[weapons_to_id[p_weapon]][bosses[p_boss]] \ + = world.options.plando_weakness[p_boss][p_weapon] + + if world.weapon_damage[0][world.options.starting_robot_master.value] < 1: + world.weapon_damage[0][world.options.starting_robot_master.value] = weapon_damage[0][world.options.starting_robot_master.value] + + # final special case + # There's a vanilla crash if Time Stopper kills Wily phase 1 + # There's multiple fixes, but ensuring Wily cannot take Time Stopper damage is best + if world.weapon_damage[8][12] > 0: + world.weapon_damage[8][12] = 0 + + # weakness validation, it is better to confirm a completable seed than respect plando + boss_health = {boss: 0x1C if boss != 12 else 0x1C * 2 for boss in [*range(8), 12]} + + weapon_energy = {key: float(0x1C) for key in weapon_costs} + weapon_boss = {boss: {weapon: world.weapon_damage[weapon][boss] for weapon in world.weapon_damage} + for boss in [*range(8), 12]} + flexibility = { + boss: ( + sum(damage_value > 0 for damage_value in + weapon_damages.values()) # Amount of weapons that hit this boss + * sum(weapon_damages.values()) # Overall damage that those weapons do + ) + for boss, weapon_damages in weapon_boss.items() if boss != 12 + } + flexibility = sorted(flexibility, key=flexibility.get) # Fast way to sort dict by value + used_weapons = {i: set() for i in [*range(8), 12]} + for boss in [*flexibility, 12]: + boss_damage = weapon_boss[boss] + weapon_weight = {weapon: (weapon_energy[weapon] / damage) if damage else 0 for weapon, damage in + boss_damage.items() if weapon_energy[weapon] > 0} + if boss_damage[8]: + boss_damage[8] = 1.75 * boss_damage[8] + if any(boss_damage[i] > 0 for i in range(8)) and 8 in weapon_weight: + # We get exactly one use of Time Stopper during the rush + # So we want to make sure that use is absolutely needed + weapon_weight[8] = min(weapon_weight[8], 0.001) + while boss_health[boss] > 0: + if boss_damage[0] > 0: + boss_health[boss] = 0 # if we can buster, we should buster + continue + highest, wp = max(zip(weapon_weight.values(), weapon_weight.keys())) + uses = weapon_energy[wp] // weapon_costs[wp] + used_weapons[boss].add(wp) + if int(uses * boss_damage[wp]) > boss_health[boss]: + used = ceil(boss_health[boss] / boss_damage[wp]) + weapon_energy[wp] -= weapon_costs[wp] * used + boss_health[boss] = 0 + elif highest <= 0: + # we are out of weapons that can actually damage the boss + # so find the weapon that has the most uses, and apply that as an additional weakness + # it should be impossible to be out of energy, simply because even if every boss took 1 from + # Quick Boomerang and no other, it would only be 28 off from defeating all 9, which Metal Blade should + # be able to cover + wp, max_uses = max((weapon, weapon_energy[weapon] // weapon_costs[weapon]) for weapon in weapon_weight + if weapon != 0) + world.weapon_damage[wp][boss] = minimum_weakness_requirement[wp] + used = min(int(weapon_energy[wp] // weapon_costs[wp]), + ceil(boss_health[boss] // minimum_weakness_requirement[wp])) + weapon_energy[wp] -= weapon_costs[wp] * used + boss_health[boss] -= int(used * minimum_weakness_requirement[wp]) + weapon_weight.pop(wp) + else: + # drain the weapon and continue + boss_health[boss] -= int(uses * boss_damage[wp]) + weapon_energy[wp] -= weapon_costs[wp] * uses + weapon_weight.pop(wp) + + world.wily_5_weapons = {boss: sorted(used_weapons[boss]) for boss in used_weapons} + + for i, boss_locations in enumerate([ + heat_man_locations, + air_man_locations, + wood_man_locations, + bubble_man_locations, + quick_man_locations, + flash_man_locations, + metal_man_locations, + crash_man_locations, + wily_1_locations, + wily_2_locations, + wily_3_locations, + wily_4_locations, + wily_5_locations, + wily_6_locations + ]): + if world.weapon_damage[0][i] > 0: + continue # this can always be in logic + weapons = [] + for weapon in range(1, 9): + if world.weapon_damage[weapon][i] > 0: + if world.weapon_damage[weapon][i] < minimum_weakness_requirement[weapon]: + continue # Atomic Fire can only be considered logical for bosses it can kill in 2 hits + weapons.append(weapons_to_name[weapon]) + if not weapons: + raise Exception(f"Attempted to have boss {i} with no weakness! Seed: {world.multiworld.seed}") + for location in boss_locations: + if i == 12: + add_rule(world.get_location(location), + lambda state, weps=tuple(weapons): state.has_all(weps, world.player)) + # TODO: when has_list gets added, check for a subset of possible weaknesses + else: + add_rule(world.get_location(location), + lambda state, weps=tuple(weapons): state.has_any(weps, world.player)) + + # Always require Crash Bomber for Boobeam Trap + add_rule(world.get_location(names.wily_4), + lambda state: state.has(names.crash_bomber, world.player)) + add_rule(world.get_location(names.wily_stage_4), + lambda state: state.has(names.crash_bomber, world.player)) + + # Need to defeat x amount of robot masters for Wily 5 + add_rule(world.get_location(names.wily_5), + lambda state: can_defeat_enough_rbms(state, world.player, world.options.wily_5_requirement.value, + world.wily_5_weapons)) + add_rule(world.get_location(names.wily_stage_5), + lambda state: can_defeat_enough_rbms(state, world.player, world.options.wily_5_requirement.value, + world.wily_5_weapons)) + + if not world.options.yoku_jumps: + add_rule(world.get_entrance("To Heat Man Stage"), + lambda state: state.has(names.item_2, world.player)) + + if not world.options.enable_lasers: + add_rule(world.get_entrance("To Quick Man Stage"), + lambda state: state.has(names.time_stopper, world.player)) + + if world.options.consumables in (Consumables.option_1up_etank, + Consumables.option_all): + add_rule(world.get_location(names.flash_man_c2), + lambda state: state.has_any([names.item_1, names.item_2, names.item_3], world.player)) + add_rule(world.get_location(names.quick_man_c1), + lambda state: state.has_any([names.item_1, names.item_2, names.item_3], world.player)) + add_rule(world.get_location(names.metal_man_c2), + lambda state: state.has_any([names.item_1, names.item_2], world.player)) + add_rule(world.get_location(names.metal_man_c3), + lambda state: state.has_any([names.item_1, names.item_2], world.player)) + add_rule(world.get_location(names.crash_man_c3), + lambda state: state.has_any([names.item_1, names.item_2, names.item_3], world.player)) + add_rule(world.get_location(names.wily_2_c5), + lambda state: state.has(names.crash_bomber, world.player)) + add_rule(world.get_location(names.wily_2_c6), + lambda state: state.has(names.crash_bomber, world.player)) + add_rule(world.get_location(names.wily_3_c2), + lambda state: state.has(names.crash_bomber, world.player)) + if world.options.consumables in (Consumables.option_weapon_health, + Consumables.option_all): + add_rule(world.get_location(names.flash_man_c3), + lambda state: state.has(names.crash_bomber, world.player)) + add_rule(world.get_location(names.flash_man_c4), + lambda state: state.has(names.crash_bomber, world.player)) + add_rule(world.get_location(names.wily_3_c1), + lambda state: state.has(names.crash_bomber, world.player)) diff --git a/worlds/mm2/src/mm2_basepatch.asm b/worlds/mm2/src/mm2_basepatch.asm new file mode 100644 index 000000000000..00c8500f03df --- /dev/null +++ b/worlds/mm2/src/mm2_basepatch.asm @@ -0,0 +1,861 @@ +norom +!headersize = 16 + +!controller_mirror = $23 +!controller_flip = $27 ; only on first frame of input, used by crash man, etc +!current_stage = $2A +!received_stages = $8A +!completed_stages = $8B +!received_item_checks = $8C +!last_wily = $8D +!deathlink = $8F +!energylink_packet = $90 +!rbm_strobe = $91 +!received_weapons = $9A +!received_items = $9B +!current_weapon = $A9 + +!stage_completion = $0F70 +!consumable_checks = $0F80 + +!CONTROLLER_SELECT = #$04 +!CONTROLLER_SELECT_START = #$0C +!CONTROLLER_ALL_BUTTON = #$0F + +!PpuControl_2000 = $2000 +!PpuMask_2001 = $2001 +!PpuAddr_2006 = $2006 +!PpuData_2007 = $2007 + +!LOAD_BANK = $C000 + +macro org(address,bank) + if == $0F + org
-$C000+($4000*)+!headersize ; org sets the position in the output file to write to (in norom, at least) + base
; base sets the position that all labels are relative to - this is necessary so labels will still start from $8000, instead of $0000 or somewhere + else + org
-$8000+($4000*)+!headersize + base
+ endif +endmacro + +%org($8400, $08) +incbin "mm2font.dat" + +%org($A900, $09) +incbin "mm2titlefont.dat" + +%org($807E, $0B) +FlashFixes: + CMP #$FF + BEQ FlashFixTarget1 + CMP #$FF + BNE FlashFixTarget2 + +%org($8086, $0B) +FlashFixTarget1: + +%org($808D, $0B) +FlashFixTarget2: + +%org($8015, $0D) +ClearRefreshHook: + ; if we're already doing a fresh load of the stage select + ; we don't need to immediately refresh it + JSR ClearRefresh + NOP + +%org($802B, $0D) +PatchFaceTiles: + LDA !received_stages + +%org($8072, $0D) +PatchFaceSprites: + LDA !received_stages + +%org($80CC, $0D) +CheckItemsForWily: + LDA !received_items + CMP #$07 + +%org($80D2, $0D) +LoadWily: + JSR GoToMostRecentWily + NOP + +%org($80DC, $0D) +CheckAccessCodes: + LDA !received_stages + +%org($8312, $0D) +HookStageSelect: + JSR RefreshRBMTiles + NOP + +%org($A315, $0D) +RemoveWeaponClear: + NOP + NOP + NOP + NOP + +;Adjust Password select flasher +%org($A32A, $0D) + LDX #$68 + +;Block password input +%org($A346, $0D) + EOR #$00 + +;Remove password text +%org($AF3A, $0D) +StartHeight: + db $AC ; set Start to center + +%org($AF49, $0D) +PasswordText: + db $40, $40, $40, $40, $40, $40, $40, $40 + +%org($AF6C, $0D) +ContinueHeight: + db $AB ; split height between 2 remaining options + +%org($AF77, $0D) +StageSelectHeight: + db $EB ; split between 2 remaining options + +%org($AF88, $0D) +GameOverPasswordText: + db $40, $40, $40, $40, $40, $40, $40, $40 + +%org($AFA5, $0D) +GetEquippedPasswordText: + db $40, $40, $40, $40, $40, $40, $40, $40 + +%org($AFAE, $0D) +GetEquippedStageSelect: + db $26, $EA + +%org($B195, $0D) +GameOverPasswordUp: + LDA #$01 ; originally 02, removing last option + +%org($B19F, $0D) +GameOverPassword: + CMP #$02 ; originally 03, remove the last option + +%org($B1ED, $0D) +FixupGameOverArrows: + db $68, $78 + +%org($BB74, $0D) +GetEquippedStage: + JSR StageGetEquipped + NOP #13 + +%org($BBD9, $0D) +GetEquippedDefault: + LDA #$01 + +%org($BC01, $0D) +GetEquippedPasswordRemove: + ORA #$01 ; originally EOR #$01, we always want 1 here + +%org($BCF1, $0D) +GetEquippedItem: + ADC #$07 + JSR ItemGetEquipped + JSR LoadItemsColor + NOP ; !!!! This is a load-bearing NOP. It gets branched to later in the function + LDX $FF + + +%org($BB08, $0D) +WilyProgress: + JSR StoreWilyProgress + NOP + +%org($BF6F, $0D) +GetEquippedStageSelectHeight: + db $B8 + +%org($805B, $0E) +InitalizeStartingRBM: + LDA #$FF ; this does two things + STA !received_stages ; we're overwriting clearing e-tanks and setting RBM available to none + +%org($8066, $0E) +BlockStartupAutoWily: + ; presumably this would be called from password? + LDA #$00 + +%org($80A7, $0E) +StageLoad: + JMP CleanWily5 + NOP + +%org($8178, $0E) +Main1: + JSR MainLoopHook + NOP + +%org($81DE, $0E) +Wily5Teleporter: + LDA $99 + CMP #$01 + BCC SkipSpawn + +%org($81F9, $0E) +SkipSpawn: +; just present to fix the branch, if we try to branch raw it'll get confused + +%org($822D, $0E) +Main2: + ; believe used in the wily 5 refights? + JSR MainLoopHook + NOP + +%org($842F, $0E) +Wily5Hook: + JMP Wily5Requirement + NOP + +%org($C10D, $0F) +Deathlink: + JSR KillMegaMan + +%org($C1BC, $0F) +RemoveETankLoss: + NOP + NOP + +%org($C23C, $0F) +WriteStageComplete: + ORA !completed_stages + STA !completed_stages + +%org($C243, $0F) +WriteReceiveItem: + ORA !received_item_checks + STA !received_item_checks + +%org($C254, $0F) +BlockAutoWily: + ; and this one is on return from stage? + LDA #$00 + +%org($C261, $0F) +WilyStageCompletion: + JSR StoreWilyStageCompletion + NOP + +%org($E5AC, $0F) +NullDeathlink: + STA $8F ; we null his HP later in the process + NOP + +%org($E5D1, $0F) +EnergylinkHook: + JSR Energylink + NOP #2 ; comment this out to enable item giving their usual reward alongside EL + +%org($E5E8, $0F) +ConsumableHook: + JSR CheckConsumable + +%org($F2E3, $0F) + +CheckConsumable: + STA $0140, Y + TXA + PHA + LDA $AD ; the consumable value + CMP #$7C + BPL .Store + print "Consumables (replace 7a): ", hex(realbase()) + CMP #$76 + BMI .Store + LDA #$00 + .Store: + STA $AD + LDA $2A + ASL + ASL + TAX + TYA + .LoopHead: + CMP #$08 + BMI .GetFlag + INX + SBC #$08 + BNE .LoopHead + .GetFlag: + TAY + LDA #$01 + .Loop2Head: + CPY #$00 + BEQ .Apply + ASL + DEY + BNE .Loop2Head + .Apply: + ORA !consumable_checks, X + STA !consumable_checks, X + PLA + TAX + RTS + +GoToMostRecentWily: + LDA !controller_mirror + CMP !CONTROLLER_SELECT_START + BEQ .Default + LDA !last_wily + BNE .Store + .Default: + LDA #$08 ; wily stage 1 + .Store: + STA !current_stage + RTS + +StoreWilyStageCompletion: + LDA #$01 + STA !stage_completion, X + INC !current_stage + LDA !current_stage + STA !last_wily + RTS + +ReturnToGameOver: + LDA #$10 + STA !PpuControl_2000 + LDA #$06 + STA !PpuMask_2001 + JMP $C1BE ; specific code that loads game over + +MainLoopHook: + LDA !controller_mirror + CMP !CONTROLLER_ALL_BUTTON + BNE .Next + JMP ReturnToGameOver + .Next: + LDA !deathlink + CMP #$01 + BNE .Next2 + JMP $E5A8 ; this kills the Mega Man + .Next2: + print "Quickswap:", hex(realbase()) + LDA #$00 ; slot data, write in enable for quickswap + CMP #$01 + BNE .Finally + LDA !controller_flip + AND !CONTROLLER_SELECT + BEQ .Finally + JMP Quickswap + .Finally: + LDA !controller_flip + AND #$08 ; this is checking for menu + RTS + +StoreWilyProgress: + STA !current_stage + TXA + PHA + LDX !current_stage + LDA #$01 + STA !stage_completion, X + PLA + TAX + print "Get Equipped Music: ", hex(realbase()) + LDA #$17 + RTS + +KillMegaMan: + JSR $C051 ; this kills the mega man + LDA #$00 + STA $06C0 ; set HP to zero so client can actually detect he died + RTS + +Wily5Requirement: + LDA #$01 + LDX #$08 + LDY #$00 + .LoopHead: + BIT $BC + BEQ .Skip + INY + .Skip: + DEX + ASL + CPX #$00 + BNE .LoopHead + print "Wily 5 Requirement:", hex(realbase()) + CPY #$08 + BCS .SpawnTeleporter + JMP $8450 + .SpawnTeleporter: + LDA #$FF + STA $BC + LDA #$01 + STA $99 + JMP $8433 + +CleanWily5: + LDA #$00 + STA $BC + STA $99 + JMP $80AB + +LoadString: + STY $00 + ASL + ASL + ASL + ASL + TAY + LDA $DB + ADC #$00 + STA $C8 + LDA #$40 + STA $C9 + LDA #$F6 + CLC + ADC $C8 + STA $CA + LDA ($C9), Y + STA $03B6 + TYA + CLC + ADC #$01 + TAY + LDA $CA + ADC #$00 + STA $CA + LDA ($C9), Y + STA $03B7 + TYA + CLC + ADC #$01 + TAY + LDA $CA + ADC #$00 + STA $CA + STY $FE + LDA #$0E + STA $FD + .LoopHead: + JSR $BD34 + LDY $FE + CPY #$40 + BNE .NotEqual + LDA $0420 + BNE .Skip + .NotEqual: + LDA ($C9), Y + .Skip: + STA $03B8 + INC $47 + INC $03B7 + LDA $FE + CLC + ADC #$01 + STA $FE + LDA $CA + ADC #$00 + STA $CA + DEC $FD + BNE .LoopHead + LDY $00 + JSR $C0AB + RTS + +StageGetEquipped: + LDA !current_stage + LDX #$00 + BCS LoadGetEquipped +ItemGetEquipped: + LDX #$02 +LoadGetEquipped: + STX $DB + ASL + ASL + PHA + SEC + JSR LoadString + PLA + ADC #$00 + PHA + SEC + JSR LoadString + PLA + ADC #$00 + PHA + SEC + JSR LoadString + LDA #$00 + SEC + JSR $BD3E + PLA + ADC #$00 + SEC + JSR LoadString + RTS + +LoadItemsColor: + LDA #$7D + STA $FD + LDA $0420 + AND #$0F + ASL + SEC + ADC #$1A + STA $FF + RTS + +Energylink: + LSR $0420, X + print "Energylink: ", hex(realbase()) + LDA #$00 + BEQ .ApplyDrop + LDA $04E0, X + BEQ .ApplyDrop ; This is a stage pickup, and not an enemy drop + STY !energylink_packet + SEC + BCS .Return + .ApplyDrop: + STY $AD + .Return: + RTS + + +Quickswap: + LDX #$0F + .LoopHead: + LDA $0420, X + BMI .Return1 ; return if we have any weapon entities spawned + DEX + CPX #$01 + BNE .LoopHead + LDX !current_weapon + BNE .DoQuickswap + LDX #$00 + .DoQuickswap: + TYA + PHA + LDX !current_weapon + INX + CPX #$09 + BPL .Items + LDA #$01 + .Loop2Head: + DEX + BEQ .FoundTarget + ASL + CPX #$00 + BNE .Loop2Head + .FoundTarget: + LDX !current_weapon + INX + .Loop3Head: + PHA + AND !received_weapons + BNE .CanSwap + PLA + INX + CPX #$09 + BPL .Items + ASL + BNE .Loop3Head + .CanSwap: + PLA + SEC + BCS .ApplySwap + .Items: + TXA + PHA + SEC + SBC #$08 + TAX + LDA #$01 + .Loop4Head: + DEX + BEQ .CheckItem + ASL + CPX #$00 + BNE .Loop4Head + .CheckItem: + TAY + PLA + TAX + TYA + .Loop5Head: + PHA + AND !received_items + BNE .CanSwap + PLA + INX + ASL + BNE .Loop5Head + LDX #$00 + SEC + BCS .ApplySwap + .Return1: + RTS + .ApplySwap: ; $F408 on old rom + LDA #$0D + JSR !LOAD_BANK + ; this is a bunch of boiler plate to make the swap work + LDA $B5 + PHA + LDA $B6 + PHA + LDA $B7 + PHA + LDA $B8 + PHA + LDA $B9 + PHA + LDA $20 + PHA + LDA $1F + PHA + ;but wait, there's more + STX !current_weapon + JSR $CC6C + LDA $1A + PHA + LDX #$00 + .Loop6Head: + STX $FD + CLC + LDA $52 + ADC $957F, X + STA $08 + LDA $53 + ADC #$00 + STA $09 + LDA $08 + LSR $09 + ROR + LSR $09 + ROR + STA $08 + AND #$3F + STA $1A + CLC + LDA $09 + ADC #$85 + STA $09 + LDA #$00 + STA $1B + LDA $FD + CMP #$08 + BCS .Past8 + LDX $A9 + LDA $9664, X + TAY + CPX #$09 + BCC .LessThanNine + LDX #$00 + BEQ .Apply + .LessThanNine: + LDX #$05 + BNE .Apply + .Past8: + LDY #$90 + LDX #$00 + .Apply: + JSR $C760 + JSR $C0AB ; iirc this is loading graphics? + LDX $FD + INX + CPX #$0F + BNE .Loop6Head + STX $FD + LDY #$90 + LDX #$00 + JSR $C760 + JSR $D2ED + ; two sections redacted here, might need to look at what they actually do? + PLA + STA $1A + PLA + STA $1F + PLA + STA $20 + PLA + STA $B9 + PLA + STA $B8 + PLA + STA $B7 + PLA + STA $B6 + PLA + STA $B5 + LDA #$00 + STA $AC + STA $2C + STA $0680 + STA $06A0 + LDA #$1A + STA $0400 + LDA #$03 + STA $AA + LDA #$30 + JSR $C051 + .Finally: + LDA #$0E + JSR !LOAD_BANK + PLA + TAY + .Return: + RTS + +RefreshRBMTiles: + ; primarily just a copy of the startup RBM setup, we just do it again + ; can't jump to it as it leads into the main loop + LDA !rbm_strobe + BNE .Update + JMP .NoUpdate + .Update: + LDA #$00 + STA !rbm_strobe + LDA #$10 + STA $F7 + STA !PpuControl_2000 + LDA #$06 + STA $F8 + STA !PpuMask_2001 + JSR $847E + JSR $843C + LDX #$00 + LDA $8A + STA $01 + .TileLoop: + STX $00 + LSR $01 + BCC .SkipTile + LDA $8531,X + STA $09 + LDA $8539,X + STA $08 + LDX #$04 + LDA #$00 + .ClearBody: + LDA $09 + STA !PpuAddr_2006 + LDA $08 + STA !PpuAddr_2006 + LDY #$04 + LDA #$00 + .ClearLine: + STA !PpuData_2007 + DEY + BNE .ClearLine + CLC + LDA $08 + ADC #$20 + STA $08 + DEX + BNE .ClearBody + .SkipTile: + LDX $00 + INX + CPX #$08 + BNE .TileLoop + LDX #$1F + JSR $829E + JSR $8473 + LDX #$00 + LDA $8A + STA $02 + LDY #$00 + .SpriteLoop: + STX $01 + LSR $02 + BCS .SkipRBM + LDA $8605,X + STA $00 + LDA $85FD,X + TAX + .WriteSprite: + LDA $8541,X + STA $0200,Y + INY + INX + DEC $00 + BNE .WriteSprite + .SkipRBM: + LDX $01 + INX + CPX #$08 + BNE .SpriteLoop + JSR $A51D + LDA #$0C + JSR $C051 + LDA #$00 + STA $2A + STA $FD + JSR $C0AB + .NoUpdate: + LDA $1C + AND #$08 + RTS + +ClearRefresh: + LDA #$00 + STA !rbm_strobe + LDA #$10 + STA $F7 + RTS + +assert realbase() <= $03F650 ; This is the start of our text data, and we absolutely cannot go past this point (text takes too much room). + +%org($F640, $0F) +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" +db $25, $4B, "PLACEHOLDER_L1" +db $25, $6B, "PLACEHOLDER_L2" +db $25, $8B, "PLACEHOLDER_L3" +db $25, $EB, "PLACEHOLDER_PL" + +%org($FFB0, $0F) +db "MM2_BASEPATCH_ARCHI " \ No newline at end of file diff --git a/worlds/mm2/src/mm2font.dat b/worlds/mm2/src/mm2font.dat new file mode 100644 index 000000000000..4bf97ee42c69 Binary files /dev/null and b/worlds/mm2/src/mm2font.dat differ diff --git a/worlds/mm2/src/mm2titlefont.dat b/worlds/mm2/src/mm2titlefont.dat new file mode 100644 index 000000000000..cb0c9b13cfc2 Binary files /dev/null and b/worlds/mm2/src/mm2titlefont.dat differ diff --git a/worlds/mm2/test/__init__.py b/worlds/mm2/test/__init__.py new file mode 100644 index 000000000000..e712b0fe2ba6 --- /dev/null +++ b/worlds/mm2/test/__init__.py @@ -0,0 +1,5 @@ +from test.bases import WorldTestBase + + +class MM2TestBase(WorldTestBase): + game = "Mega Man 2" diff --git a/worlds/mm2/test/test_access.py b/worlds/mm2/test/test_access.py new file mode 100644 index 000000000000..97ef5075a3cb --- /dev/null +++ b/worlds/mm2/test/test_access.py @@ -0,0 +1,47 @@ +from . import MM2TestBase +from ..locations import (quick_man_locations, heat_man_locations, wily_1_locations, wily_2_locations, + wily_3_locations, wily_4_locations, wily_5_locations, wily_6_locations, + energy_pickups, etank_1ups) +from ..names import * + + +class TestAccess(MM2TestBase): + options = { + "consumables": "all" + } + + def test_time_stopper(self) -> None: + """Optional based on Enable Lasers setting, confirm these are the locations affected""" + locations = [*quick_man_locations, *energy_pickups["Quick Man Stage"], *etank_1ups["Quick Man Stage"]] + items = [["Time Stopper"]] + self.assertAccessDependency(locations, items) + + def test_item_2(self) -> None: + """Optional based on Yoku Block setting, confirm these are the locations affected""" + locations = [*heat_man_locations, *etank_1ups["Heat Man Stage"]] + items = [["Item 2 - Rocket"]] + self.assertAccessDependency(locations, items, True) + + def test_any_item(self) -> None: + locations = [flash_man_c2, quick_man_c1, crash_man_c3] + items = [["Item 1 - Propeller"], ["Item 2 - Rocket"], ["Item 3 - Bouncy"]] + self.assertAccessDependency(locations, items, True) + locations = [metal_man_c2, metal_man_c3] + items = [["Item 1 - Propeller"], ["Item 2 - Rocket"]] + self.assertAccessDependency(locations, items, True) + + def test_all_items(self) -> None: + locations = [flash_man_c2, quick_man_c1, crash_man_c3, metal_man_c2, metal_man_c3, *heat_man_locations, + *etank_1ups["Heat Man Stage"], *wily_1_locations, *wily_2_locations, *wily_3_locations, + *wily_4_locations, *wily_5_locations, *wily_6_locations, *etank_1ups["Wily Stage 1"], + *etank_1ups["Wily Stage 2"], *etank_1ups["Wily Stage 3"], *etank_1ups["Wily Stage 4"], + *energy_pickups["Wily Stage 1"], *energy_pickups["Wily Stage 2"], *energy_pickups["Wily Stage 3"], + *energy_pickups["Wily Stage 4"]] + items = [["Item 1 - Propeller", "Item 2 - Rocket", "Item 3 - Bouncy"]] + self.assertAccessDependency(locations, items) + + def test_crash_bomber(self) -> None: + locations = [flash_man_c3, flash_man_c4, wily_2_c5, wily_2_c6, wily_3_c1, wily_3_c2, + wily_4, wily_stage_4] + items = [["Crash Bomber"]] + self.assertAccessDependency(locations, items) diff --git a/worlds/mm2/test/test_weakness.py b/worlds/mm2/test/test_weakness.py new file mode 100644 index 000000000000..c294ce5ac989 --- /dev/null +++ b/worlds/mm2/test/test_weakness.py @@ -0,0 +1,104 @@ +from math import ceil + +from . import MM2TestBase +from ..options import bosses + + +# Need to figure out how this test should work +def validate_wily_5(base: MM2TestBase) -> None: + world = base.multiworld.worlds[base.player] + weapon_damage = world.weapon_damage + weapon_costs = { + 0: 0, + 1: 10, + 2: 2, + 3: 3, + 4: 0.5, + 5: 0.125, + 6: 4, + 7: 0.25, + 8: 7, + } + boss_health = {boss: 0x1C if boss != 12 else 0x1C * 2 for boss in [*range(8), 12]} + weapon_energy = {key: float(0x1C) for key in weapon_costs} + weapon_boss = {boss: {weapon: world.weapon_damage[weapon][boss] for weapon in world.weapon_damage} + for boss in [*range(8), 12]} + flexibility = { + boss: ( + sum(damage_value > 0 for damage_value in + weapon_damages.values()) # Amount of weapons that hit this boss + * sum(weapon_damages.values()) # Overall damage that those weapons do + ) + for boss, weapon_damages in weapon_boss.items() if boss != 12 + } + flexibility = sorted(flexibility, key=flexibility.get) # Fast way to sort dict by value + used_weapons = {i: set() for i in [*range(8), 12]} + for boss in [*flexibility, 12]: + boss_damage = weapon_boss[boss] + weapon_weight = {weapon: (weapon_energy[weapon] / damage) if damage else 0 for weapon, damage in + boss_damage.items() if weapon_energy[weapon] > 0} + if boss_damage[8]: + boss_damage[8] = 1.75 * boss_damage[8] + if any(boss_damage[i] > 0 for i in range(8)) and 8 in weapon_weight: + # We get exactly one use of Time Stopper during the rush + # So we want to make sure that use is absolutely needed + weapon_weight[8] = min(weapon_weight[8], 0.001) + while boss_health[boss] > 0: + if boss_damage[0] > 0: + boss_health[boss] = 0 # if we can buster, we should buster + continue + highest, wp = max(zip(weapon_weight.values(), weapon_weight.keys())) + uses = weapon_energy[wp] // weapon_costs[wp] + used_weapons[boss].add(wp) + if int(uses * boss_damage[wp]) > boss_health[boss]: + used = ceil(boss_health[boss] / boss_damage[wp]) + weapon_energy[wp] -= weapon_costs[wp] * used + boss_health[boss] = 0 + elif highest <= 0: + # we are out of weapons that can actually damage the boss + base.fail(f"Ran out of weapon energy to damage " + f"{next(name for name in bosses if bosses[name] == boss)}\n" + f"Seed: {base.multiworld.seed}\n" + f"Damage Table: {weapon_damage}") + else: + # drain the weapon and continue + boss_health[boss] -= int(uses * boss_damage[wp]) + weapon_energy[wp] -= weapon_costs[wp] * uses + weapon_weight.pop(wp) + + +class StrictWeaknessTests(MM2TestBase): + options = { + "strict_weakness": True, + "yoku_jumps": True, + "enable_lasers": True + } + + def test_that_every_boss_has_a_weakness(self) -> None: + world = self.multiworld.worlds[self.player] + weapon_damage = world.weapon_damage + for boss in range(14): + if not any(weapon_damage[weapon][boss] for weapon in range(9)): + self.fail(f"Boss {boss} generated without weakness! Seed: {self.multiworld.seed}") + + def test_wily_5(self) -> None: + validate_wily_5(self) + + +class RandomStrictWeaknessTests(MM2TestBase): + options = { + "strict_weakness": True, + "random_weakness": "randomized", + "yoku_jumps": True, + "enable_lasers": True + } + + def test_that_every_boss_has_a_weakness(self) -> None: + world = self.multiworld.worlds[self.player] + weapon_damage = world.weapon_damage + for boss in range(14): + if not any(weapon_damage[weapon][boss] for weapon in range(9)): + self.fail(f"Boss {boss} generated without weakness! Seed: {self.multiworld.seed}") + + def test_wily_5(self) -> None: + validate_wily_5(self) diff --git a/worlds/mm2/text.py b/worlds/mm2/text.py new file mode 100644 index 000000000000..32d665bf6c7f --- /dev/null +++ b/worlds/mm2/text.py @@ -0,0 +1,90 @@ +from typing import DefaultDict +from collections import defaultdict + +MM2_WEAPON_ENCODING: DefaultDict[str, int] = defaultdict(lambda x: 0x6F, { + ' ': 0x40, + 'A': 0x41, + 'B': 0x42, + 'C': 0x43, + 'D': 0x44, + 'E': 0x45, + 'F': 0x46, + 'G': 0x47, + 'H': 0x48, + 'I': 0x49, + 'J': 0x4A, + 'K': 0x4B, + 'L': 0x4C, + 'M': 0x4D, + 'N': 0x4E, + 'O': 0x4F, + 'P': 0x50, + 'Q': 0x51, + 'R': 0x52, + 'S': 0x53, + 'T': 0x54, + 'U': 0x55, + 'V': 0x56, + 'W': 0x57, + 'X': 0x58, + 'Y': 0x59, + 'Z': 0x5A, + # 0x5B is the small r in Dr Light + '.': 0x5C, + ',': 0x5D, + '\'': 0x5E, + '!': 0x5F, + '(': 0x60, + ')': 0x61, + '#': 0x62, + '$': 0x63, + '%': 0x64, + '&': 0x65, + '*': 0x66, + '+': 0x67, + '/': 0x68, + '\\': 0x69, + ':': 0x6A, + ';': 0x6B, + '<': 0x6C, + '>': 0x6D, + '=': 0x6E, + '?': 0x6F, + '@': 0x70, + '[': 0x71, + ']': 0x72, + '^': 0x73, + '_': 0x74, + '`': 0x75, + '{': 0x76, + '}': 0x77, + '|': 0x78, + '~': 0x79, + '\"': 0x92, + '-': 0x94, + '0': 0xA0, + '1': 0xA1, + '2': 0xA2, + '3': 0xA3, + '4': 0xA4, + '5': 0xA5, + '6': 0xA6, + '7': 0xA7, + '8': 0xA8, + '9': 0xA9, +}) + + +class MM2TextEntry: + def __init__(self, text: str = "", coords: int = 0x0B): + self.target_area: int = 0x25 # don't change + self.coords: int = coords # 0xYX, Y can only be increments of 0x20 + self.text: str = text + + def resolve(self) -> bytes: + data = bytearray() + data.append(self.target_area) + data.append(self.coords) + data.extend([MM2_WEAPON_ENCODING[x] for x in self.text.upper()]) + data.extend([0x40] * (14 - len(self.text))) + return bytes(data) diff --git a/worlds/osrs/Names.py b/worlds/osrs/Names.py index 95aed742b6f1..cc92439ef859 100644 --- a/worlds/osrs/Names.py +++ b/worlds/osrs/Names.py @@ -93,9 +93,9 @@ class ItemNames(str, Enum): Progressive_Armor = "Progressive Armor" Progressive_Weapons = "Progressive Weapons" Progressive_Tools = "Progressive Tools" - Progressive_Range_Armor = "Progressive Range Armor" - Progressive_Range_Weapon = "Progressive Range Weapon" - Progressive_Magic = "Progressive Magic Spell" + Progressive_Range_Armor = "Progressive Ranged Armor" + Progressive_Range_Weapon = "Progressive Ranged Weapons" + Progressive_Magic = "Progressive Magic" Lobsters = "10 Lobsters" Swordfish = "5 Swordfish" Energy_Potions = "10 Energy Potions" diff --git a/worlds/osrs/__init__.py b/worlds/osrs/__init__.py index f726b4b81bf2..d74dc7cfd9c2 100644 --- a/worlds/osrs/__init__.py +++ b/worlds/osrs/__init__.py @@ -524,7 +524,9 @@ def create_region(self, name: str) -> "Region": return region def create_item(self, item_name: str) -> "Item": - item = [item for item in item_rows if item.name == item_name][0] + items = [item for item in item_rows if item.name == item_name] + assert len(items) > 0, f"No matching item found for name {item_name} for player {self.player_name}" + item = items[0] index = item_rows.index(item) return OSRSItem(item.name, item.progression, self.base_id + index, self.player) diff --git a/worlds/pokemon_emerald/rom.py b/worlds/pokemon_emerald/rom.py index 968a103ccd25..75d7d575846d 100644 --- a/worlds/pokemon_emerald/rom.py +++ b/worlds/pokemon_emerald/rom.py @@ -817,6 +817,8 @@ def _randomize_opponent_battle_type(world: "PokemonEmeraldWorld", patch: Pokemon def _randomize_move_tutor_moves(world: "PokemonEmeraldWorld", patch: PokemonEmeraldProcedurePatch, easter_egg: Tuple[int, int]) -> None: + FORTREE_MOVE_TUTOR_INDEX = 24 + if easter_egg[0] == 2: for i in range(30): patch.write_token( @@ -840,18 +842,26 @@ def _randomize_move_tutor_moves(world: "PokemonEmeraldWorld", patch: PokemonEmer # Always set Fortree move tutor to Dig patch.write_token( APTokenTypes.WRITE, - data.rom_addresses["gTutorMoves"] + (24 * 2), + data.rom_addresses["gTutorMoves"] + (FORTREE_MOVE_TUTOR_INDEX * 2), struct.pack("=50%) compatibility + if world.options.tm_tutor_compatibility.value < 50: + compatibility &= ~(1 << FORTREE_MOVE_TUTOR_INDEX) + if world.random.random() < 0.5: + compatibility |= 1 << FORTREE_MOVE_TUTOR_INDEX + patch.write_token( APTokenTypes.WRITE, data.rom_addresses["sTutorLearnsets"] + (species.species_id * 4), - struct.pack(" str: # the vanilla connection destination="Town Basement", tag="_beach"), Portal(name="Changing Room Entrance", region="Overworld", destination="Changing Room", tag="_"), - Portal(name="Cube Cave Entrance", region="Overworld", + Portal(name="Cube Cave Entrance", region="Cube Cave Entrance Region", destination="CubeRoom", tag="_"), Portal(name="Stairs from Overworld to Mountain", region="Upper Overworld", destination="Mountain", tag="_"), @@ -562,6 +562,7 @@ class DeadEnd(IntEnum): "Overworld Temple Door": RegionInfo("Overworld Redux"), # the small space betweeen the door and the portal "Overworld Town Portal": RegionInfo("Overworld Redux"), # being able to go to or come from the portal "Overworld Spawn Portal": RegionInfo("Overworld Redux"), # being able to go to or come from the portal + "Cube Cave Entrance Region": RegionInfo("Overworld Redux"), # other side of the bomb wall "Stick House": RegionInfo("Sword Cave", dead_end=DeadEnd.all_cats), "Windmill": RegionInfo("Windmill"), "Old House Back": RegionInfo("Overworld Interiors"), # part with the hc door @@ -775,6 +776,8 @@ class DeadEnd(IntEnum): [["UR"]], "Overworld Old House Door": [], + "Cube Cave Entrance Region": + [], }, "East Overworld": { "Above Ruined Passage": @@ -920,6 +923,10 @@ class DeadEnd(IntEnum): "Overworld": [], }, + "Cube Cave Entrance Region": { + "Overworld": + [], + }, "Old House Front": { "Old House Back": [], diff --git a/worlds/tunic/er_rules.py b/worlds/tunic/er_rules.py index a54ea23bcc0a..3d1973beb375 100644 --- a/worlds/tunic/er_rules.py +++ b/worlds/tunic/er_rules.py @@ -1,6 +1,7 @@ from typing import Dict, Set, List, Tuple, TYPE_CHECKING from worlds.generic.Rules import set_rule, forbid_item -from .rules import has_ability, has_sword, has_stick, has_ice_grapple_logic, has_lantern, has_mask, can_ladder_storage +from .rules import (has_ability, has_sword, has_stick, has_ice_grapple_logic, has_lantern, has_mask, can_ladder_storage, + bomb_walls) from .er_data import Portal from BaseClasses import Region, CollectionState @@ -11,6 +12,7 @@ grapple = "Magic Orb" ice_dagger = "Magic Dagger" fire_wand = "Magic Wand" +gun = "Gun" lantern = "Lantern" fairies = "Fairy" coins = "Golden Coin" @@ -31,6 +33,10 @@ def has_ladder(ladder: str, state: CollectionState, world: "TunicWorld") -> bool return not world.options.shuffle_ladders or state.has(ladder, world.player) +def can_shop(state: CollectionState, world: "TunicWorld") -> bool: + return has_sword(state, world.player) and state.can_reach_region("Shop", world.player) + + def set_er_region_rules(world: "TunicWorld", regions: Dict[str, Region], portal_pairs: Dict[Portal, Portal]) -> None: player = world.player options = world.options @@ -217,12 +223,12 @@ def set_er_region_rules(world: "TunicWorld", regions: Dict[str, Region], portal_ regions["Overworld"].connect( connecting_region=regions["Overworld after Envoy"], - rule=lambda state: state.has_any({laurels, grapple}, player) + rule=lambda state: state.has_any({laurels, grapple, gun}, player) or state.has("Sword Upgrade", player, 4) or options.logic_rules) regions["Overworld after Envoy"].connect( connecting_region=regions["Overworld"], - rule=lambda state: state.has_any({laurels, grapple}, player) + rule=lambda state: state.has_any({laurels, grapple, gun}, player) or state.has("Sword Upgrade", player, 4) or options.logic_rules) @@ -329,6 +335,12 @@ def set_er_region_rules(world: "TunicWorld", regions: Dict[str, Region], portal_ connecting_region=regions["Overworld"], rule=lambda state: state.has_any({grapple, laurels}, player)) + regions["Overworld"].connect( + connecting_region=regions["Cube Cave Entrance Region"], + rule=lambda state: state.has(gun, player) or can_shop(state, world)) + regions["Cube Cave Entrance Region"].connect( + connecting_region=regions["Overworld"]) + # Overworld side areas regions["Old House Front"].connect( connecting_region=regions["Old House Back"]) @@ -1527,6 +1539,10 @@ def set_er_location_rules(world: "TunicWorld") -> None: set_rule(world.get_location("Library Fuse"), lambda state: has_ability(prayer, state, world)) + # Bombable Walls + for location_name in bomb_walls: + set_rule(world.get_location(location_name), lambda state: state.has(gun, player) or can_shop(state, world)) + # Shop set_rule(world.get_location("Shop - Potion 1"), lambda state: has_sword(state, player)) diff --git a/worlds/tunic/items.py b/worlds/tunic/items.py index a8aec9f74485..3e7f2c1a4382 100644 --- a/worlds/tunic/items.py +++ b/worlds/tunic/items.py @@ -43,7 +43,7 @@ class TunicItemData(NamedTuple): "Magic Orb": TunicItemData(ItemClassification.progression, 1, 27), "Hero's Laurels": TunicItemData(ItemClassification.progression, 1, 28), "Lantern": TunicItemData(ItemClassification.progression, 1, 29), - "Gun": TunicItemData(ItemClassification.useful, 1, 30, "Weapons"), + "Gun": TunicItemData(ItemClassification.progression, 1, 30, "Weapons"), "Shield": TunicItemData(ItemClassification.useful, 1, 31), "Dath Stone": TunicItemData(ItemClassification.useful, 1, 32), "Hourglass": TunicItemData(ItemClassification.useful, 1, 33), diff --git a/worlds/tunic/rules.py b/worlds/tunic/rules.py index 2ff588da904d..68756869038d 100644 --- a/worlds/tunic/rules.py +++ b/worlds/tunic/rules.py @@ -1,7 +1,7 @@ from random import Random from typing import Dict, TYPE_CHECKING -from worlds.generic.Rules import set_rule, forbid_item +from worlds.generic.Rules import set_rule, forbid_item, add_rule from BaseClasses import CollectionState from .options import TunicOptions if TYPE_CHECKING: @@ -11,6 +11,7 @@ grapple = "Magic Orb" ice_dagger = "Magic Dagger" fire_wand = "Magic Wand" +gun = "Gun" lantern = "Lantern" fairies = "Fairy" coins = "Golden Coin" @@ -26,6 +27,11 @@ blue_hexagon = "Blue Questagon" gold_hexagon = "Gold Questagon" +bomb_walls = ["East Forest - Bombable Wall", "Eastern Vault Fortress - [East Wing] Bombable Wall", + "Overworld - [Central] Bombable Wall", "Overworld - [Southwest] Bombable Wall Near Fountain", + "Quarry - [West] Upper Area Bombable Wall", "Quarry - [East] Bombable Wall", + "Ruined Atoll - [Northwest] Bombable Wall"] + def randomize_ability_unlocks(random: Random, options: TunicOptions) -> Dict[str, int]: ability_requirement = [1, 1, 1] @@ -110,7 +116,7 @@ def set_region_rules(world: "TunicWorld") -> None: lambda state: state.has_any({grapple, laurels}, player) and has_ability(prayer, state, world) world.get_entrance("Overworld -> Quarry").access_rule = \ lambda state: (has_sword(state, player) or state.has(fire_wand, player)) \ - and (state.has_any({grapple, laurels}, player) or can_ladder_storage(state, world)) + and (state.has_any({grapple, laurels, gun}, player) or can_ladder_storage(state, world)) world.get_entrance("Quarry Back -> Quarry").access_rule = \ lambda state: has_sword(state, player) or state.has(fire_wand, player) world.get_entrance("Quarry -> Lower Quarry").access_rule = \ @@ -326,6 +332,13 @@ def set_location_rules(world: "TunicWorld") -> None: set_rule(world.get_location("Hero's Grave - Feathers Relic"), lambda state: state.has(laurels, player) and has_ability(prayer, state, world)) + # Bombable Walls + for location_name in bomb_walls: + # has_sword is there because you can buy bombs in the shop + set_rule(world.get_location(location_name), lambda state: state.has(gun, player) or has_sword(state, player)) + add_rule(world.get_location("Cube Cave - Holy Cross Chest"), + lambda state: state.has(gun, player) or has_sword(state, player)) + # Shop set_rule(world.get_location("Shop - Potion 1"), lambda state: has_sword(state, player)) diff --git a/worlds/v6/__init__.py b/worlds/v6/__init__.py index 3d3ee8cf58fd..b74f335189cf 100644 --- a/worlds/v6/__init__.py +++ b/worlds/v6/__init__.py @@ -49,12 +49,14 @@ def set_rules(self): self.area_cost_map = {} set_rules(self.multiworld, self.options, self.player, self.area_connections, self.area_cost_map) - def create_item(self, name: str) -> Item: - return V6Item(name, ItemClassification.progression, item_table[name], self.player) + def create_item(self, name: str, classification: ItemClassification = ItemClassification.filler) -> Item: + return V6Item(name, classification, item_table[name], self.player) def create_items(self): - trinkets = [self.create_item("Trinket " + str(i+1).zfill(2)) for i in range(0,20)] - self.multiworld.itempool += trinkets + progtrinkets = [self.create_item("Trinket " + str(i+1).zfill(2), ItemClassification.progression) for i in range(0, (4 * self.options.door_cost.value))] + filltrinkets = [self.create_item("Trinket " + str(i+1).zfill(2)) for i in range((4 * self.options.door_cost.value), 20)] + self.multiworld.itempool += progtrinkets + self.multiworld.itempool += filltrinkets def generate_basic(self): musiclist_o = [1,2,3,4,9,12] diff --git a/worlds/witness/__init__.py b/worlds/witness/__init__.py index 254064098db9..b228842019cf 100644 --- a/worlds/witness/__init__.py +++ b/worlds/witness/__init__.py @@ -15,7 +15,7 @@ from .data import static_logic as static_witness_logic from .data.item_definition_classes import DoorItemDefinition, ItemData from .data.utils import get_audio_logs -from .hints import CompactItemData, create_all_hints, make_compact_hint_data, make_laser_hints +from .hints import CompactHintData, create_all_hints, make_compact_hint_data, make_laser_hints from .locations import WitnessPlayerLocations from .options import TheWitnessOptions, witness_option_groups from .player_items import WitnessItem, WitnessPlayerItems @@ -68,12 +68,14 @@ class WitnessWorld(World): player_items: WitnessPlayerItems player_regions: WitnessPlayerRegions - log_ids_to_hints: Dict[int, CompactItemData] - laser_ids_to_hints: Dict[int, CompactItemData] + log_ids_to_hints: Dict[int, CompactHintData] + laser_ids_to_hints: Dict[int, CompactHintData] items_placed_early: List[str] own_itempool: List[WitnessItem] + panel_hunt_required_count: int + def _get_slot_data(self) -> Dict[str, Any]: return { "seed": self.random.randrange(0, 1000000), @@ -83,12 +85,14 @@ def _get_slot_data(self) -> Dict[str, Any]: "door_hexes_in_the_pool": self.player_items.get_door_ids_in_pool(), "symbols_not_in_the_game": self.player_items.get_symbol_ids_not_in_pool(), "disabled_entities": [int(h, 16) for h in self.player_logic.COMPLETELY_DISABLED_ENTITIES], + "hunt_entities": [int(h, 16) for h in self.player_logic.HUNT_ENTITIES], "log_ids_to_hints": self.log_ids_to_hints, "laser_ids_to_hints": self.laser_ids_to_hints, "progressive_item_lists": self.player_items.get_progressive_item_ids_in_pool(), "obelisk_side_id_to_EPs": static_witness_logic.OBELISK_SIDE_ID_TO_EP_HEXES, "precompleted_puzzles": [int(h, 16) for h in self.player_logic.EXCLUDED_LOCATIONS], "entity_to_name": static_witness_logic.ENTITY_ID_TO_NAME, + "panel_hunt_required_absolute": self.panel_hunt_required_count } def determine_sufficient_progression(self) -> None: @@ -151,6 +155,13 @@ def generate_early(self) -> None: if self.options.shuffle_lasers == "local": self.options.local_items.value |= self.item_name_groups["Lasers"] + if self.options.victory_condition == "panel_hunt": + total_panels = self.options.panel_hunt_total + required_percentage = self.options.panel_hunt_required_percentage + self.panel_hunt_required_count = round(total_panels * required_percentage / 100) + else: + self.panel_hunt_required_count = 0 + def create_regions(self) -> None: self.player_regions.create_regions(self, self.player_logic) @@ -169,7 +180,7 @@ def create_regions(self) -> None: for event_location in self.player_locations.EVENT_LOCATION_TABLE: item_obj = self.create_item( - self.player_logic.EVENT_ITEM_PAIRS[event_location] + self.player_logic.EVENT_ITEM_PAIRS[event_location][0] ) location_obj = self.get_location(event_location) location_obj.place_locked_item(item_obj) @@ -192,7 +203,7 @@ def create_regions(self) -> None: ] if early_items: random_early_item = self.random.choice(early_items) - if self.options.puzzle_randomization == "sigma_expert": + if self.options.puzzle_randomization == "sigma_expert" or self.options.victory_condition == "panel_hunt": # In Expert, only tag the item as early, rather than forcing it onto the gate. self.multiworld.local_early_items[self.player][random_early_item] = 1 else: @@ -305,8 +316,8 @@ def create_items(self) -> None: self.options.local_items.value.add(item_name) def fill_slot_data(self) -> Dict[str, Any]: - self.log_ids_to_hints: Dict[int, CompactItemData] = {} - self.laser_ids_to_hints: Dict[int, CompactItemData] = {} + self.log_ids_to_hints: Dict[int, CompactHintData] = {} + self.laser_ids_to_hints: Dict[int, CompactHintData] = {} already_hinted_locations = set() diff --git a/worlds/witness/data/settings/Entity_Hunt.txt b/worlds/witness/data/settings/Entity_Hunt.txt new file mode 100644 index 000000000000..4135dbd842f7 --- /dev/null +++ b/worlds/witness/data/settings/Entity_Hunt.txt @@ -0,0 +1,6 @@ +Requirement Changes: +0x03629 - Entity Hunt - True +0x03505 - 0x03629 - True + +New Connections: +Tutorial - Outside Tutorial - True diff --git a/worlds/witness/data/static_locations.py b/worlds/witness/data/static_locations.py index de321d20c0f9..d9566080a04c 100644 --- a/worlds/witness/data/static_locations.py +++ b/worlds/witness/data/static_locations.py @@ -406,6 +406,10 @@ "Mountain Bottom Floor Discard", } +GENERAL_LOCATION_HEXES = { + static_witness_logic.ENTITIES_BY_NAME[entity_name]["entity_hex"] for entity_name in GENERAL_LOCATIONS +} + OBELISK_SIDES = { "Desert Obelisk Side 1", "Desert Obelisk Side 2", diff --git a/worlds/witness/data/static_logic.py b/worlds/witness/data/static_logic.py index a9175c0c30b3..b61b0f9d2f92 100644 --- a/worlds/witness/data/static_logic.py +++ b/worlds/witness/data/static_logic.py @@ -103,6 +103,7 @@ def read_logic_file(self, lines: List[str]) -> None: "region": None, "id": None, "entityType": location_id, + "locationType": None, "area": current_area, } @@ -127,19 +128,30 @@ def read_logic_file(self, lines: List[str]) -> None: "Laser Hedges", "Laser Pressure Plates", } - is_vault_or_video = "Vault" in entity_name or "Video" in entity_name if "Discard" in entity_name: + entity_type = "Panel" location_type = "Discard" - elif is_vault_or_video or entity_name == "Tutorial Gate Close": + elif "Vault" in entity_name: + entity_type = "Panel" location_type = "Vault" elif entity_name in laser_names: - location_type = "Laser" + entity_type = "Laser" + location_type = None elif "Obelisk Side" in entity_name: + entity_type = "Obelisk Side" location_type = "Obelisk Side" + elif "Obelisk" in entity_name: + entity_type = "Obelisk" + location_type = None elif "EP" in entity_name: + entity_type = "EP" location_type = "EP" + elif entity_hex.startswith("0xFF"): + entity_type = "Event" + location_type = None else: + entity_type = "Panel" location_type = "General" required_items = parse_lambda(required_item_lambda) @@ -152,7 +164,7 @@ def read_logic_file(self, lines: List[str]) -> None: "items": required_items } - if location_type == "Obelisk Side": + if entity_type == "Obelisk Side": eps = set(next(iter(required_panels))) eps -= {"Theater to Tunnels"} @@ -167,7 +179,8 @@ def read_logic_file(self, lines: List[str]) -> None: "entity_hex": entity_hex, "region": current_region, "id": int(location_id), - "entityType": location_type, + "entityType": entity_type, + "locationType": location_type, "area": current_area, } diff --git a/worlds/witness/data/utils.py b/worlds/witness/data/utils.py index f89aaf7d3e18..11f905b18a56 100644 --- a/worlds/witness/data/utils.py +++ b/worlds/witness/data/utils.py @@ -203,6 +203,10 @@ def get_elevators_come_to_you() -> List[str]: return get_adjustment_file("settings/Door_Shuffle/Elevators_Come_To_You.txt") +def get_entity_hunt() -> List[str]: + return get_adjustment_file("settings/Entity_Hunt.txt") + + def get_sigma_normal_logic() -> List[str]: return get_adjustment_file("WitnessLogic.txt") diff --git a/worlds/witness/entity_hunt.py b/worlds/witness/entity_hunt.py new file mode 100644 index 000000000000..29b914799fdb --- /dev/null +++ b/worlds/witness/entity_hunt.py @@ -0,0 +1,234 @@ +from collections import defaultdict +from logging import debug +from pprint import pformat +from typing import TYPE_CHECKING, Dict, List, Set, Tuple + +from .data import static_logic as static_witness_logic + +if TYPE_CHECKING: + from . import WitnessWorld + from .player_logic import WitnessPlayerLogic + +DISALLOWED_ENTITIES_FOR_PANEL_HUNT = { + "0x03629", # Tutorial Gate Open, which is the panel that is locked by panel hunt + "0x03505", # Tutorial Gate Close (same thing) + "0x3352F", # Gate EP (same thing) + "0x09F7F", # Mountaintop Box Short. This is reserved for panel_hunt_postgame. + "0x00CDB", # Challenge Reallocating + "0x0051F", # Challenge Reallocating + "0x00524", # Challenge Reallocating + "0x00CD4", # Challenge Reallocating + "0x00CB9", # Challenge May Be Unsolvable + "0x00CA1", # Challenge May Be Unsolvable + "0x00C80", # Challenge May Be Unsolvable + "0x00C68", # Challenge May Be Unsolvable + "0x00C59", # Challenge May Be Unsolvable + "0x00C22", # Challenge May Be Unsolvable + "0x0A3A8", # Reset PP + "0x0A3B9", # Reset PP + "0x0A3BB", # Reset PP + "0x0A3AD", # Reset PP +} + +ALL_HUNTABLE_PANELS = [ + entity_hex + for entity_hex, entity_obj in static_witness_logic.ENTITIES_BY_HEX.items() + if entity_obj["entityType"] == "Panel" and entity_hex not in DISALLOWED_ENTITIES_FOR_PANEL_HUNT +] + + +class EntityHuntPicker: + def __init__(self, player_logic: "WitnessPlayerLogic", world: "WitnessWorld", + pre_picked_entities: Set[str]) -> None: + self.player_logic = player_logic + self.player_options = world.options + self.player_name = world.player_name + self.random = world.random + + self.PRE_PICKED_HUNT_ENTITIES = pre_picked_entities.copy() + self.HUNT_ENTITIES: Set[str] = set() + + self.ALL_ELIGIBLE_ENTITIES, self.ELIGIBLE_ENTITIES_PER_AREA = self._get_eligible_panels() + + def pick_panel_hunt_panels(self, total_amount: int) -> Set[str]: + """ + The process of picking all hunt entities is: + + 1. Add pre-defined hunt entities + 2. Pick random hunt entities to fill out the rest + 3. Replace unfair entities with fair entities + + Each of these is its own function. + """ + + self.HUNT_ENTITIES = self.PRE_PICKED_HUNT_ENTITIES.copy() + + self._pick_all_hunt_entities(total_amount) + self._replace_unfair_hunt_entities_with_good_hunt_entities() + self._log_results() + + return self.HUNT_ENTITIES + + def _entity_is_eligible(self, panel_hex: str) -> bool: + """ + Determine whether an entity is eligible for entity hunt based on player options. + """ + panel_obj = static_witness_logic.ENTITIES_BY_HEX[panel_hex] + + return ( + self.player_logic.solvability_guaranteed(panel_hex) + and not ( + # Due to an edge case, Discards have to be on in disable_non_randomized even if Discard Shuffle is off. + # However, I don't think they should be hunt panels in this case. + self.player_options.disable_non_randomized_puzzles + and not self.player_options.shuffle_discarded_panels + and panel_obj["locationType"] == "Discard" + ) + ) + + def _get_eligible_panels(self) -> Tuple[List[str], Dict[str, Set[str]]]: + """ + There are some entities that are not allowed for panel hunt for various technical of gameplay reasons. + Make a list of all the ones that *are* eligible, plus a lookup of eligible panels per area. + """ + + all_eligible_panels = [ + panel for panel in ALL_HUNTABLE_PANELS + if self._entity_is_eligible(panel) + ] + + eligible_panels_by_area = defaultdict(set) + for eligible_panel in all_eligible_panels: + associated_area = static_witness_logic.ENTITIES_BY_HEX[eligible_panel]["area"]["name"] + eligible_panels_by_area[associated_area].add(eligible_panel) + + return all_eligible_panels, eligible_panels_by_area + + def _get_percentage_of_hunt_entities_by_area(self) -> Dict[str, float]: + hunt_entities_picked_so_far_prevent_div_0 = max(len(self.HUNT_ENTITIES), 1) + + contributing_percentage_per_area = {} + for area, eligible_entities in self.ELIGIBLE_ENTITIES_PER_AREA.items(): + amount_of_already_chosen_entities = len(self.ELIGIBLE_ENTITIES_PER_AREA[area] & self.HUNT_ENTITIES) + current_percentage = amount_of_already_chosen_entities / hunt_entities_picked_so_far_prevent_div_0 + contributing_percentage_per_area[area] = current_percentage + + return contributing_percentage_per_area + + def _get_next_random_batch(self, amount: int, same_area_discouragement: float) -> List[str]: + """ + Pick the next batch of hunt entities. + Areas that already have a lot of hunt entities in them will be discouraged from getting more. + The strength of this effect is controlled by the same_area_discouragement factor from the player's options. + """ + + percentage_of_hunt_entities_by_area = self._get_percentage_of_hunt_entities_by_area() + + max_percentage = max(percentage_of_hunt_entities_by_area.values()) + if max_percentage == 0: + allowance_per_area = {area: 1.0 for area in percentage_of_hunt_entities_by_area} + else: + allowance_per_area = { + area: (max_percentage - current_percentage) / max_percentage + for area, current_percentage in percentage_of_hunt_entities_by_area.items() + } + # use same_area_discouragement as lerp factor + allowance_per_area = { + area: (1.0 - same_area_discouragement) + (weight * same_area_discouragement) + for area, weight in allowance_per_area.items() + } + + assert min(allowance_per_area.values()) >= 0, ( + f"Somehow, an area had a negative weight when picking hunt entities: {allowance_per_area}" + ) + + remaining_entities, remaining_entity_weights = [], [] + for area, eligible_entities in self.ELIGIBLE_ENTITIES_PER_AREA.items(): + for panel in eligible_entities - self.HUNT_ENTITIES: + remaining_entities.append(panel) + remaining_entity_weights.append(allowance_per_area[area]) + + # I don't think this can ever happen, but let's be safe + if sum(remaining_entity_weights) == 0: + remaining_entity_weights = [1] * len(remaining_entity_weights) + + return self.random.choices(remaining_entities, weights=remaining_entity_weights, k=amount) + + def _pick_all_hunt_entities(self, total_amount: int) -> None: + """ + The core function of the EntityHuntPicker in which all Hunt Entities are picked, + respecting the player's choices for total amount and same area discouragement. + """ + same_area_discouragement = self.player_options.panel_hunt_discourage_same_area_factor / 100 + + # If we're using random picking, just choose all the entities now and return + if not same_area_discouragement: + hunt_entities = self.random.sample( + [entity for entity in self.ALL_ELIGIBLE_ENTITIES if entity not in self.HUNT_ENTITIES], + k=total_amount - len(self.HUNT_ENTITIES), + ) + self.HUNT_ENTITIES.update(hunt_entities) + return + + # If we're discouraging entities from the same area being picked, we have to pick entities one at a time + # For higher total counts, we do them in small batches for performance + batch_size = max(1, total_amount // 20) + + while len(self.HUNT_ENTITIES) < total_amount: + actual_amount_to_pick = min(batch_size, total_amount - len(self.HUNT_ENTITIES)) + + self.HUNT_ENTITIES.update(self._get_next_random_batch(actual_amount_to_pick, same_area_discouragement)) + + def _replace_unfair_hunt_entities_with_good_hunt_entities(self) -> None: + """ + For connected entities that "solve together", make sure that the one you're guaranteed + to be able to see and interact with first is the one that is chosen, so you don't get "surprise entities". + """ + + replacements = { + "0x18488": "0x00609", # Replace Swamp Sliding Bridge Underwater -> Swamp Sliding Bridge Above Water + "0x03676": "0x03678", # Replace Quarry Upper Ramp Control -> Lower Ramp Control + "0x03675": "0x03679", # Replace Quarry Upper Lift Control -> Lower Lift Control + + "0x03702": "0x15ADD", # Jungle Vault Box -> Jungle Vault Panel + "0x03542": "0x002A6", # Mountainside Vault Box -> Mountainside Vault Panel + "0x03481": "0x033D4", # Tutorial Vault Box -> Tutorial Vault Panel + "0x0339E": "0x0CC7B", # Desert Vault Box -> Desert Vault Panel + "0x03535": "0x00AFB", # Shipwreck Vault Box -> Shipwreck Vault Panel + } + + if self.player_options.shuffle_doors < 2: + replacements.update( + { + "0x334DC": "0x334DB", # In door shuffle, the Shadows Timer Panels are disconnected + "0x17CBC": "0x2700B", # In door shuffle, the Laser Timer Panels are disconnected + } + ) + + for bad_entitiy, good_entity in replacements.items(): + # If the bad entity was picked as a hunt entity ... + if bad_entitiy not in self.HUNT_ENTITIES: + continue + + # ... and the good entity was not ... + if good_entity in self.HUNT_ENTITIES or good_entity not in self.ALL_ELIGIBLE_ENTITIES: + continue + + # ... replace the bad entity with the good entity. + self.HUNT_ENTITIES.remove(bad_entitiy) + self.HUNT_ENTITIES.add(good_entity) + + def _log_results(self) -> None: + final_percentage_by_area = self._get_percentage_of_hunt_entities_by_area() + + sorted_area_percentages_dict = dict(sorted(final_percentage_by_area.items(), key=lambda x: x[1])) + sorted_area_percentages_dict_pretty_print = { + area: str(percentage) + (" (maxed)" if self.ELIGIBLE_ENTITIES_PER_AREA[area] <= self.HUNT_ENTITIES else "") + for area, percentage in sorted_area_percentages_dict.items() + } + player_name = self.player_name + discouragemenet_factor = self.player_options.panel_hunt_discourage_same_area_factor + debug( + f'Final area percentages for player "{player_name}" ({discouragemenet_factor} discouragement):\n' + f"{pformat(sorted_area_percentages_dict_pretty_print)}" + ) diff --git a/worlds/witness/generate_data_file.py b/worlds/witness/generate_data_file.py new file mode 100644 index 000000000000..50a63a374619 --- /dev/null +++ b/worlds/witness/generate_data_file.py @@ -0,0 +1,45 @@ +from collections import defaultdict + +from data import static_logic as static_witness_logic + +if __name__ == "__main__": + with open("data/APWitnessData.h", "w") as datafile: + datafile.write("""# pragma once + +# include +# include +# include + +""") + + area_to_location_ids = defaultdict(list) + area_to_entity_ids = defaultdict(list) + + for entity_id, entity_object in static_witness_logic.ENTITIES_BY_HEX.items(): + location_id = entity_object["id"] + + area = entity_object["area"]["name"] + area_to_entity_ids[area].append(entity_id) + + if location_id is None: + continue + + area_to_location_ids[area].append(str(location_id)) + + datafile.write("inline std::map> areaNameToLocationIDs = {\n") + datafile.write( + "\n".join( + '\t{"' + area + '", { ' + ", ".join(location_ids) + " }}," + for area, location_ids in area_to_location_ids.items() + ) + ) + datafile.write("\n};\n\n") + + datafile.write("inline std::map> areaNameToEntityIDs = {\n") + datafile.write( + "\n".join( + '\t{"' + area + '", { ' + ", ".join(entity_ids) + " }}," + for area, entity_ids in area_to_entity_ids.items() + ) + ) + datafile.write("\n};\n\n") diff --git a/worlds/witness/hints.py b/worlds/witness/hints.py index a1ca1b081d3c..c8ddf260d4e6 100644 --- a/worlds/witness/hints.py +++ b/worlds/witness/hints.py @@ -1,8 +1,9 @@ import logging +import math from dataclasses import dataclass -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, Union +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, Union, cast -from BaseClasses import CollectionState, Item, Location, LocationProgressType, MultiWorld +from BaseClasses import CollectionState, Item, Location, LocationProgressType, MultiWorld, Region from .data import static_logic as static_witness_logic from .data.utils import weighted_sample @@ -11,7 +12,8 @@ if TYPE_CHECKING: from . import WitnessWorld -CompactItemData = Tuple[str, Union[str, int], int] +CompactHintArgs = Tuple[Union[str, int], Union[str, int]] +CompactHintData = Tuple[str, Union[str, int], Union[str, int]] @dataclass @@ -35,6 +37,8 @@ class WitnessWordedHint: location: Optional[Location] = None area: Optional[str] = None area_amount: Optional[int] = None + area_hunt_panels: Optional[int] = None + vague_location_hint: bool = False def get_always_hint_items(world: "WitnessWorld") -> List[str]: @@ -168,6 +172,51 @@ def get_priority_hint_locations(world: "WitnessWorld") -> List[str]: return priority +def try_getting_location_group_for_location(world: "WitnessWorld", hint_loc: Location) -> Tuple[str, str]: + allow_regions = world.options.vague_hints == "experimental" + + possible_location_groups = { + group_name: group_locations + for group_name, group_locations in world.multiworld.worlds[hint_loc.player].location_name_groups.items() + if hint_loc.name in group_locations + } + + locations_in_that_world = { + location.name for location in world.multiworld.get_locations(hint_loc.player) if not location.is_event + } + + valid_location_groups: Dict[str, int] = {} + + # Find valid location groups. + for group, locations in possible_location_groups.items(): + if group == "Everywhere": + continue + present_locations = sum(location in locations_in_that_world for location in locations) + valid_location_groups[group] = present_locations + + # If there are valid location groups, use a random one. + if valid_location_groups: + # If there are location groups with more than 1 location, remove any that only have 1. + if any(num_locs > 1 for num_locs in valid_location_groups.values()): + valid_location_groups = {name: num_locs for name, num_locs in valid_location_groups.items() if num_locs > 1} + + location_groups_with_weights = { + # Listen. Just don't worry about it. :))) + location_group: (x ** 0.6) * math.e ** (- (x / 7) ** 0.6) if x > 6 else x / 6 + for location_group, x in valid_location_groups.items() + } + + location_groups = list(location_groups_with_weights.keys()) + weights = list(location_groups_with_weights.values()) + + return world.random.choices(location_groups, weights, k=1)[0], "Group" + + if allow_regions: + return cast(Region, hint_loc.parent_region).name, "Region" + + return "Everywhere", "Everywhere" + + def word_direct_hint(world: "WitnessWorld", hint: WitnessLocationHint) -> WitnessWordedHint: location_name = hint.location.name if hint.location.player != world.player: @@ -182,12 +231,37 @@ def word_direct_hint(world: "WitnessWorld", hint: WitnessLocationHint) -> Witnes if item.player != world.player: item_name += " (" + world.multiworld.get_player_name(item.player) + ")" - if hint.hint_came_from_location: - hint_text = f"{location_name} contains {item_name}." - else: - hint_text = f"{item_name} can be found at {location_name}." + hint_text = "" + area: Optional[str] = None + + if world.options.vague_hints: + chosen_group, group_type = try_getting_location_group_for_location(world, hint.location) + + if hint.location.player == world.player: + area = chosen_group + + # local locations should only ever return a location group, as Witness defines groups for every location. + hint_text = f"{item_name} can be found in the {area} area." + else: + player_name = world.multiworld.get_player_name(hint.location.player) + + if group_type == "Everywhere": + location_name = f"a location in {player_name}'s world" + elif group_type == "Group": + location_name = f"a \"{chosen_group}\" location in {player_name}'s world" + elif group_type == "Region": + if chosen_group == "Menu": + location_name = f"a location near the start of {player_name}'s game (\"Menu\" region)" + else: + location_name = f"a location in {player_name}'s \"{chosen_group}\" region" + + if hint_text == "": + if hint.hint_came_from_location: + hint_text = f"{location_name} contains {item_name}." + else: + hint_text = f"{item_name} can be found at {location_name}." - return WitnessWordedHint(hint_text, hint.location) + return WitnessWordedHint(hint_text, hint.location, area=area, vague_location_hint=bool(world.options.vague_hints)) def hint_from_item(world: "WitnessWorld", item_name: str, @@ -222,45 +296,55 @@ def hint_from_location(world: "WitnessWorld", location: str) -> Optional[Witness return WitnessLocationHint(world.get_location(location), True) -def get_items_and_locations_in_random_order(world: "WitnessWorld", - own_itempool: List["WitnessItem"]) -> Tuple[List[str], List[str]]: - prog_items_in_this_world = sorted( +def get_item_and_location_names_in_random_order(world: "WitnessWorld", + own_itempool: List["WitnessItem"]) -> Tuple[List[str], List[str]]: + prog_item_names_in_this_world = [ item.name for item in own_itempool if item.advancement and item.code and item.location - ) - locations_in_this_world = sorted( - location.name for location in world.multiworld.get_locations(world.player) - if location.address and location.progress_type != LocationProgressType.EXCLUDED - ) + ] + world.random.shuffle(prog_item_names_in_this_world) - world.random.shuffle(prog_items_in_this_world) + locations_in_this_world = [ + location for location in world.multiworld.get_locations(world.player) + if location.item and not location.is_event and location.progress_type != LocationProgressType.EXCLUDED + ] world.random.shuffle(locations_in_this_world) - return prog_items_in_this_world, locations_in_this_world + if world.options.vague_hints: + locations_in_this_world.sort(key=lambda location: cast(Item, location.item).advancement) + + location_names_in_this_world = [location.name for location in locations_in_this_world] + + return prog_item_names_in_this_world, location_names_in_this_world def make_always_and_priority_hints(world: "WitnessWorld", own_itempool: List["WitnessItem"], already_hinted_locations: Set[Location] ) -> Tuple[List[WitnessLocationHint], List[WitnessLocationHint]]: - prog_items_in_this_world, loc_in_this_world = get_items_and_locations_in_random_order(world, own_itempool) - always_locations = [ - location for location in get_always_hint_locations(world) - if location in loc_in_this_world - ] + prog_items_in_this_world, loc_in_this_world = get_item_and_location_names_in_random_order(world, own_itempool) + always_items = [ item for item in get_always_hint_items(world) if item in prog_items_in_this_world ] - priority_locations = [ - location for location in get_priority_hint_locations(world) - if location in loc_in_this_world - ] priority_items = [ item for item in get_priority_hint_items(world) if item in prog_items_in_this_world ] + if world.options.vague_hints: + always_locations, priority_locations = [], [] + else: + always_locations = [ + location for location in get_always_hint_locations(world) + if location in loc_in_this_world + ] + priority_locations = [ + location for location in get_priority_hint_locations(world) + if location in loc_in_this_world + ] + # Get always and priority location/item hints always_location_hints = {hint_from_location(world, location) for location in always_locations} always_item_hints = {hint_from_item(world, item, own_itempool) for item in always_items} @@ -289,7 +373,7 @@ def make_always_and_priority_hints(world: "WitnessWorld", own_itempool: List["Wi def make_extra_location_hints(world: "WitnessWorld", hint_amount: int, own_itempool: List["WitnessItem"], already_hinted_locations: Set[Location], hints_to_use_first: List[WitnessLocationHint], unhinted_locations_for_hinted_areas: Dict[str, Set[Location]]) -> List[WitnessWordedHint]: - prog_items_in_this_world, locations_in_this_world = get_items_and_locations_in_random_order(world, own_itempool) + prog_items_in_this_world, locations_in_this_world = get_item_and_location_names_in_random_order(world, own_itempool) next_random_hint_is_location = world.random.randrange(0, 2) @@ -382,7 +466,7 @@ def get_hintable_areas(world: "WitnessWorld") -> Tuple[Dict[str, List[Location]] for region in static_witness_logic.ALL_AREAS_BY_NAME[area]["regions"] if region in world.player_regions.created_region_names ] - locations = [location for region in regions for location in region.get_locations() if location.address] + locations = [location for region in regions for location in region.get_locations() if not location.is_event] if locations: locations_per_area[area] = locations @@ -391,22 +475,22 @@ def get_hintable_areas(world: "WitnessWorld") -> Tuple[Dict[str, List[Location]] return locations_per_area, items_per_area -def word_area_hint(world: "WitnessWorld", hinted_area: str, corresponding_items: List[Item]) -> Tuple[str, int]: +def word_area_hint(world: "WitnessWorld", hinted_area: str, area_items: List[Item]) -> Tuple[str, int, Optional[int]]: """ Word the hint for an area using natural sounding language. This takes into account how much progression there is, how much of it is local/non-local, and whether there are any local lasers to be found in this area. """ - local_progression = sum(item.player == world.player and item.advancement for item in corresponding_items) - non_local_progression = sum(item.player != world.player and item.advancement for item in corresponding_items) + local_progression = sum(item.player == world.player and item.advancement for item in area_items) + non_local_progression = sum(item.player != world.player and item.advancement for item in area_items) laser_names = {"Symmetry Laser", "Desert Laser", "Quarry Laser", "Shadows Laser", "Town Laser", "Monastery Laser", "Jungle Laser", "Bunker Laser", "Swamp Laser", "Treehouse Laser", "Keep Laser", } local_lasers = sum( item.player == world.player and item.name in laser_names - for item in corresponding_items + for item in area_items ) total_progression = non_local_progression + local_progression @@ -415,11 +499,29 @@ def word_area_hint(world: "WitnessWorld", hinted_area: str, corresponding_items: area_progression_word = "Both" if total_progression == 2 else "All" + hint_string = f"In the {hinted_area} area, you will find " + + hunt_panels = None + if world.options.victory_condition == "panel_hunt": + hunt_panels = sum( + static_witness_logic.ENTITIES_BY_HEX[hunt_entity]["area"]["name"] == hinted_area + for hunt_entity in world.player_logic.HUNT_ENTITIES + ) + + if not hunt_panels: + hint_string += "no Hunt Panels and " + + elif hunt_panels == 1: + hint_string += "1 Hunt Panel and " + + else: + hint_string += f"{hunt_panels} Hunt Panels and " + if not total_progression: - hint_string = f"In the {hinted_area} area, you will find no progression items." + hint_string += "no progression items." elif total_progression == 1: - hint_string = f"In the {hinted_area} area, you will find 1 progression item." + hint_string += "1 progression item." if player_count > 1: if local_lasers: @@ -434,7 +536,7 @@ def word_area_hint(world: "WitnessWorld", hinted_area: str, corresponding_items: hint_string += "\nThis item is a laser." else: - hint_string = f"In the {hinted_area} area, you will find {total_progression} progression items." + hint_string += f"{total_progression} progression items." if local_lasers == total_progression: sentence_end = (" for this world." if player_count > 1 else ".") @@ -471,7 +573,7 @@ def word_area_hint(world: "WitnessWorld", hinted_area: str, corresponding_items: elif local_lasers: hint_string += f"\n{local_lasers} of them are lasers." - return hint_string, total_progression + return hint_string, total_progression, hunt_panels def make_area_hints(world: "WitnessWorld", amount: int, already_hinted_locations: Set[Location] @@ -483,9 +585,9 @@ def make_area_hints(world: "WitnessWorld", amount: int, already_hinted_locations hints = [] for hinted_area in hinted_areas: - hint_string, prog_amount = word_area_hint(world, hinted_area, items_per_area[hinted_area]) + hint_string, prog_amount, hunt_panels = word_area_hint(world, hinted_area, items_per_area[hinted_area]) - hints.append(WitnessWordedHint(hint_string, None, f"hinted_area:{hinted_area}", prog_amount)) + hints.append(WitnessWordedHint(hint_string, None, f"hinted_area:{hinted_area}", prog_amount, hunt_panels)) if len(hinted_areas) < amount: player_name = world.multiworld.get_player_name(world.player) @@ -585,29 +687,44 @@ def create_all_hints(world: "WitnessWorld", hint_amount: int, area_hints: int, return generated_hints -def make_compact_hint_data(hint: WitnessWordedHint, local_player_number: int) -> CompactItemData: +def get_compact_hint_args(hint: WitnessWordedHint, local_player_number: int) -> CompactHintArgs: + """ + Arg reference: + + Area Hint: 1st Arg is the amount of area progression and hunt panels. 2nd Arg is the name of the area. + Location Hint: 1st Arg is the location's address, second arg is the player number the location belongs to. + Junk Hint: 1st Arg is -1, second arg is this slot's player number. + """ + + # Is Area Hint + if hint.area_amount is not None: + area_amount = hint.area_amount + hunt_panels = hint.area_hunt_panels + + area_and_hunt_panels = area_amount + # Encode amounts together + if hunt_panels: + area_and_hunt_panels += 0x100 * hunt_panels + + return hint.area, area_and_hunt_panels + location = hint.location - area_amount = hint.area_amount - # -1 if junk hint, address if location hint, area string if area hint - arg_1: Union[str, int] + # Is location hint if location and location.address is not None: - arg_1 = location.address - elif hint.area is not None: - arg_1 = hint.area - else: - arg_1 = -1 - - # self.player if junk hint, player if location hint, progression amount if area hint - arg_2: int - if area_amount is not None: - arg_2 = area_amount - elif location is not None: - arg_2 = location.player - else: - arg_2 = local_player_number + if hint.vague_location_hint and location.player == local_player_number: + assert hint.area is not None # A local vague location hint should have an area argument + return location.address, "containing_area:" + hint.area + else: + return location.address, location.player # Scouting does not matter for other players (currently) + + # Is junk / undefined hint + return -1, local_player_number + - return hint.wording, arg_1, arg_2 +def make_compact_hint_data(hint: WitnessWordedHint, local_player_number: int) -> CompactHintData: + compact_arg_1, compact_arg_2 = get_compact_hint_args(hint, local_player_number) + return hint.wording, compact_arg_1, compact_arg_2 def make_laser_hints(world: "WitnessWorld", laser_names: List[str]) -> Dict[str, WitnessWordedHint]: diff --git a/worlds/witness/locations.py b/worlds/witness/locations.py index 1796f051b896..f1c16550399a 100644 --- a/worlds/witness/locations.py +++ b/worlds/witness/locations.py @@ -50,7 +50,7 @@ def __init__(self, world: "WitnessWorld", player_logic: WitnessPlayerLogic) -> N self.CHECK_PANELHEX_TO_ID = { static_witness_logic.ENTITIES_BY_NAME[ch]["entity_hex"]: static_witness_locations.ALL_LOCATIONS_TO_ID[ch] for ch in self.CHECK_LOCATIONS - if static_witness_logic.ENTITIES_BY_NAME[ch]["entityType"] in self.PANEL_TYPES_TO_SHUFFLE + if static_witness_logic.ENTITIES_BY_NAME[ch]["locationType"] in self.PANEL_TYPES_TO_SHUFFLE } dog_hex = static_witness_logic.ENTITIES_BY_NAME["Town Pet the Dog"]["entity_hex"] @@ -61,11 +61,9 @@ def __init__(self, world: "WitnessWorld", player_logic: WitnessPlayerLogic) -> N sorted(self.CHECK_PANELHEX_TO_ID.items(), key=lambda item: item[1]) ) - event_locations = set(player_logic.USED_EVENT_NAMES_BY_HEX) - self.EVENT_LOCATION_TABLE = { - static_witness_locations.get_event_name(entity_hex): None - for entity_hex in event_locations + event_location: None + for event_location in player_logic.EVENT_ITEM_PAIRS } check_dict = { diff --git a/worlds/witness/options.py b/worlds/witness/options.py index 4855fc715933..6f7222d5f9b4 100644 --- a/worlds/witness/options.py +++ b/worlds/witness/options.py @@ -173,6 +173,7 @@ class VictoryCondition(Choice): - Challenge: Beat the secret Challenge (requires Challenge Lasers). - Mountain Box Short: Input the short solution to the Mountaintop Box (requires Mountain Lasers). - Mountain Box Long: Input the long solution to the Mountaintop Box (requires Challenge Lasers). + - Panel Hunt: Solve a specific number of randomly selected panels before going to the secret ending in Tutorial. It is important to note that while the Mountain Box requires Desert Laser to be redirected in Town for that laser to count, the laser locks on the Elevator and Challenge Timer panels do not. @@ -182,6 +183,62 @@ class VictoryCondition(Choice): option_challenge = 1 option_mountain_box_short = 2 option_mountain_box_long = 3 + option_panel_hunt = 4 + + +class PanelHuntTotal(Range): + """ + Sets the number of random panels that will get marked as "Panel Hunt" panels in the "Panel Hunt" game mode. + """ + display_name = "Total Panel Hunt panels" + range_start = 5 + range_end = 100 + default = 40 + + +class PanelHuntRequiredPercentage(Range): + """ + Determines the percentage of "Panel Hunt" panels that need to be solved to win. + """ + display_name = "Percentage of required Panel Hunt panels" + range_start = 20 + range_end = 100 + default = 63 + + +class PanelHuntPostgame(Choice): + """ + In panel hunt, there are technically no postgame locations. + Depending on your options, this can leave Mountain and Caves as two huge areas with Hunt Panels in them that cannot be reached until you get enough lasers to go through the very linear Mountain descent. + Panel Hunt tends to be more fun when the world is open. + This option lets you force anything locked by lasers to be disabled, and thus ineligible for Hunt Panels. + To compensate, the respective mountain box solution (short box / long box) will be forced to be a Hunt Panel. + Does nothing if Panel Hunt is not your victory condition. + + Note: The "Mountain Lasers" option may also affect locations locked by challenge lasers if the only path to those locations leads through the Mountain Entry. + """ + + display_name = "Force postgame in Panel Hunt" + + option_everything_is_eligible = 0 + option_disable_mountain_lasers_locations = 1 + option_disable_challenge_lasers_locations = 2 + option_disable_anything_locked_by_lasers = 3 + default = 3 + + +class PanelHuntDiscourageSameAreaFactor(Range): + """ + The greater this value, the less likely it is that many Hunt Panels show up in the same area. + + At 0, Hunt Panels will be selected randomly. + At 100, Hunt Panels will be almost completely evenly distributed between areas. + """ + display_name = "Panel Hunt Discourage Same Area Factor" + + range_start = 0 + range_end = 100 + default = 40 class PuzzleRandomization(Choice): @@ -274,6 +331,25 @@ class HintAmount(Range): default = 12 +class VagueHints(Choice): + """Make Location Hints a bit more vague, where they only tell you about the general area the item is in. + Area Hints will be generated as normal. + + If set to "stable", only location groups will be used. If location groups aren't implemented for the game your item ended up in, your hint will instead only tell you that the item is "somewhere in" that game. + If set to "experimental", region names will be eligible as well, and you will never receive a "somewhere in" hint. Keep in mind that region names are not always intended to be comprehensible to players — only turn this on if you are okay with a bit of chaos. + + + The distinction does not matter in single player, as Witness implements location groups for every location. + + Also, please don't pester any devs about implementing location groups. Bring it up nicely, accept their response even if it is "No". + """ + display_name = "Vague Hints" + + option_off = 0 + option_stable = 1 + option_experimental = 2 + + class AreaHintPercentage(Range): """ There are two types of hints for The Witness. @@ -332,6 +408,10 @@ class TheWitnessOptions(PerGameCommonOptions): victory_condition: VictoryCondition mountain_lasers: MountainLasers challenge_lasers: ChallengeLasers + panel_hunt_total: PanelHuntTotal + panel_hunt_required_percentage: PanelHuntRequiredPercentage + panel_hunt_postgame: PanelHuntPostgame + panel_hunt_discourage_same_area_factor: PanelHuntDiscourageSameAreaFactor early_caves: EarlyCaves early_symbol_item: EarlySymbolItem elevators_come_to_you: ElevatorsComeToYou @@ -339,6 +419,7 @@ class TheWitnessOptions(PerGameCommonOptions): trap_weights: TrapWeights puzzle_skip_amount: PuzzleSkipAmount hint_amount: HintAmount + vague_hints: VagueHints area_hint_percentage: AreaHintPercentage laser_hints: LaserHints death_link: DeathLink @@ -352,6 +433,12 @@ class TheWitnessOptions(PerGameCommonOptions): MountainLasers, ChallengeLasers, ]), + OptionGroup("Panel Hunt Settings", [ + PanelHuntRequiredPercentage, + PanelHuntTotal, + PanelHuntPostgame, + PanelHuntDiscourageSameAreaFactor, + ], start_collapsed=True), OptionGroup("Locations", [ ShuffleDiscardedPanels, ShuffleVaultBoxes, @@ -375,6 +462,7 @@ class TheWitnessOptions(PerGameCommonOptions): ]), OptionGroup("Hints", [ HintAmount, + VagueHints, AreaHintPercentage, LaserHints ]), diff --git a/worlds/witness/player_items.py b/worlds/witness/player_items.py index 718fd7d172ba..44a959f2b428 100644 --- a/worlds/witness/player_items.py +++ b/worlds/witness/player_items.py @@ -97,7 +97,7 @@ def __init__(self, world: "WitnessWorld", player_logic: WitnessPlayerLogic, # Add event items to the item definition list for later lookup. for event_location in self._locations.EVENT_LOCATION_TABLE: - location_name = player_logic.EVENT_ITEM_PAIRS[event_location] + location_name = player_logic.EVENT_ITEM_PAIRS[event_location][0] self.item_data[location_name] = ItemData(None, ItemDefinition(0, ItemCategory.EVENT), ItemClassification.progression, False) diff --git a/worlds/witness/player_logic.py b/worlds/witness/player_logic.py index e8d11f43f51c..5125dfef0aa1 100644 --- a/worlds/witness/player_logic.py +++ b/worlds/witness/player_logic.py @@ -17,7 +17,6 @@ import copy from collections import defaultdict -from logging import warning from typing import TYPE_CHECKING, Dict, List, Set, Tuple, cast from .data import static_logic as static_witness_logic @@ -36,6 +35,7 @@ get_early_caves_list, get_early_caves_start_list, get_elevators_come_to_you, + get_entity_hunt, get_ep_all_individual, get_ep_easy, get_ep_no_eclipse, @@ -51,6 +51,7 @@ logical_or_witness_rules, parse_lambda, ) +from .entity_hunt import EntityHuntPicker if TYPE_CHECKING: from . import WitnessWorld @@ -60,7 +61,7 @@ class WitnessPlayerLogic: """WITNESS LOGIC CLASS""" VICTORY_LOCATION: str - + def __init__(self, world: "WitnessWorld", disabled_locations: Set[str], start_inv: Dict[str, int]) -> None: self.YAML_DISABLED_LOCATIONS: Set[str] = disabled_locations self.YAML_ADDED_ITEMS: Dict[str, int] = start_inv @@ -104,7 +105,7 @@ def __init__(self, world: "WitnessWorld", disabled_locations: Set[str], start_in ) self.REQUIREMENTS_BY_HEX: Dict[str, WitnessRule] = {} - self.EVENT_ITEM_PAIRS: Dict[str, str] = {} + self.EVENT_ITEM_PAIRS: Dict[str, Tuple[str, str]] = {} self.COMPLETELY_DISABLED_ENTITIES: Set[str] = set() self.DISABLE_EVERYTHING_BEHIND: Set[str] = set() self.PRECOMPLETED_LOCATIONS: Set[str] = set() @@ -112,6 +113,9 @@ def __init__(self, world: "WitnessWorld", disabled_locations: Set[str], start_in self.ADDED_CHECKS: Set[str] = set() self.VICTORY_LOCATION = "0x0356B" + self.PRE_PICKED_HUNT_ENTITIES: Set[str] = set() + self.HUNT_ENTITIES: Set[str] = set() + self.ALWAYS_EVENT_NAMES_BY_HEX = { "0x00509": "+1 Laser (Symmetry Laser)", "0x012FB": "+1 Laser (Desert Laser)", @@ -129,7 +133,7 @@ def __init__(self, world: "WitnessWorld", disabled_locations: Set[str], start_in "0xFFF00": "Bottom Floor Discard Turns On", } - self.USED_EVENT_NAMES_BY_HEX: Dict[str, str] = {} + self.USED_EVENT_NAMES_BY_HEX: Dict[str, List[str]] = {} self.CONDITIONAL_EVENTS: Dict[Tuple[str, str], str] = {} # The basic requirements to solve each entity come from StaticWitnessLogic. @@ -142,6 +146,10 @@ def __init__(self, world: "WitnessWorld", disabled_locations: Set[str], start_in # This will make the access conditions way faster, instead of recursively checking dependent entities each time. self.make_dependency_reduced_checklist() + if world.options.victory_condition == "panel_hunt": + picker = EntityHuntPicker(self, world, self.PRE_PICKED_HUNT_ENTITIES) + self.HUNT_ENTITIES = picker.pick_panel_hunt_panels(world.options.panel_hunt_total.value) + # Finalize which items actually exist in the MultiWorld and which get grouped into progressive items. self.finalize_items() @@ -226,7 +234,7 @@ def reduce_req_within_region(self, entity_hex: str) -> WitnessRule: dep_obj = self.REFERENCE_LOGIC.ENTITIES_BY_HEX.get(option_entity, {}) if option_entity in {"7 Lasers", "11 Lasers", "7 Lasers + Redirect", "11 Lasers + Redirect", - "PP2 Weirdness", "Theater to Tunnels"}: + "PP2 Weirdness", "Theater to Tunnels", "Entity Hunt"}: new_items = frozenset({frozenset([option_entity])}) elif option_entity in self.DISABLE_EVERYTHING_BEHIND: new_items = frozenset() @@ -241,12 +249,12 @@ def reduce_req_within_region(self, entity_hex: str) -> WitnessRule: # If the dependent entity is unsolvable and is NOT an EP, this requirement option is invalid. new_items = frozenset() elif option_entity in self.ALWAYS_EVENT_NAMES_BY_HEX: - new_items = frozenset({frozenset([option_entity])}) + new_items = frozenset({frozenset([self.ALWAYS_EVENT_NAMES_BY_HEX[option_entity]])}) elif (entity_hex, option_entity) in self.CONDITIONAL_EVENTS: - new_items = frozenset({frozenset([option_entity])}) - self.USED_EVENT_NAMES_BY_HEX[option_entity] = self.CONDITIONAL_EVENTS[ - (entity_hex, option_entity) - ] + new_items = frozenset({frozenset([self.CONDITIONAL_EVENTS[(entity_hex, option_entity)]])}) + self.USED_EVENT_NAMES_BY_HEX[option_entity].append( + self.CONDITIONAL_EVENTS[(entity_hex, option_entity)] + ) else: new_items = theoretical_new_items if dep_obj["region"] and entity_obj["region"] != dep_obj["region"]: @@ -404,7 +412,7 @@ def make_single_adjustment(self, adj_type: str, line: str) -> None: line = self.REFERENCE_LOGIC.ENTITIES_BY_HEX[line]["checkName"] self.ADDED_CHECKS.add(line) - def handle_postgame(self, world: "WitnessWorld") -> List[List[str]]: + def handle_regular_postgame(self, world: "WitnessWorld") -> List[List[str]]: """ In shuffle_postgame, panels that become accessible "after or at the same time as the goal" are disabled. This mostly involves the disabling of key panels (e.g. long box when the goal is short box). @@ -435,6 +443,7 @@ def handle_postgame(self, world: "WitnessWorld") -> List[List[str]]: # If we have a long box goal, Challenge is behind the amount of lasers required to just win. # This is technically slightly incorrect as the Challenge Vault Box could contain a *symbol* that is required # to open Mountain Entry (Stars 2). However, since there is a very easy sphere 1 snipe, this is not considered. + if victory == "mountain_box_long": postgame_adjustments.append(["Disabled Locations:", "0x0A332 (Challenge Timer Start)"]) @@ -479,6 +488,42 @@ def handle_postgame(self, world: "WitnessWorld") -> List[List[str]]: return postgame_adjustments + def handle_panelhunt_postgame(self, world: "WitnessWorld") -> List[List[str]]: + postgame_adjustments = [] + + # Make some quick references to some options + panel_hunt_postgame = world.options.panel_hunt_postgame + chal_lasers = world.options.challenge_lasers + + disable_mountain_lasers = ( + panel_hunt_postgame == "disable_mountain_lasers_locations" + or panel_hunt_postgame == "disable_anything_locked_by_lasers" + ) + + disable_challenge_lasers = ( + panel_hunt_postgame == "disable_challenge_lasers_locations" + or panel_hunt_postgame == "disable_anything_locked_by_lasers" + ) + + if disable_mountain_lasers: + self.DISABLE_EVERYTHING_BEHIND.add("0x09F7F") # Short box + self.PRE_PICKED_HUNT_ENTITIES.add("0x09F7F") + self.COMPLETELY_DISABLED_ENTITIES.add("0x3D9A9") # Elevator Start + + # If mountain lasers are disabled, and challenge lasers > 7, the box will need to be rotated + if chal_lasers > 7: + postgame_adjustments.append([ + "Requirement Changes:", + "0xFFF00 - 11 Lasers - True", + ]) + + if disable_challenge_lasers: + self.DISABLE_EVERYTHING_BEHIND.add("0xFFF00") # Long box + self.PRE_PICKED_HUNT_ENTITIES.add("0xFFF00") + self.COMPLETELY_DISABLED_ENTITIES.add("0x0A332") # Challenge Timer + + return postgame_adjustments + def make_options_adjustments(self, world: "WitnessWorld") -> None: """Makes logic adjustments based on options""" adjustment_linesets_in_order = [] @@ -500,10 +545,17 @@ def make_options_adjustments(self, world: "WitnessWorld") -> None: self.VICTORY_LOCATION = "0x09F7F" elif victory == "mountain_box_long": self.VICTORY_LOCATION = "0xFFF00" + elif victory == "panel_hunt": + self.VICTORY_LOCATION = "0x03629" + self.COMPLETELY_DISABLED_ENTITIES.add("0x3352F") # Exclude panels from the post-game if shuffle_postgame is false. - if not world.options.shuffle_postgame: - adjustment_linesets_in_order += self.handle_postgame(world) + if not world.options.shuffle_postgame and victory != "panel_hunt": + adjustment_linesets_in_order += self.handle_regular_postgame(world) + + # Exclude panels from the post-game if shuffle_postgame is false. + if victory == "panel_hunt" and world.options.panel_hunt_postgame: + adjustment_linesets_in_order += self.handle_panelhunt_postgame(world) # Exclude Discards / Vaults if not world.options.shuffle_discarded_panels: @@ -570,6 +622,9 @@ def make_options_adjustments(self, world: "WitnessWorld") -> None: if world.options.elevators_come_to_you: adjustment_linesets_in_order.append(get_elevators_come_to_you()) + if world.options.victory_condition == "panel_hunt": + adjustment_linesets_in_order.append(get_entity_hunt()) + for item in self.YAML_ADDED_ITEMS: adjustment_linesets_in_order.append(["Items:", item]) @@ -603,7 +658,7 @@ def make_options_adjustments(self, world: "WitnessWorld") -> None: if loc_obj["entityType"] == "EP": self.COMPLETELY_DISABLED_ENTITIES.add(loc_obj["entity_hex"]) - elif loc_obj["entityType"] in {"General", "Vault", "Discard"}: + elif loc_obj["entityType"] == "Panel": self.EXCLUDED_LOCATIONS.add(loc_obj["entity_hex"]) for adjustment_lineset in adjustment_linesets_in_order: @@ -686,6 +741,7 @@ def find_unsolvable_entities(self, world: "WitnessWorld") -> None: # Check if any regions have become unreachable. reachable_regions = self.discover_reachable_regions() new_unreachable_regions = all_regions - reachable_regions - self.UNREACHABLE_REGIONS + if new_unreachable_regions: self.UNREACHABLE_REGIONS.update(new_unreachable_regions) @@ -741,9 +797,12 @@ def reduce_connection_requirement(self, connection: Tuple[str, WitnessRule]) -> if not self.solvability_guaranteed(entity) or entity in self.DISABLE_EVERYTHING_BEHIND: individual_entity_requirements.append(frozenset()) # If a connection requires acquiring an event, add that event to its requirements. - elif (entity in self.ALWAYS_EVENT_NAMES_BY_HEX - or entity not in self.REFERENCE_LOGIC.ENTITIES_BY_HEX): + elif entity not in self.REFERENCE_LOGIC.ENTITIES_BY_HEX: individual_entity_requirements.append(frozenset({frozenset({entity})})) + elif entity in self.ALWAYS_EVENT_NAMES_BY_HEX: + individual_entity_requirements.append( + frozenset({frozenset({self.ALWAYS_EVENT_NAMES_BY_HEX[entity]})}) + ) # If a connection requires entities, use their newly calculated independent requirements. else: entity_req = self.get_entity_requirement(entity) @@ -778,7 +837,7 @@ def make_dependency_reduced_checklist(self) -> None: # We also clear any data structures that we might have filled in a previous dependency reduction self.REQUIREMENTS_BY_HEX = {} - self.USED_EVENT_NAMES_BY_HEX = {} + self.USED_EVENT_NAMES_BY_HEX = defaultdict(list) self.CONNECTIONS_BY_REGION_NAME = {} self.PROG_ITEMS_ACTUALLY_IN_THE_GAME_NO_MULTI = set() @@ -868,7 +927,6 @@ def determine_unrequired_entities(self, world: "WitnessWorld") -> None: "0x17CC4": come_to_you or eps_shuffled, # Quarry Elevator Panel "0x17E2B": come_to_you and boat_shuffled or eps_shuffled, # Swamp Long Bridge "0x0CF2A": False, # Jungle Monastery Garden Shortcut - "0x17CAA": remote_doors, # Jungle Monastery Garden Shortcut Panel "0x0364E": False, # Monastery Laser Shortcut Door "0x03713": remote_doors, # Monastery Laser Shortcut Panel "0x03313": False, # Orchard Second Gate @@ -884,23 +942,17 @@ def determine_unrequired_entities(self, world: "WitnessWorld") -> None: # Jungle Popup Wall Panel } + # In panel hunt, all panels are game, so all panels need to be reachable (unless disabled) + if goal == "panel_hunt": + for entity_hex in is_item_required_dict: + if static_witness_logic.ENTITIES_BY_HEX[entity_hex]["entityType"] == "Panel": + is_item_required_dict[entity_hex] = True + # Now, return the keys of the dict entries where the result is False to get unrequired major items self.ENTITIES_WITHOUT_ENSURED_SOLVABILITY |= { item_name for item_name, is_required in is_item_required_dict.items() if not is_required } - def make_event_item_pair(self, entity_hex: str) -> Tuple[str, str]: - """ - Makes a pair of an event panel and its event item - """ - action = " Opened" if self.REFERENCE_LOGIC.ENTITIES_BY_HEX[entity_hex]["entityType"] == "Door" else " Solved" - - name = self.REFERENCE_LOGIC.ENTITIES_BY_HEX[entity_hex]["checkName"] + action - if entity_hex not in self.USED_EVENT_NAMES_BY_HEX: - warning(f'Entity "{name}" does not have an associated event name.') - self.USED_EVENT_NAMES_BY_HEX[entity_hex] = name + " Event" - return (name, self.USED_EVENT_NAMES_BY_HEX[entity_hex]) - def make_event_panel_lists(self) -> None: """ Makes event-item pairs for entities with associated events, unless these entities are disabled. @@ -908,13 +960,36 @@ def make_event_panel_lists(self) -> None: self.ALWAYS_EVENT_NAMES_BY_HEX[self.VICTORY_LOCATION] = "Victory" - self.USED_EVENT_NAMES_BY_HEX.update(self.ALWAYS_EVENT_NAMES_BY_HEX) + for event_hex, event_name in self.ALWAYS_EVENT_NAMES_BY_HEX.items(): + self.USED_EVENT_NAMES_BY_HEX[event_hex].append(event_name) self.USED_EVENT_NAMES_BY_HEX = { - event_hex: event_name for event_hex, event_name in self.USED_EVENT_NAMES_BY_HEX.items() + event_hex: event_list for event_hex, event_list in self.USED_EVENT_NAMES_BY_HEX.items() if self.solvability_guaranteed(event_hex) } - for panel in self.USED_EVENT_NAMES_BY_HEX: - pair = self.make_event_item_pair(panel) - self.EVENT_ITEM_PAIRS[pair[0]] = pair[1] + for entity_hex, event_names in self.USED_EVENT_NAMES_BY_HEX.items(): + entity_obj = self.REFERENCE_LOGIC.ENTITIES_BY_HEX[entity_hex] + entity_name = entity_obj["checkName"] + entity_type = entity_obj["entityType"] + + if entity_type == "Door": + action = " Opened" + elif entity_type == "Laser": + action = " Activated" + else: + action = " Solved" + + for i, event_name in enumerate(event_names): + if i == 0: + self.EVENT_ITEM_PAIRS[entity_name + action] = (event_name, entity_hex) + else: + self.EVENT_ITEM_PAIRS[entity_name + action + f" (Effect {i + 1})"] = (event_name, entity_hex) + + # Make Panel Hunt Events + for entity_hex in self.HUNT_ENTITIES: + entity_obj = self.REFERENCE_LOGIC.ENTITIES_BY_HEX[entity_hex] + entity_name = entity_obj["checkName"] + self.EVENT_ITEM_PAIRS[entity_name + " (Panel Hunt)"] = ("+1 Panel Hunt", entity_hex) + + return diff --git a/worlds/witness/regions.py b/worlds/witness/regions.py index 2528c8abe22b..6d1f8093af85 100644 --- a/worlds/witness/regions.py +++ b/worlds/witness/regions.py @@ -9,7 +9,6 @@ from worlds.generic.Rules import CollectionRule -from .data import static_locations as static_witness_locations from .data import static_logic as static_witness_logic from .data.static_logic import StaticWitnessLogicObj from .data.utils import WitnessRule, optimize_witness_rule @@ -111,16 +110,24 @@ def create_regions(self, world: "WitnessWorld", player_logic: WitnessPlayerLogic if k not in player_logic.UNREACHABLE_REGIONS } + event_locations_per_region = defaultdict(list) + + for event_location, event_item_and_entity in player_logic.EVENT_ITEM_PAIRS.items(): + region = static_witness_logic.ENTITIES_BY_HEX[event_item_and_entity[1]]["region"] + if region is None: + region_name = "Entry" + else: + region_name = region["name"] + event_locations_per_region[region_name].append(event_location) + for region_name, region in regions_to_create.items(): locations_for_this_region = [ self.reference_logic.ENTITIES_BY_HEX[panel]["checkName"] for panel in region["entities"] if self.reference_logic.ENTITIES_BY_HEX[panel]["checkName"] in self.player_locations.CHECK_LOCATION_TABLE ] - locations_for_this_region += [ - static_witness_locations.get_event_name(panel) for panel in region["entities"] - if static_witness_locations.get_event_name(panel) in self.player_locations.EVENT_LOCATION_TABLE - ] + + locations_for_this_region += event_locations_per_region[region_name] all_locations = all_locations | set(locations_for_this_region) diff --git a/worlds/witness/rules.py b/worlds/witness/rules.py index 12a9a1ed4b59..eecea8f30bf0 100644 --- a/worlds/witness/rules.py +++ b/worlds/witness/rules.py @@ -10,7 +10,6 @@ from .data import static_logic as static_witness_logic from .data.utils import WitnessRule -from .locations import WitnessPlayerLocations from .player_logic import WitnessPlayerLogic if TYPE_CHECKING: @@ -31,42 +30,37 @@ ] -def _has_laser(laser_hex: str, world: "WitnessWorld", player: int, redirect_required: bool) -> CollectionRule: +def _can_do_panel_hunt(world: "WitnessWorld") -> CollectionRule: + required = world.panel_hunt_required_count + player = world.player + return lambda state: state.has("+1 Panel Hunt", player, required) + + +def _has_laser(laser_hex: str, world: "WitnessWorld", redirect_required: bool) -> CollectionRule: + player = world.player + laser_name = static_witness_logic.ENTITIES_BY_HEX[laser_hex]["checkName"] + + # Workaround for intentional naming inconsistency + if laser_name == "Symmetry Island Laser": + laser_name = "Symmetry Laser" + if laser_hex == "0x012FB" and redirect_required: - return lambda state: ( - _can_solve_panel(laser_hex, world, world.player, world.player_logic, world.player_locations)(state) - and state.has("Desert Laser Redirection", player) - ) + return lambda state: state.has_all([f"+1 Laser ({laser_name})", "Desert Laser Redirection"], player) - return _can_solve_panel(laser_hex, world, world.player, world.player_logic, world.player_locations) + return lambda state: state.has(f"+1 Laser ({laser_name})", player) def _has_lasers(amount: int, world: "WitnessWorld", redirect_required: bool) -> CollectionRule: laser_lambdas = [] for laser_hex in laser_hexes: - has_laser_lambda = _has_laser(laser_hex, world, world.player, redirect_required) + has_laser_lambda = _has_laser(laser_hex, world, redirect_required) laser_lambdas.append(has_laser_lambda) return lambda state: sum(laser_lambda(state) for laser_lambda in laser_lambdas) >= amount -def _can_solve_panel(panel: str, world: "WitnessWorld", player: int, player_logic: WitnessPlayerLogic, - player_locations: WitnessPlayerLocations) -> CollectionRule: - """ - Determines whether a panel can be solved - """ - - panel_obj = player_logic.REFERENCE_LOGIC.ENTITIES_BY_HEX[panel] - entity_name = panel_obj["checkName"] - - if entity_name + " Solved" in player_locations.EVENT_LOCATION_TABLE: - return lambda state: state.has(player_logic.EVENT_ITEM_PAIRS[entity_name + " Solved"], player) - - return make_lambda(panel, world) - - def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool: """ For Expert PP2, you need a way to access PP2 from the front, and a separate way from the back. @@ -74,10 +68,10 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool: """ player = world.player - player_regions = world.player_regions + two_way_entrance_register = world.player_regions.two_way_entrance_register front_access = ( - any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 2nd Pressure Plate", "Keep"]) + any(e.can_reach(state) for e in two_way_entrance_register["Keep 2nd Pressure Plate", "Keep"]) and state.can_reach_region("Keep", player) ) @@ -88,7 +82,7 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool: # Front access works. Now, we need to check for the many ways to access PP2 from the back. # All of those ways lead through the PP3 exit door from PP4. So we check this first. - fourth_to_third = any(e.can_reach(state) for e in player_regions.two_way_entrance_register[ + fourth_to_third = any(e.can_reach(state) for e in two_way_entrance_register[ "Keep 3rd Pressure Plate", "Keep 4th Pressure Plate" ]) @@ -100,7 +94,7 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool: # The shadows shortcut is the simplest way. shadows_shortcut = ( - any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 4th Pressure Plate", "Shadows"]) + any(e.can_reach(state) for e in two_way_entrance_register["Keep 4th Pressure Plate", "Shadows"]) ) if shadows_shortcut: @@ -108,9 +102,7 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool: # We don't have the Shadows shortcut. This means we need to come in through the PP4 exit door instead. - tower_to_pp4 = any( - e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 4th Pressure Plate", "Keep Tower"] - ) + tower_to_pp4 = any(e.can_reach(state) for e in two_way_entrance_register["Keep 4th Pressure Plate", "Keep Tower"]) # If we don't have the PP4 exit door, we've run out of options. if not tower_to_pp4: @@ -119,7 +111,7 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool: # We have the PP4 exit door. If we can get to Keep Tower from behind, we can do PP2. # The simplest way would be the Tower Shortcut. - tower_shortcut = any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep", "Keep Tower"]) + tower_shortcut = any(e.can_reach(state) for e in two_way_entrance_register["Keep", "Keep Tower"]) if tower_shortcut: return True @@ -128,18 +120,14 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool: # Getting to Keep Tower through the hedge mazes. This can be done in a multitude of ways. # No matter what, though, we would need Hedge Maze 4 Exit to Keep Tower. - tower_access_from_hedges = any( - e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 4th Maze", "Keep Tower"] - ) + tower_access_from_hedges = any(e.can_reach(state) for e in two_way_entrance_register["Keep 4th Maze", "Keep Tower"]) if not tower_access_from_hedges: return False # We can reach Keep Tower from Hedge Maze 4. If we now have the Hedge 4 Shortcut, we are immediately good. - hedge_4_shortcut = any( - e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 4th Maze", "Keep"] - ) + hedge_4_shortcut = any(e.can_reach(state) for e in two_way_entrance_register["Keep 4th Maze", "Keep"]) # If we have the hedge 4 shortcut, that works. if hedge_4_shortcut: @@ -147,27 +135,21 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool: # We don't have the hedge 4 shortcut. This means we would now need to come through Hedge Maze 3. - hedge_3_to_4 = any( - e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 4th Maze", "Keep 3rd Maze"] - ) + hedge_3_to_4 = any(e.can_reach(state) for e in two_way_entrance_register["Keep 4th Maze", "Keep 3rd Maze"]) if not hedge_3_to_4: return False # We can get to Hedge 4 from Hedge 3. If we have the Hedge 3 Shortcut, we're good. - hedge_3_shortcut = any( - e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 3rd Maze", "Keep"] - ) + hedge_3_shortcut = any(e.can_reach(state) for e in two_way_entrance_register["Keep 3rd Maze", "Keep"]) if hedge_3_shortcut: return True # We don't have Hedge 3 Shortcut. This means we would now need to come through Hedge Maze 2. - hedge_2_to_3 = any( - e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 3rd Maze", "Keep 2nd Maze"] - ) + hedge_2_to_3 = any(e.can_reach(state) for e in two_way_entrance_register["Keep 3rd Maze", "Keep 2nd Maze"]) if not hedge_2_to_3: return False @@ -175,9 +157,7 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool: # We can get to Hedge 3 from Hedge 2. If we can get from Keep to Hedge 2, we're good. # This covers both Hedge 1 Exit and Hedge 2 Shortcut, because Hedge 1 is just part of the Keep region. - return any( - e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 2nd Maze", "Keep"] - ) + return any(e.can_reach(state) for e in two_way_entrance_register["Keep 2nd Maze", "Keep"]) def _can_do_theater_to_tunnels(state: CollectionState, world: "WitnessWorld") -> bool: @@ -189,11 +169,11 @@ def _can_do_theater_to_tunnels(state: CollectionState, world: "WitnessWorld") -> # Checking for access to Theater is not necessary, as solvability of Tutorial Video is checked in the other half # of the Theater Flowers EP condition. - player_regions = world.player_regions + two_way_entrance_register = world.player_regions.two_way_entrance_register direct_access = ( - any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Tunnels", "Windmill Interior"]) - and any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Theater", "Windmill Interior"]) + any(e.can_reach(state) for e in two_way_entrance_register["Tunnels", "Windmill Interior"]) + and any(e.can_reach(state) for e in two_way_entrance_register["Theater", "Windmill Interior"]) ) if direct_access: @@ -210,14 +190,15 @@ def _can_do_theater_to_tunnels(state: CollectionState, world: "WitnessWorld") -> # We also need a way from Town to Tunnels. return ( - any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Tunnels", "Windmill Interior"]) - and any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Town", "Windmill Interior"]) - or any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Tunnels", "Town"]) + any(e.can_reach(state) for e in two_way_entrance_register["Tunnels", "Windmill Interior"]) + and any(e.can_reach(state) for e in two_way_entrance_register["Outside Windmill", "Windmill Interior"]) + or any(e.can_reach(state) for e in two_way_entrance_register["Tunnels", "Town"]) ) -def _has_item(item: str, world: "WitnessWorld", player: int, - player_logic: WitnessPlayerLogic, player_locations: WitnessPlayerLocations) -> CollectionRule: +def _has_item(item: str, world: "WitnessWorld", player: int, player_logic: WitnessPlayerLogic) -> CollectionRule: + assert item not in static_witness_logic.ENTITIES_BY_HEX, "Requirements can no longer contain entity hexes directly." + if item in player_logic.REFERENCE_LOGIC.ALL_REGIONS_BY_NAME: region = world.get_region(item) return region.can_reach @@ -233,12 +214,13 @@ def _has_item(item: str, world: "WitnessWorld", player: int, if item == "11 Lasers + Redirect": laser_req = world.options.challenge_lasers.value return _has_lasers(laser_req, world, True) + if item == "Entity Hunt": + # Right now, panel hunt is the only type of entity hunt. This may need to be changed later + return _can_do_panel_hunt(world) if item == "PP2 Weirdness": return lambda state: _can_do_expert_pp2(state, world) if item == "Theater to Tunnels": return lambda state: _can_do_theater_to_tunnels(state, world) - if item in player_logic.USED_EVENT_NAMES_BY_HEX: - return _can_solve_panel(item, world, player, player_logic, player_locations) prog_item = static_witness_logic.get_parent_progressive_item(item) return lambda state: state.has(prog_item, player, player_logic.MULTI_AMOUNTS[item]) @@ -251,7 +233,7 @@ def _meets_item_requirements(requirements: WitnessRule, world: "WitnessWorld") - """ lambda_conversion = [ - [_has_item(item, world, world.player, world.player_logic, world.player_locations) for item in subset] + [_has_item(item, world, world.player, world.player_logic) for item in subset] for subset in requirements ] @@ -279,7 +261,8 @@ def set_rules(world: "WitnessWorld") -> None: real_location = location if location in world.player_locations.EVENT_LOCATION_TABLE: - real_location = location[:-7] + entity_hex = world.player_logic.EVENT_ITEM_PAIRS[location][1] + real_location = static_witness_logic.ENTITIES_BY_HEX[entity_hex]["checkName"] associated_entity = world.player_logic.REFERENCE_LOGIC.ENTITIES_BY_NAME[real_location] entity_hex = associated_entity["entity_hex"] diff --git a/worlds/witness/test/__init__.py b/worlds/witness/test/__init__.py index 0a24467feab2..d1b90ca47d9e 100644 --- a/worlds/witness/test/__init__.py +++ b/worlds/witness/test/__init__.py @@ -159,3 +159,36 @@ def get_items_by_name(self, item_names: Union[str, Iterable[str]], player: int) if isinstance(item_names, str): item_names = (item_names,) return [item for item in self.multiworld.itempool if item.name in item_names and item.player == player] + + def assert_location_exists(self, location_name: str, player: int, strict_check: bool = True) -> None: + """ + Assert that a location exists in this world. + If strict_check, also make sure that this (non-event) location COULD exist. + """ + + world = self.multiworld.worlds[player] + + if strict_check: + self.assertIn(location_name, world.location_name_to_id, f"Location {location_name} can never exist") + + try: + world.get_location(location_name) + except KeyError: + self.fail(f"Location {location_name} does not exist.") + + def assert_location_does_not_exist(self, location_name: str, player: int, strict_check: bool = True) -> None: + """ + Assert that a location exists in this world. + If strict_check, be explicit about whether the location could exist in the first place. + """ + + world = self.multiworld.worlds[player] + + if strict_check: + self.assertIn(location_name, world.location_name_to_id, f"Location {location_name} can never exist") + + self.assertRaises( + KeyError, + lambda _: world.get_location(location_name), + f"Location {location_name} exists, but is not supposed to.", + ) diff --git a/worlds/witness/test/test_panel_hunt.py b/worlds/witness/test/test_panel_hunt.py new file mode 100644 index 000000000000..2fc16f787e67 --- /dev/null +++ b/worlds/witness/test/test_panel_hunt.py @@ -0,0 +1,107 @@ +from BaseClasses import CollectionState, Item +from worlds.witness.test import WitnessTestBase, WitnessMultiworldTestBase + + +class TestMaxPanelHuntMinChecks(WitnessTestBase): + options = { + "victory_condition": "panel_hunt", + "panel_hunt_total": 100, + "panel_hunt_required_percentage": 100, + "panel_hunt_postgame": "disable_anything_locked_by_lasers", + "disable_non_randomized_puzzles": True, + "shuffle_discarded_panels": False, + "shuffle_vault_boxes": False, + } + + def test_correct_panels_were_picked(self): + with self.subTest("Check that 100 Hunt Panels were actually picked."): + self.assertEqual(len(self.multiworld.find_item_locations("+1 Panel Hunt", self.player)), 100) + + with self.subTest("Check that 100 Hunt Panels are enough"): + state_100 = CollectionState(self.multiworld) + panel_hunt_item = self.get_item_by_name("+1 Panel Hunt") + + for _ in range(100): + state_100.collect(panel_hunt_item, True) + state_100.sweep_for_events([self.world.get_location("Tutorial Gate Open Solved")]) + + self.assertTrue(self.multiworld.completion_condition[self.player](state_100)) + + with self.subTest("Check that 99 Hunt Panels are not enough"): + state_99 = CollectionState(self.multiworld) + panel_hunt_item = self.get_item_by_name("+1 Panel Hunt") + + for _ in range(99): + state_99.collect(panel_hunt_item, True) + state_99.sweep_for_events([self.world.get_location("Tutorial Gate Open Solved")]) + + self.assertFalse(self.multiworld.completion_condition[self.player](state_99)) + + +class TestPanelHuntPostgame(WitnessMultiworldTestBase): + options_per_world = [ + { + "panel_hunt_postgame": "everything_is_eligible" + }, + { + "panel_hunt_postgame": "disable_mountain_lasers_locations" + }, + { + "panel_hunt_postgame": "disable_challenge_lasers_locations" + }, + { + "panel_hunt_postgame": "disable_anything_locked_by_lasers" + }, + ] + + common_options = { + "victory_condition": "panel_hunt", + "panel_hunt_total": 40, + + # Make sure we can check for Short vs Long Lasers locations by making Mountain Bottom Floor Discard accessible. + "shuffle_doors": "doors", + "shuffle_discarded_panels": True, + } + + def test_panel_hunt_postgame(self): + for player_minus_one, options in enumerate(self.options_per_world): + player = player_minus_one + 1 + postgame_option = options["panel_hunt_postgame"] + with self.subTest(f"Test that \"{postgame_option}\" results in 40 Hunt Panels."): + self.assertEqual(len(self.multiworld.find_item_locations("+1 Panel Hunt", player)), 40) + + # Test that the box gets extra checks from panel_hunt_postgame + + with self.subTest("Test that \"everything_is_eligible\" has no Mountaintop Box Hunt Panels."): + self.assert_location_does_not_exist("Mountaintop Box Short (Panel Hunt)", 1, strict_check=False) + self.assert_location_does_not_exist("Mountaintop Box Long (Panel Hunt)", 1, strict_check=False) + + with self.subTest("Test that \"disable_mountain_lasers_locations\" has a Hunt Panel for Short, but not Long."): + self.assert_location_exists("Mountaintop Box Short (Panel Hunt)", 2, strict_check=False) + self.assert_location_does_not_exist("Mountaintop Box Long (Panel Hunt)", 2, strict_check=False) + + with self.subTest("Test that \"disable_challenge_lasers_locations\" has a Hunt Panel for Long, but not Short."): + self.assert_location_does_not_exist("Mountaintop Box Short (Panel Hunt)", 3, strict_check=False) + self.assert_location_exists("Mountaintop Box Long (Panel Hunt)", 3, strict_check=False) + + with self.subTest("Test that \"disable_anything_locked_by_lasers\" has both Mountaintop Box Hunt Panels."): + self.assert_location_exists("Mountaintop Box Short (Panel Hunt)", 4, strict_check=False) + self.assert_location_exists("Mountaintop Box Long (Panel Hunt)", 4, strict_check=False) + + # Check panel_hunt_postgame locations get disabled + + with self.subTest("Test that \"everything_is_eligible\" does not disable any locked-by-lasers panels."): + self.assert_location_exists("Mountain Floor 1 Right Row 5", 1) + self.assert_location_exists("Mountain Bottom Floor Discard", 1) + + with self.subTest("Test that \"disable_mountain_lasers_locations\" disables only Shortbox-Locked panels."): + self.assert_location_does_not_exist("Mountain Floor 1 Right Row 5", 2) + self.assert_location_exists("Mountain Bottom Floor Discard", 2) + + with self.subTest("Test that \"disable_challenge_lasers_locations\" disables only Longbox-Locked panels."): + self.assert_location_exists("Mountain Floor 1 Right Row 5", 3) + self.assert_location_does_not_exist("Mountain Bottom Floor Discard", 3) + + with self.subTest("Test that \"everything_is_eligible\" disables only Shortbox-Locked panels."): + self.assert_location_does_not_exist("Mountain Floor 1 Right Row 5", 4) + self.assert_location_does_not_exist("Mountain Bottom Floor Discard", 4) diff --git a/worlds/witness/test/test_roll_other_options.py b/worlds/witness/test/test_roll_other_options.py index 71743c326038..3912ce252e53 100644 --- a/worlds/witness/test/test_roll_other_options.py +++ b/worlds/witness/test/test_roll_other_options.py @@ -34,6 +34,7 @@ class TestMiscOptions(WitnessTestBase): "laser_hints": True, "hint_amount": 40, "area_hint_percentage": 100, + "vague_hints": "experimental", } diff --git a/worlds/witness/test/test_weird_traversals.py b/worlds/witness/test/test_weird_traversals.py new file mode 100644 index 000000000000..47b69b01fb4a --- /dev/null +++ b/worlds/witness/test/test_weird_traversals.py @@ -0,0 +1,66 @@ +from ..test import WitnessTestBase + + +class TestWeirdTraversalRequirements(WitnessTestBase): + options = { + "shuffle_vault_boxes": True, + "shuffle_symbols": False, + "shuffle_EPs": "individual", + "EP_difficulty": "tedious", + "shuffle_doors": "doors", + "door_groupings": "off", + "puzzle_randomization": "sigma_expert", + } + + def test_weird_traversal_requirements(self) -> None: + """ + Test that Tunnels Theater Flowers EP and Expert PP2 consider all valid paths logically. + """ + + with self.subTest("Tunnels Theater Flowers EP"): + self.assertAccessDependency( + ["Tunnels Theater Flowers EP"], + [ + ["Theater Exit Left (Door)", "Windmill Entry (Door)", "Tunnels Theater Shortcut (Door)"], + ["Theater Exit Right (Door)", "Windmill Entry (Door)", "Tunnels Theater Shortcut (Door)"], + ["Theater Exit Left (Door)", "Tunnels Town Shortcut (Door)"], + ["Theater Exit Right (Door)", "Tunnels Town Shortcut (Door)"], + ["Theater Entry (Door)", "Tunnels Theater Shortcut (Door)"], + ["Theater Entry (Door)", "Windmill Entry (Door)", "Tunnels Town Shortcut (Door)"], + ], + only_check_listed=True, + ) + + with self.subTest("Expert Keep Pressure Plates 2"): + # Always necessary + self.assertAccessDependency( + ["Keep Pressure Plates 2"], + [["Keep Pressure Plates 1 Exit (Door)"]], + only_check_listed=True, + ) + + # Always necessary + self.assertAccessDependency( + ["Keep Pressure Plates 2"], + [["Keep Pressure Plates 3 Exit (Door)"]], + only_check_listed=True, + ) + + # All the possible "Exit methods" from PP3 + self.assertAccessDependency( + ["Keep Pressure Plates 2"], + [ + ["Keep Shadows Shortcut (Door)"], + ["Keep Pressure Plates 4 Exit (Door)", "Keep Tower Shortcut (Door)"], + ["Keep Pressure Plates 4 Exit (Door)", "Keep Hedge Maze 4 Exit (Door)", + "Keep Hedge Maze 4 Shortcut (Door)"], + ["Keep Pressure Plates 4 Exit (Door)", "Keep Hedge Maze 4 Exit (Door)", + "Keep Hedge Maze 3 Exit (Door)", "Keep Hedge Maze 3 Shortcut (Door)"], + ["Keep Pressure Plates 4 Exit (Door)", "Keep Hedge Maze 4 Exit (Door)", + "Keep Hedge Maze 3 Exit (Door)", "Keep Hedge Maze 2 Exit (Door)", + "Keep Hedge Maze 2 Shortcut (Door)"], + ["Keep Pressure Plates 4 Exit (Door)", "Keep Hedge Maze 4 Exit (Door)", + "Keep Hedge Maze 3 Exit (Door)", "Keep Hedge Maze 2 Exit (Door)", "Keep Hedge Maze 1 Exit (Door)"], + ], + only_check_listed=True, + ) diff --git a/worlds/yachtdice/Items.py b/worlds/yachtdice/Items.py new file mode 100644 index 000000000000..fa52c93ad6f2 --- /dev/null +++ b/worlds/yachtdice/Items.py @@ -0,0 +1,118 @@ +import typing + +from BaseClasses import Item, ItemClassification + + +class ItemData(typing.NamedTuple): + code: typing.Optional[int] + classification: ItemClassification + + +class YachtDiceItem(Item): + game: str = "Yacht Dice" + + +# the starting index is chosen semi-randomly to be 16871244000 + + +item_table = { + # victory item, always placed manually at goal location + "Victory": ItemData(16871244000 - 1, ItemClassification.progression), + "Dice": ItemData(16871244000, ItemClassification.progression), + "Dice Fragment": ItemData(16871244001, ItemClassification.progression), + "Roll": ItemData(16871244002, ItemClassification.progression), + "Roll Fragment": ItemData(16871244003, ItemClassification.progression), + "Fixed Score Multiplier": ItemData(16871244005, ItemClassification.progression), + "Step Score Multiplier": ItemData(16871244006, ItemClassification.progression), + "Category Ones": ItemData(16871244103, ItemClassification.progression), + "Category Twos": ItemData(16871244104, ItemClassification.progression), + "Category Threes": ItemData(16871244105, ItemClassification.progression), + "Category Fours": ItemData(16871244106, ItemClassification.progression), + "Category Fives": ItemData(16871244107, ItemClassification.progression), + "Category Sixes": ItemData(16871244108, ItemClassification.progression), + "Category Choice": ItemData(16871244109, ItemClassification.progression), + "Category Inverse Choice": ItemData(16871244110, ItemClassification.progression), + "Category Pair": ItemData(16871244111, ItemClassification.progression), + "Category Three of a Kind": ItemData(16871244112, ItemClassification.progression), + "Category Four of a Kind": ItemData(16871244113, ItemClassification.progression), + "Category Tiny Straight": ItemData(16871244114, ItemClassification.progression), + "Category Small Straight": ItemData(16871244115, ItemClassification.progression), + "Category Large Straight": ItemData(16871244116, ItemClassification.progression), + "Category Full House": ItemData(16871244117, ItemClassification.progression), + "Category Yacht": ItemData(16871244118, ItemClassification.progression), + "Category Distincts": ItemData(16871244123, ItemClassification.progression), + "Category Two times Ones": ItemData(16871244124, ItemClassification.progression), + "Category Half of Sixes": ItemData(16871244125, ItemClassification.progression), + "Category Twos and Threes": ItemData(16871244126, ItemClassification.progression), + "Category Sum of Odds": ItemData(16871244127, ItemClassification.progression), + "Category Sum of Evens": ItemData(16871244128, ItemClassification.progression), + "Category Double Threes and Fours": ItemData(16871244129, ItemClassification.progression), + "Category Quadruple Ones and Twos": ItemData(16871244130, ItemClassification.progression), + "Category Micro Straight": ItemData(16871244131, ItemClassification.progression), + "Category Three Odds": ItemData(16871244132, ItemClassification.progression), + "Category 1-2-1 Consecutive": ItemData(16871244133, ItemClassification.progression), + "Category Three Distinct Dice": ItemData(16871244134, ItemClassification.progression), + "Category Two Pair": ItemData(16871244135, ItemClassification.progression), + "Category 2-1-2 Consecutive": ItemData(16871244136, ItemClassification.progression), + "Category Five Distinct Dice": ItemData(16871244137, ItemClassification.progression), + "Category 4&5 Full House": ItemData(16871244138, ItemClassification.progression), + # filler items + "Encouragement": ItemData(16871244200, ItemClassification.filler), + "Fun Fact": ItemData(16871244201, ItemClassification.filler), + "Story Chapter": ItemData(16871244202, ItemClassification.filler), + "Good RNG": ItemData(16871244203, ItemClassification.filler), + "Bad RNG": ItemData(16871244204, ItemClassification.trap), + "Bonus Point": ItemData(16871244205, ItemClassification.useful), # not included in logic + # These points are included in the logic and might be necessary to progress. + "1 Point": ItemData(16871244301, ItemClassification.progression_skip_balancing), + "10 Points": ItemData(16871244302, ItemClassification.progression), + "100 Points": ItemData(16871244303, ItemClassification.progression), +} + +# item groups for better hinting +item_groups = { + "Score Multiplier": { + "Step Score Multiplier", + "Fixed Score Multiplier" + }, + "Categories": { + "Category Ones", + "Category Twos", + "Category Threes", + "Category Fours", + "Category Fives", + "Category Sixes", + "Category Choice", + "Category Inverse Choice", + "Category Pair", + "Category Three of a Kind", + "Category Four of a Kind", + "Category Tiny Straight", + "Category Small Straight", + "Category Large Straight", + "Category Full House", + "Category Yacht", + "Category Distincts", + "Category Two times Ones", + "Category Half of Sixes", + "Category Twos and Threes", + "Category Sum of Odds", + "Category Sum of Evens", + "Category Double Threes and Fours", + "Category Quadruple Ones and Twos", + "Category Micro Straight", + "Category Three Odds", + "Category 1-2-1 Consecutive", + "Category Three Distinct Dice", + "Category Two Pair", + "Category 2-1-2 Consecutive", + "Category Five Distinct Dice", + "Category 4&5 Full House", + }, + "Points": { + "100 Points", + "10 Points", + "1 Point", + "Bonus Point" + }, +} diff --git a/worlds/yachtdice/Locations.py b/worlds/yachtdice/Locations.py new file mode 100644 index 000000000000..a9a236466fcc --- /dev/null +++ b/worlds/yachtdice/Locations.py @@ -0,0 +1,79 @@ +import typing + +from BaseClasses import Location + + +class LocData(typing.NamedTuple): + id: int + region: str + score: int + + +class YachtDiceLocation(Location): + game: str = "Yacht Dice" + + def __init__(self, player: int, name: str, score: int, address: typing.Optional[int], parent): + super().__init__(player, name, address, parent) + self.yacht_dice_score = score + + +all_locations = {} +starting_index = 16871244500 # 500 more than the starting index for items (not necessary, but this is what it is now) + + +def all_locations_fun(max_score): + """ + Function that is called when this file is loaded, which loads in ALL possible locations, score 1 to 1000 + """ + return {f"{i} score": LocData(starting_index + i, "Board", i) for i in range(1, max_score + 1)} + + +def ini_locations(goal_score, max_score, number_of_locations, dif, skip_early_locations, number_of_players): + """ + function that loads in all locations necessary for the game, so based on options. + will make sure that goal_score and max_score are included locations + """ + scaling = 2 # parameter that determines how many low-score location there are. + # need more low-score locations or lower difficulties: + if dif == 1: + scaling = 3 + elif dif == 2: + scaling = 2.3 + + scores = [] + # the scores follow the function int( 1 + (percentage ** scaling) * (max_score-1) ) + # however, this will have many low values, sometimes repeating. + # to avoid repeating scores, highest_score keeps tracks of the highest score location + # and the next score will always be at least highest_score + 1 + # note that current_score is at most max_score-1 + highest_score = 0 + start_score = 0 + + if skip_early_locations: + scaling = 1.95 + if number_of_players > 2: + scaling = max(1.2, 2.2 - number_of_players * 0.1) + + for i in range(number_of_locations - 1): + percentage = i / number_of_locations + current_score = int(start_score + 1 + (percentage**scaling) * (max_score - start_score - 2)) + if current_score <= highest_score: + current_score = highest_score + 1 + highest_score = current_score + scores += [current_score] + + if goal_score != max_score: + # if the goal score is not in the list, find the closest one and make it the goal. + if goal_score not in scores: + closest_num = min(scores, key=lambda x: abs(x - goal_score)) + scores[scores.index(closest_num)] = goal_score + + scores += [max_score] + + location_table = {f"{score} score": LocData(starting_index + score, "Board", score) for score in scores} + + return location_table + + +# we need to run this function to initialize all scores from 1 to 1000, even though not all are used +all_locations = all_locations_fun(1000) diff --git a/worlds/yachtdice/Options.py b/worlds/yachtdice/Options.py new file mode 100644 index 000000000000..e687936224c3 --- /dev/null +++ b/worlds/yachtdice/Options.py @@ -0,0 +1,332 @@ +from dataclasses import dataclass + +from Options import Choice, OptionGroup, PerGameCommonOptions, Range + + +class GameDifficulty(Choice): + """ + Difficulty. This option determines how difficult the scores are to achieve. + Easy: for beginners. No luck required, just roll the dice and have fun. Lower final goal. + Medium: intended difficulty. If you play smart, you will finish the game without any trouble. + Hard: you will need to play smart and be lucky. + Extreme: really hard mode, which requires many brain wrinkles and insane luck. NOT RECOMMENDED FOR MULTIWORLDS. + """ + + display_name = "Game difficulty" + option_easy = 1 + option_medium = 2 + option_hard = 3 + option_extreme = 4 + default = 2 + + +class ScoreForLastCheck(Range): + """ + The items in the item pool will always allow you to reach a score of 1000. + By default, the last check is also at a score of 1000. + However, you can set the score for the last check to be lower. This will make the game shorter and easier. + """ + + display_name = "Score for last check" + range_start = 500 + range_end = 1000 + default = 1000 + + +class ScoreForGoal(Range): + """ + This option determines what score you need to reach to finish the game. + It cannot be higher than the score for the last check (if it is, this option is changed automatically). + """ + + display_name = "Score for goal" + range_start = 500 + range_end = 1000 + default = 777 + + +class MinimalNumberOfDiceAndRolls(Choice): + """ + The minimal number of dice and rolls in the pool. + These are guaranteed, unlike the later items. + You can never get more than 8 dice and 5 rolls. + You start with one dice and one roll. + """ + + display_name = "Minimal number of dice and rolls in pool" + option_5_dice_and_3_rolls = 2 + option_5_dice_and_5_rolls = 3 + option_6_dice_and_4_rolls = 4 + option_7_dice_and_3_rolls = 5 + option_8_dice_and_2_rolls = 6 + default = 2 + + +class NumberDiceFragmentsPerDice(Range): + """ + Dice can be split into fragments, gathering enough will give you an extra dice. + You start with one dice, and there will always be one full dice in the pool. + The other dice are split into fragments, according to this option. + Setting this to 1 fragment per dice just puts "Dice" objects in the pool. + """ + + display_name = "Number of dice fragments per dice" + range_start = 1 + range_end = 5 + default = 4 + + +class NumberRollFragmentsPerRoll(Range): + """ + Rolls can be split into fragments, gathering enough will give you an extra roll. + You start with one roll, and there will always be one full roll in the pool. + The other three rolls are split into fragments, according to this option. + Setting this to 1 fragment per roll just puts "Roll" objects in the pool. + """ + + display_name = "Number of roll fragments per roll" + range_start = 1 + range_end = 5 + default = 4 + + +class AlternativeCategories(Range): + """ + There are 16 default categories, but there are also 16 alternative categories. + These alternative categories can be randomly selected to replace the default categories. + They are a little strange, but can give a fun new experience. + In the game, you can hover over categories to check what they do. + This option determines the number of alternative categories in your game. + """ + + display_name = "Number of alternative categories" + range_start = 0 + range_end = 16 + default = 0 + + +class ChanceOfDice(Range): + """ + The item pool is always filled in such a way that you can reach a score of 1000. + Extra progression items are added that will help you on your quest. + You can set the weight for each extra progressive item in the following options. + + Of course, more dice = more points! + """ + + display_name = "Weight of adding Dice" + range_start = 0 + range_end = 100 + default = 5 + + +class ChanceOfRoll(Range): + """ + With more rolls, you will be able to reach higher scores. + """ + + display_name = "Weight of adding Roll" + range_start = 0 + range_end = 100 + default = 20 + + +class ChanceOfFixedScoreMultiplier(Range): + """ + Getting a Fixed Score Multiplier will boost all future scores by 10%. + """ + + display_name = "Weight of adding Fixed Score Multiplier" + range_start = 0 + range_end = 100 + default = 30 + + +class ChanceOfStepScoreMultiplier(Range): + """ + The Step Score Multiplier boosts your multiplier after every roll by 1%, and resets on sheet reset. + So, keep high scoring categories for later to get the most out of them. + By default, this item is not included. It is fun however, you just need to know the above strategy. + """ + + display_name = "Weight of adding Step Score Multiplier" + range_start = 0 + range_end = 100 + default = 0 + + +class ChanceOfDoubleCategory(Range): + """ + This option allows categories to appear multiple times. + Each time you get a category after the first, its score value gets doubled. + """ + + display_name = "Weight of adding Category copy" + range_start = 0 + range_end = 100 + default = 50 + + +class ChanceOfPoints(Range): + """ + Are you tired of rolling dice countless times and tallying up points one by one, all by yourself? + Worry not, as this option will simply add some points items to the item pool! + And getting one of these points items gives you... points! + Imagine how nice it would be to find tons of them. Or even better, having others find them FOR you! + """ + + display_name = "Weight of adding Points" + range_start = 0 + range_end = 100 + default = 20 + + +class PointsSize(Choice): + """ + If you choose to add points to the item pool, you can choose to have many small points, + medium-size points, a few larger points, or a mix of them. + """ + + display_name = "Size of points" + option_small = 1 + option_medium = 2 + option_large = 3 + option_mix = 4 + default = 2 + + +class MinimizeExtraItems(Choice): + """ + Besides necessary items, Yacht Dice has extra useful/filler items in the item pool. + It is possible however to decrease the number of locations and extra items. + This option will: + - decrease the number of locations at the start (you'll start with 2 dice and 2 rolls). + - will limit the number of dice/roll fragments per dice/roll to 2. + - in multiplayer games, it will reduce the number of filler items. + """ + + display_name = "Minimize extra items" + option_no_dont = 1 + option_yes_please = 2 + default = 1 + + +class AddExtraPoints(Choice): + """ + Yacht Dice typically has space for extra items. + This option determines if bonus points are put into the item pool. + They make the game a little bit easier, as they are not considered in the logic. + + All Of It: fill all locations with extra points + Sure: put some bonus points in + Never: do not put any bonus points + """ + + display_name = "Extra bonus in the pool" + option_all_of_it = 1 + option_sure = 2 + option_never = 3 + default = 2 + + +class AddStoryChapters(Choice): + """ + Yacht Dice typically has space for more items. + This option determines if extra story chapters are put into the item pool. + Note: if you have extra points on "all_of_it", there will not be story chapters. + + All Of It: fill all locations with story chapters + Sure: if there is space left, put in 10 story chapters. + Never: do not put any story chapters in, I do not like reading (but I am glad you are reading THIS!) + """ + + display_name = "Extra story chapters in the pool" + option_all_of_it = 1 + option_sure = 2 + option_never = 3 + default = 3 + + +class WhichStory(Choice): + """ + The most important part of Yacht Dice is the narrative. + Of course you will need to add story chapters to the item pool. + You can read story chapters in the feed on the website and there are several stories to choose from. + """ + + display_name = "Story" + option_the_quest_of_the_dice_warrior = 1 + option_the_tragedy_of_fortunas_gambit = 2 + option_the_dicey_animal_dice_game = 3 + option_whispers_of_fate = 4 + option_a_yacht_dice_odyssey = 5 + option_a_rollin_rhyme_adventure = 6 + option_random_story = -1 + default = -1 + + +class AllowManual(Choice): + """ + If allowed, players can roll IRL dice and input them manually into the game. + By sending "manual" in the chat, an input field appears where you can type your dice rolls. + Of course, we cannot check anymore if the player is playing fair. + """ + + display_name = "Allow manual inputs" + option_yes_allow = 1 + option_no_dont_allow = 2 + default = 1 + + +@dataclass +class YachtDiceOptions(PerGameCommonOptions): + game_difficulty: GameDifficulty + score_for_last_check: ScoreForLastCheck + score_for_goal: ScoreForGoal + + minimal_number_of_dice_and_rolls: MinimalNumberOfDiceAndRolls + number_of_dice_fragments_per_dice: NumberDiceFragmentsPerDice + number_of_roll_fragments_per_roll: NumberRollFragmentsPerRoll + + alternative_categories: AlternativeCategories + + allow_manual_input: AllowManual + + # the following options determine what extra items are shuffled into the pool: + weight_of_dice: ChanceOfDice + weight_of_roll: ChanceOfRoll + weight_of_fixed_score_multiplier: ChanceOfFixedScoreMultiplier + weight_of_step_score_multiplier: ChanceOfStepScoreMultiplier + weight_of_double_category: ChanceOfDoubleCategory + weight_of_points: ChanceOfPoints + points_size: PointsSize + + minimize_extra_items: MinimizeExtraItems + add_bonus_points: AddExtraPoints + add_story_chapters: AddStoryChapters + which_story: WhichStory + + +yd_option_groups = [ + OptionGroup( + "Extra progression items", + [ + ChanceOfDice, + ChanceOfRoll, + ChanceOfFixedScoreMultiplier, + ChanceOfStepScoreMultiplier, + ChanceOfDoubleCategory, + ChanceOfPoints, + PointsSize, + ], + ), + OptionGroup( + "Other items", + [ + MinimizeExtraItems, + AddExtraPoints, + AddStoryChapters, + WhichStory + ], + ), +] diff --git a/worlds/yachtdice/Rules.py b/worlds/yachtdice/Rules.py new file mode 100644 index 000000000000..1db5cebccdef --- /dev/null +++ b/worlds/yachtdice/Rules.py @@ -0,0 +1,239 @@ +import math +from collections import Counter, defaultdict +from typing import List, Optional + +from BaseClasses import MultiWorld + +from worlds.generic.Rules import set_rule + +from .YachtWeights import yacht_weights + +# This module adds logic to the apworld. +# In short, we ran a simulation for every possible combination of dice and rolls you can have, per category. +# This simulation has a good strategy for locking dice. +# This gives rise to an approximate discrete distribution per category. +# We calculate the distribution of the total score. +# We then pick a correct percentile to reflect the correct score that should be in logic. +# The score is logic is *much* lower than the actual maximum reachable score. + + +class Category: + def __init__(self, name, quantity=1): + self.name = name + self.quantity = quantity # how many times you have the category + + # return mean score of a category + def mean_score(self, num_dice, num_rolls): + if num_dice <= 0 or num_rolls <= 0: + return 0 + mean_score = 0 + for key, value in yacht_weights[self.name, min(8, num_dice), min(8, num_rolls)].items(): + mean_score += key * value / 100000 + return mean_score * self.quantity + + +class ListState: + def __init__(self, state: List[str]): + self.state = state + self.item_counts = Counter(state) + + def count(self, item: str, player: Optional[str] = None) -> int: + return self.item_counts[item] + + +def extract_progression(state, player, frags_per_dice, frags_per_roll, allowed_categories): + """ + method to obtain a list of what items the player has. + this includes categories, dice, rolls and score multiplier etc. + First, we convert the state if it's a list, so we can use state.count(item, player) + """ + if isinstance(state, list): + state = ListState(state=state) + + number_of_dice = state.count("Dice", player) + state.count("Dice Fragment", player) // frags_per_dice + number_of_rerolls = state.count("Roll", player) + state.count("Roll Fragment", player) // frags_per_roll + number_of_fixed_mults = state.count("Fixed Score Multiplier", player) + number_of_step_mults = state.count("Step Score Multiplier", player) + + categories = [ + Category(category_name, state.count(category_name, player)) + for category_name in allowed_categories + if state.count(category_name, player) # want all categories that have count >= 1 + ] + + extra_points_in_logic = state.count("1 Point", player) + extra_points_in_logic += state.count("10 Points", player) * 10 + extra_points_in_logic += state.count("100 Points", player) * 100 + + return ( + categories, + number_of_dice, + number_of_rerolls, + number_of_fixed_mults * 0.1, + number_of_step_mults * 0.01, + extra_points_in_logic, + ) + + +# We will store the results of this function as it is called often for the same parameters. + + +yachtdice_cache = {} + + +def dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mult, diff, player): + """ + Function that returns the feasible score in logic based on items obtained. + """ + tup = ( + tuple([c.name + str(c.quantity) for c in categories]), + num_dice, + num_rolls, + fixed_mult, + step_mult, + diff, + ) # identifier + + if player not in yachtdice_cache: + yachtdice_cache[player] = {} + + if tup in yachtdice_cache[player]: + return yachtdice_cache[player][tup] + + # sort categories because for the step multiplier, you will want low-scoring categories first + categories.sort(key=lambda category: category.mean_score(num_dice, num_rolls)) + + # function to add two discrete distribution. + # defaultdict is a dict where you don't need to check if an id is present, you can just use += (lot faster) + def add_distributions(dist1, dist2): + combined_dist = defaultdict(float) + for val1, prob1 in dist1.items(): + for val2, prob2 in dist2.items(): + combined_dist[val1 + val2] += prob1 * prob2 + return dict(combined_dist) + + # function to take the maximum of "times" i.i.d. dist1. + # (I have tried using defaultdict here too but this made it slower.) + def max_dist(dist1, mults): + new_dist = {0: 1} + for mult in mults: + temp_dist = {} + for val1, prob1 in new_dist.items(): + for val2, prob2 in dist1.items(): + new_val = int(max(val1, val2 * mult)) + new_prob = prob1 * prob2 + + # Update the probability for the new value + if new_val in temp_dist: + temp_dist[new_val] += new_prob + else: + temp_dist[new_val] = new_prob + new_dist = temp_dist + + return new_dist + + # Returns percentile value of a distribution. + def percentile_distribution(dist, percentile): + sorted_values = sorted(dist.keys()) + cumulative_prob = 0 + + for val in sorted_values: + cumulative_prob += dist[val] + if cumulative_prob >= percentile: + return val + + # Return the last value if percentile is higher than all probabilities + return sorted_values[-1] + + # parameters for logic. + # perc_return is, per difficulty, the percentages of total score it returns (it averages out the values) + # diff_divide determines how many shots the logic gets per category. Lower = more shots. + perc_return = [[0], [0.1, 0.5], [0.3, 0.7], [0.55, 0.85], [0.85, 0.95]][diff] + diff_divide = [0, 9, 7, 3, 2][diff] + + # calculate total distribution + total_dist = {0: 1} + for j, category in enumerate(categories): + if num_dice <= 0 or num_rolls <= 0: + dist = {0: 100000} + else: + dist = yacht_weights[category.name, min(8, num_dice), min(8, num_rolls)].copy() + + for key in dist.keys(): + dist[key] /= 100000 + + cat_mult = 2 ** (category.quantity - 1) + + # for higher difficulties, the simulation gets multiple tries for categories. + max_tries = j // diff_divide + mults = [(1 + fixed_mult + step_mult * ii) * cat_mult for ii in range(max(0, j - max_tries), j + 1)] + dist = max_dist(dist, mults) + + total_dist = add_distributions(total_dist, dist) + + # save result into the cache, then return it + outcome = sum([percentile_distribution(total_dist, perc) for perc in perc_return]) / len(perc_return) + yachtdice_cache[player][tup] = max(5, math.floor(outcome)) # at least 5. + + # cache management; we rarely/never need more than 400 entries. But if for some reason it became large, + # delete the first entry of the player cache. + if len(yachtdice_cache[player]) > 400: + # Remove the oldest item + oldest_tup = next(iter(yachtdice_cache[player])) + del yachtdice_cache[player][oldest_tup] + + return yachtdice_cache[player][tup] + + +def dice_simulation_fill_pool(state, frags_per_dice, frags_per_roll, allowed_categories, difficulty, player): + """ + Returns the feasible score that one can reach with the current state, options and difficulty. + This function is called with state being a list, during filling of item pool. + """ + categories, num_dice, num_rolls, fixed_mult, step_mult, expoints = extract_progression( + state, "state_is_a_list", frags_per_dice, frags_per_roll, allowed_categories + ) + return ( + dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mult, difficulty, player) + expoints + ) + + +def dice_simulation_state_change(state, player, frags_per_dice, frags_per_roll, allowed_categories, difficulty): + """ + Returns the feasible score that one can reach with the current state, options and difficulty. + This function is called with state being a AP state object, while doing access rules. + """ + + if state.prog_items[player]["state_is_fresh"] == 0: + state.prog_items[player]["state_is_fresh"] = 1 + categories, num_dice, num_rolls, fixed_mult, step_mult, expoints = extract_progression( + state, player, frags_per_dice, frags_per_roll, allowed_categories + ) + state.prog_items[player]["maximum_achievable_score"] = ( + dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mult, difficulty, player) + + expoints + ) + + return state.prog_items[player]["maximum_achievable_score"] + + +def set_yacht_rules(world: MultiWorld, player: int, frags_per_dice, frags_per_roll, allowed_categories, difficulty): + """ + Sets rules on reaching scores + """ + + for location in world.get_locations(player): + set_rule( + location, + lambda state, curscore=location.yacht_dice_score, player=player: dice_simulation_state_change( + state, player, frags_per_dice, frags_per_roll, allowed_categories, difficulty + ) + >= curscore, + ) + + +def set_yacht_completion_rules(world: MultiWorld, player: int): + """ + Sets rules on completion condition + """ + world.completion_condition[player] = lambda state: state.has("Victory", player) diff --git a/worlds/yachtdice/YachtWeights.py b/worlds/yachtdice/YachtWeights.py new file mode 100644 index 000000000000..ee387fdf212d --- /dev/null +++ b/worlds/yachtdice/YachtWeights.py @@ -0,0 +1,3562 @@ +# A file containing the results of our simulations. +# Every entry consists of a key. This key has input category, number of dice, and number of rolls. +# The value then shows a list of all possible scores to get, and how many times of 100000 it achieved. + +# example: ("Category Choice", 2, 2): +# {8: 13639, 9: 12220, 10: 13755, 5: 4889, 6: 9840, 7: 14772, 12: 7780, 11: 15622, 2: 1269, 3: 2445, 4: 3769} +# this example shows the outcomes for the category "Category Choice", with 2 dice and 2 rolls. +# 13639 out of 100000 times, a score of 8 was achieved for example. +yacht_weights = { + ("Category Ones", 0, 0): {0: 100000}, + ("Category Ones", 0, 1): {0: 100000}, + ("Category Ones", 0, 2): {0: 100000}, + ("Category Ones", 0, 3): {0: 100000}, + ("Category Ones", 0, 4): {0: 100000}, + ("Category Ones", 0, 5): {0: 100000}, + ("Category Ones", 0, 6): {0: 100000}, + ("Category Ones", 0, 7): {0: 100000}, + ("Category Ones", 0, 8): {0: 100000}, + ("Category Ones", 1, 0): {0: 100000}, + ("Category Ones", 1, 1): {0: 83416, 1: 16584}, + ("Category Ones", 1, 2): {0: 69346, 1: 30654}, + ("Category Ones", 1, 3): {0: 57756, 1: 42244}, + ("Category Ones", 1, 4): {0: 48709, 1: 51291}, + ("Category Ones", 1, 5): {0: 40214, 1: 59786}, + ("Category Ones", 1, 6): {0: 33491, 1: 66509}, + ("Category Ones", 1, 7): {0: 27838, 1: 72162}, + ("Category Ones", 1, 8): {0: 23094, 1: 76906}, + ("Category Ones", 2, 0): {0: 100000}, + ("Category Ones", 2, 1): {0: 69715, 1: 30285}, + ("Category Ones", 2, 2): {0: 48066, 1: 51934}, + ("Category Ones", 2, 3): {0: 33544, 1: 48585, 2: 17871}, + ("Category Ones", 2, 4): {0: 23342, 1: 50092, 2: 26566}, + ("Category Ones", 2, 5): {0: 16036, 1: 48250, 2: 35714}, + ("Category Ones", 2, 6): {0: 11355, 1: 44545, 2: 44100}, + ("Category Ones", 2, 7): {0: 7812, 1: 40248, 2: 51940}, + ("Category Ones", 2, 8): {0: 5395, 1: 35484, 2: 59121}, + ("Category Ones", 3, 0): {0: 100000}, + ("Category Ones", 3, 1): {0: 57462, 1: 42538}, + ("Category Ones", 3, 2): {0: 33327, 1: 44253, 2: 22420}, + ("Category Ones", 3, 3): {0: 19432, 1: 42237, 2: 38331}, + ("Category Ones", 3, 4): {0: 11191, 1: 36208, 2: 38606, 3: 13995}, + ("Category Ones", 3, 5): {0: 6536, 1: 28891, 2: 43130, 3: 21443}, + ("Category Ones", 3, 6): {0: 3697, 1: 22501, 2: 44196, 3: 29606}, + ("Category Ones", 3, 7): {0: 2134, 2: 60499, 3: 37367}, + ("Category Ones", 3, 8): {0: 1280, 2: 53518, 3: 45202}, + ("Category Ones", 4, 0): {0: 100000}, + ("Category Ones", 4, 1): {0: 48178, 1: 38635, 2: 13187}, + ("Category Ones", 4, 2): {0: 23349, 1: 40775, 2: 35876}, + ("Category Ones", 4, 3): {0: 11366, 1: 32547, 2: 35556, 3: 20531}, + ("Category Ones", 4, 4): {0: 5331, 1: 23241, 2: 37271, 3: 34157}, + ("Category Ones", 4, 5): {0: 2640, 2: 49872, 3: 47488}, + ("Category Ones", 4, 6): {0: 1253, 2: 39816, 3: 39298, 4: 19633}, + ("Category Ones", 4, 7): {0: 6915, 2: 24313, 3: 41680, 4: 27092}, + ("Category Ones", 4, 8): {0: 4228, 3: 61312, 4: 34460}, + ("Category Ones", 5, 0): {0: 100000}, + ("Category Ones", 5, 1): {0: 40042, 1: 40202, 2: 19756}, + ("Category Ones", 5, 2): {0: 16212, 1: 35432, 2: 31231, 3: 17125}, + ("Category Ones", 5, 3): {0: 6556, 1: 23548, 2: 34509, 3: 35387}, + ("Category Ones", 5, 4): {0: 2552, 2: 44333, 3: 32048, 4: 21067}, + ("Category Ones", 5, 5): {0: 8783, 2: 23245, 3: 34614, 4: 33358}, + ("Category Ones", 5, 6): {0: 4513, 3: 49603, 4: 32816, 5: 13068}, + ("Category Ones", 5, 7): {0: 2295, 3: 40470, 4: 37869, 5: 19366}, + ("Category Ones", 5, 8): {0: 73, 3: 33115, 4: 40166, 5: 26646}, + ("Category Ones", 6, 0): {0: 100000}, + ("Category Ones", 6, 1): {0: 33501, 1: 40042, 2: 26457}, + ("Category Ones", 6, 2): {0: 11326, 1: 29379, 2: 32368, 3: 26927}, + ("Category Ones", 6, 3): {0: 3764, 2: 46660, 3: 28928, 4: 20648}, + ("Category Ones", 6, 4): {0: 1231, 2: 29883, 3: 31038, 4: 37848}, + ("Category Ones", 6, 5): {0: 4208, 3: 41897, 4: 30878, 5: 23017}, + ("Category Ones", 6, 6): {0: 1850, 3: 30396, 4: 33022, 5: 34732}, + ("Category Ones", 6, 7): {0: 5503, 4: 48099, 5: 32432, 6: 13966}, + ("Category Ones", 6, 8): {0: 2896, 4: 39616, 5: 37005, 6: 20483}, + ("Category Ones", 7, 0): {0: 100000}, + ("Category Ones", 7, 1): {0: 27838, 1: 39224, 2: 32938}, + ("Category Ones", 7, 2): {0: 7796, 1: 23850, 2: 31678, 3: 23224, 4: 13452}, + ("Category Ones", 7, 3): {0: 2247, 2: 35459, 3: 29131, 4: 33163}, + ("Category Ones", 7, 4): {0: 5252, 3: 41207, 4: 28065, 5: 25476}, + ("Category Ones", 7, 5): {0: 174, 3: 29347, 4: 28867, 5: 26190, 6: 15422}, + ("Category Ones", 7, 6): {0: 4625, 4: 38568, 5: 30596, 6: 26211}, + ("Category Ones", 7, 7): {0: 230, 4: 30109, 5: 32077, 6: 37584}, + ("Category Ones", 7, 8): {0: 5519, 5: 45718, 6: 33357, 7: 15406}, + ("Category Ones", 8, 0): {0: 100000}, + ("Category Ones", 8, 1): {0: 23156, 1: 37295, 2: 26136, 3: 13413}, + ("Category Ones", 8, 2): {0: 5472, 2: 48372, 3: 25847, 4: 20309}, + ("Category Ones", 8, 3): {0: 8661, 3: 45896, 4: 24664, 5: 20779}, + ("Category Ones", 8, 4): {0: 2807, 3: 29707, 4: 27157, 5: 23430, 6: 16899}, + ("Category Ones", 8, 5): {0: 5173, 4: 36033, 5: 27792, 6: 31002}, + ("Category Ones", 8, 6): {0: 255, 4: 25642, 5: 27508, 6: 27112, 7: 19483}, + ("Category Ones", 8, 7): {0: 4236, 5: 35323, 6: 30438, 7: 30003}, + ("Category Ones", 8, 8): {0: 310, 5: 27692, 6: 30830, 7: 41168}, + ("Category Twos", 0, 0): {0: 100000}, + ("Category Twos", 0, 1): {0: 100000}, + ("Category Twos", 0, 2): {0: 100000}, + ("Category Twos", 0, 3): {0: 100000}, + ("Category Twos", 0, 4): {0: 100000}, + ("Category Twos", 0, 5): {0: 100000}, + ("Category Twos", 0, 6): {0: 100000}, + ("Category Twos", 0, 7): {0: 100000}, + ("Category Twos", 0, 8): {0: 100000}, + ("Category Twos", 1, 0): {0: 100000}, + ("Category Twos", 1, 1): {0: 83475, 2: 16525}, + ("Category Twos", 1, 2): {0: 69690, 2: 30310}, + ("Category Twos", 1, 3): {0: 57818, 2: 42182}, + ("Category Twos", 1, 4): {0: 48418, 2: 51582}, + ("Category Twos", 1, 5): {0: 40301, 2: 59699}, + ("Category Twos", 1, 6): {0: 33558, 2: 66442}, + ("Category Twos", 1, 7): {0: 28182, 2: 71818}, + ("Category Twos", 1, 8): {0: 23406, 2: 76594}, + ("Category Twos", 2, 0): {0: 100000}, + ("Category Twos", 2, 1): {0: 69724, 2: 30276}, + ("Category Twos", 2, 2): {0: 48238, 2: 42479, 4: 9283}, + ("Category Twos", 2, 3): {0: 33290, 2: 48819, 4: 17891}, + ("Category Twos", 2, 4): {0: 23136, 2: 49957, 4: 26907}, + ("Category Twos", 2, 5): {0: 16146, 2: 48200, 4: 35654}, + ("Category Twos", 2, 6): {0: 11083, 2: 44497, 4: 44420}, + ("Category Twos", 2, 7): {0: 7662, 2: 40343, 4: 51995}, + ("Category Twos", 2, 8): {0: 5354, 2: 35526, 4: 59120}, + ("Category Twos", 3, 0): {0: 100000}, + ("Category Twos", 3, 1): {0: 58021, 2: 34522, 4: 7457}, + ("Category Twos", 3, 2): {0: 33548, 2: 44261, 4: 22191}, + ("Category Twos", 3, 3): {0: 19375, 2: 42372, 4: 30748, 6: 7505}, + ("Category Twos", 3, 4): {0: 10998, 2: 36435, 4: 38569, 6: 13998}, + ("Category Twos", 3, 5): {0: 6519, 2: 28838, 4: 43283, 6: 21360}, + ("Category Twos", 3, 6): {0: 3619, 2: 22498, 4: 44233, 6: 29650}, + ("Category Twos", 3, 7): {0: 2195, 2: 16979, 4: 43684, 6: 37142}, + ("Category Twos", 3, 8): {0: 1255, 2: 12420, 4: 40920, 6: 45405}, + ("Category Twos", 4, 0): {0: 100000}, + ("Category Twos", 4, 1): {0: 48235, 2: 38602, 4: 13163}, + ("Category Twos", 4, 2): {0: 23289, 2: 40678, 4: 27102, 6: 8931}, + ("Category Twos", 4, 3): {0: 11177, 2: 32677, 4: 35702, 6: 20444}, + ("Category Twos", 4, 4): {0: 5499, 2: 23225, 4: 37240, 6: 26867, 8: 7169}, + ("Category Twos", 4, 5): {0: 2574, 2: 15782, 4: 34605, 6: 34268, 8: 12771}, + ("Category Twos", 4, 6): {0: 1259, 4: 39616, 6: 39523, 8: 19602}, + ("Category Twos", 4, 7): {0: 622, 4: 30426, 6: 41894, 8: 27058}, + ("Category Twos", 4, 8): {0: 4091, 4: 18855, 6: 42309, 8: 34745}, + ("Category Twos", 5, 0): {0: 100000}, + ("Category Twos", 5, 1): {0: 40028, 2: 40241, 4: 19731}, + ("Category Twos", 5, 2): {0: 16009, 2: 35901, 4: 31024, 6: 17066}, + ("Category Twos", 5, 3): {0: 6489, 2: 23477, 4: 34349, 6: 25270, 8: 10415}, + ("Category Twos", 5, 4): {0: 2658, 2: 14032, 4: 30199, 6: 32214, 8: 20897}, + ("Category Twos", 5, 5): {0: 1032, 4: 31627, 6: 33993, 8: 25853, 10: 7495}, + ("Category Twos", 5, 6): {0: 450, 4: 20693, 6: 32774, 8: 32900, 10: 13183}, + ("Category Twos", 5, 7): {0: 2396, 4: 11231, 6: 29481, 8: 37636, 10: 19256}, + ("Category Twos", 5, 8): {0: 1171, 6: 31564, 8: 40798, 10: 26467}, + ("Category Twos", 6, 0): {0: 100000}, + ("Category Twos", 6, 1): {0: 33502, 2: 40413, 4: 26085}, + ("Category Twos", 6, 2): {0: 11210, 2: 29638, 4: 32701, 6: 18988, 8: 7463}, + ("Category Twos", 6, 3): {0: 3673, 2: 16459, 4: 29795, 6: 29102, 8: 20971}, + ("Category Twos", 6, 4): {0: 1243, 4: 30025, 6: 31053, 8: 25066, 10: 12613}, + ("Category Twos", 6, 5): {0: 4194, 4: 13949, 6: 28142, 8: 30723, 10: 22992}, + ("Category Twos", 6, 6): {0: 1800, 6: 30677, 8: 32692, 10: 26213, 12: 8618}, + ("Category Twos", 6, 7): {0: 775, 6: 21013, 8: 31410, 10: 32532, 12: 14270}, + ("Category Twos", 6, 8): {0: 2855, 6: 11432, 8: 27864, 10: 37237, 12: 20612}, + ("Category Twos", 7, 0): {0: 100000}, + ("Category Twos", 7, 1): {0: 27683, 2: 39060, 4: 23574, 6: 9683}, + ("Category Twos", 7, 2): {0: 7824, 2: 24031, 4: 31764, 6: 23095, 8: 13286}, + ("Category Twos", 7, 3): {0: 2148, 2: 11019, 4: 24197, 6: 29599, 8: 21250, 10: 11787}, + ("Category Twos", 7, 4): {0: 564, 4: 19036, 6: 26395, 8: 28409, 10: 18080, 12: 7516}, + ("Category Twos", 7, 5): {0: 1913, 6: 27198, 8: 29039, 10: 26129, 12: 15721}, + ("Category Twos", 7, 6): {0: 54, 6: 17506, 8: 25752, 10: 30413, 12: 26275}, + ("Category Twos", 7, 7): {0: 2179, 8: 28341, 10: 32054, 12: 27347, 14: 10079}, + ("Category Twos", 7, 8): {0: 942, 8: 19835, 10: 30248, 12: 33276, 14: 15699}, + ("Category Twos", 8, 0): {0: 100000}, + ("Category Twos", 8, 1): {0: 23378, 2: 37157, 4: 26082, 6: 13383}, + ("Category Twos", 8, 2): {0: 5420, 2: 19164, 4: 29216, 6: 25677, 8: 20523}, + ("Category Twos", 8, 3): {0: 1271, 4: 26082, 6: 27054, 8: 24712, 10: 20881}, + ("Category Twos", 8, 4): {0: 2889, 6: 29552, 8: 27389, 10: 23232, 12: 16938}, + ("Category Twos", 8, 5): {0: 879, 6: 16853, 8: 23322, 10: 27882, 12: 20768, 14: 10296}, + ("Category Twos", 8, 6): {0: 2041, 8: 24140, 10: 27398, 12: 27048, 14: 19373}, + ("Category Twos", 8, 7): {0: 74, 8: 15693, 10: 23675, 12: 30829, 14: 22454, 16: 7275}, + ("Category Twos", 8, 8): {2: 2053, 10: 25677, 12: 31310, 14: 28983, 16: 11977}, + ("Category Threes", 0, 0): {0: 100000}, + ("Category Threes", 0, 1): {0: 100000}, + ("Category Threes", 0, 2): {0: 100000}, + ("Category Threes", 0, 3): {0: 100000}, + ("Category Threes", 0, 4): {0: 100000}, + ("Category Threes", 0, 5): {0: 100000}, + ("Category Threes", 0, 6): {0: 100000}, + ("Category Threes", 0, 7): {0: 100000}, + ("Category Threes", 0, 8): {0: 100000}, + ("Category Threes", 1, 0): {0: 100000}, + ("Category Threes", 1, 1): {0: 83343, 3: 16657}, + ("Category Threes", 1, 2): {0: 69569, 3: 30431}, + ("Category Threes", 1, 3): {0: 57872, 3: 42128}, + ("Category Threes", 1, 4): {0: 48081, 3: 51919}, + ("Category Threes", 1, 5): {0: 40271, 3: 59729}, + ("Category Threes", 1, 6): {0: 33201, 3: 66799}, + ("Category Threes", 1, 7): {0: 27903, 3: 72097}, + ("Category Threes", 1, 8): {0: 23240, 3: 76760}, + ("Category Threes", 2, 0): {0: 100000}, + ("Category Threes", 2, 1): {0: 69419, 3: 30581}, + ("Category Threes", 2, 2): {0: 48202, 3: 42590, 6: 9208}, + ("Category Threes", 2, 3): {0: 33376, 3: 48849, 6: 17775}, + ("Category Threes", 2, 4): {0: 23276, 3: 49810, 6: 26914}, + ("Category Threes", 2, 5): {0: 16092, 3: 47718, 6: 36190}, + ("Category Threes", 2, 6): {0: 11232, 3: 44515, 6: 44253}, + ("Category Threes", 2, 7): {0: 7589, 3: 40459, 6: 51952}, + ("Category Threes", 2, 8): {0: 5447, 3: 35804, 6: 58749}, + ("Category Threes", 3, 0): {0: 100000}, + ("Category Threes", 3, 1): {0: 57964, 3: 34701, 6: 7335}, + ("Category Threes", 3, 2): {0: 33637, 3: 44263, 6: 22100}, + ("Category Threes", 3, 3): {0: 19520, 3: 42382, 6: 30676, 9: 7422}, + ("Category Threes", 3, 4): {0: 11265, 3: 35772, 6: 39042, 9: 13921}, + ("Category Threes", 3, 5): {0: 6419, 3: 28916, 6: 43261, 9: 21404}, + ("Category Threes", 3, 6): {0: 3810, 3: 22496, 6: 44388, 9: 29306}, + ("Category Threes", 3, 7): {0: 2174, 3: 16875, 6: 43720, 9: 37231}, + ("Category Threes", 3, 8): {0: 1237, 3: 12471, 6: 41222, 9: 45070}, + ("Category Threes", 4, 0): {0: 100000}, + ("Category Threes", 4, 1): {0: 48121, 3: 38786, 6: 13093}, + ("Category Threes", 4, 2): {0: 23296, 3: 40989, 6: 26998, 9: 8717}, + ("Category Threes", 4, 3): {0: 11233, 3: 32653, 6: 35710, 9: 20404}, + ("Category Threes", 4, 4): {0: 5463, 3: 23270, 6: 37468, 9: 26734, 12: 7065}, + ("Category Threes", 4, 5): {0: 2691, 3: 15496, 6: 34539, 9: 34635, 12: 12639}, + ("Category Threes", 4, 6): {0: 1221, 3: 10046, 6: 29811, 9: 39190, 12: 19732}, + ("Category Threes", 4, 7): {0: 599, 6: 30742, 9: 41614, 12: 27045}, + ("Category Threes", 4, 8): {0: 309, 6: 22719, 9: 42236, 12: 34736}, + ("Category Threes", 5, 0): {0: 100000}, + ("Category Threes", 5, 1): {0: 40183, 3: 40377, 6: 19440}, + ("Category Threes", 5, 2): {0: 16197, 3: 35494, 6: 30937, 9: 17372}, + ("Category Threes", 5, 3): {0: 6583, 3: 23394, 6: 34432, 9: 25239, 12: 10352}, + ("Category Threes", 5, 4): {0: 2636, 3: 14072, 6: 30134, 9: 32371, 12: 20787}, + ("Category Threes", 5, 5): {0: 1075, 3: 7804, 6: 23010, 9: 34811, 12: 25702, 15: 7598}, + ("Category Threes", 5, 6): {0: 418, 6: 20888, 9: 32809, 12: 32892, 15: 12993}, + ("Category Threes", 5, 7): {0: 2365, 6: 11416, 9: 29072, 12: 37604, 15: 19543}, + ("Category Threes", 5, 8): {0: 1246, 6: 7425, 9: 24603, 12: 40262, 15: 26464}, + ("Category Threes", 6, 0): {0: 100000}, + ("Category Threes", 6, 1): {0: 33473, 3: 40175, 6: 20151, 9: 6201}, + ("Category Threes", 6, 2): {0: 11147, 3: 29592, 6: 32630, 9: 19287, 12: 7344}, + ("Category Threes", 6, 3): {0: 3628, 3: 16528, 6: 29814, 9: 29006, 12: 15888, 15: 5136}, + ("Category Threes", 6, 4): {0: 1262, 3: 8236, 6: 21987, 9: 30953, 12: 24833, 15: 12729}, + ("Category Threes", 6, 5): {0: 416, 6: 17769, 9: 27798, 12: 31197, 15: 18256, 18: 4564}, + ("Category Threes", 6, 6): {0: 1796, 6: 8372, 9: 22175, 12: 32897, 15: 26264, 18: 8496}, + ("Category Threes", 6, 7): {0: 791, 9: 21074, 12: 31385, 15: 32666, 18: 14084}, + ("Category Threes", 6, 8): {0: 20, 9: 14150, 12: 28320, 15: 36982, 18: 20528}, + ("Category Threes", 7, 0): {0: 100000}, + ("Category Threes", 7, 1): {0: 27933, 3: 39105, 6: 23338, 9: 9624}, + ("Category Threes", 7, 2): {0: 7794, 3: 23896, 6: 31832, 9: 23110, 12: 13368}, + ("Category Threes", 7, 3): {0: 2138, 3: 11098, 6: 24140, 9: 29316, 12: 21386, 15: 11922}, + ("Category Threes", 7, 4): {0: 590, 6: 19385, 9: 26233, 12: 28244, 15: 18118, 18: 7430}, + ("Category Threes", 7, 5): {0: 1941, 6: 7953, 9: 19439, 12: 28977, 15: 26078, 18: 15612}, + ("Category Threes", 7, 6): {0: 718, 9: 16963, 12: 25793, 15: 30535, 18: 20208, 21: 5783}, + ("Category Threes", 7, 7): {0: 2064, 9: 7941, 12: 20571, 15: 31859, 18: 27374, 21: 10191}, + ("Category Threes", 7, 8): {0: 963, 12: 19864, 15: 30313, 18: 33133, 21: 15727}, + ("Category Threes", 8, 0): {0: 100000}, + ("Category Threes", 8, 1): {0: 23337, 3: 37232, 6: 25968, 9: 13463}, + ("Category Threes", 8, 2): {0: 5310, 3: 18930, 6: 29232, 9: 26016, 12: 14399, 15: 6113}, + ("Category Threes", 8, 3): {0: 1328, 3: 7328, 6: 18754, 9: 27141, 12: 24703, 15: 14251, 18: 6495}, + ("Category Threes", 8, 4): {0: 2719, 6: 9554, 9: 20607, 12: 26898, 15: 23402, 18: 12452, 21: 4368}, + ("Category Threes", 8, 5): {0: 905, 9: 16848, 12: 23248, 15: 27931, 18: 20616, 21: 10452}, + ("Category Threes", 8, 6): {0: 1914, 9: 6890, 12: 17302, 15: 27235, 18: 27276, 21: 19383}, + ("Category Threes", 8, 7): {0: 800, 12: 15127, 15: 23682, 18: 30401, 21: 22546, 24: 7444}, + ("Category Threes", 8, 8): {0: 2041, 12: 7211, 15: 18980, 18: 30657, 21: 29074, 24: 12037}, + ("Category Fours", 0, 0): {0: 100000}, + ("Category Fours", 0, 1): {0: 100000}, + ("Category Fours", 0, 2): {0: 100000}, + ("Category Fours", 0, 3): {0: 100000}, + ("Category Fours", 0, 4): {0: 100000}, + ("Category Fours", 0, 5): {0: 100000}, + ("Category Fours", 0, 6): {0: 100000}, + ("Category Fours", 0, 7): {0: 100000}, + ("Category Fours", 0, 8): {0: 100000}, + ("Category Fours", 1, 0): {0: 100000}, + ("Category Fours", 1, 1): {0: 83260, 4: 16740}, + ("Category Fours", 1, 2): {0: 69514, 4: 30486}, + ("Category Fours", 1, 3): {0: 58017, 4: 41983}, + ("Category Fours", 1, 4): {0: 48389, 4: 51611}, + ("Category Fours", 1, 5): {0: 40201, 4: 59799}, + ("Category Fours", 1, 6): {0: 33496, 4: 66504}, + ("Category Fours", 1, 7): {0: 28052, 4: 71948}, + ("Category Fours", 1, 8): {0: 23431, 4: 76569}, + ("Category Fours", 2, 0): {0: 100000}, + ("Category Fours", 2, 1): {0: 69379, 4: 30621}, + ("Category Fours", 2, 2): {0: 48538, 4: 42240, 8: 9222}, + ("Category Fours", 2, 3): {0: 33756, 4: 48555, 8: 17689}, + ("Category Fours", 2, 4): {0: 23070, 4: 49916, 8: 27014}, + ("Category Fours", 2, 5): {0: 16222, 4: 48009, 8: 35769}, + ("Category Fours", 2, 6): {0: 11125, 4: 44400, 8: 44475}, + ("Category Fours", 2, 7): {0: 7919, 4: 40216, 8: 51865}, + ("Category Fours", 2, 8): {0: 5348, 4: 35757, 8: 58895}, + ("Category Fours", 3, 0): {0: 100000}, + ("Category Fours", 3, 1): {0: 57914, 4: 34622, 8: 7464}, + ("Category Fours", 3, 2): {0: 33621, 4: 44110, 8: 22269}, + ("Category Fours", 3, 3): {0: 19153, 4: 42425, 8: 30898, 12: 7524}, + ("Category Fours", 3, 4): {0: 11125, 4: 36011, 8: 39024, 12: 13840}, + ("Category Fours", 3, 5): {0: 6367, 4: 29116, 8: 43192, 12: 21325}, + ("Category Fours", 3, 6): {0: 3643, 4: 22457, 8: 44477, 12: 29423}, + ("Category Fours", 3, 7): {0: 2178, 4: 16802, 8: 43275, 12: 37745}, + ("Category Fours", 3, 8): {0: 1255, 4: 12301, 8: 41132, 12: 45312}, + ("Category Fours", 4, 0): {0: 100000}, + ("Category Fours", 4, 1): {0: 48465, 4: 38398, 8: 13137}, + ("Category Fours", 4, 2): {0: 23296, 4: 40911, 8: 27073, 12: 8720}, + ("Category Fours", 4, 3): {0: 11200, 4: 33191, 8: 35337, 12: 20272}, + ("Category Fours", 4, 4): {0: 5447, 4: 23066, 8: 37441, 12: 26861, 16: 7185}, + ("Category Fours", 4, 5): {0: 2533, 4: 15668, 8: 34781, 12: 34222, 16: 12796}, + ("Category Fours", 4, 6): {0: 1314, 4: 10001, 8: 29850, 12: 39425, 16: 19410}, + ("Category Fours", 4, 7): {0: 592, 4: 6231, 8: 24250, 12: 41917, 16: 27010}, + ("Category Fours", 4, 8): {0: 302, 8: 23055, 12: 41866, 16: 34777}, + ("Category Fours", 5, 0): {0: 100000}, + ("Category Fours", 5, 1): {0: 40215, 4: 40127, 8: 16028, 12: 3630}, + ("Category Fours", 5, 2): {0: 15946, 4: 35579, 8: 31158, 12: 13998, 16: 3319}, + ("Category Fours", 5, 3): {0: 6479, 4: 23705, 8: 34575, 12: 24783, 16: 10458}, + ("Category Fours", 5, 4): {0: 2635, 4: 13889, 8: 30079, 12: 32428, 16: 17263, 20: 3706}, + ("Category Fours", 5, 5): {0: 1160, 4: 7756, 8: 23332, 12: 34254, 16: 25803, 20: 7695}, + ("Category Fours", 5, 6): {0: 434, 8: 20773, 12: 32910, 16: 32752, 20: 13131}, + ("Category Fours", 5, 7): {0: 169, 8: 13536, 12: 29123, 16: 37701, 20: 19471}, + ("Category Fours", 5, 8): {0: 1267, 8: 7340, 12: 24807, 16: 40144, 20: 26442}, + ("Category Fours", 6, 0): {0: 100000}, + ("Category Fours", 6, 1): {0: 33632, 4: 39856, 8: 20225, 12: 6287}, + ("Category Fours", 6, 2): {0: 11175, 4: 29824, 8: 32381, 12: 19179, 16: 7441}, + ("Category Fours", 6, 3): {0: 3698, 4: 16329, 8: 29939, 12: 29071, 16: 15808, 20: 5155}, + ("Category Fours", 6, 4): {0: 1284, 4: 7889, 8: 21748, 12: 31107, 16: 25281, 20: 12691}, + ("Category Fours", 6, 5): {0: 462, 8: 17601, 12: 27817, 16: 31233, 20: 18386, 24: 4501}, + ("Category Fours", 6, 6): {0: 1783, 8: 8344, 12: 22156, 16: 32690, 20: 26192, 24: 8835}, + ("Category Fours", 6, 7): {0: 767, 12: 20974, 16: 31490, 20: 32639, 24: 14130}, + ("Category Fours", 6, 8): {0: 357, 12: 13912, 16: 27841, 20: 37380, 24: 20510}, + ("Category Fours", 7, 0): {0: 100000}, + ("Category Fours", 7, 1): {0: 27821, 4: 39289, 8: 23327, 12: 9563}, + ("Category Fours", 7, 2): {0: 7950, 4: 24026, 8: 31633, 12: 23169, 16: 13222}, + ("Category Fours", 7, 3): {0: 2194, 4: 11153, 8: 24107, 12: 29411, 16: 21390, 20: 11745}, + ("Category Fours", 7, 4): {0: 560, 8: 19291, 12: 26330, 16: 28118, 20: 18174, 24: 7527}, + ("Category Fours", 7, 5): {0: 1858, 8: 7862, 12: 19425, 16: 29003, 20: 26113, 24: 15739}, + ("Category Fours", 7, 6): {0: 679, 12: 16759, 16: 25831, 20: 30724, 24: 20147, 28: 5860}, + ("Category Fours", 7, 7): {0: 13, 12: 10063, 16: 20524, 20: 31843, 24: 27368, 28: 10189}, + ("Category Fours", 7, 8): {4: 864, 16: 19910, 20: 30153, 24: 33428, 28: 15645}, + ("Category Fours", 8, 0): {0: 100000}, + ("Category Fours", 8, 1): {0: 23275, 4: 37161, 8: 25964, 12: 13600}, + ("Category Fours", 8, 2): {0: 5421, 4: 19014, 8: 29259, 12: 25812, 16: 14387, 20: 6107}, + ("Category Fours", 8, 3): {0: 1277, 4: 7349, 8: 18330, 12: 27186, 16: 25138, 20: 14371, 24: 6349}, + ("Category Fours", 8, 4): {0: 289, 8: 11929, 12: 20282, 16: 26960, 20: 23292, 24: 12927, 28: 4321}, + ("Category Fours", 8, 5): {0: 835, 12: 16706, 16: 23588, 20: 27754, 24: 20767, 28: 10350}, + ("Category Fours", 8, 6): {0: 21, 12: 8911, 16: 17296, 20: 27398, 24: 27074, 28: 15457, 32: 3843}, + ("Category Fours", 8, 7): {0: 745, 16: 15069, 20: 23737, 24: 30628, 28: 22590, 32: 7231}, + ("Category Fours", 8, 8): {0: 1949, 16: 7021, 20: 18630, 24: 31109, 28: 29548, 32: 11743}, + ("Category Fives", 0, 0): {0: 100000}, + ("Category Fives", 0, 1): {0: 100000}, + ("Category Fives", 0, 2): {0: 100000}, + ("Category Fives", 0, 3): {0: 100000}, + ("Category Fives", 0, 4): {0: 100000}, + ("Category Fives", 0, 5): {0: 100000}, + ("Category Fives", 0, 6): {0: 100000}, + ("Category Fives", 0, 7): {0: 100000}, + ("Category Fives", 0, 8): {0: 100000}, + ("Category Fives", 1, 0): {0: 100000}, + ("Category Fives", 1, 1): {0: 83338, 5: 16662}, + ("Category Fives", 1, 2): {0: 69499, 5: 30501}, + ("Category Fives", 1, 3): {0: 57799, 5: 42201}, + ("Category Fives", 1, 4): {0: 48311, 5: 51689}, + ("Category Fives", 1, 5): {0: 40084, 5: 59916}, + ("Category Fives", 1, 6): {0: 33440, 5: 66560}, + ("Category Fives", 1, 7): {0: 27730, 5: 72270}, + ("Category Fives", 1, 8): {0: 23210, 5: 76790}, + ("Category Fives", 2, 0): {0: 100000}, + ("Category Fives", 2, 1): {0: 69299, 5: 27864, 10: 2837}, + ("Category Fives", 2, 2): {0: 48156, 5: 42526, 10: 9318}, + ("Category Fives", 2, 3): {0: 33225, 5: 49153, 10: 17622}, + ("Category Fives", 2, 4): {0: 23218, 5: 50075, 10: 26707}, + ("Category Fives", 2, 5): {0: 15939, 5: 48313, 10: 35748}, + ("Category Fives", 2, 6): {0: 11340, 5: 44324, 10: 44336}, + ("Category Fives", 2, 7): {0: 7822, 5: 40388, 10: 51790}, + ("Category Fives", 2, 8): {0: 5386, 5: 35636, 10: 58978}, + ("Category Fives", 3, 0): {0: 100000}, + ("Category Fives", 3, 1): {0: 58034, 5: 34541, 10: 7425}, + ("Category Fives", 3, 2): {0: 33466, 5: 44227, 10: 19403, 15: 2904}, + ("Category Fives", 3, 3): {0: 19231, 5: 42483, 10: 30794, 15: 7492}, + ("Category Fives", 3, 4): {0: 11196, 5: 36192, 10: 38673, 15: 13939}, + ("Category Fives", 3, 5): {0: 6561, 5: 29163, 10: 43014, 15: 21262}, + ("Category Fives", 3, 6): {0: 3719, 5: 22181, 10: 44611, 15: 29489}, + ("Category Fives", 3, 7): {0: 2099, 5: 16817, 10: 43466, 15: 37618}, + ("Category Fives", 3, 8): {0: 1281, 5: 12473, 10: 40936, 15: 45310}, + ("Category Fives", 4, 0): {0: 100000}, + ("Category Fives", 4, 1): {0: 48377, 5: 38345, 10: 13278}, + ("Category Fives", 4, 2): {0: 23126, 5: 40940, 10: 27041, 15: 8893}, + ("Category Fives", 4, 3): {0: 11192, 5: 32597, 10: 35753, 15: 17250, 20: 3208}, + ("Category Fives", 4, 4): {0: 5362, 5: 23073, 10: 37379, 15: 26968, 20: 7218}, + ("Category Fives", 4, 5): {0: 2655, 5: 15662, 10: 34602, 15: 34186, 20: 12895}, + ("Category Fives", 4, 6): {0: 1291, 5: 9959, 10: 29833, 15: 39417, 20: 19500}, + ("Category Fives", 4, 7): {0: 623, 5: 6231, 10: 24360, 15: 41779, 20: 27007}, + ("Category Fives", 4, 8): {0: 313, 10: 23001, 15: 41957, 20: 34729}, + ("Category Fives", 5, 0): {0: 100000}, + ("Category Fives", 5, 1): {0: 39911, 5: 40561, 10: 16029, 15: 3499}, + ("Category Fives", 5, 2): {0: 16178, 5: 35517, 10: 31246, 15: 13793, 20: 3266}, + ("Category Fives", 5, 3): {0: 6526, 5: 23716, 10: 34430, 15: 25017, 20: 10311}, + ("Category Fives", 5, 4): {0: 2615, 5: 13975, 10: 30133, 15: 32247, 20: 17219, 25: 3811}, + ("Category Fives", 5, 5): {0: 1063, 5: 7876, 10: 23203, 15: 34489, 20: 25757, 25: 7612}, + ("Category Fives", 5, 6): {0: 429, 5: 4091, 10: 16696, 15: 32855, 20: 32891, 25: 13038}, + ("Category Fives", 5, 7): {0: 159, 10: 13509, 15: 29416, 20: 37778, 25: 19138}, + ("Category Fives", 5, 8): {0: 1179, 10: 7453, 15: 24456, 20: 40615, 25: 26297}, + ("Category Fives", 6, 0): {0: 100000}, + ("Category Fives", 6, 1): {0: 33476, 5: 40167, 10: 20181, 15: 6176}, + ("Category Fives", 6, 2): {0: 11322, 5: 29613, 10: 32664, 15: 19004, 20: 7397}, + ("Category Fives", 6, 3): {0: 3765, 5: 16288, 10: 29770, 15: 29233, 20: 15759, 25: 5185}, + ("Category Fives", 6, 4): {0: 1201, 5: 8226, 10: 21518, 15: 31229, 20: 25160, 25: 12666}, + ("Category Fives", 6, 5): {0: 433, 10: 17879, 15: 27961, 20: 30800, 25: 18442, 30: 4485}, + ("Category Fives", 6, 6): {0: 141, 10: 10040, 15: 22226, 20: 32744, 25: 26341, 30: 8508}, + ("Category Fives", 6, 7): {0: 772, 10: 4724, 15: 16206, 20: 31363, 25: 32784, 30: 14151}, + ("Category Fives", 6, 8): {0: 297, 15: 13902, 20: 28004, 25: 37178, 30: 20619}, + ("Category Fives", 7, 0): {0: 100000}, + ("Category Fives", 7, 1): {0: 27826, 5: 39154, 10: 23567, 15: 9453}, + ("Category Fives", 7, 2): {0: 7609, 5: 24193, 10: 31722, 15: 23214, 20: 10140, 25: 3122}, + ("Category Fives", 7, 3): {0: 2262, 5: 11013, 10: 24443, 15: 29307, 20: 21387, 25: 11588}, + ("Category Fives", 7, 4): {0: 618, 5: 4583, 10: 14761, 15: 26159, 20: 28335, 25: 18050, 30: 7494}, + ("Category Fives", 7, 5): {0: 183, 10: 9616, 15: 19685, 20: 28915, 25: 26000, 30: 12883, 35: 2718}, + ("Category Fives", 7, 6): {0: 670, 15: 16878, 20: 25572, 25: 30456, 30: 20695, 35: 5729}, + ("Category Fives", 7, 7): {0: 255, 15: 9718, 20: 20696, 25: 31883, 30: 27333, 35: 10115}, + ("Category Fives", 7, 8): {0: 927, 15: 4700, 20: 15292, 25: 30298, 30: 33015, 35: 15768}, + ("Category Fives", 8, 0): {0: 100000}, + ("Category Fives", 8, 1): {0: 23333, 5: 37259, 10: 25947, 15: 10392, 20: 3069}, + ("Category Fives", 8, 2): {0: 5425, 5: 18915, 10: 29380, 15: 25994, 20: 14056, 25: 6230}, + ("Category Fives", 8, 3): {0: 1258, 5: 7317, 10: 18783, 15: 27375, 20: 24542, 25: 14322, 30: 6403}, + ("Category Fives", 8, 4): {0: 271, 10: 11864, 15: 20267, 20: 27158, 25: 23589, 30: 12529, 35: 4322}, + ("Category Fives", 8, 5): {0: 943, 10: 4260, 15: 12456, 20: 23115, 25: 27968, 30: 20704, 35: 10554}, + ("Category Fives", 8, 6): {0: 281, 15: 8625, 20: 17201, 25: 27484, 30: 27178, 35: 15414, 40: 3817}, + ("Category Fives", 8, 7): {0: 746, 20: 14964, 25: 23717, 30: 30426, 35: 22677, 40: 7470}, + ("Category Fives", 8, 8): {0: 261, 20: 8927, 25: 18714, 30: 31084, 35: 29126, 40: 11888}, + ("Category Sixes", 0, 0): {0: 100000}, + ("Category Sixes", 0, 1): {0: 100000}, + ("Category Sixes", 0, 2): {0: 100000}, + ("Category Sixes", 0, 3): {0: 100000}, + ("Category Sixes", 0, 4): {0: 100000}, + ("Category Sixes", 0, 5): {0: 100000}, + ("Category Sixes", 0, 6): {0: 100000}, + ("Category Sixes", 0, 7): {0: 100000}, + ("Category Sixes", 0, 8): {0: 100000}, + ("Category Sixes", 1, 0): {0: 100000}, + ("Category Sixes", 1, 1): {0: 83168, 6: 16832}, + ("Category Sixes", 1, 2): {0: 69548, 6: 30452}, + ("Category Sixes", 1, 3): {0: 57697, 6: 42303}, + ("Category Sixes", 1, 4): {0: 48043, 6: 51957}, + ("Category Sixes", 1, 5): {0: 39912, 6: 60088}, + ("Category Sixes", 1, 6): {0: 33499, 6: 66501}, + ("Category Sixes", 1, 7): {0: 28251, 6: 71749}, + ("Category Sixes", 1, 8): {0: 23206, 6: 76794}, + ("Category Sixes", 2, 0): {0: 100000}, + ("Category Sixes", 2, 1): {0: 69463, 6: 27651, 12: 2886}, + ("Category Sixes", 2, 2): {0: 47896, 6: 42794, 12: 9310}, + ("Category Sixes", 2, 3): {0: 33394, 6: 48757, 12: 17849}, + ("Category Sixes", 2, 4): {0: 23552, 6: 49554, 12: 26894}, + ("Category Sixes", 2, 5): {0: 16090, 6: 48098, 12: 35812}, + ("Category Sixes", 2, 6): {0: 11073, 6: 44833, 12: 44094}, + ("Category Sixes", 2, 7): {0: 7737, 6: 40480, 12: 51783}, + ("Category Sixes", 2, 8): {0: 5379, 6: 35672, 12: 58949}, + ("Category Sixes", 3, 0): {0: 100000}, + ("Category Sixes", 3, 1): {0: 57718, 6: 34818, 12: 7464}, + ("Category Sixes", 3, 2): {0: 33610, 6: 44328, 12: 19159, 18: 2903}, + ("Category Sixes", 3, 3): {0: 19366, 6: 42246, 12: 30952, 18: 7436}, + ("Category Sixes", 3, 4): {0: 11144, 6: 36281, 12: 38817, 18: 13758}, + ("Category Sixes", 3, 5): {0: 6414, 6: 28891, 12: 43114, 18: 21581}, + ("Category Sixes", 3, 6): {0: 3870, 6: 22394, 12: 44318, 18: 29418}, + ("Category Sixes", 3, 7): {0: 2188, 6: 16803, 12: 43487, 18: 37522}, + ("Category Sixes", 3, 8): {0: 1289, 6: 12421, 12: 41082, 18: 45208}, + ("Category Sixes", 4, 0): {0: 100000}, + ("Category Sixes", 4, 1): {0: 48197, 6: 38521, 12: 13282}, + ("Category Sixes", 4, 2): {0: 23155, 6: 41179, 12: 26935, 18: 8731}, + ("Category Sixes", 4, 3): {0: 11256, 6: 32609, 12: 35588, 18: 17390, 24: 3157}, + ("Category Sixes", 4, 4): {0: 5324, 6: 23265, 12: 37209, 18: 26929, 24: 7273}, + ("Category Sixes", 4, 5): {0: 2658, 6: 15488, 12: 34685, 18: 34476, 24: 12693}, + ("Category Sixes", 4, 6): {0: 1282, 6: 9997, 12: 29855, 18: 39379, 24: 19487}, + ("Category Sixes", 4, 7): {0: 588, 6: 6202, 12: 24396, 18: 41935, 24: 26879}, + ("Category Sixes", 4, 8): {0: 317, 6: 3863, 12: 19042, 18: 42180, 24: 34598}, + ("Category Sixes", 5, 0): {0: 100000}, + ("Category Sixes", 5, 1): {0: 40393, 6: 39904, 12: 16206, 18: 3497}, + ("Category Sixes", 5, 2): {0: 16202, 6: 35664, 12: 31241, 18: 13612, 24: 3281}, + ("Category Sixes", 5, 3): {0: 6456, 6: 23539, 12: 34585, 18: 25020, 24: 10400}, + ("Category Sixes", 5, 4): {0: 2581, 6: 13980, 12: 30355, 18: 32198, 24: 17115, 30: 3771}, + ("Category Sixes", 5, 5): {0: 1119, 6: 7775, 12: 23063, 18: 34716, 24: 25568, 30: 7759}, + ("Category Sixes", 5, 6): {0: 392, 6: 4171, 12: 16724, 18: 32792, 24: 32829, 30: 13092}, + ("Category Sixes", 5, 7): {0: 197, 12: 13627, 18: 29190, 24: 37560, 30: 19426}, + ("Category Sixes", 5, 8): {0: 1246, 12: 7404, 18: 24560, 24: 40134, 30: 26656}, + ("Category Sixes", 6, 0): {0: 100000}, + ("Category Sixes", 6, 1): {0: 33316, 6: 40218, 12: 20198, 18: 6268}, + ("Category Sixes", 6, 2): {0: 11256, 6: 29444, 12: 32590, 18: 19196, 24: 7514}, + ("Category Sixes", 6, 3): {0: 3787, 6: 16266, 12: 29873, 18: 29107, 24: 15863, 30: 5104}, + ("Category Sixes", 6, 4): {0: 1286, 6: 8066, 12: 21653, 18: 31264, 24: 25039, 30: 12692}, + ("Category Sixes", 6, 5): {0: 413, 6: 3777, 12: 13962, 18: 27705, 24: 30919, 30: 18670, 36: 4554}, + ("Category Sixes", 6, 6): {0: 146, 12: 10040, 18: 22320, 24: 32923, 30: 26086, 36: 8485}, + ("Category Sixes", 6, 7): {0: 814, 12: 4698, 18: 16286, 24: 31577, 30: 32487, 36: 14138}, + ("Category Sixes", 6, 8): {0: 328, 18: 14004, 24: 28064, 30: 37212, 36: 20392}, + ("Category Sixes", 7, 0): {0: 100000}, + ("Category Sixes", 7, 1): {0: 27852, 6: 38984, 12: 23499, 18: 9665}, + ("Category Sixes", 7, 2): {0: 7883, 6: 23846, 12: 31558, 18: 23295, 24: 10316, 30: 3102}, + ("Category Sixes", 7, 3): {0: 2186, 6: 10928, 12: 24321, 18: 29650, 24: 21177, 30: 9209, 36: 2529}, + ("Category Sixes", 7, 4): {0: 603, 6: 4459, 12: 14673, 18: 26303, 24: 28335, 30: 18228, 36: 7399}, + ("Category Sixes", 7, 5): {0: 172, 12: 9654, 18: 19381, 24: 29254, 30: 25790, 36: 12992, 42: 2757}, + ("Category Sixes", 7, 6): {0: 704, 12: 3864, 18: 13039, 24: 25760, 30: 30698, 36: 20143, 42: 5792}, + ("Category Sixes", 7, 7): {0: 257, 18: 9857, 24: 20557, 30: 31709, 36: 27546, 42: 10074}, + ("Category Sixes", 7, 8): {0: 872, 18: 4658, 24: 15419, 30: 30259, 36: 33183, 42: 15609}, + ("Category Sixes", 8, 0): {0: 100000}, + ("Category Sixes", 8, 1): {0: 23220, 6: 37213, 12: 25961, 18: 10483, 24: 3123}, + ("Category Sixes", 8, 2): {0: 5280, 6: 18943, 12: 29664, 18: 25777, 24: 14170, 30: 6166}, + ("Category Sixes", 8, 3): {0: 1246, 6: 7112, 12: 18757, 18: 27277, 24: 24802, 30: 14351, 36: 6455}, + ("Category Sixes", 8, 4): {0: 301, 12: 12044, 18: 20247, 24: 27146, 30: 23403, 36: 12524, 42: 4335}, + ("Category Sixes", 8, 5): {0: 859, 12: 4241, 18: 12477, 24: 23471, 30: 27655, 36: 20803, 42: 10494}, + ("Category Sixes", 8, 6): {0: 277, 18: 8656, 24: 17373, 30: 27347, 36: 27024, 42: 15394, 48: 3929}, + ("Category Sixes", 8, 7): {0: 766, 18: 3503, 24: 11451, 30: 23581, 36: 30772, 42: 22654, 48: 7273}, + ("Category Sixes", 8, 8): {6: 262, 24: 8866, 30: 18755, 36: 31116, 42: 28870, 48: 12131}, + ("Category Choice", 0, 0): {0: 100000}, + ("Category Choice", 0, 1): {0: 100000}, + ("Category Choice", 0, 2): {0: 100000}, + ("Category Choice", 0, 3): {0: 100000}, + ("Category Choice", 0, 4): {0: 100000}, + ("Category Choice", 0, 5): {0: 100000}, + ("Category Choice", 0, 6): {0: 100000}, + ("Category Choice", 0, 7): {0: 100000}, + ("Category Choice", 0, 8): {0: 100000}, + ("Category Choice", 1, 0): {0: 100000}, + ("Category Choice", 1, 1): {1: 16642, 3: 33501, 5: 33218, 6: 16639}, + ("Category Choice", 1, 2): {1: 10921, 3: 22060, 5: 39231, 6: 27788}, + ("Category Choice", 1, 3): {1: 9416, 4: 27917, 5: 22740, 6: 39927}, + ("Category Choice", 1, 4): {1: 15490, 3: 15489, 6: 69021}, + ("Category Choice", 1, 5): {1: 12817, 3: 12757, 6: 74426}, + ("Category Choice", 1, 6): {1: 10513, 3: 10719, 6: 78768}, + ("Category Choice", 1, 7): {1: 8893, 6: 91107}, + ("Category Choice", 1, 8): {1: 14698, 6: 85302}, + ("Category Choice", 2, 0): {0: 100000}, + ("Category Choice", 2, 1): {2: 8504, 6: 32987, 8: 30493, 11: 28016}, + ("Category Choice", 2, 2): {2: 3714, 7: 33270, 9: 25859, 11: 37157}, + ("Category Choice", 2, 3): {2: 5113, 5: 10402, 8: 25783, 10: 24173, 12: 34529}, + ("Category Choice", 2, 4): {2: 1783, 4: 8908, 8: 23189, 10: 22115, 12: 44005}, + ("Category Choice", 2, 5): {2: 7575, 8: 20444, 11: 38062, 12: 33919}, + ("Category Choice", 2, 6): {2: 5153, 9: 26383, 11: 25950, 12: 42514}, + ("Category Choice", 2, 7): {2: 3638, 7: 15197, 9: 14988, 12: 66177}, + ("Category Choice", 2, 8): {2: 2448, 7: 13306, 9: 12754, 12: 71492}, + ("Category Choice", 3, 0): {0: 100000}, + ("Category Choice", 3, 1): {3: 4589, 6: 11560, 9: 21469, 11: 25007, 13: 28332, 15: 9043}, + ("Category Choice", 3, 2): {3: 1380, 6: 8622, 9: 14417, 12: 23457, 14: 24807, 17: 27317}, + ("Category Choice", 3, 3): {3: 1605, 7: 9370, 10: 13491, 13: 24408, 15: 23065, 17: 28061}, + ("Category Choice", 3, 4): {3: 7212, 13: 32000, 15: 22707, 17: 38081}, + ("Category Choice", 3, 5): {3: 7989, 11: 10756, 14: 23811, 16: 21668, 18: 35776}, + ("Category Choice", 3, 6): {3: 3251, 10: 10272, 14: 21653, 17: 37049, 18: 27775}, + ("Category Choice", 3, 7): {3: 1018, 9: 8591, 15: 28080, 17: 26469, 18: 35842}, + ("Category Choice", 3, 8): {3: 6842, 15: 25118, 17: 24534, 18: 43506}, + ("Category Choice", 4, 0): {0: 100000}, + ("Category Choice", 4, 1): {4: 5386, 9: 10561, 13: 28501, 15: 21902, 17: 23999, 19: 9651}, + ("Category Choice", 4, 2): {4: 7510, 12: 10646, 16: 28145, 18: 22596, 19: 17705, 21: 13398}, + ("Category Choice", 4, 3): {4: 2392, 11: 8547, 14: 13300, 18: 29887, 20: 21680, 21: 15876, 23: 8318}, + ("Category Choice", 4, 4): {4: 2258, 12: 8230, 15: 12216, 19: 31486, 21: 20698, 23: 25112}, + ("Category Choice", 4, 5): {4: 2209, 13: 8484, 16: 11343, 19: 21913, 21: 21675, 23: 34376}, + ("Category Choice", 4, 6): {4: 2179, 14: 8704, 17: 12056, 20: 23300, 22: 20656, 24: 33105}, + ("Category Choice", 4, 7): {5: 7652, 19: 20489, 21: 20365, 23: 26176, 24: 25318}, + ("Category Choice", 4, 8): {5: 3231, 16: 8958, 21: 28789, 23: 25837, 24: 33185}, + ("Category Choice", 5, 0): {0: 100000}, + ("Category Choice", 5, 1): {5: 1575, 10: 8293, 13: 12130, 17: 28045, 20: 40099, 23: 9858}, + ("Category Choice", 5, 2): {5: 3298, 14: 10211, 17: 13118, 21: 28204, 24: 34078, 26: 11091}, + ("Category Choice", 5, 3): {6: 2633, 15: 8316, 18: 11302, 22: 26605, 24: 20431, 26: 22253, 28: 8460}, + ("Category Choice", 5, 4): {5: 4084, 17: 9592, 20: 13422, 24: 28620, 26: 20353, 27: 14979, 29: 8950}, + ("Category Choice", 5, 5): {6: 348, 14: 8075, 20: 10195, 22: 14679, 25: 22335, 28: 28253, 29: 16115}, + ("Category Choice", 5, 6): {7: 3204, 19: 9258, 22: 11859, 25: 21412, 27: 20895, 29: 33372}, + ("Category Choice", 5, 7): {8: 2983, 20: 9564, 23: 12501, 26: 22628, 29: 34285, 30: 18039}, + ("Category Choice", 5, 8): {9: 323, 17: 8259, 25: 20762, 27: 20118, 29: 25318, 30: 25220}, + ("Category Choice", 6, 0): {0: 100000}, + ("Category Choice", 6, 1): {6: 6102, 17: 21746, 21: 26524, 23: 25004, 25: 11086, 27: 9538}, + ("Category Choice", 6, 2): {8: 1504, 16: 8676, 20: 10032, 22: 14673, 26: 27312, 27: 16609, 29: 12133, 31: 9061}, + ("Category Choice", 6, 3): {6: 1896, 18: 8914, 22: 10226, 24: 14822, 28: 27213, 31: 28868, 33: 8061}, + ("Category Choice", 6, 4): {9: 441, 17: 8018, 25: 22453, 29: 26803, 32: 32275, 34: 10010}, + ("Category Choice", 6, 5): {10: 1788, 21: 8763, 25: 10319, 27: 14763, 31: 30144, 33: 23879, 35: 10344}, + ("Category Choice", 6, 6): {13: 876, 21: 8303, 28: 24086, 31: 21314, 34: 28149, 35: 17272}, + ("Category Choice", 6, 7): {12: 3570, 25: 9625, 28: 11348, 31: 20423, 33: 20469, 35: 34565}, + ("Category Choice", 6, 8): {12: 3450, 26: 9544, 29: 12230, 32: 22130, 35: 33671, 36: 18975}, + ("Category Choice", 7, 0): {0: 100000}, + ("Category Choice", 7, 1): {7: 1237, 15: 8100, 21: 23947, 25: 25361, 27: 22186, 31: 19169}, + ("Category Choice", 7, 2): {10: 2086, 20: 8960, 26: 23657, 30: 25264, 31: 15759, 33: 12356, 35: 11918}, + ("Category Choice", 7, 3): {10: 4980, 24: 9637, 27: 11247, 29: 15046, 33: 33492, 35: 13130, 37: 12468}, + ("Category Choice", 7, 4): {13: 2260, 24: 8651, 30: 23022, 34: 25656, 37: 29910, 39: 10501}, + ("Category Choice", 7, 5): {12: 3879, 27: 8154, 30: 10292, 32: 14692, 36: 27425, 38: 23596, 40: 11962}, + ("Category Choice", 7, 6): {14: 1957, 27: 8230, 33: 23945, 37: 29286, 39: 24519, 41: 12063}, + ("Category Choice", 7, 7): {16: 599, 26: 8344, 34: 22981, 37: 20883, 40: 28045, 42: 19148}, + ("Category Choice", 7, 8): {14: 3639, 31: 8907, 34: 10904, 37: 20148, 39: 20219, 41: 21627, 42: 14556}, + ("Category Choice", 8, 0): {0: 100000}, + ("Category Choice", 8, 1): {10: 752, 17: 8385, 24: 21460, 26: 15361, 29: 23513, 31: 12710, 35: 17819}, + ("Category Choice", 8, 2): {11: 5900, 26: 10331, 29: 11435, 31: 14533, 34: 23939, 36: 13855, 38: 10165, 40: 9842}, + ("Category Choice", 8, 3): {12: 2241, 26: 8099, 32: 20474, 34: 14786, 38: 31140, 40: 11751, 42: 11509}, + ("Category Choice", 8, 4): {16: 1327, 27: 8361, 34: 19865, 36: 15078, 40: 32325, 42: 12218, 44: 10826}, + ("Category Choice", 8, 5): {16: 4986, 32: 9031, 35: 10214, 37: 14528, 41: 25608, 42: 16131, 44: 11245, 46: 8257}, + ("Category Choice", 8, 6): {16: 2392, 32: 8742, 38: 23237, 42: 26333, 45: 30725, 47: 8571}, + ("Category Choice", 8, 7): {20: 1130, 32: 8231, 39: 22137, 43: 28783, 45: 25221, 47: 14498}, + ("Category Choice", 8, 8): {20: 73, 28: 8033, 40: 21670, 43: 20615, 46: 28105, 48: 21504}, + ("Category Inverse Choice", 0, 0): {0: 100000}, + ("Category Inverse Choice", 0, 1): {0: 100000}, + ("Category Inverse Choice", 0, 2): {0: 100000}, + ("Category Inverse Choice", 0, 3): {0: 100000}, + ("Category Inverse Choice", 0, 4): {0: 100000}, + ("Category Inverse Choice", 0, 5): {0: 100000}, + ("Category Inverse Choice", 0, 6): {0: 100000}, + ("Category Inverse Choice", 0, 7): {0: 100000}, + ("Category Inverse Choice", 0, 8): {0: 100000}, + ("Category Inverse Choice", 1, 0): {0: 100000}, + ("Category Inverse Choice", 1, 1): {1: 16642, 3: 33501, 5: 33218, 6: 16639}, + ("Category Inverse Choice", 1, 2): {1: 10921, 3: 22060, 5: 39231, 6: 27788}, + ("Category Inverse Choice", 1, 3): {1: 9416, 4: 27917, 5: 22740, 6: 39927}, + ("Category Inverse Choice", 1, 4): {1: 15490, 3: 15489, 6: 69021}, + ("Category Inverse Choice", 1, 5): {1: 12817, 3: 12757, 6: 74426}, + ("Category Inverse Choice", 1, 6): {1: 10513, 3: 10719, 6: 78768}, + ("Category Inverse Choice", 1, 7): {1: 8893, 6: 91107}, + ("Category Inverse Choice", 1, 8): {1: 14698, 6: 85302}, + ("Category Inverse Choice", 2, 0): {0: 100000}, + ("Category Inverse Choice", 2, 1): {2: 8504, 6: 32987, 8: 30493, 11: 28016}, + ("Category Inverse Choice", 2, 2): {2: 3714, 7: 33270, 9: 25859, 11: 37157}, + ("Category Inverse Choice", 2, 3): {2: 5113, 5: 10402, 8: 25783, 10: 24173, 12: 34529}, + ("Category Inverse Choice", 2, 4): {2: 1783, 4: 8908, 8: 23189, 10: 22115, 12: 44005}, + ("Category Inverse Choice", 2, 5): {2: 7575, 8: 20444, 11: 38062, 12: 33919}, + ("Category Inverse Choice", 2, 6): {2: 5153, 9: 26383, 11: 25950, 12: 42514}, + ("Category Inverse Choice", 2, 7): {2: 3638, 7: 15197, 9: 14988, 12: 66177}, + ("Category Inverse Choice", 2, 8): {2: 2448, 7: 13306, 9: 12754, 12: 71492}, + ("Category Inverse Choice", 3, 0): {0: 100000}, + ("Category Inverse Choice", 3, 1): {3: 4589, 6: 11560, 9: 21469, 11: 25007, 13: 28332, 15: 9043}, + ("Category Inverse Choice", 3, 2): {3: 1380, 6: 8622, 9: 14417, 12: 23457, 14: 24807, 17: 27317}, + ("Category Inverse Choice", 3, 3): {3: 1605, 7: 9370, 10: 13491, 13: 24408, 15: 23065, 17: 28061}, + ("Category Inverse Choice", 3, 4): {3: 7212, 13: 32000, 15: 22707, 17: 38081}, + ("Category Inverse Choice", 3, 5): {3: 7989, 11: 10756, 14: 23811, 16: 21668, 18: 35776}, + ("Category Inverse Choice", 3, 6): {3: 3251, 10: 10272, 14: 21653, 17: 37049, 18: 27775}, + ("Category Inverse Choice", 3, 7): {3: 1018, 9: 8591, 15: 28080, 17: 26469, 18: 35842}, + ("Category Inverse Choice", 3, 8): {3: 6842, 15: 25118, 17: 24534, 18: 43506}, + ("Category Inverse Choice", 4, 0): {0: 100000}, + ("Category Inverse Choice", 4, 1): {4: 5386, 9: 10561, 13: 28501, 15: 21902, 17: 23999, 19: 9651}, + ("Category Inverse Choice", 4, 2): {4: 7510, 12: 10646, 16: 28145, 18: 22596, 19: 17705, 21: 13398}, + ("Category Inverse Choice", 4, 3): {4: 2392, 11: 8547, 14: 13300, 18: 29887, 20: 21680, 21: 15876, 23: 8318}, + ("Category Inverse Choice", 4, 4): {4: 2258, 12: 8230, 15: 12216, 19: 31486, 21: 20698, 23: 25112}, + ("Category Inverse Choice", 4, 5): {4: 2209, 13: 8484, 16: 11343, 19: 21913, 21: 21675, 23: 34376}, + ("Category Inverse Choice", 4, 6): {4: 2179, 14: 8704, 17: 12056, 20: 23300, 22: 20656, 24: 33105}, + ("Category Inverse Choice", 4, 7): {5: 7652, 19: 20489, 21: 20365, 23: 26176, 24: 25318}, + ("Category Inverse Choice", 4, 8): {5: 3231, 16: 8958, 21: 28789, 23: 25837, 24: 33185}, + ("Category Inverse Choice", 5, 0): {0: 100000}, + ("Category Inverse Choice", 5, 1): {5: 1575, 10: 8293, 13: 12130, 17: 28045, 20: 40099, 23: 9858}, + ("Category Inverse Choice", 5, 2): {5: 3298, 14: 10211, 17: 13118, 21: 28204, 24: 34078, 26: 11091}, + ("Category Inverse Choice", 5, 3): {6: 2633, 15: 8316, 18: 11302, 22: 26605, 24: 20431, 26: 22253, 28: 8460}, + ("Category Inverse Choice", 5, 4): {5: 4084, 17: 9592, 20: 13422, 24: 28620, 26: 20353, 27: 14979, 29: 8950}, + ("Category Inverse Choice", 5, 5): {6: 348, 14: 8075, 20: 10195, 22: 14679, 25: 22335, 28: 28253, 29: 16115}, + ("Category Inverse Choice", 5, 6): {7: 3204, 19: 9258, 22: 11859, 25: 21412, 27: 20895, 29: 33372}, + ("Category Inverse Choice", 5, 7): {8: 2983, 20: 9564, 23: 12501, 26: 22628, 29: 34285, 30: 18039}, + ("Category Inverse Choice", 5, 8): {9: 323, 17: 8259, 25: 20762, 27: 20118, 29: 25318, 30: 25220}, + ("Category Inverse Choice", 6, 0): {0: 100000}, + ("Category Inverse Choice", 6, 1): {6: 6102, 17: 21746, 21: 26524, 23: 25004, 25: 11086, 27: 9538}, + ("Category Inverse Choice", 6, 2): { + 8: 1504, + 16: 8676, + 20: 10032, + 22: 14673, + 26: 27312, + 27: 16609, + 29: 12133, + 31: 9061, + }, + ("Category Inverse Choice", 6, 3): {6: 1896, 18: 8914, 22: 10226, 24: 14822, 28: 27213, 31: 28868, 33: 8061}, + ("Category Inverse Choice", 6, 4): {9: 441, 17: 8018, 25: 22453, 29: 26803, 32: 32275, 34: 10010}, + ("Category Inverse Choice", 6, 5): {10: 1788, 21: 8763, 25: 10319, 27: 14763, 31: 30144, 33: 23879, 35: 10344}, + ("Category Inverse Choice", 6, 6): {13: 876, 21: 8303, 28: 24086, 31: 21314, 34: 28149, 35: 17272}, + ("Category Inverse Choice", 6, 7): {12: 3570, 25: 9625, 28: 11348, 31: 20423, 33: 20469, 35: 34565}, + ("Category Inverse Choice", 6, 8): {12: 3450, 26: 9544, 29: 12230, 32: 22130, 35: 33671, 36: 18975}, + ("Category Inverse Choice", 7, 0): {0: 100000}, + ("Category Inverse Choice", 7, 1): {7: 1237, 15: 8100, 21: 23947, 25: 25361, 27: 22186, 31: 19169}, + ("Category Inverse Choice", 7, 2): {10: 2086, 20: 8960, 26: 23657, 30: 25264, 31: 15759, 33: 12356, 35: 11918}, + ("Category Inverse Choice", 7, 3): {10: 4980, 24: 9637, 27: 11247, 29: 15046, 33: 33492, 35: 13130, 37: 12468}, + ("Category Inverse Choice", 7, 4): {13: 2260, 24: 8651, 30: 23022, 34: 25656, 37: 29910, 39: 10501}, + ("Category Inverse Choice", 7, 5): {12: 3879, 27: 8154, 30: 10292, 32: 14692, 36: 27425, 38: 23596, 40: 11962}, + ("Category Inverse Choice", 7, 6): {14: 1957, 27: 8230, 33: 23945, 37: 29286, 39: 24519, 41: 12063}, + ("Category Inverse Choice", 7, 7): {16: 599, 26: 8344, 34: 22981, 37: 20883, 40: 28045, 42: 19148}, + ("Category Inverse Choice", 7, 8): {14: 3639, 31: 8907, 34: 10904, 37: 20148, 39: 20219, 41: 21627, 42: 14556}, + ("Category Inverse Choice", 8, 0): {0: 100000}, + ("Category Inverse Choice", 8, 1): {10: 752, 17: 8385, 24: 21460, 26: 15361, 29: 23513, 31: 12710, 35: 17819}, + ("Category Inverse Choice", 8, 2): { + 11: 5900, + 26: 10331, + 29: 11435, + 31: 14533, + 34: 23939, + 36: 13855, + 38: 10165, + 40: 9842, + }, + ("Category Inverse Choice", 8, 3): {12: 2241, 26: 8099, 32: 20474, 34: 14786, 38: 31140, 40: 11751, 42: 11509}, + ("Category Inverse Choice", 8, 4): {16: 1327, 27: 8361, 34: 19865, 36: 15078, 40: 32325, 42: 12218, 44: 10826}, + ("Category Inverse Choice", 8, 5): { + 16: 4986, + 32: 9031, + 35: 10214, + 37: 14528, + 41: 25608, + 42: 16131, + 44: 11245, + 46: 8257, + }, + ("Category Inverse Choice", 8, 6): {16: 2392, 32: 8742, 38: 23237, 42: 26333, 45: 30725, 47: 8571}, + ("Category Inverse Choice", 8, 7): {20: 1130, 32: 8231, 39: 22137, 43: 28783, 45: 25221, 47: 14498}, + ("Category Inverse Choice", 8, 8): {20: 73, 28: 8033, 40: 21670, 43: 20615, 46: 28105, 48: 21504}, + ("Category Pair", 0, 0): {0: 100000}, + ("Category Pair", 0, 1): {0: 100000}, + ("Category Pair", 0, 2): {0: 100000}, + ("Category Pair", 0, 3): {0: 100000}, + ("Category Pair", 0, 4): {0: 100000}, + ("Category Pair", 0, 5): {0: 100000}, + ("Category Pair", 0, 6): {0: 100000}, + ("Category Pair", 0, 7): {0: 100000}, + ("Category Pair", 0, 8): {0: 100000}, + ("Category Pair", 1, 0): {0: 100000}, + ("Category Pair", 1, 1): {0: 100000}, + ("Category Pair", 1, 2): {0: 100000}, + ("Category Pair", 1, 3): {0: 100000}, + ("Category Pair", 1, 4): {0: 100000}, + ("Category Pair", 1, 5): {0: 100000}, + ("Category Pair", 1, 6): {0: 100000}, + ("Category Pair", 1, 7): {0: 100000}, + ("Category Pair", 1, 8): {0: 100000}, + ("Category Pair", 2, 0): {0: 100000}, + ("Category Pair", 2, 1): {0: 83388, 10: 16612}, + ("Category Pair", 2, 2): {0: 69422, 10: 30578}, + ("Category Pair", 2, 3): {0: 57830, 10: 42170}, + ("Category Pair", 2, 4): {0: 48195, 10: 51805}, + ("Category Pair", 2, 5): {0: 40117, 10: 59883}, + ("Category Pair", 2, 6): {0: 33286, 10: 66714}, + ("Category Pair", 2, 7): {0: 27917, 10: 72083}, + ("Category Pair", 2, 8): {0: 23354, 10: 76646}, + ("Category Pair", 3, 0): {0: 100000}, + ("Category Pair", 3, 1): {0: 55518, 10: 44482}, + ("Category Pair", 3, 2): {0: 30904, 10: 69096}, + ("Category Pair", 3, 3): {0: 17242, 10: 82758}, + ("Category Pair", 3, 4): {0: 9486, 10: 90514}, + ("Category Pair", 3, 5): {0: 5362, 10: 94638}, + ("Category Pair", 3, 6): {0: 2909, 10: 97091}, + ("Category Pair", 3, 7): {0: 1574, 10: 98426}, + ("Category Pair", 3, 8): {0: 902, 10: 99098}, + ("Category Pair", 4, 0): {0: 100000}, + ("Category Pair", 4, 1): {0: 27789, 10: 72211}, + ("Category Pair", 4, 2): {0: 7799, 10: 92201}, + ("Category Pair", 4, 3): {0: 2113, 10: 97887}, + ("Category Pair", 4, 4): {0: 601, 10: 99399}, + ("Category Pair", 4, 5): {0: 155, 10: 99845}, + ("Category Pair", 4, 6): {0: 43, 10: 99957}, + ("Category Pair", 4, 7): {0: 10, 10: 99990}, + ("Category Pair", 4, 8): {0: 3, 10: 99997}, + ("Category Pair", 5, 0): {0: 100000}, + ("Category Pair", 5, 1): {0: 9298, 10: 90702}, + ("Category Pair", 5, 2): {0: 863, 10: 99137}, + ("Category Pair", 5, 3): {0: 79, 10: 99921}, + ("Category Pair", 5, 4): {0: 2, 10: 99998}, + ("Category Pair", 5, 5): {0: 2, 10: 99998}, + ("Category Pair", 5, 6): {10: 100000}, + ("Category Pair", 5, 7): {10: 100000}, + ("Category Pair", 5, 8): {10: 100000}, + ("Category Pair", 6, 0): {0: 100000}, + ("Category Pair", 6, 1): {0: 1541, 10: 98459}, + ("Category Pair", 6, 2): {0: 23, 10: 99977}, + ("Category Pair", 6, 3): {10: 100000}, + ("Category Pair", 6, 4): {10: 100000}, + ("Category Pair", 6, 5): {10: 100000}, + ("Category Pair", 6, 6): {10: 100000}, + ("Category Pair", 6, 7): {10: 100000}, + ("Category Pair", 6, 8): {10: 100000}, + ("Category Pair", 7, 0): {0: 100000}, + ("Category Pair", 7, 1): {10: 100000}, + ("Category Pair", 7, 2): {10: 100000}, + ("Category Pair", 7, 3): {10: 100000}, + ("Category Pair", 7, 4): {10: 100000}, + ("Category Pair", 7, 5): {10: 100000}, + ("Category Pair", 7, 6): {10: 100000}, + ("Category Pair", 7, 7): {10: 100000}, + ("Category Pair", 7, 8): {10: 100000}, + ("Category Pair", 8, 0): {0: 100000}, + ("Category Pair", 8, 1): {10: 100000}, + ("Category Pair", 8, 2): {10: 100000}, + ("Category Pair", 8, 3): {10: 100000}, + ("Category Pair", 8, 4): {10: 100000}, + ("Category Pair", 8, 5): {10: 100000}, + ("Category Pair", 8, 6): {10: 100000}, + ("Category Pair", 8, 7): {10: 100000}, + ("Category Pair", 8, 8): {10: 100000}, + ("Category Three of a Kind", 0, 0): {0: 100000}, + ("Category Three of a Kind", 0, 1): {0: 100000}, + ("Category Three of a Kind", 0, 2): {0: 100000}, + ("Category Three of a Kind", 0, 3): {0: 100000}, + ("Category Three of a Kind", 0, 4): {0: 100000}, + ("Category Three of a Kind", 0, 5): {0: 100000}, + ("Category Three of a Kind", 0, 6): {0: 100000}, + ("Category Three of a Kind", 0, 7): {0: 100000}, + ("Category Three of a Kind", 0, 8): {0: 100000}, + ("Category Three of a Kind", 1, 0): {0: 100000}, + ("Category Three of a Kind", 1, 1): {0: 100000}, + ("Category Three of a Kind", 1, 2): {0: 100000}, + ("Category Three of a Kind", 1, 3): {0: 100000}, + ("Category Three of a Kind", 1, 4): {0: 100000}, + ("Category Three of a Kind", 1, 5): {0: 100000}, + ("Category Three of a Kind", 1, 6): {0: 100000}, + ("Category Three of a Kind", 1, 7): {0: 100000}, + ("Category Three of a Kind", 1, 8): {0: 100000}, + ("Category Three of a Kind", 2, 0): {0: 100000}, + ("Category Three of a Kind", 2, 1): {0: 100000}, + ("Category Three of a Kind", 2, 2): {0: 100000}, + ("Category Three of a Kind", 2, 3): {0: 100000}, + ("Category Three of a Kind", 2, 4): {0: 100000}, + ("Category Three of a Kind", 2, 5): {0: 100000}, + ("Category Three of a Kind", 2, 6): {0: 100000}, + ("Category Three of a Kind", 2, 7): {0: 100000}, + ("Category Three of a Kind", 2, 8): {0: 100000}, + ("Category Three of a Kind", 3, 0): {0: 100000}, + ("Category Three of a Kind", 3, 1): {0: 97222, 20: 2778}, + ("Category Three of a Kind", 3, 2): {0: 88880, 20: 11120}, + ("Category Three of a Kind", 3, 3): {0: 78187, 20: 21813}, + ("Category Three of a Kind", 3, 4): {0: 67476, 20: 32524}, + ("Category Three of a Kind", 3, 5): {0: 57476, 20: 42524}, + ("Category Three of a Kind", 3, 6): {0: 48510, 20: 51490}, + ("Category Three of a Kind", 3, 7): {0: 40921, 20: 59079}, + ("Category Three of a Kind", 3, 8): {0: 34533, 20: 65467}, + ("Category Three of a Kind", 4, 0): {0: 100000}, + ("Category Three of a Kind", 4, 1): {0: 90316, 20: 9684}, + ("Category Three of a Kind", 4, 2): {0: 68401, 20: 31599}, + ("Category Three of a Kind", 4, 3): {0: 49383, 20: 50617}, + ("Category Three of a Kind", 4, 4): {0: 34399, 20: 65601}, + ("Category Three of a Kind", 4, 5): {0: 24154, 20: 75846}, + ("Category Three of a Kind", 4, 6): {0: 16802, 20: 83198}, + ("Category Three of a Kind", 4, 7): {0: 11623, 20: 88377}, + ("Category Three of a Kind", 4, 8): {0: 8105, 20: 91895}, + ("Category Three of a Kind", 5, 0): {0: 100000}, + ("Category Three of a Kind", 5, 1): {0: 78629, 20: 21371}, + ("Category Three of a Kind", 5, 2): {0: 46013, 20: 53987}, + ("Category Three of a Kind", 5, 3): {0: 25698, 20: 74302}, + ("Category Three of a Kind", 5, 4): {0: 14205, 20: 85795}, + ("Category Three of a Kind", 5, 5): {0: 7932, 20: 92068}, + ("Category Three of a Kind", 5, 6): {0: 4357, 20: 95643}, + ("Category Three of a Kind", 5, 7): {0: 2432, 20: 97568}, + ("Category Three of a Kind", 5, 8): {0: 1378, 20: 98622}, + ("Category Three of a Kind", 6, 0): {0: 100000}, + ("Category Three of a Kind", 6, 1): {0: 63231, 20: 36769}, + ("Category Three of a Kind", 6, 2): {0: 26818, 20: 73182}, + ("Category Three of a Kind", 6, 3): {0: 11075, 20: 88925}, + ("Category Three of a Kind", 6, 4): {0: 4749, 20: 95251}, + ("Category Three of a Kind", 6, 5): {0: 1982, 20: 98018}, + ("Category Three of a Kind", 6, 6): {0: 827, 20: 99173}, + ("Category Three of a Kind", 6, 7): {0: 358, 20: 99642}, + ("Category Three of a Kind", 6, 8): {0: 146, 20: 99854}, + ("Category Three of a Kind", 7, 0): {0: 100000}, + ("Category Three of a Kind", 7, 1): {0: 45975, 20: 54025}, + ("Category Three of a Kind", 7, 2): {0: 13207, 20: 86793}, + ("Category Three of a Kind", 7, 3): {0: 3727, 20: 96273}, + ("Category Three of a Kind", 7, 4): {0: 1097, 20: 98903}, + ("Category Three of a Kind", 7, 5): {0: 313, 20: 99687}, + ("Category Three of a Kind", 7, 6): {0: 96, 20: 99904}, + ("Category Three of a Kind", 7, 7): {0: 22, 20: 99978}, + ("Category Three of a Kind", 7, 8): {0: 8, 20: 99992}, + ("Category Three of a Kind", 8, 0): {0: 100000}, + ("Category Three of a Kind", 8, 1): {0: 29316, 20: 70684}, + ("Category Three of a Kind", 8, 2): {0: 5027, 20: 94973}, + ("Category Three of a Kind", 8, 3): {0: 857, 20: 99143}, + ("Category Three of a Kind", 8, 4): {0: 162, 20: 99838}, + ("Category Three of a Kind", 8, 5): {0: 25, 20: 99975}, + ("Category Three of a Kind", 8, 6): {0: 4, 20: 99996}, + ("Category Three of a Kind", 8, 7): {0: 1, 20: 99999}, + ("Category Three of a Kind", 8, 8): {20: 100000}, + ("Category Four of a Kind", 0, 0): {0: 100000}, + ("Category Four of a Kind", 0, 1): {0: 100000}, + ("Category Four of a Kind", 0, 2): {0: 100000}, + ("Category Four of a Kind", 0, 3): {0: 100000}, + ("Category Four of a Kind", 0, 4): {0: 100000}, + ("Category Four of a Kind", 0, 5): {0: 100000}, + ("Category Four of a Kind", 0, 6): {0: 100000}, + ("Category Four of a Kind", 0, 7): {0: 100000}, + ("Category Four of a Kind", 0, 8): {0: 100000}, + ("Category Four of a Kind", 1, 0): {0: 100000}, + ("Category Four of a Kind", 1, 1): {0: 100000}, + ("Category Four of a Kind", 1, 2): {0: 100000}, + ("Category Four of a Kind", 1, 3): {0: 100000}, + ("Category Four of a Kind", 1, 4): {0: 100000}, + ("Category Four of a Kind", 1, 5): {0: 100000}, + ("Category Four of a Kind", 1, 6): {0: 100000}, + ("Category Four of a Kind", 1, 7): {0: 100000}, + ("Category Four of a Kind", 1, 8): {0: 100000}, + ("Category Four of a Kind", 2, 0): {0: 100000}, + ("Category Four of a Kind", 2, 1): {0: 100000}, + ("Category Four of a Kind", 2, 2): {0: 100000}, + ("Category Four of a Kind", 2, 3): {0: 100000}, + ("Category Four of a Kind", 2, 4): {0: 100000}, + ("Category Four of a Kind", 2, 5): {0: 100000}, + ("Category Four of a Kind", 2, 6): {0: 100000}, + ("Category Four of a Kind", 2, 7): {0: 100000}, + ("Category Four of a Kind", 2, 8): {0: 100000}, + ("Category Four of a Kind", 3, 0): {0: 100000}, + ("Category Four of a Kind", 3, 1): {0: 100000}, + ("Category Four of a Kind", 3, 2): {0: 100000}, + ("Category Four of a Kind", 3, 3): {0: 100000}, + ("Category Four of a Kind", 3, 4): {0: 100000}, + ("Category Four of a Kind", 3, 5): {0: 100000}, + ("Category Four of a Kind", 3, 6): {0: 100000}, + ("Category Four of a Kind", 3, 7): {0: 100000}, + ("Category Four of a Kind", 3, 8): {0: 100000}, + ("Category Four of a Kind", 4, 0): {0: 100000}, + ("Category Four of a Kind", 4, 1): {0: 99516, 30: 484}, + ("Category Four of a Kind", 4, 2): {0: 96122, 30: 3878}, + ("Category Four of a Kind", 4, 3): {0: 89867, 30: 10133}, + ("Category Four of a Kind", 4, 4): {0: 81771, 30: 18229}, + ("Category Four of a Kind", 4, 5): {0: 72893, 30: 27107}, + ("Category Four of a Kind", 4, 6): {0: 64000, 30: 36000}, + ("Category Four of a Kind", 4, 7): {0: 55921, 30: 44079}, + ("Category Four of a Kind", 4, 8): {0: 48175, 30: 51825}, + ("Category Four of a Kind", 5, 0): {0: 100000}, + ("Category Four of a Kind", 5, 1): {0: 97938, 30: 2062}, + ("Category Four of a Kind", 5, 2): {0: 86751, 30: 13249}, + ("Category Four of a Kind", 5, 3): {0: 70886, 30: 29114}, + ("Category Four of a Kind", 5, 4): {0: 54807, 30: 45193}, + ("Category Four of a Kind", 5, 5): {0: 41729, 30: 58271}, + ("Category Four of a Kind", 5, 6): {0: 30960, 30: 69040}, + ("Category Four of a Kind", 5, 7): {0: 22207, 30: 77793}, + ("Category Four of a Kind", 5, 8): {0: 16027, 30: 83973}, + ("Category Four of a Kind", 6, 0): {0: 100000}, + ("Category Four of a Kind", 6, 1): {0: 94810, 30: 5190}, + ("Category Four of a Kind", 6, 2): {0: 73147, 30: 26853}, + ("Category Four of a Kind", 6, 3): {0: 49873, 30: 50127}, + ("Category Four of a Kind", 6, 4): {0: 31913, 30: 68087}, + ("Category Four of a Kind", 6, 5): {0: 19877, 30: 80123}, + ("Category Four of a Kind", 6, 6): {0: 11973, 30: 88027}, + ("Category Four of a Kind", 6, 7): {0: 7324, 30: 92676}, + ("Category Four of a Kind", 6, 8): {0: 4221, 30: 95779}, + ("Category Four of a Kind", 7, 0): {0: 100000}, + ("Category Four of a Kind", 7, 1): {0: 89422, 30: 10578}, + ("Category Four of a Kind", 7, 2): {0: 57049, 30: 42951}, + ("Category Four of a Kind", 7, 3): {0: 30903, 30: 69097}, + ("Category Four of a Kind", 7, 4): {0: 15962, 30: 84038}, + ("Category Four of a Kind", 7, 5): {0: 8148, 30: 91852}, + ("Category Four of a Kind", 7, 6): {0: 3943, 30: 96057}, + ("Category Four of a Kind", 7, 7): {0: 1933, 30: 98067}, + ("Category Four of a Kind", 7, 8): {0: 912, 30: 99088}, + ("Category Four of a Kind", 8, 0): {0: 100000}, + ("Category Four of a Kind", 8, 1): {0: 81614, 30: 18386}, + ("Category Four of a Kind", 8, 2): {0: 40524, 30: 59476}, + ("Category Four of a Kind", 8, 3): {0: 17426, 30: 82574}, + ("Category Four of a Kind", 8, 4): {0: 6958, 30: 93042}, + ("Category Four of a Kind", 8, 5): {0: 2862, 30: 97138}, + ("Category Four of a Kind", 8, 6): {0: 1049, 30: 98951}, + ("Category Four of a Kind", 8, 7): {0: 401, 30: 99599}, + ("Category Four of a Kind", 8, 8): {0: 156, 30: 99844}, + ("Category Tiny Straight", 0, 0): {0: 100000}, + ("Category Tiny Straight", 0, 1): {0: 100000}, + ("Category Tiny Straight", 0, 2): {0: 100000}, + ("Category Tiny Straight", 0, 3): {0: 100000}, + ("Category Tiny Straight", 0, 4): {0: 100000}, + ("Category Tiny Straight", 0, 5): {0: 100000}, + ("Category Tiny Straight", 0, 6): {0: 100000}, + ("Category Tiny Straight", 0, 7): {0: 100000}, + ("Category Tiny Straight", 0, 8): {0: 100000}, + ("Category Tiny Straight", 1, 0): {0: 100000}, + ("Category Tiny Straight", 1, 1): {0: 100000}, + ("Category Tiny Straight", 1, 2): {0: 100000}, + ("Category Tiny Straight", 1, 3): {0: 100000}, + ("Category Tiny Straight", 1, 4): {0: 100000}, + ("Category Tiny Straight", 1, 5): {0: 100000}, + ("Category Tiny Straight", 1, 6): {0: 100000}, + ("Category Tiny Straight", 1, 7): {0: 100000}, + ("Category Tiny Straight", 1, 8): {0: 100000}, + ("Category Tiny Straight", 2, 0): {0: 100000}, + ("Category Tiny Straight", 2, 1): {0: 100000}, + ("Category Tiny Straight", 2, 2): {0: 100000}, + ("Category Tiny Straight", 2, 3): {0: 100000}, + ("Category Tiny Straight", 2, 4): {0: 100000}, + ("Category Tiny Straight", 2, 5): {0: 100000}, + ("Category Tiny Straight", 2, 6): {0: 100000}, + ("Category Tiny Straight", 2, 7): {0: 100000}, + ("Category Tiny Straight", 2, 8): {0: 100000}, + ("Category Tiny Straight", 3, 0): {0: 100000}, + ("Category Tiny Straight", 3, 1): {0: 91672, 20: 8328}, + ("Category Tiny Straight", 3, 2): {0: 79082, 20: 20918}, + ("Category Tiny Straight", 3, 3): {0: 66490, 20: 33510}, + ("Category Tiny Straight", 3, 4): {0: 55797, 20: 44203}, + ("Category Tiny Straight", 3, 5): {0: 46967, 20: 53033}, + ("Category Tiny Straight", 3, 6): {0: 39595, 20: 60405}, + ("Category Tiny Straight", 3, 7): {0: 33384, 20: 66616}, + ("Category Tiny Straight", 3, 8): {0: 28747, 20: 71253}, + ("Category Tiny Straight", 4, 0): {0: 100000}, + ("Category Tiny Straight", 4, 1): {0: 78812, 20: 21188}, + ("Category Tiny Straight", 4, 2): {0: 55525, 20: 44475}, + ("Category Tiny Straight", 4, 3): {0: 38148, 20: 61852}, + ("Category Tiny Straight", 4, 4): {0: 26432, 20: 73568}, + ("Category Tiny Straight", 4, 5): {0: 18225, 20: 81775}, + ("Category Tiny Straight", 4, 6): {0: 12758, 20: 87242}, + ("Category Tiny Straight", 4, 7): {0: 8991, 20: 91009}, + ("Category Tiny Straight", 4, 8): {0: 6325, 20: 93675}, + ("Category Tiny Straight", 5, 0): {0: 100000}, + ("Category Tiny Straight", 5, 1): {0: 64979, 20: 35021}, + ("Category Tiny Straight", 5, 2): {0: 36509, 20: 63491}, + ("Category Tiny Straight", 5, 3): {0: 20576, 20: 79424}, + ("Category Tiny Straight", 5, 4): {0: 11585, 20: 88415}, + ("Category Tiny Straight", 5, 5): {0: 6874, 20: 93126}, + ("Category Tiny Straight", 5, 6): {0: 3798, 20: 96202}, + ("Category Tiny Straight", 5, 7): {0: 2214, 20: 97786}, + ("Category Tiny Straight", 5, 8): {0: 1272, 20: 98728}, + ("Category Tiny Straight", 6, 0): {0: 100000}, + ("Category Tiny Straight", 6, 1): {0: 52157, 20: 47843}, + ("Category Tiny Straight", 6, 2): {0: 23641, 20: 76359}, + ("Category Tiny Straight", 6, 3): {0: 10883, 20: 89117}, + ("Category Tiny Straight", 6, 4): {0: 5127, 20: 94873}, + ("Category Tiny Straight", 6, 5): {0: 2442, 20: 97558}, + ("Category Tiny Straight", 6, 6): {0: 1158, 20: 98842}, + ("Category Tiny Straight", 6, 7): {0: 542, 20: 99458}, + ("Category Tiny Straight", 6, 8): {0: 252, 20: 99748}, + ("Category Tiny Straight", 7, 0): {0: 100000}, + ("Category Tiny Straight", 7, 1): {0: 41492, 20: 58508}, + ("Category Tiny Straight", 7, 2): {0: 15072, 20: 84928}, + ("Category Tiny Straight", 7, 3): {0: 5905, 20: 94095}, + ("Category Tiny Straight", 7, 4): {0: 2246, 20: 97754}, + ("Category Tiny Straight", 7, 5): {0: 942, 20: 99058}, + ("Category Tiny Straight", 7, 6): {0: 337, 20: 99663}, + ("Category Tiny Straight", 7, 7): {0: 155, 20: 99845}, + ("Category Tiny Straight", 7, 8): {0: 61, 20: 99939}, + ("Category Tiny Straight", 8, 0): {0: 100000}, + ("Category Tiny Straight", 8, 1): {0: 32993, 20: 67007}, + ("Category Tiny Straight", 8, 2): {0: 10074, 20: 89926}, + ("Category Tiny Straight", 8, 3): {0: 3158, 20: 96842}, + ("Category Tiny Straight", 8, 4): {0: 1060, 20: 98940}, + ("Category Tiny Straight", 8, 5): {0: 356, 20: 99644}, + ("Category Tiny Straight", 8, 6): {0: 117, 20: 99883}, + ("Category Tiny Straight", 8, 7): {0: 32, 20: 99968}, + ("Category Tiny Straight", 8, 8): {0: 10, 20: 99990}, + ("Category Small Straight", 0, 0): {0: 100000}, + ("Category Small Straight", 0, 1): {0: 100000}, + ("Category Small Straight", 0, 2): {0: 100000}, + ("Category Small Straight", 0, 3): {0: 100000}, + ("Category Small Straight", 0, 4): {0: 100000}, + ("Category Small Straight", 0, 5): {0: 100000}, + ("Category Small Straight", 0, 6): {0: 100000}, + ("Category Small Straight", 0, 7): {0: 100000}, + ("Category Small Straight", 0, 8): {0: 100000}, + ("Category Small Straight", 1, 0): {0: 100000}, + ("Category Small Straight", 1, 1): {0: 100000}, + ("Category Small Straight", 1, 2): {0: 100000}, + ("Category Small Straight", 1, 3): {0: 100000}, + ("Category Small Straight", 1, 4): {0: 100000}, + ("Category Small Straight", 1, 5): {0: 100000}, + ("Category Small Straight", 1, 6): {0: 100000}, + ("Category Small Straight", 1, 7): {0: 100000}, + ("Category Small Straight", 1, 8): {0: 100000}, + ("Category Small Straight", 2, 0): {0: 100000}, + ("Category Small Straight", 2, 1): {0: 100000}, + ("Category Small Straight", 2, 2): {0: 100000}, + ("Category Small Straight", 2, 3): {0: 100000}, + ("Category Small Straight", 2, 4): {0: 100000}, + ("Category Small Straight", 2, 5): {0: 100000}, + ("Category Small Straight", 2, 6): {0: 100000}, + ("Category Small Straight", 2, 7): {0: 100000}, + ("Category Small Straight", 2, 8): {0: 100000}, + ("Category Small Straight", 3, 0): {0: 100000}, + ("Category Small Straight", 3, 1): {0: 100000}, + ("Category Small Straight", 3, 2): {0: 100000}, + ("Category Small Straight", 3, 3): {0: 100000}, + ("Category Small Straight", 3, 4): {0: 100000}, + ("Category Small Straight", 3, 5): {0: 100000}, + ("Category Small Straight", 3, 6): {0: 100000}, + ("Category Small Straight", 3, 7): {0: 100000}, + ("Category Small Straight", 3, 8): {0: 100000}, + ("Category Small Straight", 4, 0): {0: 100000}, + ("Category Small Straight", 4, 1): {0: 94516, 30: 5484}, + ("Category Small Straight", 4, 2): {0: 82700, 30: 17300}, + ("Category Small Straight", 4, 3): {0: 67926, 30: 32074}, + ("Category Small Straight", 4, 4): {0: 54265, 30: 45735}, + ("Category Small Straight", 4, 5): {0: 42130, 30: 57870}, + ("Category Small Straight", 4, 6): {0: 32536, 30: 67464}, + ("Category Small Straight", 4, 7): {0: 25008, 30: 74992}, + ("Category Small Straight", 4, 8): {0: 19595, 30: 80405}, + ("Category Small Straight", 5, 0): {0: 100000}, + ("Category Small Straight", 5, 1): {0: 84528, 30: 15472}, + ("Category Small Straight", 5, 2): {0: 60775, 30: 39225}, + ("Category Small Straight", 5, 3): {0: 39543, 30: 60457}, + ("Category Small Straight", 5, 4): {0: 24760, 30: 75240}, + ("Category Small Straight", 5, 5): {0: 15713, 30: 84287}, + ("Category Small Straight", 5, 6): {0: 10199, 30: 89801}, + ("Category Small Straight", 5, 7): {0: 6618, 30: 93382}, + ("Category Small Straight", 5, 8): {0: 4205, 30: 95795}, + ("Category Small Straight", 6, 0): {0: 100000}, + ("Category Small Straight", 6, 1): {0: 73121, 30: 26879}, + ("Category Small Straight", 6, 2): {0: 41832, 30: 58168}, + ("Category Small Straight", 6, 3): {0: 21949, 30: 78051}, + ("Category Small Straight", 6, 4): {0: 11304, 30: 88696}, + ("Category Small Straight", 6, 5): {0: 6063, 30: 93937}, + ("Category Small Straight", 6, 6): {0: 3362, 30: 96638}, + ("Category Small Straight", 6, 7): {0: 1799, 30: 98201}, + ("Category Small Straight", 6, 8): {0: 1069, 30: 98931}, + ("Category Small Straight", 7, 0): {0: 100000}, + ("Category Small Straight", 7, 1): {0: 61837, 30: 38163}, + ("Category Small Straight", 7, 2): {0: 28202, 30: 71798}, + ("Category Small Straight", 7, 3): {0: 12187, 30: 87813}, + ("Category Small Straight", 7, 4): {0: 5427, 30: 94573}, + ("Category Small Straight", 7, 5): {0: 2444, 30: 97556}, + ("Category Small Straight", 7, 6): {0: 1144, 30: 98856}, + ("Category Small Straight", 7, 7): {0: 588, 30: 99412}, + ("Category Small Straight", 7, 8): {0: 258, 30: 99742}, + ("Category Small Straight", 8, 0): {0: 100000}, + ("Category Small Straight", 8, 1): {0: 51394, 30: 48606}, + ("Category Small Straight", 8, 2): {0: 19090, 30: 80910}, + ("Category Small Straight", 8, 3): {0: 7104, 30: 92896}, + ("Category Small Straight", 8, 4): {0: 2645, 30: 97355}, + ("Category Small Straight", 8, 5): {0: 1010, 30: 98990}, + ("Category Small Straight", 8, 6): {0: 408, 30: 99592}, + ("Category Small Straight", 8, 7): {0: 153, 30: 99847}, + ("Category Small Straight", 8, 8): {0: 78, 30: 99922}, + ("Category Large Straight", 0, 0): {0: 100000}, + ("Category Large Straight", 0, 1): {0: 100000}, + ("Category Large Straight", 0, 2): {0: 100000}, + ("Category Large Straight", 0, 3): {0: 100000}, + ("Category Large Straight", 0, 4): {0: 100000}, + ("Category Large Straight", 0, 5): {0: 100000}, + ("Category Large Straight", 0, 6): {0: 100000}, + ("Category Large Straight", 0, 7): {0: 100000}, + ("Category Large Straight", 0, 8): {0: 100000}, + ("Category Large Straight", 1, 0): {0: 100000}, + ("Category Large Straight", 1, 1): {0: 100000}, + ("Category Large Straight", 1, 2): {0: 100000}, + ("Category Large Straight", 1, 3): {0: 100000}, + ("Category Large Straight", 1, 4): {0: 100000}, + ("Category Large Straight", 1, 5): {0: 100000}, + ("Category Large Straight", 1, 6): {0: 100000}, + ("Category Large Straight", 1, 7): {0: 100000}, + ("Category Large Straight", 1, 8): {0: 100000}, + ("Category Large Straight", 2, 0): {0: 100000}, + ("Category Large Straight", 2, 1): {0: 100000}, + ("Category Large Straight", 2, 2): {0: 100000}, + ("Category Large Straight", 2, 3): {0: 100000}, + ("Category Large Straight", 2, 4): {0: 100000}, + ("Category Large Straight", 2, 5): {0: 100000}, + ("Category Large Straight", 2, 6): {0: 100000}, + ("Category Large Straight", 2, 7): {0: 100000}, + ("Category Large Straight", 2, 8): {0: 100000}, + ("Category Large Straight", 3, 0): {0: 100000}, + ("Category Large Straight", 3, 1): {0: 100000}, + ("Category Large Straight", 3, 2): {0: 100000}, + ("Category Large Straight", 3, 3): {0: 100000}, + ("Category Large Straight", 3, 4): {0: 100000}, + ("Category Large Straight", 3, 5): {0: 100000}, + ("Category Large Straight", 3, 6): {0: 100000}, + ("Category Large Straight", 3, 7): {0: 100000}, + ("Category Large Straight", 3, 8): {0: 100000}, + ("Category Large Straight", 4, 0): {0: 100000}, + ("Category Large Straight", 4, 1): {0: 100000}, + ("Category Large Straight", 4, 2): {0: 100000}, + ("Category Large Straight", 4, 3): {0: 100000}, + ("Category Large Straight", 4, 4): {0: 100000}, + ("Category Large Straight", 4, 5): {0: 100000}, + ("Category Large Straight", 4, 6): {0: 100000}, + ("Category Large Straight", 4, 7): {0: 100000}, + ("Category Large Straight", 4, 8): {0: 100000}, + ("Category Large Straight", 5, 0): {0: 100000}, + ("Category Large Straight", 5, 1): {0: 96929, 40: 3071}, + ("Category Large Straight", 5, 2): {0: 87056, 40: 12944}, + ("Category Large Straight", 5, 3): {0: 75101, 40: 24899}, + ("Category Large Straight", 5, 4): {0: 63617, 40: 36383}, + ("Category Large Straight", 5, 5): {0: 53149, 40: 46851}, + ("Category Large Straight", 5, 6): {0: 44321, 40: 55679}, + ("Category Large Straight", 5, 7): {0: 36948, 40: 63052}, + ("Category Large Straight", 5, 8): {0: 30661, 40: 69339}, + ("Category Large Straight", 6, 0): {0: 100000}, + ("Category Large Straight", 6, 1): {0: 90756, 40: 9244}, + ("Category Large Straight", 6, 2): {0: 69805, 40: 30195}, + ("Category Large Straight", 6, 3): {0: 49814, 40: 50186}, + ("Category Large Straight", 6, 4): {0: 35102, 40: 64898}, + ("Category Large Straight", 6, 5): {0: 24385, 40: 75615}, + ("Category Large Straight", 6, 6): {0: 17018, 40: 82982}, + ("Category Large Straight", 6, 7): {0: 11739, 40: 88261}, + ("Category Large Straight", 6, 8): {0: 7972, 40: 92028}, + ("Category Large Straight", 7, 0): {0: 100000}, + ("Category Large Straight", 7, 1): {0: 82840, 40: 17160}, + ("Category Large Straight", 7, 2): {0: 52821, 40: 47179}, + ("Category Large Straight", 7, 3): {0: 31348, 40: 68652}, + ("Category Large Straight", 7, 4): {0: 18166, 40: 81834}, + ("Category Large Straight", 7, 5): {0: 10690, 40: 89310}, + ("Category Large Straight", 7, 6): {0: 6051, 40: 93949}, + ("Category Large Straight", 7, 7): {0: 3617, 40: 96383}, + ("Category Large Straight", 7, 8): {0: 1941, 40: 98059}, + ("Category Large Straight", 8, 0): {0: 100000}, + ("Category Large Straight", 8, 1): {0: 73520, 40: 26480}, + ("Category Large Straight", 8, 2): {0: 39031, 40: 60969}, + ("Category Large Straight", 8, 3): {0: 19156, 40: 80844}, + ("Category Large Straight", 8, 4): {0: 9304, 40: 90696}, + ("Category Large Straight", 8, 5): {0: 4420, 40: 95580}, + ("Category Large Straight", 8, 6): {0: 2141, 40: 97859}, + ("Category Large Straight", 8, 7): {0: 1037, 40: 98963}, + ("Category Large Straight", 8, 8): {0: 511, 40: 99489}, + ("Category Full House", 0, 0): {0: 100000}, + ("Category Full House", 0, 1): {0: 100000}, + ("Category Full House", 0, 2): {0: 100000}, + ("Category Full House", 0, 3): {0: 100000}, + ("Category Full House", 0, 4): {0: 100000}, + ("Category Full House", 0, 5): {0: 100000}, + ("Category Full House", 0, 6): {0: 100000}, + ("Category Full House", 0, 7): {0: 100000}, + ("Category Full House", 0, 8): {0: 100000}, + ("Category Full House", 1, 0): {0: 100000}, + ("Category Full House", 1, 1): {0: 100000}, + ("Category Full House", 1, 2): {0: 100000}, + ("Category Full House", 1, 3): {0: 100000}, + ("Category Full House", 1, 4): {0: 100000}, + ("Category Full House", 1, 5): {0: 100000}, + ("Category Full House", 1, 6): {0: 100000}, + ("Category Full House", 1, 7): {0: 100000}, + ("Category Full House", 1, 8): {0: 100000}, + ("Category Full House", 2, 0): {0: 100000}, + ("Category Full House", 2, 1): {0: 100000}, + ("Category Full House", 2, 2): {0: 100000}, + ("Category Full House", 2, 3): {0: 100000}, + ("Category Full House", 2, 4): {0: 100000}, + ("Category Full House", 2, 5): {0: 100000}, + ("Category Full House", 2, 6): {0: 100000}, + ("Category Full House", 2, 7): {0: 100000}, + ("Category Full House", 2, 8): {0: 100000}, + ("Category Full House", 3, 0): {0: 100000}, + ("Category Full House", 3, 1): {0: 100000}, + ("Category Full House", 3, 2): {0: 100000}, + ("Category Full House", 3, 3): {0: 100000}, + ("Category Full House", 3, 4): {0: 100000}, + ("Category Full House", 3, 5): {0: 100000}, + ("Category Full House", 3, 6): {0: 100000}, + ("Category Full House", 3, 7): {0: 100000}, + ("Category Full House", 3, 8): {0: 100000}, + ("Category Full House", 4, 0): {0: 100000}, + ("Category Full House", 4, 1): {0: 100000}, + ("Category Full House", 4, 2): {0: 100000}, + ("Category Full House", 4, 3): {0: 100000}, + ("Category Full House", 4, 4): {0: 100000}, + ("Category Full House", 4, 5): {0: 100000}, + ("Category Full House", 4, 6): {0: 100000}, + ("Category Full House", 4, 7): {0: 100000}, + ("Category Full House", 4, 8): {0: 100000}, + ("Category Full House", 5, 0): {0: 100000}, + ("Category Full House", 5, 1): {0: 96155, 25: 3845}, + ("Category Full House", 5, 2): {0: 81391, 25: 18609}, + ("Category Full House", 5, 3): {0: 64300, 25: 35700}, + ("Category Full House", 5, 4): {0: 49669, 25: 50331}, + ("Category Full House", 5, 5): {0: 38019, 25: 61981}, + ("Category Full House", 5, 6): {0: 29751, 25: 70249}, + ("Category Full House", 5, 7): {0: 22960, 25: 77040}, + ("Category Full House", 5, 8): {0: 18650, 25: 81350}, + ("Category Full House", 6, 0): {0: 100000}, + ("Category Full House", 6, 1): {0: 82989, 25: 17011}, + ("Category Full House", 6, 2): {0: 47153, 25: 52847}, + ("Category Full House", 6, 3): {0: 24151, 25: 75849}, + ("Category Full House", 6, 4): {0: 12519, 25: 87481}, + ("Category Full House", 6, 5): {0: 6524, 25: 93476}, + ("Category Full House", 6, 6): {0: 3606, 25: 96394}, + ("Category Full House", 6, 7): {0: 1959, 25: 98041}, + ("Category Full House", 6, 8): {0: 1026, 25: 98974}, + ("Category Full House", 7, 0): {0: 100000}, + ("Category Full House", 7, 1): {0: 60232, 25: 39768}, + ("Category Full House", 7, 2): {0: 18894, 25: 81106}, + ("Category Full House", 7, 3): {0: 5682, 25: 94318}, + ("Category Full House", 7, 4): {0: 1706, 25: 98294}, + ("Category Full House", 7, 5): {0: 522, 25: 99478}, + ("Category Full House", 7, 6): {0: 146, 25: 99854}, + ("Category Full House", 7, 7): {0: 54, 25: 99946}, + ("Category Full House", 7, 8): {0: 18, 25: 99982}, + ("Category Full House", 8, 0): {0: 100000}, + ("Category Full House", 8, 1): {0: 35909, 25: 64091}, + ("Category Full House", 8, 2): {0: 5712, 25: 94288}, + ("Category Full House", 8, 3): {0: 930, 25: 99070}, + ("Category Full House", 8, 4): {0: 165, 25: 99835}, + ("Category Full House", 8, 5): {0: 19, 25: 99981}, + ("Category Full House", 8, 6): {0: 6, 25: 99994}, + ("Category Full House", 8, 7): {25: 100000}, + ("Category Full House", 8, 8): {25: 100000}, + ("Category Yacht", 0, 0): {0: 100000}, + ("Category Yacht", 0, 1): {0: 100000}, + ("Category Yacht", 0, 2): {0: 100000}, + ("Category Yacht", 0, 3): {0: 100000}, + ("Category Yacht", 0, 4): {0: 100000}, + ("Category Yacht", 0, 5): {0: 100000}, + ("Category Yacht", 0, 6): {0: 100000}, + ("Category Yacht", 0, 7): {0: 100000}, + ("Category Yacht", 0, 8): {0: 100000}, + ("Category Yacht", 1, 0): {0: 100000}, + ("Category Yacht", 1, 1): {0: 100000}, + ("Category Yacht", 1, 2): {0: 100000}, + ("Category Yacht", 1, 3): {0: 100000}, + ("Category Yacht", 1, 4): {0: 100000}, + ("Category Yacht", 1, 5): {0: 100000}, + ("Category Yacht", 1, 6): {0: 100000}, + ("Category Yacht", 1, 7): {0: 100000}, + ("Category Yacht", 1, 8): {0: 100000}, + ("Category Yacht", 2, 0): {0: 100000}, + ("Category Yacht", 2, 1): {0: 100000}, + ("Category Yacht", 2, 2): {0: 100000}, + ("Category Yacht", 2, 3): {0: 100000}, + ("Category Yacht", 2, 4): {0: 100000}, + ("Category Yacht", 2, 5): {0: 100000}, + ("Category Yacht", 2, 6): {0: 100000}, + ("Category Yacht", 2, 7): {0: 100000}, + ("Category Yacht", 2, 8): {0: 100000}, + ("Category Yacht", 3, 0): {0: 100000}, + ("Category Yacht", 3, 1): {0: 100000}, + ("Category Yacht", 3, 2): {0: 100000}, + ("Category Yacht", 3, 3): {0: 100000}, + ("Category Yacht", 3, 4): {0: 100000}, + ("Category Yacht", 3, 5): {0: 100000}, + ("Category Yacht", 3, 6): {0: 100000}, + ("Category Yacht", 3, 7): {0: 100000}, + ("Category Yacht", 3, 8): {0: 100000}, + ("Category Yacht", 4, 0): {0: 100000}, + ("Category Yacht", 4, 1): {0: 100000}, + ("Category Yacht", 4, 2): {0: 100000}, + ("Category Yacht", 4, 3): {0: 100000}, + ("Category Yacht", 4, 4): {0: 100000}, + ("Category Yacht", 4, 5): {0: 100000}, + ("Category Yacht", 4, 6): {0: 100000}, + ("Category Yacht", 4, 7): {0: 100000}, + ("Category Yacht", 4, 8): {0: 100000}, + ("Category Yacht", 5, 0): {0: 100000}, + ("Category Yacht", 5, 1): {0: 100000}, + ("Category Yacht", 5, 2): {0: 98727, 50: 1273}, + ("Category Yacht", 5, 3): {0: 95347, 50: 4653}, + ("Category Yacht", 5, 4): {0: 89969, 50: 10031}, + ("Category Yacht", 5, 5): {0: 83124, 50: 16876}, + ("Category Yacht", 5, 6): {0: 75023, 50: 24977}, + ("Category Yacht", 5, 7): {0: 67007, 50: 32993}, + ("Category Yacht", 5, 8): {0: 58618, 50: 41382}, + ("Category Yacht", 6, 0): {0: 100000}, + ("Category Yacht", 6, 1): {0: 99571, 50: 429}, + ("Category Yacht", 6, 2): {0: 94726, 50: 5274}, + ("Category Yacht", 6, 3): {0: 84366, 50: 15634}, + ("Category Yacht", 6, 4): {0: 70782, 50: 29218}, + ("Category Yacht", 6, 5): {0: 56573, 50: 43427}, + ("Category Yacht", 6, 6): {0: 44206, 50: 55794}, + ("Category Yacht", 6, 7): {0: 33578, 50: 66422}, + ("Category Yacht", 6, 8): {0: 25079, 50: 74921}, + ("Category Yacht", 7, 0): {0: 100000}, + ("Category Yacht", 7, 1): {0: 98833, 50: 1167}, + ("Category Yacht", 7, 2): {0: 87511, 50: 12489}, + ("Category Yacht", 7, 3): {0: 68252, 50: 31748}, + ("Category Yacht", 7, 4): {0: 49065, 50: 50935}, + ("Category Yacht", 7, 5): {0: 33364, 50: 66636}, + ("Category Yacht", 7, 6): {0: 21483, 50: 78517}, + ("Category Yacht", 7, 7): {0: 13597, 50: 86403}, + ("Category Yacht", 7, 8): {0: 8483, 50: 91517}, + ("Category Yacht", 8, 0): {0: 100000}, + ("Category Yacht", 8, 1): {0: 97212, 50: 2788}, + ("Category Yacht", 8, 2): {0: 76962, 50: 23038}, + ("Category Yacht", 8, 3): {0: 50533, 50: 49467}, + ("Category Yacht", 8, 4): {0: 29981, 50: 70019}, + ("Category Yacht", 8, 5): {0: 16776, 50: 83224}, + ("Category Yacht", 8, 6): {0: 9079, 50: 90921}, + ("Category Yacht", 8, 7): {0: 4705, 50: 95295}, + ("Category Yacht", 8, 8): {0: 2363, 50: 97637}, + ("Category Distincts", 1, 1): {1: 100000}, + ("Category Distincts", 1, 2): {1: 100000}, + ("Category Distincts", 1, 3): {1: 100000}, + ("Category Distincts", 1, 4): {1: 100000}, + ("Category Distincts", 1, 5): {1: 100000}, + ("Category Distincts", 1, 6): {1: 100000}, + ("Category Distincts", 1, 7): {1: 100000}, + ("Category Distincts", 1, 8): {1: 100000}, + ("Category Distincts", 2, 1): {1: 16804, 2: 83196}, + ("Category Distincts", 2, 2): {1: 2686, 2: 97314}, + ("Category Distincts", 2, 3): {1: 463, 2: 99537}, + ("Category Distincts", 2, 4): {1: 66, 2: 99934}, + ("Category Distincts", 2, 5): {1: 11, 2: 99989}, + ("Category Distincts", 2, 6): {1: 1, 2: 99999}, + ("Category Distincts", 2, 7): {2: 100000}, + ("Category Distincts", 2, 8): {2: 100000}, + ("Category Distincts", 3, 1): {1: 2760, 2: 41714, 3: 55526}, + ("Category Distincts", 3, 2): {1: 78, 3: 99922}, + ("Category Distincts", 3, 3): {1: 4866, 3: 95134}, + ("Category Distincts", 3, 4): {2: 1659, 3: 98341}, + ("Category Distincts", 3, 5): {2: 575, 3: 99425}, + ("Category Distincts", 3, 6): {2: 200, 3: 99800}, + ("Category Distincts", 3, 7): {2: 69, 3: 99931}, + ("Category Distincts", 3, 8): {2: 22, 3: 99978}, + ("Category Distincts", 4, 1): {1: 494, 3: 71611, 4: 27895}, + ("Category Distincts", 4, 2): {1: 1893, 3: 36922, 4: 61185}, + ("Category Distincts", 4, 3): {2: 230, 4: 99770}, + ("Category Distincts", 4, 4): {2: 21, 4: 99979}, + ("Category Distincts", 4, 5): {2: 4906, 4: 95094}, + ("Category Distincts", 4, 6): {3: 2494, 4: 97506}, + ("Category Distincts", 4, 7): {3: 1297, 4: 98703}, + ("Category Distincts", 4, 8): {3: 611, 4: 99389}, + ("Category Distincts", 5, 1): {1: 5798, 3: 38538, 4: 55664}, + ("Category Distincts", 5, 2): {2: 196, 4: 68119, 5: 31685}, + ("Category Distincts", 5, 3): {2: 3022, 4: 44724, 5: 52254}, + ("Category Distincts", 5, 4): {3: 722, 4: 31632, 5: 67646}, + ("Category Distincts", 5, 5): {3: 215, 4: 21391, 5: 78394}, + ("Category Distincts", 5, 6): {3: 55, 5: 99945}, + ("Category Distincts", 5, 7): {3: 15, 5: 99985}, + ("Category Distincts", 5, 8): {3: 6463, 5: 93537}, + ("Category Distincts", 6, 1): {1: 2027, 3: 22985, 4: 50464, 5: 24524}, + ("Category Distincts", 6, 2): {2: 3299, 4: 35174, 5: 61527}, + ("Category Distincts", 6, 3): {3: 417, 5: 79954, 6: 19629}, + ("Category Distincts", 6, 4): {3: 7831, 5: 61029, 6: 31140}, + ("Category Distincts", 6, 5): {3: 3699, 5: 54997, 6: 41304}, + ("Category Distincts", 6, 6): {4: 1557, 5: 47225, 6: 51218}, + ("Category Distincts", 6, 7): {4: 728, 5: 40465, 6: 58807}, + ("Category Distincts", 6, 8): {4: 321, 5: 33851, 6: 65828}, + ("Category Distincts", 7, 1): {1: 665, 4: 57970, 5: 41365}, + ("Category Distincts", 7, 2): {2: 839, 5: 75578, 6: 23583}, + ("Category Distincts", 7, 3): {3: 6051, 5: 50312, 6: 43637}, + ("Category Distincts", 7, 4): {3: 1796, 5: 38393, 6: 59811}, + ("Category Distincts", 7, 5): {4: 529, 5: 27728, 6: 71743}, + ("Category Distincts", 7, 6): {4: 164, 6: 99836}, + ("Category Distincts", 7, 7): {4: 53, 6: 99947}, + ("Category Distincts", 7, 8): {4: 14, 6: 99986}, + ("Category Distincts", 8, 1): {1: 7137, 4: 36582, 5: 56281}, + ("Category Distincts", 8, 2): {2: 233, 5: 59964, 6: 39803}, + ("Category Distincts", 8, 3): {3: 1976, 5: 34748, 6: 63276}, + ("Category Distincts", 8, 4): {4: 389, 5: 21008, 6: 78603}, + ("Category Distincts", 8, 5): {4: 78, 6: 99922}, + ("Category Distincts", 8, 6): {4: 7177, 6: 92823}, + ("Category Distincts", 8, 7): {4: 4179, 6: 95821}, + ("Category Distincts", 8, 8): {5: 2440, 6: 97560}, + ("Category Two times Ones", 0, 0): {0: 100000}, + ("Category Two times Ones", 0, 1): {0: 100000}, + ("Category Two times Ones", 0, 2): {0: 100000}, + ("Category Two times Ones", 0, 3): {0: 100000}, + ("Category Two times Ones", 0, 4): {0: 100000}, + ("Category Two times Ones", 0, 5): {0: 100000}, + ("Category Two times Ones", 0, 6): {0: 100000}, + ("Category Two times Ones", 0, 7): {0: 100000}, + ("Category Two times Ones", 0, 8): {0: 100000}, + ("Category Two times Ones", 1, 0): {0: 100000}, + ("Category Two times Ones", 1, 1): {0: 83475, 2: 16525}, + ("Category Two times Ones", 1, 2): {0: 69690, 2: 30310}, + ("Category Two times Ones", 1, 3): {0: 57818, 2: 42182}, + ("Category Two times Ones", 1, 4): {0: 48418, 2: 51582}, + ("Category Two times Ones", 1, 5): {0: 40301, 2: 59699}, + ("Category Two times Ones", 1, 6): {0: 33558, 2: 66442}, + ("Category Two times Ones", 1, 7): {0: 28182, 2: 71818}, + ("Category Two times Ones", 1, 8): {0: 23406, 2: 76594}, + ("Category Two times Ones", 2, 0): {0: 100000}, + ("Category Two times Ones", 2, 1): {0: 69724, 2: 30276}, + ("Category Two times Ones", 2, 2): {0: 48238, 2: 42479, 4: 9283}, + ("Category Two times Ones", 2, 3): {0: 33290, 2: 48819, 4: 17891}, + ("Category Two times Ones", 2, 4): {0: 23136, 2: 49957, 4: 26907}, + ("Category Two times Ones", 2, 5): {0: 16146, 2: 48200, 4: 35654}, + ("Category Two times Ones", 2, 6): {0: 11083, 2: 44497, 4: 44420}, + ("Category Two times Ones", 2, 7): {0: 7662, 2: 40343, 4: 51995}, + ("Category Two times Ones", 2, 8): {0: 5354, 2: 35526, 4: 59120}, + ("Category Two times Ones", 3, 0): {0: 100000}, + ("Category Two times Ones", 3, 1): {0: 58021, 2: 34522, 4: 7457}, + ("Category Two times Ones", 3, 2): {0: 33548, 2: 44261, 4: 22191}, + ("Category Two times Ones", 3, 3): {0: 19375, 2: 42372, 4: 30748, 6: 7505}, + ("Category Two times Ones", 3, 4): {0: 10998, 2: 36435, 4: 38569, 6: 13998}, + ("Category Two times Ones", 3, 5): {0: 6519, 2: 28838, 4: 43283, 6: 21360}, + ("Category Two times Ones", 3, 6): {0: 3619, 2: 22498, 4: 44233, 6: 29650}, + ("Category Two times Ones", 3, 7): {0: 2195, 2: 16979, 4: 43684, 6: 37142}, + ("Category Two times Ones", 3, 8): {0: 1255, 2: 12420, 4: 40920, 6: 45405}, + ("Category Two times Ones", 4, 0): {0: 100000}, + ("Category Two times Ones", 4, 1): {0: 48235, 2: 38602, 4: 13163}, + ("Category Two times Ones", 4, 2): {0: 23289, 2: 40678, 4: 27102, 6: 8931}, + ("Category Two times Ones", 4, 3): {0: 11177, 2: 32677, 4: 35702, 6: 20444}, + ("Category Two times Ones", 4, 4): {0: 5499, 2: 23225, 4: 37240, 6: 26867, 8: 7169}, + ("Category Two times Ones", 4, 5): {0: 2574, 2: 15782, 4: 34605, 6: 34268, 8: 12771}, + ("Category Two times Ones", 4, 6): {0: 1259, 4: 39616, 6: 39523, 8: 19602}, + ("Category Two times Ones", 4, 7): {0: 622, 4: 30426, 6: 41894, 8: 27058}, + ("Category Two times Ones", 4, 8): {0: 4091, 4: 18855, 6: 42309, 8: 34745}, + ("Category Two times Ones", 5, 0): {0: 100000}, + ("Category Two times Ones", 5, 1): {0: 40028, 2: 40241, 4: 19731}, + ("Category Two times Ones", 5, 2): {0: 16009, 2: 35901, 4: 31024, 6: 17066}, + ("Category Two times Ones", 5, 3): {0: 6489, 2: 23477, 4: 34349, 6: 25270, 8: 10415}, + ("Category Two times Ones", 5, 4): {0: 2658, 2: 14032, 4: 30199, 6: 32214, 8: 20897}, + ("Category Two times Ones", 5, 5): {0: 1032, 4: 31627, 6: 33993, 8: 25853, 10: 7495}, + ("Category Two times Ones", 5, 6): {0: 450, 4: 20693, 6: 32774, 8: 32900, 10: 13183}, + ("Category Two times Ones", 5, 7): {0: 2396, 4: 11231, 6: 29481, 8: 37636, 10: 19256}, + ("Category Two times Ones", 5, 8): {0: 1171, 6: 31564, 8: 40798, 10: 26467}, + ("Category Two times Ones", 6, 0): {0: 100000}, + ("Category Two times Ones", 6, 1): {0: 33502, 2: 40413, 4: 26085}, + ("Category Two times Ones", 6, 2): {0: 11210, 2: 29638, 4: 32701, 6: 18988, 8: 7463}, + ("Category Two times Ones", 6, 3): {0: 3673, 2: 16459, 4: 29795, 6: 29102, 8: 20971}, + ("Category Two times Ones", 6, 4): {0: 1243, 4: 30025, 6: 31053, 8: 25066, 10: 12613}, + ("Category Two times Ones", 6, 5): {0: 4194, 4: 13949, 6: 28142, 8: 30723, 10: 22992}, + ("Category Two times Ones", 6, 6): {0: 1800, 6: 30677, 8: 32692, 10: 26213, 12: 8618}, + ("Category Two times Ones", 6, 7): {0: 775, 6: 21013, 8: 31410, 10: 32532, 12: 14270}, + ("Category Two times Ones", 6, 8): {0: 2855, 6: 11432, 8: 27864, 10: 37237, 12: 20612}, + ("Category Two times Ones", 7, 0): {0: 100000}, + ("Category Two times Ones", 7, 1): {0: 27683, 2: 39060, 4: 23574, 6: 9683}, + ("Category Two times Ones", 7, 2): {0: 7824, 2: 24031, 4: 31764, 6: 23095, 8: 13286}, + ("Category Two times Ones", 7, 3): {0: 2148, 2: 11019, 4: 24197, 6: 29599, 8: 21250, 10: 11787}, + ("Category Two times Ones", 7, 4): {0: 564, 4: 19036, 6: 26395, 8: 28409, 10: 18080, 12: 7516}, + ("Category Two times Ones", 7, 5): {0: 1913, 6: 27198, 8: 29039, 10: 26129, 12: 15721}, + ("Category Two times Ones", 7, 6): {0: 54, 6: 17506, 8: 25752, 10: 30413, 12: 26275}, + ("Category Two times Ones", 7, 7): {0: 2179, 8: 28341, 10: 32054, 12: 27347, 14: 10079}, + ("Category Two times Ones", 7, 8): {0: 942, 8: 19835, 10: 30248, 12: 33276, 14: 15699}, + ("Category Two times Ones", 8, 0): {0: 100000}, + ("Category Two times Ones", 8, 1): {0: 23378, 2: 37157, 4: 26082, 6: 13383}, + ("Category Two times Ones", 8, 2): {0: 5420, 2: 19164, 4: 29216, 6: 25677, 8: 20523}, + ("Category Two times Ones", 8, 3): {0: 1271, 4: 26082, 6: 27054, 8: 24712, 10: 20881}, + ("Category Two times Ones", 8, 4): {0: 2889, 6: 29552, 8: 27389, 10: 23232, 12: 16938}, + ("Category Two times Ones", 8, 5): {0: 879, 6: 16853, 8: 23322, 10: 27882, 12: 20768, 14: 10296}, + ("Category Two times Ones", 8, 6): {0: 2041, 8: 24140, 10: 27398, 12: 27048, 14: 19373}, + ("Category Two times Ones", 8, 7): {0: 74, 8: 15693, 10: 23675, 12: 30829, 14: 22454, 16: 7275}, + ("Category Two times Ones", 8, 8): {2: 2053, 10: 25677, 12: 31310, 14: 28983, 16: 11977}, + ("Category Half of Sixes", 0, 0): {0: 100000}, + ("Category Half of Sixes", 0, 1): {0: 100000}, + ("Category Half of Sixes", 0, 2): {0: 100000}, + ("Category Half of Sixes", 0, 3): {0: 100000}, + ("Category Half of Sixes", 0, 4): {0: 100000}, + ("Category Half of Sixes", 0, 5): {0: 100000}, + ("Category Half of Sixes", 0, 6): {0: 100000}, + ("Category Half of Sixes", 0, 7): {0: 100000}, + ("Category Half of Sixes", 0, 8): {0: 100000}, + ("Category Half of Sixes", 1, 0): {0: 100000}, + ("Category Half of Sixes", 1, 1): {0: 83343, 3: 16657}, + ("Category Half of Sixes", 1, 2): {0: 69569, 3: 30431}, + ("Category Half of Sixes", 1, 3): {0: 57872, 3: 42128}, + ("Category Half of Sixes", 1, 4): {0: 48081, 3: 51919}, + ("Category Half of Sixes", 1, 5): {0: 40271, 3: 59729}, + ("Category Half of Sixes", 1, 6): {0: 33201, 3: 66799}, + ("Category Half of Sixes", 1, 7): {0: 27903, 3: 72097}, + ("Category Half of Sixes", 1, 8): {0: 23240, 3: 76760}, + ("Category Half of Sixes", 2, 0): {0: 100000}, + ("Category Half of Sixes", 2, 1): {0: 69419, 3: 30581}, + ("Category Half of Sixes", 2, 2): {0: 48202, 3: 42590, 6: 9208}, + ("Category Half of Sixes", 2, 3): {0: 33376, 3: 48849, 6: 17775}, + ("Category Half of Sixes", 2, 4): {0: 23276, 3: 49810, 6: 26914}, + ("Category Half of Sixes", 2, 5): {0: 16092, 3: 47718, 6: 36190}, + ("Category Half of Sixes", 2, 6): {0: 11232, 3: 44515, 6: 44253}, + ("Category Half of Sixes", 2, 7): {0: 7589, 3: 40459, 6: 51952}, + ("Category Half of Sixes", 2, 8): {0: 5447, 3: 35804, 6: 58749}, + ("Category Half of Sixes", 3, 0): {0: 100000}, + ("Category Half of Sixes", 3, 1): {0: 57964, 3: 34701, 6: 7335}, + ("Category Half of Sixes", 3, 2): {0: 33637, 3: 44263, 6: 22100}, + ("Category Half of Sixes", 3, 3): {0: 19520, 3: 42382, 6: 30676, 9: 7422}, + ("Category Half of Sixes", 3, 4): {0: 11265, 3: 35772, 6: 39042, 9: 13921}, + ("Category Half of Sixes", 3, 5): {0: 6419, 3: 28916, 6: 43261, 9: 21404}, + ("Category Half of Sixes", 3, 6): {0: 3810, 3: 22496, 6: 44388, 9: 29306}, + ("Category Half of Sixes", 3, 7): {0: 2174, 3: 16875, 6: 43720, 9: 37231}, + ("Category Half of Sixes", 3, 8): {0: 1237, 3: 12471, 6: 41222, 9: 45070}, + ("Category Half of Sixes", 4, 0): {0: 100000}, + ("Category Half of Sixes", 4, 1): {0: 48121, 3: 38786, 6: 13093}, + ("Category Half of Sixes", 4, 2): {0: 23296, 3: 40989, 6: 26998, 9: 8717}, + ("Category Half of Sixes", 4, 3): {0: 11233, 3: 32653, 6: 35710, 9: 20404}, + ("Category Half of Sixes", 4, 4): {0: 5463, 3: 23270, 6: 37468, 9: 26734, 12: 7065}, + ("Category Half of Sixes", 4, 5): {0: 2691, 3: 15496, 6: 34539, 9: 34635, 12: 12639}, + ("Category Half of Sixes", 4, 6): {0: 1221, 3: 10046, 6: 29811, 9: 39190, 12: 19732}, + ("Category Half of Sixes", 4, 7): {0: 599, 6: 30742, 9: 41614, 12: 27045}, + ("Category Half of Sixes", 4, 8): {0: 309, 6: 22719, 9: 42236, 12: 34736}, + ("Category Half of Sixes", 5, 0): {0: 100000}, + ("Category Half of Sixes", 5, 1): {0: 40183, 3: 40377, 6: 19440}, + ("Category Half of Sixes", 5, 2): {0: 16197, 3: 35494, 6: 30937, 9: 17372}, + ("Category Half of Sixes", 5, 3): {0: 6583, 3: 23394, 6: 34432, 9: 25239, 12: 10352}, + ("Category Half of Sixes", 5, 4): {0: 2636, 3: 14072, 6: 30134, 9: 32371, 12: 20787}, + ("Category Half of Sixes", 5, 5): {0: 1075, 3: 7804, 6: 23010, 9: 34811, 12: 25702, 15: 7598}, + ("Category Half of Sixes", 5, 6): {0: 418, 6: 20888, 9: 32809, 12: 32892, 15: 12993}, + ("Category Half of Sixes", 5, 7): {0: 2365, 6: 11416, 9: 29072, 12: 37604, 15: 19543}, + ("Category Half of Sixes", 5, 8): {0: 1246, 6: 7425, 9: 24603, 12: 40262, 15: 26464}, + ("Category Half of Sixes", 6, 0): {0: 100000}, + ("Category Half of Sixes", 6, 1): {0: 33473, 3: 40175, 6: 20151, 9: 6201}, + ("Category Half of Sixes", 6, 2): {0: 11147, 3: 29592, 6: 32630, 9: 19287, 12: 7344}, + ("Category Half of Sixes", 6, 3): {0: 3628, 3: 16528, 6: 29814, 9: 29006, 12: 15888, 15: 5136}, + ("Category Half of Sixes", 6, 4): {0: 1262, 3: 8236, 6: 21987, 9: 30953, 12: 24833, 15: 12729}, + ("Category Half of Sixes", 6, 5): {0: 416, 6: 17769, 9: 27798, 12: 31197, 15: 18256, 18: 4564}, + ("Category Half of Sixes", 6, 6): {0: 1796, 6: 8372, 9: 22175, 12: 32897, 15: 26264, 18: 8496}, + ("Category Half of Sixes", 6, 7): {0: 791, 9: 21074, 12: 31385, 15: 32666, 18: 14084}, + ("Category Half of Sixes", 6, 8): {0: 20, 9: 14150, 12: 28320, 15: 36982, 18: 20528}, + ("Category Half of Sixes", 7, 0): {0: 100000}, + ("Category Half of Sixes", 7, 1): {0: 27933, 3: 39105, 6: 23338, 9: 9624}, + ("Category Half of Sixes", 7, 2): {0: 7794, 3: 23896, 6: 31832, 9: 23110, 12: 13368}, + ("Category Half of Sixes", 7, 3): {0: 2138, 3: 11098, 6: 24140, 9: 29316, 12: 21386, 15: 11922}, + ("Category Half of Sixes", 7, 4): {0: 590, 6: 19385, 9: 26233, 12: 28244, 15: 18118, 18: 7430}, + ("Category Half of Sixes", 7, 5): {0: 1941, 6: 7953, 9: 19439, 12: 28977, 15: 26078, 18: 15612}, + ("Category Half of Sixes", 7, 6): {0: 718, 9: 16963, 12: 25793, 15: 30535, 18: 20208, 21: 5783}, + ("Category Half of Sixes", 7, 7): {0: 2064, 9: 7941, 12: 20571, 15: 31859, 18: 27374, 21: 10191}, + ("Category Half of Sixes", 7, 8): {0: 963, 12: 19864, 15: 30313, 18: 33133, 21: 15727}, + ("Category Half of Sixes", 8, 0): {0: 100000}, + ("Category Half of Sixes", 8, 1): {0: 23337, 3: 37232, 6: 25968, 9: 13463}, + ("Category Half of Sixes", 8, 2): {0: 5310, 3: 18930, 6: 29232, 9: 26016, 12: 14399, 15: 6113}, + ("Category Half of Sixes", 8, 3): {0: 1328, 3: 7328, 6: 18754, 9: 27141, 12: 24703, 15: 14251, 18: 6495}, + ("Category Half of Sixes", 8, 4): {0: 2719, 6: 9554, 9: 20607, 12: 26898, 15: 23402, 18: 12452, 21: 4368}, + ("Category Half of Sixes", 8, 5): {0: 905, 9: 16848, 12: 23248, 15: 27931, 18: 20616, 21: 10452}, + ("Category Half of Sixes", 8, 6): {0: 1914, 9: 6890, 12: 17302, 15: 27235, 18: 27276, 21: 19383}, + ("Category Half of Sixes", 8, 7): {0: 800, 12: 15127, 15: 23682, 18: 30401, 21: 22546, 24: 7444}, + ("Category Half of Sixes", 8, 8): {0: 2041, 12: 7211, 15: 18980, 18: 30657, 21: 29074, 24: 12037}, + ("Category Twos and Threes", 1, 1): {0: 66466, 3: 33534}, + ("Category Twos and Threes", 1, 2): {0: 55640, 3: 44360}, + ("Category Twos and Threes", 1, 3): {0: 46223, 3: 53777}, + ("Category Twos and Threes", 1, 4): {0: 38552, 3: 61448}, + ("Category Twos and Threes", 1, 5): {0: 32320, 3: 67680}, + ("Category Twos and Threes", 1, 6): {0: 26733, 3: 73267}, + ("Category Twos and Threes", 1, 7): {0: 22289, 3: 77711}, + ("Category Twos and Threes", 1, 8): {0: 18676, 3: 81324}, + ("Category Twos and Threes", 2, 1): {0: 44565, 2: 21965, 3: 25172, 5: 8298}, + ("Category Twos and Threes", 2, 2): {0: 30855, 3: 51429, 6: 17716}, + ("Category Twos and Threes", 2, 3): {0: 21509, 3: 51178, 6: 27313}, + ("Category Twos and Threes", 2, 4): {0: 14935, 3: 48581, 6: 36484}, + ("Category Twos and Threes", 2, 5): {0: 10492, 3: 44256, 6: 45252}, + ("Category Twos and Threes", 2, 6): {0: 10775, 3: 35936, 6: 53289}, + ("Category Twos and Threes", 2, 7): {0: 7375, 3: 32469, 6: 60156}, + ("Category Twos and Threes", 2, 8): {0: 5212, 3: 35730, 6: 59058}, + ("Category Twos and Threes", 3, 1): {0: 29892, 2: 22136, 3: 27781, 6: 20191}, + ("Category Twos and Threes", 3, 2): {0: 17285, 3: 44257, 6: 38458}, + ("Category Twos and Threes", 3, 3): {0: 9889, 3: 36505, 6: 40112, 8: 13494}, + ("Category Twos and Threes", 3, 4): {0: 5717, 3: 28317, 6: 43044, 9: 22922}, + ("Category Twos and Threes", 3, 5): {0: 5795, 3: 19123, 6: 45004, 9: 30078}, + ("Category Twos and Threes", 3, 6): {0: 3273, 3: 21888, 6: 36387, 9: 38452}, + ("Category Twos and Threes", 3, 7): {0: 1917, 3: 16239, 6: 35604, 9: 46240}, + ("Category Twos and Threes", 3, 8): {0: 1124, 3: 12222, 6: 33537, 9: 53117}, + ("Category Twos and Threes", 4, 1): {0: 19619, 3: 46881, 6: 33500}, + ("Category Twos and Threes", 4, 2): {0: 9395, 3: 33926, 6: 37832, 9: 18847}, + ("Category Twos and Threes", 4, 3): {0: 4538, 3: 22968, 6: 38891, 9: 33603}, + ("Category Twos and Threes", 4, 4): {0: 4402, 3: 12654, 6: 35565, 9: 34784, 11: 12595}, + ("Category Twos and Threes", 4, 5): {0: 2065, 3: 14351, 6: 23592, 9: 38862, 12: 21130}, + ("Category Twos and Threes", 4, 6): {0: 1044, 3: 9056, 6: 20013, 9: 41255, 12: 28632}, + ("Category Twos and Threes", 4, 7): {0: 6310, 7: 24021, 9: 34297, 12: 35372}, + ("Category Twos and Threes", 4, 8): {0: 3694, 6: 18611, 9: 34441, 12: 43254}, + ("Category Twos and Threes", 5, 1): {0: 13070, 3: 33021, 5: 24568, 6: 16417, 8: 12924}, + ("Category Twos and Threes", 5, 2): {0: 5213, 3: 24275, 6: 37166, 9: 24746, 11: 8600}, + ("Category Twos and Threes", 5, 3): {0: 4707, 3: 10959, 6: 31388, 9: 33265, 12: 19681}, + ("Category Twos and Threes", 5, 4): {0: 1934, 3: 12081, 6: 17567, 9: 35282, 12: 33136}, + ("Category Twos and Threes", 5, 5): {0: 380, 2: 7025, 6: 13268, 9: 33274, 12: 33255, 14: 12798}, + ("Category Twos and Threes", 5, 6): {0: 3745, 6: 15675, 9: 22902, 12: 44665, 15: 13013}, + ("Category Twos and Threes", 5, 7): {0: 1969, 6: 10700, 9: 19759, 12: 39522, 15: 28050}, + ("Category Twos and Threes", 5, 8): {0: 13, 2: 7713, 10: 23957, 12: 32501, 15: 35816}, + ("Category Twos and Threes", 6, 1): {0: 8955, 3: 26347, 5: 24850, 8: 39848}, + ("Category Twos and Threes", 6, 2): {0: 2944, 3: 16894, 6: 32156, 9: 37468, 12: 10538}, + ("Category Twos and Threes", 6, 3): {0: 2484, 3: 13120, 6: 15999, 9: 32271, 12: 24898, 14: 11228}, + ("Category Twos and Threes", 6, 4): {0: 320, 2: 6913, 6: 10814, 9: 28622, 12: 31337, 15: 21994}, + ("Category Twos and Threes", 6, 5): {0: 3135, 6: 12202, 9: 16495, 12: 33605, 15: 26330, 17: 8233}, + ("Category Twos and Threes", 6, 6): {0: 98, 3: 8409, 9: 12670, 12: 31959, 15: 38296, 18: 8568}, + ("Category Twos and Threes", 6, 7): {0: 4645, 9: 15210, 12: 21906, 15: 44121, 18: 14118}, + ("Category Twos and Threes", 6, 8): {0: 2367, 9: 10679, 12: 18916, 15: 38806, 18: 29232}, + ("Category Twos and Threes", 7, 1): {0: 5802, 3: 28169, 6: 26411, 9: 31169, 11: 8449}, + ("Category Twos and Threes", 7, 2): {0: 4415, 6: 34992, 9: 31238, 12: 20373, 14: 8982}, + ("Category Twos and Threes", 7, 3): {0: 471, 2: 8571, 6: 10929, 9: 28058, 12: 28900, 14: 14953, 16: 8118}, + ("Category Twos and Threes", 7, 4): {0: 3487, 6: 12139, 9: 14001, 12: 30314, 15: 23096, 18: 16963}, + ("Category Twos and Threes", 7, 5): {0: 40, 2: 7460, 12: 36006, 15: 31388, 18: 25106}, + ("Category Twos and Threes", 7, 6): {0: 3554, 9: 11611, 12: 15116, 15: 32501, 18: 27524, 20: 9694}, + ("Category Twos and Threes", 7, 7): {0: 157, 6: 8396, 13: 19880, 15: 22333, 18: 39121, 21: 10113}, + ("Category Twos and Threes", 7, 8): {0: 31, 5: 4682, 12: 14446, 15: 20934, 18: 44127, 21: 15780}, + ("Category Twos and Threes", 8, 1): {0: 3799, 3: 22551, 6: 23754, 8: 29290, 10: 11990, 12: 8616}, + ("Category Twos and Threes", 8, 2): {0: 902, 4: 14360, 6: 13750, 9: 29893, 13: 30770, 15: 10325}, + ("Category Twos and Threes", 8, 3): {0: 2221, 4: 8122, 9: 23734, 12: 28527, 16: 28942, 18: 8454}, + ("Category Twos and Threes", 8, 4): {0: 140, 3: 8344, 12: 33635, 15: 28711, 18: 20093, 20: 9077}, + ("Category Twos and Threes", 8, 5): {0: 3601, 9: 10269, 12: 12458, 15: 28017, 18: 24815, 21: 20840}, + ("Category Twos and Threes", 8, 6): {0: 4104, 11: 10100, 15: 25259, 18: 30949, 21: 29588}, + ("Category Twos and Threes", 8, 7): {0: 3336, 12: 10227, 15: 14149, 18: 31155, 21: 29325, 23: 11808}, + ("Category Twos and Threes", 8, 8): {3: 7, 5: 7726, 16: 17997, 18: 21517, 21: 40641, 24: 12112}, + ("Category Sum of Odds", 1, 1): {0: 50084, 1: 16488, 3: 16584, 5: 16844}, + ("Category Sum of Odds", 1, 2): {0: 44489, 3: 27886, 5: 27625}, + ("Category Sum of Odds", 1, 3): {0: 27892, 3: 32299, 5: 39809}, + ("Category Sum of Odds", 1, 4): {0: 30917, 3: 19299, 5: 49784}, + ("Category Sum of Odds", 1, 5): {0: 25892, 3: 15941, 5: 58167}, + ("Category Sum of Odds", 1, 6): {0: 21678, 3: 13224, 5: 65098}, + ("Category Sum of Odds", 1, 7): {0: 17840, 3: 11191, 5: 70969}, + ("Category Sum of Odds", 1, 8): {0: 14690, 5: 85310}, + ("Category Sum of Odds", 2, 1): {0: 24611, 1: 19615, 3: 22234, 6: 25168, 8: 8372}, + ("Category Sum of Odds", 2, 2): {0: 11216, 3: 33181, 6: 32416, 8: 15414, 10: 7773}, + ("Category Sum of Odds", 2, 3): {0: 13730, 3: 17055, 5: 34933, 8: 18363, 10: 15919}, + ("Category Sum of Odds", 2, 4): {0: 9599, 3: 11842, 5: 34490, 8: 19129, 10: 24940}, + ("Category Sum of Odds", 2, 5): {0: 6652, 5: 40845, 8: 18712, 10: 33791}, + ("Category Sum of Odds", 2, 6): {0: 10404, 5: 20970, 8: 26124, 10: 42502}, + ("Category Sum of Odds", 2, 7): {0: 7262, 5: 26824, 8: 15860, 10: 50054}, + ("Category Sum of Odds", 2, 8): {0: 4950, 5: 23253, 8: 14179, 10: 57618}, + ("Category Sum of Odds", 3, 1): {0: 12467, 1: 16736, 4: 20970, 6: 29252, 8: 11660, 10: 8915}, + ("Category Sum of Odds", 3, 2): {0: 8635, 3: 15579, 6: 27649, 9: 30585, 13: 17552}, + ("Category Sum of Odds", 3, 3): {0: 5022, 6: 32067, 8: 21631, 11: 24032, 13: 17248}, + ("Category Sum of Odds", 3, 4): {0: 8260, 6: 17955, 8: 18530, 11: 28631, 13: 14216, 15: 12408}, + ("Category Sum of Odds", 3, 5): {0: 4685, 5: 13863, 8: 14915, 11: 30363, 13: 16370, 15: 19804}, + ("Category Sum of Odds", 3, 6): {0: 2766, 5: 10213, 8: 11372, 10: 30968, 13: 17133, 15: 27548}, + ("Category Sum of Odds", 3, 7): {0: 543, 3: 8448, 10: 28784, 13: 26258, 15: 35967}, + ("Category Sum of Odds", 3, 8): {0: 3760, 6: 8911, 11: 27672, 13: 16221, 15: 43436}, + ("Category Sum of Odds", 4, 1): {0: 18870, 5: 28873, 6: 18550, 9: 20881, 11: 12826}, + ("Category Sum of Odds", 4, 2): {0: 7974, 6: 23957, 9: 27982, 11: 15953, 13: 13643, 15: 10491}, + ("Category Sum of Odds", 4, 3): {0: 1778, 3: 8154, 8: 25036, 11: 24307, 13: 18030, 15: 14481, 18: 8214}, + ("Category Sum of Odds", 4, 4): {0: 1862, 4: 8889, 8: 11182, 11: 21997, 13: 19483, 16: 20879, 20: 15708}, + ("Category Sum of Odds", 4, 5): {0: 5687, 7: 8212, 11: 18674, 13: 17578, 16: 25572, 18: 12704, 20: 11573}, + ("Category Sum of Odds", 4, 6): {0: 6549, 11: 17161, 13: 15290, 16: 28355, 18: 14865, 20: 17780}, + ("Category Sum of Odds", 4, 7): {0: 5048, 10: 11824, 13: 12343, 16: 29544, 18: 15947, 20: 25294}, + ("Category Sum of Odds", 4, 8): {0: 3060, 10: 8747, 15: 29415, 18: 25762, 20: 33016}, + ("Category Sum of Odds", 5, 1): {0: 3061, 3: 22078, 6: 26935, 9: 23674, 11: 15144, 14: 9108}, + ("Category Sum of Odds", 5, 2): {0: 5813, 7: 19297, 9: 14666, 11: 17165, 14: 21681, 16: 10586, 18: 10792}, + ("Category Sum of Odds", 5, 3): {0: 3881, 6: 9272, 9: 10300, 11: 13443, 14: 24313, 16: 13969, 19: 16420, 21: 8402}, + ("Category Sum of Odds", 5, 4): {0: 4213, 8: 9656, 13: 24199, 16: 22188, 18: 16440, 20: 14313, 23: 8991}, + ("Category Sum of Odds", 5, 5): {0: 4997, 10: 9128, 13: 11376, 16: 20859, 18: 17548, 21: 20120, 25: 15972}, + ("Category Sum of Odds", 5, 6): { + 0: 4581, + 11: 8516, + 14: 11335, + 16: 10647, + 18: 16866, + 21: 24256, + 23: 11945, + 25: 11854, + }, + ("Category Sum of Odds", 5, 7): {0: 176, 6: 8052, 16: 17535, 18: 14878, 21: 27189, 23: 14100, 25: 18070}, + ("Category Sum of Odds", 5, 8): {0: 2, 2: 6622, 15: 12097, 18: 12454, 21: 28398, 23: 15254, 25: 25173}, + ("Category Sum of Odds", 6, 1): {0: 11634, 4: 12188, 6: 16257, 9: 23909, 11: 13671, 13: 13125, 16: 9216}, + ("Category Sum of Odds", 6, 2): {0: 1403, 4: 8241, 10: 22151, 12: 14245, 14: 15279, 17: 19690, 21: 18991}, + ("Category Sum of Odds", 6, 3): { + 0: 6079, + 9: 10832, + 12: 10094, + 14: 13221, + 17: 22538, + 19: 12673, + 21: 15363, + 24: 9200, + }, + ("Category Sum of Odds", 6, 4): {0: 5771, 11: 9419, 16: 22239, 19: 22715, 21: 12847, 23: 12798, 25: 9237, 28: 4974}, + ("Category Sum of Odds", 6, 5): { + 0: 2564, + 11: 8518, + 17: 20753, + 19: 14121, + 21: 13179, + 23: 15752, + 25: 14841, + 28: 10272, + }, + ("Category Sum of Odds", 6, 6): {0: 4310, 14: 8668, 19: 20891, 21: 12052, 23: 16882, 26: 19954, 30: 17243}, + ("Category Sum of Odds", 6, 7): { + 0: 5233, + 16: 8503, + 19: 11127, + 21: 10285, + 23: 16141, + 26: 23993, + 28: 12043, + 30: 12675, + }, + ("Category Sum of Odds", 6, 8): {0: 510, 12: 8107, 21: 17013, 23: 14396, 26: 26771, 28: 13964, 30: 19239}, + ("Category Sum of Odds", 7, 1): { + 0: 2591, + 2: 8436, + 5: 11759, + 7: 13733, + 9: 15656, + 11: 14851, + 13: 12301, + 15: 11871, + 18: 8802, + }, + ("Category Sum of Odds", 7, 2): { + 0: 4730, + 8: 8998, + 11: 10573, + 13: 13099, + 15: 13819, + 17: 13594, + 19: 12561, + 21: 12881, + 24: 9745, + }, + ("Category Sum of Odds", 7, 3): { + 0: 2549, + 9: 8523, + 15: 19566, + 17: 12251, + 19: 13562, + 21: 13473, + 23: 11918, + 27: 18158, + }, + ("Category Sum of Odds", 7, 4): {0: 6776, 14: 9986, 19: 20914, 22: 21006, 24: 12685, 26: 10835, 30: 17798}, + ("Category Sum of Odds", 7, 5): { + 0: 2943, + 14: 8009, + 20: 20248, + 22: 11896, + 24: 14166, + 26: 12505, + 28: 13136, + 30: 10486, + 33: 6611, + }, + ("Category Sum of Odds", 7, 6): { + 2: 1990, + 15: 8986, + 22: 19198, + 24: 13388, + 26: 12513, + 28: 15893, + 30: 15831, + 35: 12201, + }, + ("Category Sum of Odds", 7, 7): { + 4: 559, + 14: 8153, + 21: 11671, + 24: 12064, + 26: 11473, + 28: 16014, + 31: 20785, + 33: 10174, + 35: 9107, + }, + ("Category Sum of Odds", 7, 8): {0: 3, 8: 5190, 21: 8049, 24: 10585, 28: 25255, 31: 24333, 33: 12445, 35: 14140}, + ("Category Sum of Odds", 8, 1): {0: 7169, 7: 19762, 9: 14044, 11: 14858, 13: 13399, 15: 10801, 17: 11147, 20: 8820}, + ("Category Sum of Odds", 8, 2): { + 0: 7745, + 11: 10927, + 14: 10849, + 16: 13103, + 18: 13484, + 20: 12487, + 22: 10815, + 24: 11552, + 27: 9038, + }, + ("Category Sum of Odds", 8, 3): { + 0: 3867, + 12: 9356, + 18: 19408, + 20: 12379, + 22: 12519, + 24: 12260, + 26: 11008, + 28: 10726, + 31: 8477, + }, + ("Category Sum of Odds", 8, 4): { + 1: 3971, + 15: 9176, + 21: 18732, + 23: 12900, + 25: 13405, + 27: 11603, + 29: 10400, + 33: 19813, + }, + ("Category Sum of Odds", 8, 5): { + 1: 490, + 12: 8049, + 20: 9682, + 23: 10177, + 25: 12856, + 27: 12369, + 29: 12781, + 32: 18029, + 34: 11315, + 38: 4252, + }, + ("Category Sum of Odds", 8, 6): { + 4: 86, + 11: 8038, + 22: 9157, + 25: 10729, + 27: 11053, + 29: 13606, + 31: 12383, + 33: 14068, + 35: 12408, + 38: 8472, + }, + ("Category Sum of Odds", 8, 7): { + 6: 1852, + 20: 8020, + 27: 17455, + 29: 12898, + 31: 12181, + 33: 15650, + 35: 17577, + 40: 14367, + }, + ("Category Sum of Odds", 8, 8): { + 4: 8, + 11: 8008, + 26: 10314, + 29: 11446, + 31: 10714, + 33: 16060, + 36: 21765, + 38: 10622, + 40: 11063, + }, + ("Category Sum of Evens", 1, 1): {0: 49585, 2: 16733, 4: 16854, 6: 16828}, + ("Category Sum of Evens", 1, 2): {0: 33244, 2: 11087, 4: 28025, 6: 27644}, + ("Category Sum of Evens", 1, 3): {0: 22259, 4: 42357, 6: 35384}, + ("Category Sum of Evens", 1, 4): {0: 18511, 4: 35651, 6: 45838}, + ("Category Sum of Evens", 1, 5): {0: 15428, 4: 29656, 6: 54916}, + ("Category Sum of Evens", 1, 6): {0: 12927, 4: 24370, 6: 62703}, + ("Category Sum of Evens", 1, 7): {0: 14152, 4: 17087, 6: 68761}, + ("Category Sum of Evens", 1, 8): {0: 11920, 4: 14227, 6: 73853}, + ("Category Sum of Evens", 2, 1): {0: 25229, 2: 16545, 4: 19538, 6: 21987, 10: 16701}, + ("Category Sum of Evens", 2, 2): {0: 11179, 4: 27164, 6: 24451, 8: 13966, 10: 15400, 12: 7840}, + ("Category Sum of Evens", 2, 3): {0: 8099, 4: 16354, 6: 20647, 8: 17887, 10: 24736, 12: 12277}, + ("Category Sum of Evens", 2, 4): {0: 5687, 4: 11219, 6: 20711, 8: 14290, 10: 26976, 12: 21117}, + ("Category Sum of Evens", 2, 5): {0: 3991, 6: 27157, 8: 11641, 10: 26842, 12: 30369}, + ("Category Sum of Evens", 2, 6): {0: 2741, 6: 23123, 10: 35050, 12: 39086}, + ("Category Sum of Evens", 2, 7): {0: 1122, 6: 20538, 10: 30952, 12: 47388}, + ("Category Sum of Evens", 2, 8): {0: 3950, 6: 14006, 10: 27341, 12: 54703}, + ("Category Sum of Evens", 3, 1): {0: 12538, 2: 12516, 4: 16530, 6: 21270, 8: 13745, 10: 11209, 14: 12192}, + ("Category Sum of Evens", 3, 2): {0: 7404, 4: 10459, 6: 15644, 8: 15032, 10: 18955, 12: 15021, 16: 17485}, + ("Category Sum of Evens", 3, 3): {0: 2176, 6: 14148, 8: 12295, 10: 20247, 12: 18001, 14: 15953, 16: 17180}, + ("Category Sum of Evens", 3, 4): {0: 4556, 8: 15062, 10: 17232, 12: 18975, 14: 15832, 16: 18749, 18: 9594}, + ("Category Sum of Evens", 3, 5): {0: 2575, 8: 10825, 10: 13927, 12: 19533, 14: 14402, 16: 21954, 18: 16784}, + ("Category Sum of Evens", 3, 6): {0: 1475, 6: 7528, 10: 10614, 12: 19070, 14: 12940, 16: 23882, 18: 24491}, + ("Category Sum of Evens", 3, 7): {0: 862, 6: 5321, 12: 26291, 14: 10985, 16: 24254, 18: 32287}, + ("Category Sum of Evens", 3, 8): {0: 138, 4: 4086, 12: 22703, 16: 32516, 18: 40557}, + ("Category Sum of Evens", 4, 1): {0: 6214, 4: 20921, 6: 17434, 8: 15427, 10: 14158, 12: 11354, 16: 14492}, + ("Category Sum of Evens", 4, 2): { + 0: 2868, + 6: 13362, + 8: 10702, + 10: 15154, + 12: 15715, + 14: 14104, + 16: 12485, + 20: 15610, + }, + ("Category Sum of Evens", 4, 3): { + 0: 573, + 8: 10496, + 10: 10269, + 12: 12879, + 14: 16224, + 16: 17484, + 18: 13847, + 20: 10518, + 22: 7710, + }, + ("Category Sum of Evens", 4, 4): { + 0: 1119, + 6: 5124, + 12: 17394, + 14: 12763, + 16: 17947, + 18: 16566, + 20: 13338, + 22: 15749, + }, + ("Category Sum of Evens", 4, 5): {0: 3477, 12: 12738, 16: 26184, 18: 18045, 20: 14172, 22: 16111, 24: 9273}, + ("Category Sum of Evens", 4, 6): {0: 991, 12: 10136, 16: 21089, 18: 18805, 20: 13848, 22: 20013, 24: 15118}, + ("Category Sum of Evens", 4, 7): {0: 2931, 16: 21174, 18: 18952, 20: 12601, 22: 21947, 24: 22395}, + ("Category Sum of Evens", 4, 8): {0: 1798, 12: 6781, 18: 27146, 20: 11505, 22: 23056, 24: 29714}, + ("Category Sum of Evens", 5, 1): { + 0: 3192, + 4: 13829, + 6: 13373, + 8: 13964, + 10: 14656, + 12: 13468, + 14: 10245, + 18: 17273, + }, + ("Category Sum of Evens", 5, 2): { + 0: 3217, + 8: 10390, + 12: 22094, + 14: 13824, + 16: 14674, + 18: 12124, + 22: 16619, + 24: 7058, + }, + ("Category Sum of Evens", 5, 3): { + 0: 3904, + 12: 11004, + 14: 10339, + 16: 13128, + 18: 14686, + 20: 15282, + 22: 13294, + 26: 18363, + }, + ("Category Sum of Evens", 5, 4): { + 0: 43, + 4: 4025, + 14: 10648, + 16: 10437, + 18: 12724, + 20: 14710, + 22: 16005, + 24: 12896, + 28: 18512, + }, + ("Category Sum of Evens", 5, 5): { + 0: 350, + 8: 4392, + 16: 11641, + 18: 10297, + 20: 12344, + 22: 16826, + 24: 15490, + 26: 12235, + 28: 16425, + }, + ("Category Sum of Evens", 5, 6): { + 0: 374, + 10: 4670, + 18: 13498, + 22: 25729, + 24: 17286, + 26: 13565, + 28: 15274, + 30: 9604, + }, + ("Category Sum of Evens", 5, 7): {0: 1473, 18: 11310, 22: 21341, 24: 18114, 26: 13349, 28: 19048, 30: 15365}, + ("Category Sum of Evens", 5, 8): {0: 1, 4: 3753, 20: 10318, 22: 11699, 24: 18376, 26: 12500, 28: 21211, 30: 22142}, + ("Category Sum of Evens", 6, 1): { + 0: 4767, + 6: 15250, + 8: 11527, + 10: 13220, + 12: 13855, + 14: 12217, + 16: 10036, + 20: 19128, + }, + ("Category Sum of Evens", 6, 2): { + 0: 1380, + 6: 5285, + 12: 13888, + 14: 10495, + 16: 12112, + 18: 12962, + 20: 12458, + 22: 10842, + 26: 14076, + 28: 6502, + }, + ("Category Sum of Evens", 6, 3): { + 0: 1230, + 16: 17521, + 18: 10098, + 20: 12628, + 22: 13809, + 24: 13594, + 26: 11930, + 30: 19190, + }, + ("Category Sum of Evens", 6, 4): {0: 1235, 18: 15534, 22: 22081, 24: 13471, 26: 13991, 28: 12906, 32: 20782}, + ("Category Sum of Evens", 6, 5): {0: 1241, 20: 15114, 24: 21726, 26: 13874, 28: 15232, 30: 12927, 34: 19886}, + ("Category Sum of Evens", 6, 6): {0: 1224, 22: 15886, 26: 21708, 28: 15982, 30: 15534, 32: 12014, 34: 17652}, + ("Category Sum of Evens", 6, 7): {4: 1437, 24: 17624, 28: 24727, 30: 17083, 32: 13001, 34: 15604, 36: 10524}, + ("Category Sum of Evens", 6, 8): {4: 1707, 24: 11310, 28: 20871, 30: 18101, 32: 12842, 34: 18840, 36: 16329}, + ("Category Sum of Evens", 7, 1): { + 0: 6237, + 8: 15390, + 10: 11183, + 12: 12690, + 14: 12463, + 16: 11578, + 20: 17339, + 22: 8870, + 26: 4250, + }, + ("Category Sum of Evens", 7, 2): { + 0: 1433, + 14: 16705, + 18: 19797, + 20: 11747, + 22: 12101, + 24: 10947, + 28: 16547, + 32: 10723, + }, + ("Category Sum of Evens", 7, 3): { + 0: 2135, + 14: 5836, + 20: 13766, + 22: 10305, + 24: 12043, + 26: 13153, + 28: 12644, + 30: 10884, + 34: 19234, + }, + ("Category Sum of Evens", 7, 4): { + 0: 1762, + 22: 16471, + 26: 20839, + 28: 12907, + 30: 13018, + 32: 11907, + 34: 10022, + 38: 13074, + }, + ("Category Sum of Evens", 7, 5): { + 4: 1630, + 24: 14719, + 28: 20377, + 30: 12713, + 32: 13273, + 34: 13412, + 36: 10366, + 40: 13510, + }, + ("Category Sum of Evens", 7, 6): { + 4: 1436, + 26: 14275, + 30: 20680, + 32: 12798, + 34: 15385, + 36: 13346, + 38: 10011, + 40: 12069, + }, + ("Category Sum of Evens", 7, 7): { + 6: 2815, + 24: 6584, + 30: 16532, + 32: 11106, + 34: 15613, + 36: 15702, + 38: 12021, + 40: 12478, + 42: 7149, + }, + ("Category Sum of Evens", 7, 8): {10: 1490, 30: 16831, 34: 23888, 36: 16970, 38: 12599, 40: 16137, 42: 12085}, + ("Category Sum of Evens", 8, 1): { + 0: 3709, + 8: 10876, + 12: 19246, + 14: 11696, + 16: 11862, + 18: 11145, + 22: 16877, + 24: 9272, + 28: 5317, + }, + ("Category Sum of Evens", 8, 2): { + 0: 1361, + 16: 14530, + 20: 17637, + 22: 10922, + 24: 11148, + 26: 10879, + 30: 17754, + 34: 15769, + }, + ("Category Sum of Evens", 8, 3): { + 2: 1601, + 22: 14895, + 26: 18464, + 28: 11561, + 30: 12249, + 32: 11747, + 34: 10070, + 38: 19413, + }, + ("Category Sum of Evens", 8, 4): { + 0: 2339, + 20: 5286, + 26: 11746, + 30: 19858, + 32: 12344, + 34: 12243, + 36: 11307, + 40: 16632, + 42: 8245, + }, + ("Category Sum of Evens", 8, 5): { + 4: 1798, + 28: 14824, + 32: 18663, + 34: 12180, + 36: 12458, + 38: 12260, + 40: 10958, + 44: 16859, + }, + ("Category Sum of Evens", 8, 6): { + 6: 2908, + 26: 6292, + 32: 13573, + 34: 10367, + 36: 12064, + 38: 12862, + 40: 13920, + 42: 11359, + 46: 16655, + }, + ("Category Sum of Evens", 8, 7): { + 8: 2652, + 28: 6168, + 34: 13922, + 36: 10651, + 38: 12089, + 40: 14999, + 42: 13899, + 44: 10574, + 46: 15046, + }, + ("Category Sum of Evens", 8, 8): { + 10: 2547, + 30: 6023, + 36: 15354, + 38: 10354, + 40: 14996, + 42: 16214, + 44: 11803, + 46: 13670, + 48: 9039, + }, + ("Category Double Threes and Fours", 1, 1): {0: 66749, 6: 16591, 8: 16660}, + ("Category Double Threes and Fours", 1, 2): {0: 44675, 6: 27694, 8: 27631}, + ("Category Double Threes and Fours", 1, 3): {0: 29592, 6: 35261, 8: 35147}, + ("Category Double Threes and Fours", 1, 4): {0: 24601, 6: 29406, 8: 45993}, + ("Category Double Threes and Fours", 1, 5): {0: 20499, 6: 24420, 8: 55081}, + ("Category Double Threes and Fours", 1, 6): {0: 17116, 6: 20227, 8: 62657}, + ("Category Double Threes and Fours", 1, 7): {0: 14193, 6: 17060, 8: 68747}, + ("Category Double Threes and Fours", 1, 8): {0: 11977, 6: 13924, 8: 74099}, + ("Category Double Threes and Fours", 2, 1): {0: 44382, 6: 22191, 8: 22251, 14: 11176}, + ("Category Double Threes and Fours", 2, 2): {0: 19720, 6: 24652, 8: 24891, 14: 23096, 16: 7641}, + ("Category Double Threes and Fours", 2, 3): {0: 8765, 6: 21008, 8: 20929, 12: 12201, 14: 24721, 16: 12376}, + ("Category Double Threes and Fours", 2, 4): {0: 6164, 6: 14466, 8: 22828, 14: 35406, 16: 21136}, + ("Category Double Threes and Fours", 2, 5): {0: 4307, 6: 10005, 8: 22620, 14: 32879, 16: 30189}, + ("Category Double Threes and Fours", 2, 6): {0: 2879, 8: 28513, 14: 29530, 16: 39078}, + ("Category Double Threes and Fours", 2, 7): {0: 2042, 8: 24335, 14: 26250, 16: 47373}, + ("Category Double Threes and Fours", 2, 8): {0: 1385, 8: 23166, 14: 20907, 16: 54542}, + ("Category Double Threes and Fours", 3, 1): {0: 29378, 6: 22335, 8: 22138, 14: 16783, 16: 9366}, + ("Category Double Threes and Fours", 3, 2): { + 0: 8894, + 6: 16518, + 8: 16277, + 12: 10334, + 14: 20757, + 16: 12265, + 22: 14955, + }, + ("Category Double Threes and Fours", 3, 3): { + 0: 2643, + 8: 18522, + 12: 11066, + 14: 21922, + 16: 11045, + 20: 17235, + 22: 17567, + }, + ("Category Double Threes and Fours", 3, 4): { + 0: 1523, + 8: 13773, + 14: 26533, + 16: 18276, + 20: 11695, + 22: 18521, + 24: 9679, + }, + ("Category Double Threes and Fours", 3, 5): {0: 845, 8: 10218, 14: 20245, 16: 20293, 22: 31908, 24: 16491}, + ("Category Double Threes and Fours", 3, 6): {0: 499, 8: 7230, 14: 15028, 16: 20914, 22: 31835, 24: 24494}, + ("Category Double Threes and Fours", 3, 7): {0: 1298, 8: 5434, 16: 30595, 22: 29980, 24: 32693}, + ("Category Double Threes and Fours", 3, 8): {0: 178, 6: 4363, 16: 27419, 22: 27614, 24: 40426}, + ("Category Double Threes and Fours", 4, 1): {0: 19809, 6: 19538, 8: 19765, 14: 22348, 18: 12403, 22: 6137}, + ("Category Double Threes and Fours", 4, 2): { + 0: 3972, + 8: 19440, + 14: 27646, + 16: 12978, + 20: 11442, + 22: 11245, + 24: 6728, + 28: 6549, + }, + ("Category Double Threes and Fours", 4, 3): { + 0: 745, + 6: 7209, + 14: 19403, + 18: 11744, + 20: 15371, + 22: 15441, + 26: 13062, + 30: 17025, + }, + ("Category Double Threes and Fours", 4, 4): { + 0: 371, + 6: 4491, + 14: 13120, + 16: 10176, + 20: 11583, + 22: 18508, + 24: 10280, + 28: 15624, + 30: 15847, + }, + ("Category Double Threes and Fours", 4, 5): { + 0: 163, + 6: 4251, + 16: 15796, + 22: 26145, + 24: 17306, + 28: 10930, + 30: 16244, + 32: 9165, + }, + ("Category Double Threes and Fours", 4, 6): {0: 79, 16: 14439, 22: 21763, 24: 18861, 30: 29518, 32: 15340}, + ("Category Double Threes and Fours", 4, 7): {0: 1042, 16: 12543, 22: 13634, 24: 20162, 30: 30259, 32: 22360}, + ("Category Double Threes and Fours", 4, 8): {0: 20, 6: 2490, 16: 6901, 22: 10960, 24: 20269, 30: 29442, 32: 29918}, + ("Category Double Threes and Fours", 5, 1): { + 0: 13122, + 6: 16411, + 8: 16451, + 14: 24768, + 16: 10392, + 22: 14528, + 26: 4328, + }, + ("Category Double Threes and Fours", 5, 2): { + 0: 1676, + 8: 10787, + 14: 20218, + 18: 11102, + 20: 12668, + 22: 12832, + 26: 10994, + 30: 15390, + 34: 4333, + }, + ("Category Double Threes and Fours", 5, 3): { + 0: 223, + 14: 12365, + 16: 7165, + 20: 11385, + 22: 11613, + 26: 15182, + 28: 13665, + 32: 14400, + 36: 14002, + }, + ("Category Double Threes and Fours", 5, 4): { + 0: 95, + 6: 2712, + 16: 8862, + 22: 18696, + 26: 12373, + 28: 13488, + 30: 14319, + 34: 12414, + 38: 17041, + }, + ("Category Double Threes and Fours", 5, 5): { + 0: 1333, + 14: 5458, + 22: 13613, + 24: 10772, + 28: 11201, + 30: 16810, + 32: 10248, + 36: 14426, + 38: 16139, + }, + ("Category Double Threes and Fours", 5, 6): { + 0: 16, + 16: 6354, + 24: 16213, + 30: 25369, + 32: 16845, + 36: 10243, + 38: 15569, + 40: 9391, + }, + ("Category Double Threes and Fours", 5, 7): { + 0: 161, + 12: 3457, + 24: 12437, + 30: 21495, + 32: 18636, + 38: 28581, + 40: 15233, + }, + ("Category Double Threes and Fours", 5, 8): { + 0: 478, + 16: 4861, + 26: 10119, + 30: 13694, + 32: 19681, + 38: 29177, + 40: 21990, + }, + ("Category Double Threes and Fours", 6, 1): { + 0: 8738, + 6: 13463, + 8: 12988, + 14: 24653, + 16: 11068, + 22: 19621, + 26: 5157, + 30: 4312, + }, + ("Category Double Threes and Fours", 6, 2): { + 0: 784, + 6: 5735, + 14: 13407, + 16: 8170, + 20: 11349, + 22: 11356, + 26: 12465, + 28: 10790, + 30: 11527, + 38: 14417, + }, + ("Category Double Threes and Fours", 6, 3): { + 0: 72, + 14: 8986, + 22: 13700, + 26: 12357, + 28: 12114, + 32: 15882, + 36: 19286, + 40: 13540, + 44: 4063, + }, + ("Category Double Threes and Fours", 6, 4): { + 0: 439, + 18: 7427, + 22: 9284, + 28: 14203, + 30: 10836, + 34: 14646, + 36: 12511, + 38: 10194, + 42: 10202, + 46: 10258, + }, + ("Category Double Threes and Fours", 6, 5): { + 0: 166, + 20: 7618, + 24: 5198, + 30: 17479, + 34: 12496, + 36: 12190, + 38: 14163, + 42: 12571, + 46: 18119, + }, + ("Category Double Threes and Fours", 6, 6): { + 0: 1843, + 22: 5905, + 30: 12997, + 32: 10631, + 36: 10342, + 38: 16439, + 40: 10795, + 44: 13485, + 46: 17563, + }, + ("Category Double Threes and Fours", 6, 7): { + 0: 31, + 12: 2221, + 24: 5004, + 32: 15743, + 38: 24402, + 40: 17005, + 46: 25241, + 48: 10353, + }, + ("Category Double Threes and Fours", 6, 8): { + 8: 79, + 16: 4037, + 32: 12559, + 38: 20863, + 40: 18347, + 46: 27683, + 48: 16432, + }, + ("Category Double Threes and Fours", 7, 1): { + 0: 5803, + 6: 10242, + 8: 10404, + 14: 22886, + 16: 10934, + 22: 19133, + 24: 7193, + 28: 8167, + 32: 5238, + }, + ("Category Double Threes and Fours", 7, 2): { + 0: 357, + 14: 17082, + 22: 17524, + 26: 11974, + 28: 11132, + 32: 13186, + 36: 13959, + 40: 10028, + 44: 4758, + }, + ("Category Double Threes and Fours", 7, 3): { + 0: 361, + 18: 7136, + 22: 5983, + 28: 13899, + 32: 12974, + 34: 10088, + 36: 10081, + 40: 14481, + 44: 14127, + 46: 6547, + 50: 4323, + }, + ("Category Double Threes and Fours", 7, 4): { + 0: 1182, + 18: 4299, + 30: 16331, + 34: 11316, + 36: 10741, + 40: 16028, + 44: 18815, + 48: 15225, + 52: 6063, + }, + ("Category Double Threes and Fours", 7, 5): { + 0: 45, + 12: 3763, + 32: 17140, + 38: 19112, + 42: 13655, + 44: 11990, + 46: 11137, + 50: 10646, + 54: 12512, + }, + ("Category Double Threes and Fours", 7, 6): { + 8: 2400, + 28: 5277, + 32: 5084, + 38: 16047, + 42: 12133, + 44: 11451, + 46: 14027, + 50: 13198, + 54: 20383, + }, + ("Category Double Threes and Fours", 7, 7): { + 6: 1968, + 30: 5585, + 38: 12210, + 40: 10376, + 46: 25548, + 48: 15392, + 54: 21666, + 56: 7255, + }, + ("Category Double Threes and Fours", 7, 8): { + 8: 42, + 20: 2293, + 32: 4653, + 40: 15068, + 46: 23170, + 48: 17057, + 54: 25601, + 56: 12116, + }, + ("Category Double Threes and Fours", 8, 1): { + 0: 3982, + 8: 15658, + 14: 20388, + 16: 10234, + 20: 10167, + 22: 10162, + 28: 15330, + 32: 8758, + 36: 5321, + }, + ("Category Double Threes and Fours", 8, 2): { + 0: 161, + 6: 3169, + 14: 7106, + 22: 16559, + 28: 16400, + 32: 12950, + 36: 16399, + 40: 10090, + 44: 11474, + 48: 5692, + }, + ("Category Double Threes and Fours", 8, 3): { + 0: 856, + 16: 4092, + 30: 13686, + 34: 12838, + 38: 15010, + 42: 17085, + 46: 14067, + 50: 11844, + 52: 6500, + 56: 4022, + }, + ("Category Double Threes and Fours", 8, 4): { + 0: 36, + 12: 2795, + 30: 9742, + 36: 11726, + 40: 12404, + 44: 18791, + 48: 14662, + 52: 15518, + 54: 8066, + 58: 6260, + }, + ("Category Double Threes and Fours", 8, 5): { + 6: 8, + 12: 2948, + 30: 5791, + 38: 10658, + 42: 10175, + 46: 19359, + 50: 14449, + 52: 10531, + 56: 13257, + 60: 12824, + }, + ("Category Double Threes and Fours", 8, 6): { + 0: 2, + 12: 2528, + 32: 4832, + 40: 11436, + 46: 17832, + 50: 13016, + 52: 11631, + 54: 12058, + 58: 11458, + 62: 15207, + }, + ("Category Double Threes and Fours", 8, 7): { + 6: 2, + 12: 2204, + 40: 9320, + 46: 14688, + 50: 11494, + 52: 10602, + 54: 14541, + 58: 13849, + 62: 23300, + }, + ("Category Double Threes and Fours", 8, 8): { + 8: 1, + 16: 1773, + 42: 8766, + 48: 17452, + 54: 24338, + 56: 15722, + 62: 22745, + 64: 9203, + }, + ("Category Quadruple Ones and Twos", 1, 1): {0: 66567, 4: 16803, 8: 16630}, + ("Category Quadruple Ones and Twos", 1, 2): {0: 44809, 4: 27448, 8: 27743}, + ("Category Quadruple Ones and Twos", 1, 3): {0: 37100, 4: 23184, 8: 39716}, + ("Category Quadruple Ones and Twos", 1, 4): {0: 30963, 4: 19221, 8: 49816}, + ("Category Quadruple Ones and Twos", 1, 5): {0: 25316, 4: 16079, 8: 58605}, + ("Category Quadruple Ones and Twos", 1, 6): {0: 21505, 4: 13237, 8: 65258}, + ("Category Quadruple Ones and Twos", 1, 7): {0: 17676, 4: 11100, 8: 71224}, + ("Category Quadruple Ones and Twos", 1, 8): {0: 14971, 4: 9323, 8: 75706}, + ("Category Quadruple Ones and Twos", 2, 1): {0: 44566, 4: 22273, 8: 24842, 12: 8319}, + ("Category Quadruple Ones and Twos", 2, 2): {0: 19963, 4: 24890, 8: 32262, 12: 15172, 16: 7713}, + ("Category Quadruple Ones and Twos", 2, 3): {0: 13766, 4: 17158, 8: 34907, 12: 18539, 16: 15630}, + ("Category Quadruple Ones and Twos", 2, 4): {0: 9543, 4: 11981, 8: 34465, 12: 19108, 16: 24903}, + ("Category Quadruple Ones and Twos", 2, 5): {0: 6472, 4: 8302, 8: 32470, 12: 18612, 16: 34144}, + ("Category Quadruple Ones and Twos", 2, 6): {0: 4569, 4: 5737, 8: 29716, 12: 17216, 16: 42762}, + ("Category Quadruple Ones and Twos", 2, 7): {0: 3146, 8: 30463, 12: 15756, 16: 50635}, + ("Category Quadruple Ones and Twos", 2, 8): {0: 2265, 8: 26302, 12: 14167, 16: 57266}, + ("Category Quadruple Ones and Twos", 3, 1): {0: 29440, 4: 22574, 8: 27747, 12: 11557, 16: 8682}, + ("Category Quadruple Ones and Twos", 3, 2): {0: 8857, 4: 16295, 8: 26434, 12: 22986, 16: 16799, 20: 8629}, + ("Category Quadruple Ones and Twos", 3, 3): {0: 5063, 4: 9447, 8: 22255, 12: 21685, 16: 24084, 20: 11167, 24: 6299}, + ("Category Quadruple Ones and Twos", 3, 4): { + 0: 2864, + 4: 5531, + 8: 17681, + 12: 18400, + 16: 28524, + 20: 14552, + 24: 12448, + }, + ("Category Quadruple Ones and Twos", 3, 5): {0: 1676, 8: 16697, 12: 14755, 16: 30427, 20: 16602, 24: 19843}, + ("Category Quadruple Ones and Twos", 3, 6): {0: 2681, 8: 10259, 12: 11326, 16: 31125, 20: 16984, 24: 27625}, + ("Category Quadruple Ones and Twos", 3, 7): {0: 1688, 8: 7543, 12: 8769, 16: 29367, 20: 17085, 24: 35548}, + ("Category Quadruple Ones and Twos", 3, 8): {0: 941, 8: 5277, 12: 6388, 16: 27741, 20: 16170, 24: 43483}, + ("Category Quadruple Ones and Twos", 4, 1): {0: 19691, 4: 19657, 8: 27288, 12: 16126, 16: 11167, 24: 6071}, + ("Category Quadruple Ones and Twos", 4, 2): { + 0: 4023, + 4: 9776, + 8: 19015, + 12: 22094, + 16: 20986, + 20: 13805, + 24: 10301, + }, + ("Category Quadruple Ones and Twos", 4, 3): { + 0: 1848, + 8: 17116, + 12: 16853, + 16: 22831, + 20: 18400, + 24: 14480, + 28: 8472, + }, + ("Category Quadruple Ones and Twos", 4, 4): { + 0: 930, + 8: 10375, + 12: 12063, + 16: 21220, + 20: 19266, + 24: 20615, + 28: 9443, + 32: 6088, + }, + ("Category Quadruple Ones and Twos", 4, 5): { + 0: 1561, + 12: 12612, + 16: 18209, + 20: 17910, + 24: 25474, + 28: 12864, + 32: 11370, + }, + ("Category Quadruple Ones and Twos", 4, 6): { + 0: 722, + 12: 7979, + 16: 14796, + 20: 15416, + 24: 28256, + 28: 14675, + 32: 18156, + }, + ("Category Quadruple Ones and Twos", 4, 7): { + 0: 115, + 12: 5304, + 16: 11547, + 20: 12289, + 24: 29181, + 28: 16052, + 32: 25512, + }, + ("Category Quadruple Ones and Twos", 4, 8): {0: 164, 8: 2971, 16: 8888, 20: 9679, 24: 28785, 28: 16180, 32: 33333}, + ("Category Quadruple Ones and Twos", 5, 1): { + 0: 13112, + 4: 16534, + 8: 24718, + 12: 18558, + 16: 14547, + 20: 7055, + 24: 5476, + }, + ("Category Quadruple Ones and Twos", 5, 2): { + 0: 1764, + 4: 5529, + 8: 12216, + 12: 17687, + 16: 20808, + 20: 18149, + 24: 12849, + 28: 6991, + 32: 4007, + }, + ("Category Quadruple Ones and Twos", 5, 3): { + 0: 719, + 8: 8523, + 12: 11074, + 16: 17322, + 20: 19002, + 24: 18643, + 28: 12827, + 32: 7960, + 36: 3930, + }, + ("Category Quadruple Ones and Twos", 5, 4): { + 0: 1152, + 12: 9790, + 16: 12913, + 20: 15867, + 24: 20749, + 28: 16398, + 32: 14218, + 36: 8913, + }, + ("Category Quadruple Ones and Twos", 5, 5): { + 0: 98, + 12: 5549, + 16: 8863, + 20: 12037, + 24: 20010, + 28: 17568, + 32: 19789, + 36: 9319, + 40: 6767, + }, + ("Category Quadruple Ones and Twos", 5, 6): { + 0: 194, + 8: 2663, + 16: 5734, + 20: 8436, + 24: 17830, + 28: 16864, + 32: 24246, + 36: 12115, + 40: 11918, + }, + ("Category Quadruple Ones and Twos", 5, 7): { + 0: 1449, + 20: 9396, + 24: 14936, + 28: 14969, + 32: 27238, + 36: 14094, + 40: 17918, + }, + ("Category Quadruple Ones and Twos", 5, 8): { + 0: 747, + 20: 6034, + 24: 11929, + 28: 12517, + 32: 28388, + 36: 15339, + 40: 25046, + }, + ("Category Quadruple Ones and Twos", 6, 1): { + 0: 8646, + 4: 13011, + 8: 21357, + 12: 19385, + 16: 17008, + 20: 10409, + 24: 6249, + 28: 3935, + }, + ("Category Quadruple Ones and Twos", 6, 2): { + 0: 844, + 8: 10311, + 12: 12792, + 16: 17480, + 20: 18814, + 24: 16492, + 28: 11889, + 32: 6893, + 36: 4485, + }, + ("Category Quadruple Ones and Twos", 6, 3): { + 0: 1241, + 12: 9634, + 16: 11685, + 20: 15584, + 24: 17967, + 28: 16506, + 32: 13314, + 36: 8034, + 40: 6035, + }, + ("Category Quadruple Ones and Twos", 6, 4): { + 0: 1745, + 16: 9804, + 20: 10562, + 24: 15746, + 28: 17174, + 32: 17787, + 36: 12820, + 40: 9289, + 44: 5073, + }, + ("Category Quadruple Ones and Twos", 6, 5): { + 0: 2076, + 20: 10247, + 24: 12264, + 28: 14810, + 32: 19588, + 36: 16002, + 40: 14682, + 44: 6410, + 48: 3921, + }, + ("Category Quadruple Ones and Twos", 6, 6): { + 0: 884, + 20: 5943, + 24: 8774, + 28: 11481, + 32: 19145, + 36: 16864, + 40: 19906, + 44: 9386, + 48: 7617, + }, + ("Category Quadruple Ones and Twos", 6, 7): { + 0: 1386, + 24: 8138, + 28: 8372, + 32: 17207, + 36: 16148, + 40: 24051, + 44: 11862, + 48: 12836, + }, + ("Category Quadruple Ones and Twos", 6, 8): { + 0: 1841, + 28: 9606, + 32: 14489, + 36: 14585, + 40: 26779, + 44: 13821, + 48: 18879, + }, + ("Category Quadruple Ones and Twos", 7, 1): { + 0: 5780, + 4: 10185, + 8: 17905, + 12: 18364, + 16: 18160, + 20: 13115, + 24: 8617, + 32: 7874, + }, + ("Category Quadruple Ones and Twos", 7, 2): { + 0: 1795, + 12: 12828, + 16: 13204, + 20: 16895, + 24: 17562, + 28: 15061, + 32: 11122, + 36: 6507, + 40: 5026, + }, + ("Category Quadruple Ones and Twos", 7, 3): { + 0: 2065, + 16: 10495, + 20: 11008, + 24: 14839, + 28: 16393, + 32: 16118, + 36: 12681, + 40: 8773, + 48: 7628, + }, + ("Category Quadruple Ones and Twos", 7, 4): { + 0: 1950, + 20: 9612, + 24: 10535, + 28: 13596, + 32: 16527, + 36: 15938, + 40: 14071, + 44: 9192, + 48: 8579, + }, + ("Category Quadruple Ones and Twos", 7, 5): { + 0: 223, + 20: 5144, + 24: 6337, + 28: 9400, + 32: 14443, + 36: 15955, + 40: 17820, + 44: 13369, + 48: 10702, + 56: 6607, + }, + ("Category Quadruple Ones and Twos", 7, 6): { + 0: 271, + 24: 5976, + 28: 5988, + 32: 11398, + 36: 13738, + 40: 19063, + 44: 15587, + 48: 15867, + 52: 7202, + 56: 4910, + }, + ("Category Quadruple Ones and Twos", 7, 7): { + 0: 1032, + 28: 5724, + 32: 8275, + 36: 10801, + 40: 18184, + 44: 16470, + 48: 20467, + 52: 9969, + 56: 9078, + }, + ("Category Quadruple Ones and Twos", 7, 8): { + 0: 1508, + 32: 7832, + 36: 7770, + 40: 16197, + 44: 15477, + 48: 24388, + 52: 12403, + 56: 14425, + }, + ("Category Quadruple Ones and Twos", 8, 1): { + 0: 3811, + 4: 7682, + 8: 14638, + 12: 17214, + 16: 18191, + 20: 14651, + 24: 10976, + 28: 6591, + 36: 6246, + }, + ("Category Quadruple Ones and Twos", 8, 2): { + 0: 906, + 12: 7768, + 16: 9421, + 20: 13623, + 24: 16213, + 28: 16246, + 32: 14131, + 36: 10076, + 40: 6198, + 48: 5418, + }, + ("Category Quadruple Ones and Twos", 8, 3): { + 0: 224, + 8: 2520, + 20: 11222, + 24: 10733, + 28: 13934, + 32: 15751, + 36: 14882, + 40: 12409, + 44: 8920, + 48: 5462, + 52: 3943, + }, + ("Category Quadruple Ones and Twos", 8, 4): { + 0: 233, + 20: 5163, + 24: 6057, + 28: 9073, + 32: 12990, + 36: 14756, + 40: 15851, + 44: 13795, + 48: 10706, + 52: 6310, + 56: 5066, + }, + ("Category Quadruple Ones and Twos", 8, 5): { + 0: 76, + 12: 2105, + 28: 8316, + 32: 8993, + 36: 12039, + 40: 15561, + 44: 15382, + 48: 15278, + 52: 10629, + 56: 7377, + 60: 4244, + }, + ("Category Quadruple Ones and Twos", 8, 6): { + 4: 262, + 32: 10321, + 36: 8463, + 40: 13177, + 44: 14818, + 48: 17731, + 52: 14024, + 56: 12425, + 60: 5446, + 64: 3333, + }, + ("Category Quadruple Ones and Twos", 8, 7): { + 8: 300, + 32: 5443, + 36: 5454, + 40: 10276, + 44: 12582, + 48: 18487, + 52: 15549, + 56: 17187, + 60: 8149, + 64: 6573, + }, + ("Category Quadruple Ones and Twos", 8, 8): { + 8: 354, + 36: 5678, + 40: 7484, + 44: 9727, + 48: 17080, + 52: 15898, + 56: 21877, + 60: 10773, + 64: 11129, + }, + ("Category Micro Straight", 1, 1): {0: 100000}, + ("Category Micro Straight", 1, 2): {0: 100000}, + ("Category Micro Straight", 1, 3): {0: 100000}, + ("Category Micro Straight", 1, 4): {0: 100000}, + ("Category Micro Straight", 1, 5): {0: 100000}, + ("Category Micro Straight", 1, 6): {0: 100000}, + ("Category Micro Straight", 1, 7): {0: 100000}, + ("Category Micro Straight", 1, 8): {0: 100000}, + ("Category Micro Straight", 2, 1): {0: 72326, 10: 27674}, + ("Category Micro Straight", 2, 2): {0: 48546, 10: 51454}, + ("Category Micro Straight", 2, 3): {0: 32619, 10: 67381}, + ("Category Micro Straight", 2, 4): {0: 21659, 10: 78341}, + ("Category Micro Straight", 2, 5): {0: 14288, 10: 85712}, + ("Category Micro Straight", 2, 6): {0: 9882, 10: 90118}, + ("Category Micro Straight", 2, 7): {0: 6502, 10: 93498}, + ("Category Micro Straight", 2, 8): {0: 4161, 10: 95839}, + ("Category Micro Straight", 3, 1): {0: 41943, 10: 58057}, + ("Category Micro Straight", 3, 2): {0: 15524, 10: 84476}, + ("Category Micro Straight", 3, 3): {0: 5700, 10: 94300}, + ("Category Micro Straight", 3, 4): {0: 2127, 10: 97873}, + ("Category Micro Straight", 3, 5): {0: 744, 10: 99256}, + ("Category Micro Straight", 3, 6): {0: 260, 10: 99740}, + ("Category Micro Straight", 3, 7): {0: 115, 10: 99885}, + ("Category Micro Straight", 3, 8): {0: 34, 10: 99966}, + ("Category Micro Straight", 4, 1): {0: 22307, 10: 77693}, + ("Category Micro Straight", 4, 2): {0: 4420, 10: 95580}, + ("Category Micro Straight", 4, 3): {0: 806, 10: 99194}, + ("Category Micro Straight", 4, 4): {0: 205, 10: 99795}, + ("Category Micro Straight", 4, 5): {0: 20, 10: 99980}, + ("Category Micro Straight", 4, 6): {0: 5, 10: 99995}, + ("Category Micro Straight", 4, 7): {0: 1, 10: 99999}, + ("Category Micro Straight", 4, 8): {0: 1, 10: 99999}, + ("Category Micro Straight", 5, 1): {0: 11685, 10: 88315}, + ("Category Micro Straight", 5, 2): {0: 1141, 10: 98859}, + ("Category Micro Straight", 5, 3): {0: 119, 10: 99881}, + ("Category Micro Straight", 5, 4): {0: 11, 10: 99989}, + ("Category Micro Straight", 5, 5): {0: 1, 10: 99999}, + ("Category Micro Straight", 5, 6): {10: 100000}, + ("Category Micro Straight", 5, 7): {10: 100000}, + ("Category Micro Straight", 5, 8): {10: 100000}, + ("Category Micro Straight", 6, 1): {0: 5937, 10: 94063}, + ("Category Micro Straight", 6, 2): {0: 307, 10: 99693}, + ("Category Micro Straight", 6, 3): {0: 9, 10: 99991}, + ("Category Micro Straight", 6, 4): {0: 1, 10: 99999}, + ("Category Micro Straight", 6, 5): {10: 100000}, + ("Category Micro Straight", 6, 6): {10: 100000}, + ("Category Micro Straight", 6, 7): {10: 100000}, + ("Category Micro Straight", 6, 8): {10: 100000}, + ("Category Micro Straight", 7, 1): {0: 3072, 10: 96928}, + ("Category Micro Straight", 7, 2): {0: 85, 10: 99915}, + ("Category Micro Straight", 7, 3): {0: 2, 10: 99998}, + ("Category Micro Straight", 7, 4): {10: 100000}, + ("Category Micro Straight", 7, 5): {10: 100000}, + ("Category Micro Straight", 7, 6): {10: 100000}, + ("Category Micro Straight", 7, 7): {10: 100000}, + ("Category Micro Straight", 7, 8): {10: 100000}, + ("Category Micro Straight", 8, 1): {0: 1544, 10: 98456}, + ("Category Micro Straight", 8, 2): {0: 15, 10: 99985}, + ("Category Micro Straight", 8, 3): {10: 100000}, + ("Category Micro Straight", 8, 4): {10: 100000}, + ("Category Micro Straight", 8, 5): {10: 100000}, + ("Category Micro Straight", 8, 6): {10: 100000}, + ("Category Micro Straight", 8, 7): {10: 100000}, + ("Category Micro Straight", 8, 8): {10: 100000}, + ("Category Three Odds", 1, 1): {0: 100000}, + ("Category Three Odds", 1, 2): {0: 100000}, + ("Category Three Odds", 1, 3): {0: 100000}, + ("Category Three Odds", 1, 4): {0: 100000}, + ("Category Three Odds", 1, 5): {0: 100000}, + ("Category Three Odds", 1, 6): {0: 100000}, + ("Category Three Odds", 1, 7): {0: 100000}, + ("Category Three Odds", 1, 8): {0: 100000}, + ("Category Three Odds", 2, 1): {0: 100000}, + ("Category Three Odds", 2, 2): {0: 100000}, + ("Category Three Odds", 2, 3): {0: 100000}, + ("Category Three Odds", 2, 4): {0: 100000}, + ("Category Three Odds", 2, 5): {0: 100000}, + ("Category Three Odds", 2, 6): {0: 100000}, + ("Category Three Odds", 2, 7): {0: 100000}, + ("Category Three Odds", 2, 8): {0: 100000}, + ("Category Three Odds", 3, 1): {0: 87592, 20: 12408}, + ("Category Three Odds", 3, 2): {0: 57855, 20: 42145}, + ("Category Three Odds", 3, 3): {0: 32668, 20: 67332}, + ("Category Three Odds", 3, 4): {0: 17508, 20: 82492}, + ("Category Three Odds", 3, 5): {0: 9156, 20: 90844}, + ("Category Three Odds", 3, 6): {0: 4572, 20: 95428}, + ("Category Three Odds", 3, 7): {0: 2325, 20: 97675}, + ("Category Three Odds", 3, 8): {0: 1116, 20: 98884}, + ("Category Three Odds", 4, 1): {0: 68669, 20: 31331}, + ("Category Three Odds", 4, 2): {0: 26140, 20: 73860}, + ("Category Three Odds", 4, 3): {0: 7837, 20: 92163}, + ("Category Three Odds", 4, 4): {0: 2169, 20: 97831}, + ("Category Three Odds", 4, 5): {0: 516, 20: 99484}, + ("Category Three Odds", 4, 6): {0: 156, 20: 99844}, + ("Category Three Odds", 4, 7): {0: 40, 20: 99960}, + ("Category Three Odds", 4, 8): {0: 12, 20: 99988}, + ("Category Three Odds", 5, 1): {0: 49908, 20: 50092}, + ("Category Three Odds", 5, 2): {0: 10373, 20: 89627}, + ("Category Three Odds", 5, 3): {0: 1640, 20: 98360}, + ("Category Three Odds", 5, 4): {0: 223, 20: 99777}, + ("Category Three Odds", 5, 5): {0: 24, 20: 99976}, + ("Category Three Odds", 5, 6): {0: 3, 20: 99997}, + ("Category Three Odds", 5, 7): {0: 1, 20: 99999}, + ("Category Three Odds", 5, 8): {20: 100000}, + ("Category Three Odds", 6, 1): {0: 34566, 20: 65434}, + ("Category Three Odds", 6, 2): {0: 3766, 20: 96234}, + ("Category Three Odds", 6, 3): {0: 291, 20: 99709}, + ("Category Three Odds", 6, 4): {0: 22, 20: 99978}, + ("Category Three Odds", 6, 5): {20: 100000}, + ("Category Three Odds", 6, 6): {20: 100000}, + ("Category Three Odds", 6, 7): {20: 100000}, + ("Category Three Odds", 6, 8): {20: 100000}, + ("Category Three Odds", 7, 1): {0: 22722, 20: 77278}, + ("Category Three Odds", 7, 2): {0: 1291, 20: 98709}, + ("Category Three Odds", 7, 3): {0: 38, 20: 99962}, + ("Category Three Odds", 7, 4): {0: 2, 20: 99998}, + ("Category Three Odds", 7, 5): {20: 100000}, + ("Category Three Odds", 7, 6): {20: 100000}, + ("Category Three Odds", 7, 7): {20: 100000}, + ("Category Three Odds", 7, 8): {20: 100000}, + ("Category Three Odds", 8, 1): {0: 14556, 20: 85444}, + ("Category Three Odds", 8, 2): {0: 430, 20: 99570}, + ("Category Three Odds", 8, 3): {0: 3, 20: 99997}, + ("Category Three Odds", 8, 4): {20: 100000}, + ("Category Three Odds", 8, 5): {20: 100000}, + ("Category Three Odds", 8, 6): {20: 100000}, + ("Category Three Odds", 8, 7): {20: 100000}, + ("Category Three Odds", 8, 8): {20: 100000}, + ("Category 1-2-1 Consecutive", 1, 1): {0: 100000}, + ("Category 1-2-1 Consecutive", 1, 2): {0: 100000}, + ("Category 1-2-1 Consecutive", 1, 3): {0: 100000}, + ("Category 1-2-1 Consecutive", 1, 4): {0: 100000}, + ("Category 1-2-1 Consecutive", 1, 5): {0: 100000}, + ("Category 1-2-1 Consecutive", 1, 6): {0: 100000}, + ("Category 1-2-1 Consecutive", 1, 7): {0: 100000}, + ("Category 1-2-1 Consecutive", 1, 8): {0: 100000}, + ("Category 1-2-1 Consecutive", 2, 1): {0: 100000}, + ("Category 1-2-1 Consecutive", 2, 2): {0: 100000}, + ("Category 1-2-1 Consecutive", 2, 3): {0: 100000}, + ("Category 1-2-1 Consecutive", 2, 4): {0: 100000}, + ("Category 1-2-1 Consecutive", 2, 5): {0: 100000}, + ("Category 1-2-1 Consecutive", 2, 6): {0: 100000}, + ("Category 1-2-1 Consecutive", 2, 7): {0: 100000}, + ("Category 1-2-1 Consecutive", 2, 8): {0: 100000}, + ("Category 1-2-1 Consecutive", 3, 1): {0: 100000}, + ("Category 1-2-1 Consecutive", 3, 2): {0: 100000}, + ("Category 1-2-1 Consecutive", 3, 3): {0: 100000}, + ("Category 1-2-1 Consecutive", 3, 4): {0: 100000}, + ("Category 1-2-1 Consecutive", 3, 5): {0: 100000}, + ("Category 1-2-1 Consecutive", 3, 6): {0: 100000}, + ("Category 1-2-1 Consecutive", 3, 7): {0: 100000}, + ("Category 1-2-1 Consecutive", 3, 8): {0: 100000}, + ("Category 1-2-1 Consecutive", 4, 1): {0: 96371, 30: 3629}, + ("Category 1-2-1 Consecutive", 4, 2): {0: 86605, 30: 13395}, + ("Category 1-2-1 Consecutive", 4, 3): {0: 75037, 30: 24963}, + ("Category 1-2-1 Consecutive", 4, 4): {0: 63656, 30: 36344}, + ("Category 1-2-1 Consecutive", 4, 5): {0: 53869, 30: 46131}, + ("Category 1-2-1 Consecutive", 4, 6): {0: 45131, 30: 54869}, + ("Category 1-2-1 Consecutive", 4, 7): {0: 37535, 30: 62465}, + ("Category 1-2-1 Consecutive", 4, 8): {0: 31425, 30: 68575}, + ("Category 1-2-1 Consecutive", 5, 1): {0: 86632, 30: 13368}, + ("Category 1-2-1 Consecutive", 5, 2): {0: 62779, 30: 37221}, + ("Category 1-2-1 Consecutive", 5, 3): {0: 46034, 30: 53966}, + ("Category 1-2-1 Consecutive", 5, 4): {0: 34983, 30: 65017}, + ("Category 1-2-1 Consecutive", 5, 5): {0: 28056, 30: 71944}, + ("Category 1-2-1 Consecutive", 5, 6): {0: 23150, 30: 76850}, + ("Category 1-2-1 Consecutive", 5, 7): {0: 19577, 30: 80423}, + ("Category 1-2-1 Consecutive", 5, 8): {0: 17613, 30: 82387}, + ("Category 1-2-1 Consecutive", 6, 1): {0: 71928, 30: 28072}, + ("Category 1-2-1 Consecutive", 6, 2): {0: 40724, 30: 59276}, + ("Category 1-2-1 Consecutive", 6, 3): {0: 26723, 30: 73277}, + ("Category 1-2-1 Consecutive", 6, 4): {0: 19685, 30: 80315}, + ("Category 1-2-1 Consecutive", 6, 5): {0: 15460, 30: 84540}, + ("Category 1-2-1 Consecutive", 6, 6): {0: 12526, 30: 87474}, + ("Category 1-2-1 Consecutive", 6, 7): {0: 10014, 30: 89986}, + ("Category 1-2-1 Consecutive", 6, 8): {0: 8251, 30: 91749}, + ("Category 1-2-1 Consecutive", 7, 1): {0: 55544, 30: 44456}, + ("Category 1-2-1 Consecutive", 7, 2): {0: 24840, 30: 75160}, + ("Category 1-2-1 Consecutive", 7, 3): {0: 15102, 30: 84898}, + ("Category 1-2-1 Consecutive", 7, 4): {0: 10541, 30: 89459}, + ("Category 1-2-1 Consecutive", 7, 5): {0: 7720, 30: 92280}, + ("Category 1-2-1 Consecutive", 7, 6): {0: 5554, 30: 94446}, + ("Category 1-2-1 Consecutive", 7, 7): {0: 4106, 30: 95894}, + ("Category 1-2-1 Consecutive", 7, 8): {0: 3025, 30: 96975}, + ("Category 1-2-1 Consecutive", 8, 1): {0: 40693, 30: 59307}, + ("Category 1-2-1 Consecutive", 8, 2): {0: 14827, 30: 85173}, + ("Category 1-2-1 Consecutive", 8, 3): {0: 8195, 30: 91805}, + ("Category 1-2-1 Consecutive", 8, 4): {0: 5383, 30: 94617}, + ("Category 1-2-1 Consecutive", 8, 5): {0: 3395, 30: 96605}, + ("Category 1-2-1 Consecutive", 8, 6): {0: 2299, 30: 97701}, + ("Category 1-2-1 Consecutive", 8, 7): {0: 1412, 30: 98588}, + ("Category 1-2-1 Consecutive", 8, 8): {0: 872, 30: 99128}, + ("Category Three Distinct Dice", 1, 1): {0: 100000}, + ("Category Three Distinct Dice", 1, 2): {0: 100000}, + ("Category Three Distinct Dice", 1, 3): {0: 100000}, + ("Category Three Distinct Dice", 1, 4): {0: 100000}, + ("Category Three Distinct Dice", 1, 5): {0: 100000}, + ("Category Three Distinct Dice", 1, 6): {0: 100000}, + ("Category Three Distinct Dice", 1, 7): {0: 100000}, + ("Category Three Distinct Dice", 1, 8): {0: 100000}, + ("Category Three Distinct Dice", 2, 1): {0: 100000}, + ("Category Three Distinct Dice", 2, 2): {0: 100000}, + ("Category Three Distinct Dice", 2, 3): {0: 100000}, + ("Category Three Distinct Dice", 2, 4): {0: 100000}, + ("Category Three Distinct Dice", 2, 5): {0: 100000}, + ("Category Three Distinct Dice", 2, 6): {0: 100000}, + ("Category Three Distinct Dice", 2, 7): {0: 100000}, + ("Category Three Distinct Dice", 2, 8): {0: 100000}, + ("Category Three Distinct Dice", 3, 1): {0: 44707, 20: 55293}, + ("Category Three Distinct Dice", 3, 2): {0: 15078, 20: 84922}, + ("Category Three Distinct Dice", 3, 3): {0: 5056, 20: 94944}, + ("Category Three Distinct Dice", 3, 4): {0: 1688, 20: 98312}, + ("Category Three Distinct Dice", 3, 5): {0: 516, 20: 99484}, + ("Category Three Distinct Dice", 3, 6): {0: 182, 20: 99818}, + ("Category Three Distinct Dice", 3, 7): {0: 56, 20: 99944}, + ("Category Three Distinct Dice", 3, 8): {0: 15, 20: 99985}, + ("Category Three Distinct Dice", 4, 1): {0: 16721, 20: 83279}, + ("Category Three Distinct Dice", 4, 2): {0: 1826, 20: 98174}, + ("Category Three Distinct Dice", 4, 3): {0: 203, 20: 99797}, + ("Category Three Distinct Dice", 4, 4): {0: 18, 20: 99982}, + ("Category Three Distinct Dice", 4, 5): {0: 3, 20: 99997}, + ("Category Three Distinct Dice", 4, 6): {20: 100000}, + ("Category Three Distinct Dice", 4, 7): {20: 100000}, + ("Category Three Distinct Dice", 4, 8): {20: 100000}, + ("Category Three Distinct Dice", 5, 1): {0: 5904, 20: 94096}, + ("Category Three Distinct Dice", 5, 2): {0: 236, 20: 99764}, + ("Category Three Distinct Dice", 5, 3): {0: 12, 20: 99988}, + ("Category Three Distinct Dice", 5, 4): {20: 100000}, + ("Category Three Distinct Dice", 5, 5): {20: 100000}, + ("Category Three Distinct Dice", 5, 6): {20: 100000}, + ("Category Three Distinct Dice", 5, 7): {20: 100000}, + ("Category Three Distinct Dice", 5, 8): {20: 100000}, + ("Category Three Distinct Dice", 6, 1): {0: 1992, 20: 98008}, + ("Category Three Distinct Dice", 6, 2): {0: 21, 20: 99979}, + ("Category Three Distinct Dice", 6, 3): {20: 100000}, + ("Category Three Distinct Dice", 6, 4): {20: 100000}, + ("Category Three Distinct Dice", 6, 5): {20: 100000}, + ("Category Three Distinct Dice", 6, 6): {20: 100000}, + ("Category Three Distinct Dice", 6, 7): {20: 100000}, + ("Category Three Distinct Dice", 6, 8): {20: 100000}, + ("Category Three Distinct Dice", 7, 1): {0: 692, 20: 99308}, + ("Category Three Distinct Dice", 7, 2): {0: 4, 20: 99996}, + ("Category Three Distinct Dice", 7, 3): {20: 100000}, + ("Category Three Distinct Dice", 7, 4): {20: 100000}, + ("Category Three Distinct Dice", 7, 5): {20: 100000}, + ("Category Three Distinct Dice", 7, 6): {20: 100000}, + ("Category Three Distinct Dice", 7, 7): {20: 100000}, + ("Category Three Distinct Dice", 7, 8): {20: 100000}, + ("Category Three Distinct Dice", 8, 1): {0: 243, 20: 99757}, + ("Category Three Distinct Dice", 8, 2): {0: 1, 20: 99999}, + ("Category Three Distinct Dice", 8, 3): {20: 100000}, + ("Category Three Distinct Dice", 8, 4): {20: 100000}, + ("Category Three Distinct Dice", 8, 5): {20: 100000}, + ("Category Three Distinct Dice", 8, 6): {20: 100000}, + ("Category Three Distinct Dice", 8, 7): {20: 100000}, + ("Category Three Distinct Dice", 8, 8): {20: 100000}, + ("Category Two Pair", 1, 1): {0: 100000}, + ("Category Two Pair", 1, 2): {0: 100000}, + ("Category Two Pair", 1, 3): {0: 100000}, + ("Category Two Pair", 1, 4): {0: 100000}, + ("Category Two Pair", 1, 5): {0: 100000}, + ("Category Two Pair", 1, 6): {0: 100000}, + ("Category Two Pair", 1, 7): {0: 100000}, + ("Category Two Pair", 1, 8): {0: 100000}, + ("Category Two Pair", 2, 1): {0: 100000}, + ("Category Two Pair", 2, 2): {0: 100000}, + ("Category Two Pair", 2, 3): {0: 100000}, + ("Category Two Pair", 2, 4): {0: 100000}, + ("Category Two Pair", 2, 5): {0: 100000}, + ("Category Two Pair", 2, 6): {0: 100000}, + ("Category Two Pair", 2, 7): {0: 100000}, + ("Category Two Pair", 2, 8): {0: 100000}, + ("Category Two Pair", 3, 1): {0: 100000}, + ("Category Two Pair", 3, 2): {0: 100000}, + ("Category Two Pair", 3, 3): {0: 100000}, + ("Category Two Pair", 3, 4): {0: 100000}, + ("Category Two Pair", 3, 5): {0: 100000}, + ("Category Two Pair", 3, 6): {0: 100000}, + ("Category Two Pair", 3, 7): {0: 100000}, + ("Category Two Pair", 3, 8): {0: 100000}, + ("Category Two Pair", 4, 1): {0: 93065, 30: 6935}, + ("Category Two Pair", 4, 2): {0: 82102, 30: 17898}, + ("Category Two Pair", 4, 3): {0: 71209, 30: 28791}, + ("Category Two Pair", 4, 4): {0: 61609, 30: 38391}, + ("Category Two Pair", 4, 5): {0: 53036, 30: 46964}, + ("Category Two Pair", 4, 6): {0: 45705, 30: 54295}, + ("Category Two Pair", 4, 7): {0: 39398, 30: 60602}, + ("Category Two Pair", 4, 8): {0: 33673, 30: 66327}, + ("Category Two Pair", 5, 1): {0: 72847, 30: 27153}, + ("Category Two Pair", 5, 2): {0: 46759, 30: 53241}, + ("Category Two Pair", 5, 3): {0: 29462, 30: 70538}, + ("Category Two Pair", 5, 4): {0: 18351, 30: 81649}, + ("Category Two Pair", 5, 5): {0: 11793, 30: 88207}, + ("Category Two Pair", 5, 6): {0: 7385, 30: 92615}, + ("Category Two Pair", 5, 7): {0: 4610, 30: 95390}, + ("Category Two Pair", 5, 8): {0: 2938, 30: 97062}, + ("Category Two Pair", 6, 1): {0: 44431, 30: 55569}, + ("Category Two Pair", 6, 2): {0: 17183, 30: 82817}, + ("Category Two Pair", 6, 3): {0: 6759, 30: 93241}, + ("Category Two Pair", 6, 4): {0: 2562, 30: 97438}, + ("Category Two Pair", 6, 5): {0: 948, 30: 99052}, + ("Category Two Pair", 6, 6): {0: 375, 30: 99625}, + ("Category Two Pair", 6, 7): {0: 138, 30: 99862}, + ("Category Two Pair", 6, 8): {0: 57, 30: 99943}, + ("Category Two Pair", 7, 1): {0: 19888, 30: 80112}, + ("Category Two Pair", 7, 2): {0: 3935, 30: 96065}, + ("Category Two Pair", 7, 3): {0: 801, 30: 99199}, + ("Category Two Pair", 7, 4): {0: 175, 30: 99825}, + ("Category Two Pair", 7, 5): {0: 31, 30: 99969}, + ("Category Two Pair", 7, 6): {0: 7, 30: 99993}, + ("Category Two Pair", 7, 7): {0: 2, 30: 99998}, + ("Category Two Pair", 7, 8): {30: 100000}, + ("Category Two Pair", 8, 1): {0: 6791, 30: 93209}, + ("Category Two Pair", 8, 2): {0: 588, 30: 99412}, + ("Category Two Pair", 8, 3): {0: 61, 30: 99939}, + ("Category Two Pair", 8, 4): {0: 6, 30: 99994}, + ("Category Two Pair", 8, 5): {30: 100000}, + ("Category Two Pair", 8, 6): {30: 100000}, + ("Category Two Pair", 8, 7): {30: 100000}, + ("Category Two Pair", 8, 8): {30: 100000}, + ("Category 2-1-2 Consecutive", 1, 1): {0: 100000}, + ("Category 2-1-2 Consecutive", 1, 2): {0: 100000}, + ("Category 2-1-2 Consecutive", 1, 3): {0: 100000}, + ("Category 2-1-2 Consecutive", 1, 4): {0: 100000}, + ("Category 2-1-2 Consecutive", 1, 5): {0: 100000}, + ("Category 2-1-2 Consecutive", 1, 6): {0: 100000}, + ("Category 2-1-2 Consecutive", 1, 7): {0: 100000}, + ("Category 2-1-2 Consecutive", 1, 8): {0: 100000}, + ("Category 2-1-2 Consecutive", 2, 1): {0: 100000}, + ("Category 2-1-2 Consecutive", 2, 2): {0: 100000}, + ("Category 2-1-2 Consecutive", 2, 3): {0: 100000}, + ("Category 2-1-2 Consecutive", 2, 4): {0: 100000}, + ("Category 2-1-2 Consecutive", 2, 5): {0: 100000}, + ("Category 2-1-2 Consecutive", 2, 6): {0: 100000}, + ("Category 2-1-2 Consecutive", 2, 7): {0: 100000}, + ("Category 2-1-2 Consecutive", 2, 8): {0: 100000}, + ("Category 2-1-2 Consecutive", 3, 1): {0: 100000}, + ("Category 2-1-2 Consecutive", 3, 2): {0: 100000}, + ("Category 2-1-2 Consecutive", 3, 3): {0: 100000}, + ("Category 2-1-2 Consecutive", 3, 4): {0: 100000}, + ("Category 2-1-2 Consecutive", 3, 5): {0: 100000}, + ("Category 2-1-2 Consecutive", 3, 6): {0: 100000}, + ("Category 2-1-2 Consecutive", 3, 7): {0: 100000}, + ("Category 2-1-2 Consecutive", 3, 8): {0: 100000}, + ("Category 2-1-2 Consecutive", 4, 1): {0: 100000}, + ("Category 2-1-2 Consecutive", 4, 2): {0: 100000}, + ("Category 2-1-2 Consecutive", 4, 3): {0: 100000}, + ("Category 2-1-2 Consecutive", 4, 4): {0: 100000}, + ("Category 2-1-2 Consecutive", 4, 5): {0: 100000}, + ("Category 2-1-2 Consecutive", 4, 6): {0: 100000}, + ("Category 2-1-2 Consecutive", 4, 7): {0: 100000}, + ("Category 2-1-2 Consecutive", 4, 8): {0: 100000}, + ("Category 2-1-2 Consecutive", 5, 1): {0: 98403, 40: 1597}, + ("Category 2-1-2 Consecutive", 5, 2): {0: 90651, 40: 9349}, + ("Category 2-1-2 Consecutive", 5, 3): {0: 80100, 40: 19900}, + ("Category 2-1-2 Consecutive", 5, 4): {0: 69131, 40: 30869}, + ("Category 2-1-2 Consecutive", 5, 5): {0: 58252, 40: 41748}, + ("Category 2-1-2 Consecutive", 5, 6): {0: 49405, 40: 50595}, + ("Category 2-1-2 Consecutive", 5, 7): {0: 41585, 40: 58415}, + ("Category 2-1-2 Consecutive", 5, 8): {0: 34952, 40: 65048}, + ("Category 2-1-2 Consecutive", 6, 1): {0: 93465, 40: 6535}, + ("Category 2-1-2 Consecutive", 6, 2): {0: 73416, 40: 26584}, + ("Category 2-1-2 Consecutive", 6, 3): {0: 54041, 40: 45959}, + ("Category 2-1-2 Consecutive", 6, 4): {0: 38535, 40: 61465}, + ("Category 2-1-2 Consecutive", 6, 5): {0: 27366, 40: 72634}, + ("Category 2-1-2 Consecutive", 6, 6): {0: 18924, 40: 81076}, + ("Category 2-1-2 Consecutive", 6, 7): {0: 13387, 40: 86613}, + ("Category 2-1-2 Consecutive", 6, 8): {0: 9134, 40: 90866}, + ("Category 2-1-2 Consecutive", 7, 1): {0: 84168, 40: 15832}, + ("Category 2-1-2 Consecutive", 7, 2): {0: 52659, 40: 47341}, + ("Category 2-1-2 Consecutive", 7, 3): {0: 30435, 40: 69565}, + ("Category 2-1-2 Consecutive", 7, 4): {0: 17477, 40: 82523}, + ("Category 2-1-2 Consecutive", 7, 5): {0: 9782, 40: 90218}, + ("Category 2-1-2 Consecutive", 7, 6): {0: 5316, 40: 94684}, + ("Category 2-1-2 Consecutive", 7, 7): {0: 2995, 40: 97005}, + ("Category 2-1-2 Consecutive", 7, 8): {0: 1689, 40: 98311}, + ("Category 2-1-2 Consecutive", 8, 1): {0: 71089, 40: 28911}, + ("Category 2-1-2 Consecutive", 8, 2): {0: 33784, 40: 66216}, + ("Category 2-1-2 Consecutive", 8, 3): {0: 14820, 40: 85180}, + ("Category 2-1-2 Consecutive", 8, 4): {0: 6265, 40: 93735}, + ("Category 2-1-2 Consecutive", 8, 5): {0: 2600, 40: 97400}, + ("Category 2-1-2 Consecutive", 8, 6): {0: 1155, 40: 98845}, + ("Category 2-1-2 Consecutive", 8, 7): {0: 487, 40: 99513}, + ("Category 2-1-2 Consecutive", 8, 8): {0: 190, 40: 99810}, + ("Category Five Distinct Dice", 1, 1): {0: 100000}, + ("Category Five Distinct Dice", 1, 2): {0: 100000}, + ("Category Five Distinct Dice", 1, 3): {0: 100000}, + ("Category Five Distinct Dice", 1, 4): {0: 100000}, + ("Category Five Distinct Dice", 1, 5): {0: 100000}, + ("Category Five Distinct Dice", 1, 6): {0: 100000}, + ("Category Five Distinct Dice", 1, 7): {0: 100000}, + ("Category Five Distinct Dice", 1, 8): {0: 100000}, + ("Category Five Distinct Dice", 2, 1): {0: 100000}, + ("Category Five Distinct Dice", 2, 2): {0: 100000}, + ("Category Five Distinct Dice", 2, 3): {0: 100000}, + ("Category Five Distinct Dice", 2, 4): {0: 100000}, + ("Category Five Distinct Dice", 2, 5): {0: 100000}, + ("Category Five Distinct Dice", 2, 6): {0: 100000}, + ("Category Five Distinct Dice", 2, 7): {0: 100000}, + ("Category Five Distinct Dice", 2, 8): {0: 100000}, + ("Category Five Distinct Dice", 3, 1): {0: 100000}, + ("Category Five Distinct Dice", 3, 2): {0: 100000}, + ("Category Five Distinct Dice", 3, 3): {0: 100000}, + ("Category Five Distinct Dice", 3, 4): {0: 100000}, + ("Category Five Distinct Dice", 3, 5): {0: 100000}, + ("Category Five Distinct Dice", 3, 6): {0: 100000}, + ("Category Five Distinct Dice", 3, 7): {0: 100000}, + ("Category Five Distinct Dice", 3, 8): {0: 100000}, + ("Category Five Distinct Dice", 4, 1): {0: 100000}, + ("Category Five Distinct Dice", 4, 2): {0: 100000}, + ("Category Five Distinct Dice", 4, 3): {0: 100000}, + ("Category Five Distinct Dice", 4, 4): {0: 100000}, + ("Category Five Distinct Dice", 4, 5): {0: 100000}, + ("Category Five Distinct Dice", 4, 6): {0: 100000}, + ("Category Five Distinct Dice", 4, 7): {0: 100000}, + ("Category Five Distinct Dice", 4, 8): {0: 100000}, + ("Category Five Distinct Dice", 5, 1): {0: 90907, 25: 9093}, + ("Category Five Distinct Dice", 5, 2): {0: 68020, 25: 31980}, + ("Category Five Distinct Dice", 5, 3): {0: 47692, 25: 52308}, + ("Category Five Distinct Dice", 5, 4): {0: 32383, 25: 67617}, + ("Category Five Distinct Dice", 5, 5): {0: 21631, 25: 78369}, + ("Category Five Distinct Dice", 5, 6): {0: 14366, 25: 85634}, + ("Category Five Distinct Dice", 5, 7): {0: 9568, 25: 90432}, + ("Category Five Distinct Dice", 5, 8): {0: 6360, 25: 93640}, + ("Category Five Distinct Dice", 6, 1): {0: 75051, 25: 24949}, + ("Category Five Distinct Dice", 6, 2): {0: 38409, 25: 61591}, + ("Category Five Distinct Dice", 6, 3): {0: 17505, 25: 82495}, + ("Category Five Distinct Dice", 6, 4): {0: 7862, 25: 92138}, + ("Category Five Distinct Dice", 6, 5): {0: 3538, 25: 96462}, + ("Category Five Distinct Dice", 6, 6): {0: 1645, 25: 98355}, + ("Category Five Distinct Dice", 6, 7): {0: 714, 25: 99286}, + ("Category Five Distinct Dice", 6, 8): {0: 341, 25: 99659}, + ("Category Five Distinct Dice", 7, 1): {0: 58588, 25: 41412}, + ("Category Five Distinct Dice", 7, 2): {0: 19487, 25: 80513}, + ("Category Five Distinct Dice", 7, 3): {0: 6043, 25: 93957}, + ("Category Five Distinct Dice", 7, 4): {0: 1799, 25: 98201}, + ("Category Five Distinct Dice", 7, 5): {0: 544, 25: 99456}, + ("Category Five Distinct Dice", 7, 6): {0: 169, 25: 99831}, + ("Category Five Distinct Dice", 7, 7): {0: 59, 25: 99941}, + ("Category Five Distinct Dice", 7, 8): {0: 11, 25: 99989}, + ("Category Five Distinct Dice", 8, 1): {0: 43586, 25: 56414}, + ("Category Five Distinct Dice", 8, 2): {0: 9615, 25: 90385}, + ("Category Five Distinct Dice", 8, 3): {0: 1944, 25: 98056}, + ("Category Five Distinct Dice", 8, 4): {0: 383, 25: 99617}, + ("Category Five Distinct Dice", 8, 5): {0: 77, 25: 99923}, + ("Category Five Distinct Dice", 8, 6): {0: 18, 25: 99982}, + ("Category Five Distinct Dice", 8, 7): {0: 3, 25: 99997}, + ("Category Five Distinct Dice", 8, 8): {0: 2, 25: 99998}, + ("Category 4&5 Full House", 1, 1): {0: 100000}, + ("Category 4&5 Full House", 1, 2): {0: 100000}, + ("Category 4&5 Full House", 1, 3): {0: 100000}, + ("Category 4&5 Full House", 1, 4): {0: 100000}, + ("Category 4&5 Full House", 1, 5): {0: 100000}, + ("Category 4&5 Full House", 1, 6): {0: 100000}, + ("Category 4&5 Full House", 1, 7): {0: 100000}, + ("Category 4&5 Full House", 1, 8): {0: 100000}, + ("Category 4&5 Full House", 2, 1): {0: 100000}, + ("Category 4&5 Full House", 2, 2): {0: 100000}, + ("Category 4&5 Full House", 2, 3): {0: 100000}, + ("Category 4&5 Full House", 2, 4): {0: 100000}, + ("Category 4&5 Full House", 2, 5): {0: 100000}, + ("Category 4&5 Full House", 2, 6): {0: 100000}, + ("Category 4&5 Full House", 2, 7): {0: 100000}, + ("Category 4&5 Full House", 2, 8): {0: 100000}, + ("Category 4&5 Full House", 3, 1): {0: 100000}, + ("Category 4&5 Full House", 3, 2): {0: 100000}, + ("Category 4&5 Full House", 3, 3): {0: 100000}, + ("Category 4&5 Full House", 3, 4): {0: 100000}, + ("Category 4&5 Full House", 3, 5): {0: 100000}, + ("Category 4&5 Full House", 3, 6): {0: 100000}, + ("Category 4&5 Full House", 3, 7): {0: 100000}, + ("Category 4&5 Full House", 3, 8): {0: 100000}, + ("Category 4&5 Full House", 4, 1): {0: 100000}, + ("Category 4&5 Full House", 4, 2): {0: 100000}, + ("Category 4&5 Full House", 4, 3): {0: 100000}, + ("Category 4&5 Full House", 4, 4): {0: 100000}, + ("Category 4&5 Full House", 4, 5): {0: 100000}, + ("Category 4&5 Full House", 4, 6): {0: 100000}, + ("Category 4&5 Full House", 4, 7): {0: 100000}, + ("Category 4&5 Full House", 4, 8): {0: 100000}, + ("Category 4&5 Full House", 5, 1): {0: 99724, 50: 276}, + ("Category 4&5 Full House", 5, 2): {0: 96607, 50: 3393}, + ("Category 4&5 Full House", 5, 3): {0: 88788, 50: 11212}, + ("Category 4&5 Full House", 5, 4): {0: 77799, 50: 22201}, + ("Category 4&5 Full House", 5, 5): {0: 65797, 50: 34203}, + ("Category 4&5 Full House", 5, 6): {0: 54548, 50: 45452}, + ("Category 4&5 Full House", 5, 7): {0: 44898, 50: 55102}, + ("Category 4&5 Full House", 5, 8): {0: 36881, 50: 63119}, + ("Category 4&5 Full House", 6, 1): {0: 98841, 50: 1159}, + ("Category 4&5 Full House", 6, 2): {0: 88680, 50: 11320}, + ("Category 4&5 Full House", 6, 3): {0: 70215, 50: 29785}, + ("Category 4&5 Full House", 6, 4): {0: 50801, 50: 49199}, + ("Category 4&5 Full House", 6, 5): {0: 35756, 50: 64244}, + ("Category 4&5 Full House", 6, 6): {0: 24698, 50: 75302}, + ("Category 4&5 Full House", 6, 7): {0: 17145, 50: 82855}, + ("Category 4&5 Full House", 6, 8): {0: 11846, 50: 88154}, + ("Category 4&5 Full House", 7, 1): {0: 97090, 50: 2910}, + ("Category 4&5 Full House", 7, 2): {0: 77440, 50: 22560}, + ("Category 4&5 Full House", 7, 3): {0: 51372, 50: 48628}, + ("Category 4&5 Full House", 7, 4): {0: 30566, 50: 69434}, + ("Category 4&5 Full House", 7, 5): {0: 17866, 50: 82134}, + ("Category 4&5 Full House", 7, 6): {0: 10521, 50: 89479}, + ("Category 4&5 Full House", 7, 7): {0: 6204, 50: 93796}, + ("Category 4&5 Full House", 7, 8): {0: 3670, 50: 96330}, + ("Category 4&5 Full House", 8, 1): {0: 94172, 50: 5828}, + ("Category 4&5 Full House", 8, 2): {0: 64693, 50: 35307}, + ("Category 4&5 Full House", 8, 3): {0: 35293, 50: 64707}, + ("Category 4&5 Full House", 8, 4): {0: 17749, 50: 82251}, + ("Category 4&5 Full House", 8, 5): {0: 8740, 50: 91260}, + ("Category 4&5 Full House", 8, 6): {0: 4550, 50: 95450}, + ("Category 4&5 Full House", 8, 7): {0: 2218, 50: 97782}, + ("Category 4&5 Full House", 8, 8): {0: 1084, 50: 98916}, +} diff --git a/worlds/yachtdice/__init__.py b/worlds/yachtdice/__init__.py new file mode 100644 index 000000000000..c36c59544f15 --- /dev/null +++ b/worlds/yachtdice/__init__.py @@ -0,0 +1,533 @@ +import math +from typing import Dict + +from BaseClasses import CollectionState, Entrance, Item, Region, Tutorial + +from worlds.AutoWorld import WebWorld, World + +from .Items import YachtDiceItem, item_groups, item_table +from .Locations import YachtDiceLocation, all_locations, ini_locations +from .Options import ( + AddExtraPoints, + AddStoryChapters, + GameDifficulty, + MinimalNumberOfDiceAndRolls, + MinimizeExtraItems, + PointsSize, + YachtDiceOptions, + yd_option_groups, +) +from .Rules import dice_simulation_fill_pool, set_yacht_completion_rules, set_yacht_rules + + +class YachtDiceWeb(WebWorld): + tutorials = [ + Tutorial( + "Multiworld Setup Guide", + "A guide to setting up Yacht Dice. This guide covers single-player, multiworld, and website.", + "English", + "setup_en.md", + "setup/en", + ["Spineraks"], + ) + ] + + option_groups = yd_option_groups + + +class YachtDiceWorld(World): + """ + Yacht Dice is a straightforward game, custom-made for Archipelago, + where you cast your dice to chart a course for high scores, + unlocking valuable treasures along the way. + Discover more dice, extra rolls, multipliers, + and unlockable categories to navigate the depths of the game. + Roll your way to victory by reaching the target score! + """ + + game: str = "Yacht Dice" + options_dataclass = YachtDiceOptions + + web = YachtDiceWeb() + + item_name_to_id = {name: data.code for name, data in item_table.items()} + + location_name_to_id = {name: data.id for name, data in all_locations.items()} + + item_name_groups = item_groups + + ap_world_version = "2.1.1" + + def _get_yachtdice_data(self): + return { + # "world_seed": self.multiworld.per_slot_randoms[self.player].getrandbits(32), + "seed_name": self.multiworld.seed_name, + "player_name": self.multiworld.get_player_name(self.player), + "player_id": self.player, + "race": self.multiworld.is_race, + } + + def generate_early(self): + """ + In generate early, we fill the item-pool, then determine the number of locations, and add filler items. + """ + self.itempool = [] + self.precollected = [] + + # number of dice and rolls in the pull + opt_dice_and_rolls = self.options.minimal_number_of_dice_and_rolls + + if opt_dice_and_rolls == MinimalNumberOfDiceAndRolls.option_5_dice_and_3_rolls: + num_of_dice = 5 + num_of_rolls = 3 + elif opt_dice_and_rolls == MinimalNumberOfDiceAndRolls.option_5_dice_and_5_rolls: + num_of_dice = 5 + num_of_rolls = 5 + elif opt_dice_and_rolls == MinimalNumberOfDiceAndRolls.option_6_dice_and_4_rolls: + num_of_dice = 6 + num_of_rolls = 4 + elif opt_dice_and_rolls == MinimalNumberOfDiceAndRolls.option_7_dice_and_3_rolls: + num_of_dice = 7 + num_of_rolls = 3 + elif opt_dice_and_rolls == MinimalNumberOfDiceAndRolls.option_8_dice_and_2_rolls: + num_of_dice = 8 + num_of_rolls = 2 + else: + raise Exception(f"[Yacht Dice] Unknown MinimalNumberOfDiceAndRolls options {opt_dice_and_rolls}") + + # amount of dice and roll fragments needed to get a dice or roll + self.frags_per_dice = self.options.number_of_dice_fragments_per_dice.value + self.frags_per_roll = self.options.number_of_roll_fragments_per_roll.value + + if self.options.minimize_extra_items == MinimizeExtraItems.option_yes_please: + self.frags_per_dice = min(self.frags_per_dice, 2) + self.frags_per_roll = min(self.frags_per_roll, 2) + + # set difficulty + diff_value = self.options.game_difficulty + if diff_value == GameDifficulty.option_easy: + self.difficulty = 1 + elif diff_value == GameDifficulty.option_medium: + self.difficulty = 2 + elif diff_value == GameDifficulty.option_hard: + self.difficulty = 3 + elif diff_value == GameDifficulty.option_extreme: + self.difficulty = 4 + else: + raise Exception(f"[Yacht Dice] Unknown GameDifficulty options {diff_value}") + + # Create a list with the specified number of 1s + num_ones = self.options.alternative_categories.value + categorylist = [1] * num_ones + [0] * (16 - num_ones) + + # Shuffle the list to randomize the order + self.random.shuffle(categorylist) + + # A list of all possible categories. + # Every entry in the list has two categories, one 'default' category and one 'alt'. + # You get either of the two for every entry, so a total of 16 unique categories. + all_categories = [ + ["Category Choice", "Category Double Threes and Fours"], + ["Category Inverse Choice", "Category Quadruple Ones and Twos"], + ["Category Ones", "Category Distincts"], + ["Category Twos", "Category Two times Ones"], + ["Category Threes", "Category Half of Sixes"], + ["Category Fours", "Category Twos and Threes"], + ["Category Fives", "Category Sum of Odds"], + ["Category Sixes", "Category Sum of Evens"], + ["Category Pair", "Category Micro Straight"], + ["Category Three of a Kind", "Category Three Odds"], + ["Category Four of a Kind", "Category 1-2-1 Consecutive"], + ["Category Tiny Straight", "Category Three Distinct Dice"], + ["Category Small Straight", "Category Two Pair"], + ["Category Large Straight", "Category 2-1-2 Consecutive"], + ["Category Full House", "Category Five Distinct Dice"], + ["Category Yacht", "Category 4&5 Full House"], + ] + + # categories used in this game. + self.possible_categories = [] + + for index, cats in enumerate(all_categories): + self.possible_categories.append(cats[categorylist[index]]) + + # Add Choice and Inverse choice (or their alts) to the precollected list. + if index == 0 or index == 1: + self.precollected.append(cats[categorylist[index]]) + else: + self.itempool.append(cats[categorylist[index]]) + + # Also start with one Roll and one Dice + self.precollected.append("Dice") + num_of_dice_to_add = num_of_dice - 1 + self.precollected.append("Roll") + num_of_rolls_to_add = num_of_rolls - 1 + + self.skip_early_locations = False + if self.options.minimize_extra_items == MinimizeExtraItems.option_yes_please: + self.precollected.append("Dice") + num_of_dice_to_add -= 1 + self.precollected.append("Roll") + num_of_rolls_to_add -= 1 + self.skip_early_locations = True + + if num_of_dice_to_add > 0: + self.itempool.append("Dice") + num_of_dice_to_add -= 1 + if num_of_rolls_to_add > 0: + self.itempool.append("Roll") + num_of_rolls_to_add -= 1 + + # if one fragment per dice, just add "Dice" objects + if num_of_dice_to_add > 0: + if self.frags_per_dice == 1: + self.itempool += ["Dice"] * num_of_dice_to_add # minus one because one is in start inventory + else: + self.itempool += ["Dice Fragment"] * (self.frags_per_dice * num_of_dice_to_add) + + # if one fragment per roll, just add "Roll" objects + if num_of_rolls_to_add > 0: + if self.frags_per_roll == 1: + self.itempool += ["Roll"] * num_of_rolls_to_add # minus one because one is in start inventory + else: + self.itempool.append("Roll") # always add a full roll to make generation easier (will be early) + self.itempool += ["Roll Fragment"] * (self.frags_per_roll * num_of_rolls_to_add) + + already_items = len(self.itempool) + + # Yacht Dice needs extra filler items so it doesn't get stuck in generation. + # For now, we calculate the number of extra items we'll need later. + if self.options.minimize_extra_items == MinimizeExtraItems.option_yes_please: + extra_percentage = max(0.1, 0.8 - self.multiworld.players / 10) + elif self.options.minimize_extra_items == MinimizeExtraItems.option_no_dont: + extra_percentage = 0.72 + else: + raise Exception(f"[Yacht Dice] Unknown MinimizeExtraItems options {self.options.minimize_extra_items}") + extra_locations_needed = max(10, math.ceil(already_items * extra_percentage)) + + # max score is the value of the last check. Goal score is the score needed to 'finish' the game + self.max_score = self.options.score_for_last_check.value + self.goal_score = min(self.max_score, self.options.score_for_goal.value) + + # Yacht Dice adds items into the pool until a score of at least 1000 is reached. + # the yaml contains weights, which determine how likely it is that specific items get added. + # If all weights are 0, some of them will be made to be non-zero later. + weights: Dict[str, float] = { + "Dice": self.options.weight_of_dice.value, + "Roll": self.options.weight_of_roll.value, + "Fixed Score Multiplier": self.options.weight_of_fixed_score_multiplier.value, + "Step Score Multiplier": self.options.weight_of_step_score_multiplier.value, + "Double category": self.options.weight_of_double_category.value, + "Points": self.options.weight_of_points.value, + } + + # if the player wants extra rolls or dice, fill the pool with fragments until close to an extra roll/dice + if weights["Dice"] > 0 and self.frags_per_dice > 1: + self.itempool += ["Dice Fragment"] * (self.frags_per_dice - 1) + if weights["Roll"] > 0 and self.frags_per_roll > 1: + self.itempool += ["Roll Fragment"] * (self.frags_per_roll - 1) + + # calibrate the weights, since the impact of each of the items is different + weights["Dice"] = weights["Dice"] / 5 * self.frags_per_dice + weights["Roll"] = weights["Roll"] / 5 * self.frags_per_roll + + extra_points_added = 0 + multipliers_added = 0 + items_added = 0 + + def get_item_to_add(weights, extra_points_added, multipliers_added, items_added): + items_added += 1 + + all_items = self.itempool + self.precollected + dice_fragments_in_pool = all_items.count("Dice") * self.frags_per_dice + all_items.count("Dice Fragment") + if dice_fragments_in_pool + 1 >= 9 * self.frags_per_dice: + weights["Dice"] = 0 # don't allow >=9 dice + roll_fragments_in_pool = all_items.count("Roll") * self.frags_per_roll + all_items.count("Roll Fragment") + if roll_fragments_in_pool + 1 >= 6 * self.frags_per_roll: + weights["Roll"] = 0 # don't allow >= 6 rolls + + # Don't allow too many multipliers + if multipliers_added > 50: + weights["Fixed Score Multiplier"] = 0 + weights["Step Score Multiplier"] = 0 + + # Don't allow too many extra points + if extra_points_added > 300: + weights["Points"] = 0 + + # if all weights are zero, allow to add fixed score multiplier, double category, points. + if sum(weights.values()) == 0: + if multipliers_added <= 50: + weights["Fixed Score Multiplier"] = 1 + weights["Double category"] = 1 + if extra_points_added <= 300: + weights["Points"] = 1 + + # Next, add the appropriate item. We'll slightly alter weights to avoid too many of the same item + which_item_to_add = self.random.choices(list(weights.keys()), weights=list(weights.values()))[0] + + if which_item_to_add == "Dice": + weights["Dice"] /= 1 + self.frags_per_dice + return "Dice" if self.frags_per_dice == 1 else "Dice Fragment" + elif which_item_to_add == "Roll": + weights["Roll"] /= 1 + self.frags_per_roll + return "Roll" if self.frags_per_roll == 1 else "Roll Fragment" + elif which_item_to_add == "Fixed Score Multiplier": + weights["Fixed Score Multiplier"] /= 1.05 + multipliers_added += 1 + return "Fixed Score Multiplier" + elif which_item_to_add == "Step Score Multiplier": + weights["Step Score Multiplier"] /= 1.1 + multipliers_added += 1 + return "Step Score Multiplier" + elif which_item_to_add == "Double category": + # Below entries are the weights to add each category. + # Prefer to add choice or number categories, because the other categories are too "all or nothing", + # which often don't give any points, until you get overpowered, and then they give all points. + cat_weights = [2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1] + weights["Double category"] /= 1.1 + return self.random.choices(self.possible_categories, weights=cat_weights)[0] + elif which_item_to_add == "Points": + score_dist = self.options.points_size + probs = {"1 Point": 1, "10 Points": 0, "100 Points": 0} + if score_dist == PointsSize.option_small: + probs = {"1 Point": 0.9, "10 Points": 0.1, "100 Points": 0} + elif score_dist == PointsSize.option_medium: + probs = {"1 Point": 0, "10 Points": 1, "100 Points": 0} + elif score_dist == PointsSize.option_large: + probs = {"1 Point": 0, "10 Points": 0.3, "100 Points": 0.7} + elif score_dist == PointsSize.option_mix: + probs = {"1 Point": 0.3, "10 Points": 0.4, "100 Points": 0.3} + else: + raise Exception(f"[Yacht Dice] Unknown PointsSize options {score_dist}") + choice = self.random.choices(list(probs.keys()), weights=list(probs.values()))[0] + if choice == "1 Point": + weights["Points"] /= 1.01 + extra_points_added += 1 + return "1 Point" + elif choice == "10 Points": + weights["Points"] /= 1.1 + extra_points_added += 10 + return "10 Points" + elif choice == "100 Points": + weights["Points"] /= 2 + extra_points_added += 100 + return "100 Points" + else: + raise Exception("Unknown point value (Yacht Dice)") + else: + raise Exception(f"Invalid index when adding new items in Yacht Dice: {which_item_to_add}") + + # adding 17 items as a start seems like the smartest way to get close to 1000 points + for _ in range(17): + self.itempool.append(get_item_to_add(weights, extra_points_added, multipliers_added, items_added)) + + score_in_logic = dice_simulation_fill_pool( + self.itempool + self.precollected, + self.frags_per_dice, + self.frags_per_roll, + self.possible_categories, + self.difficulty, + self.player, + ) + + # if we overshoot, remove items until you get below 1000, then return the last removed item + if score_in_logic > 1000: + removed_item = "" + while score_in_logic > 1000: + removed_item = self.itempool.pop() + score_in_logic = dice_simulation_fill_pool( + self.itempool + self.precollected, + self.frags_per_dice, + self.frags_per_roll, + self.possible_categories, + self.difficulty, + self.player, + ) + self.itempool.append(removed_item) + else: + # Keep adding items until a score of 1000 is in logic + while score_in_logic < 1000: + item_to_add = get_item_to_add(weights, extra_points_added, multipliers_added, items_added) + self.itempool.append(item_to_add) + if item_to_add == "1 Point": + score_in_logic += 1 + elif item_to_add == "10 Points": + score_in_logic += 10 + elif item_to_add == "100 Points": + score_in_logic += 100 + else: + score_in_logic = dice_simulation_fill_pool( + self.itempool + self.precollected, + self.frags_per_dice, + self.frags_per_roll, + self.possible_categories, + self.difficulty, + self.player, + ) + + # count the number of locations in the game. + already_items = len(self.itempool) + 1 # +1 because of Victory item + + # We need to add more filler/useful items if there are many items in the pool to guarantee successful generation + extra_locations_needed += (already_items - 45) // 15 + self.number_of_locations = already_items + extra_locations_needed + + # From here, we will count the number of items in the self.itempool, and add useful/filler items to the pool, + # making sure not to exceed the number of locations. + + # first, we flood the entire pool with extra points (useful), if that setting is chosen. + if self.options.add_bonus_points == AddExtraPoints.option_all_of_it: # all of the extra points + already_items = len(self.itempool) + 1 + self.itempool += ["Bonus Point"] * min(self.number_of_locations - already_items, 100) + + # second, we flood the entire pool with story chapters (filler), if that setting is chosen. + if self.options.add_story_chapters == AddStoryChapters.option_all_of_it: # all of the story chapters + already_items = len(self.itempool) + 1 + number_of_items = min(self.number_of_locations - already_items, 100) + number_of_items = (number_of_items // 10) * 10 # story chapters always come in multiples of 10 + self.itempool += ["Story Chapter"] * number_of_items + + # add some extra points (useful) + if self.options.add_bonus_points == AddExtraPoints.option_sure: # add extra points if wanted + already_items = len(self.itempool) + 1 + self.itempool += ["Bonus Point"] * min(self.number_of_locations - already_items, 10) + + # add some story chapters (filler) + if self.options.add_story_chapters == AddStoryChapters.option_sure: # add extra points if wanted + already_items = len(self.itempool) + 1 + if self.number_of_locations - already_items >= 10: + self.itempool += ["Story Chapter"] * 10 + + # add some more extra points if there is still room + if self.options.add_bonus_points == AddExtraPoints.option_sure: + already_items = len(self.itempool) + 1 + self.itempool += ["Bonus Point"] * min(self.number_of_locations - already_items, 10) + + # add some encouragements filler-items if there is still room + already_items = len(self.itempool) + 1 + self.itempool += ["Encouragement"] * min(self.number_of_locations - already_items, 5) + + # add some fun facts filler-items if there is still room + already_items = len(self.itempool) + 1 + self.itempool += ["Fun Fact"] * min(self.number_of_locations - already_items, 5) + + # finally, add some "Good RNG" and "Bad RNG" items to complete the item pool + # these items are filler and do not do anything. + + # probability of Good and Bad rng, based on difficulty for fun :) + + p = 1.1 - 0.25 * self.difficulty + already_items = len(self.itempool) + 1 + self.itempool += self.random.choices( + ["Good RNG", "Bad RNG"], weights=[p, 1 - p], k=self.number_of_locations - already_items + ) + + # we are done adding items. Now because of the last step, number of items should be number of locations + already_items = len(self.itempool) + 1 + if already_items != self.number_of_locations: + raise Exception( + f"[Yacht Dice] Number in self.itempool is not number of locations " + f"{already_items} {self.number_of_locations}." + ) + + # add precollected items using push_precollected. Items in self.itempool get created in create_items + for item in self.precollected: + self.multiworld.push_precollected(self.create_item(item)) + + # make sure one dice and one roll is early, so that you will have 2 dice and 2 rolls soon + self.multiworld.early_items[self.player]["Dice"] = 1 + self.multiworld.early_items[self.player]["Roll"] = 1 + + def create_items(self): + self.multiworld.itempool += [self.create_item(name) for name in self.itempool] + + def create_regions(self): + # call the ini_locations function, that generates locations based on the inputs. + location_table = ini_locations( + self.goal_score, + self.max_score, + self.number_of_locations, + self.difficulty, + self.skip_early_locations, + self.multiworld.players, + ) + + # simple menu-board construction + menu = Region("Menu", self.player, self.multiworld) + board = Region("Board", self.player, self.multiworld) + + # add locations to board, one for every location in the location_table + board.locations = [ + YachtDiceLocation(self.player, loc_name, loc_data.score, loc_data.id, board) + for loc_name, loc_data in location_table.items() + if loc_data.region == board.name + ] + + # Add the victory item to the correct location. + # The website declares that the game is complete when the victory item is obtained. + victory_location_name = f"{self.goal_score} score" + self.get_location(victory_location_name).place_locked_item(self.create_item("Victory")) + + # add the regions + connection = Entrance(self.player, "New Board", menu) + menu.exits.append(connection) + connection.connect(board) + self.multiworld.regions += [menu, board] + + def set_rules(self): + """ + set rules per location, and add the rule for beating the game + """ + set_yacht_rules( + self.multiworld, + self.player, + self.frags_per_dice, + self.frags_per_roll, + self.possible_categories, + self.difficulty, + ) + set_yacht_completion_rules(self.multiworld, self.player) + + def fill_slot_data(self): + """ + make slot data, which consists of yachtdice_data, options, and some other variables. + """ + yacht_dice_data = self._get_yachtdice_data() + yacht_dice_options = self.options.as_dict( + "game_difficulty", + "score_for_last_check", + "score_for_goal", + "number_of_dice_fragments_per_dice", + "number_of_roll_fragments_per_roll", + "which_story", + "allow_manual_input", + ) + slot_data = {**yacht_dice_data, **yacht_dice_options} # combine the two + slot_data["number_of_dice_fragments_per_dice"] = self.frags_per_dice + slot_data["number_of_roll_fragments_per_roll"] = self.frags_per_roll + slot_data["goal_score"] = self.goal_score + slot_data["last_check_score"] = self.max_score + slot_data["allowed_categories"] = self.possible_categories + slot_data["ap_world_version"] = self.ap_world_version + return slot_data + + def create_item(self, name: str) -> Item: + item_data = item_table[name] + item = YachtDiceItem(name, item_data.classification, item_data.code, self.player) + return item + + # We overwrite these function to monitor when states have changed. See also dice_simulation in Rules.py + def collect(self, state: CollectionState, item: Item) -> bool: + change = super().collect(state, item) + if change: + state.prog_items[self.player]["state_is_fresh"] = 0 + + return change + + def remove(self, state: CollectionState, item: Item) -> bool: + change = super().remove(state, item) + if change: + state.prog_items[self.player]["state_is_fresh"] = 0 + + return change diff --git a/worlds/yachtdice/docs/en_Yacht Dice.md b/worlds/yachtdice/docs/en_Yacht Dice.md new file mode 100644 index 000000000000..53eefe9e9c4b --- /dev/null +++ b/worlds/yachtdice/docs/en_Yacht Dice.md @@ -0,0 +1,15 @@ +# Yacht Dice + +Welcome to Yacht Dice, the ultimate dice-rolling adventure in Archipelago! Cast your dice, chase high scores, and unlock valuable treasures. Discover new dice, extra rolls, multipliers, and special scoring categories to enhance your game. Roll your way to victory by reaching the target score! + +## Understanding Location Checks +In Yacht Dice, location checks happen when you hit certain scores for the first time. The target score for your next location check is always displayed on the website. + +## Items and Their Effects +When you receive an item, it could be extra dice, extra rolls, score multipliers, or new scoring categories. These boosts help you sail towards higher scores and more loot. Other items include extra points, lore, and fun facts to enrich your journey. + +## Winning the Game +Victory in Yacht Dice is all about reaching the target score. You can set your own target score, which is displayed on the website. Once you hit it, you've conquered the game! + +## How to Access Options +Need to tweak your game? Head over to the [player options page](../player-options) for all your configuration options and to export your config file. diff --git a/worlds/yachtdice/docs/setup_en.md b/worlds/yachtdice/docs/setup_en.md new file mode 100644 index 000000000000..c76cd398ce55 --- /dev/null +++ b/worlds/yachtdice/docs/setup_en.md @@ -0,0 +1,21 @@ +# Yacht Dice Randomizer Setup Guide + +## Required Software + +- A browser (you are probably using one right now!). +- Archipelago from the [Archipelago Releases Page](https://github.com/ArchipelagoMW/Archipelago/releases). + +## Playing the game +Open the Yacht Dice website. There are two options: +- Download the latest release from [Yacht Dice Release](https://github.com/spinerak/ArchipelagoYachtDice/releases/latest) and unzip the Website.zip. Then open player.html in your browser. +- Cruise over to the [Yacht Dice website](https://yacht-dice-ap.netlify.app/). This also works on mobile. If the website is not available, use the first option. + +Both options have an "offline" play option to try out the game without having to generate a game first. + +## Play with Archipelago + +- Create your yaml file via the [Yacht Dice Player Options Page](../player-options). +- After generating, open the Yacht Dice website. After the tutoroll, fill in the room information. +- After logging in, you are good to go. The website has a built-in client, where you can chat and send commands. + +For more information on yaml files, generating Archipelago games, and connecting to servers, please see the [Basic Multiworld Setup Guide](/tutorial/Archipelago/setup/en).