From 774457b362d4497b3dba07231db7e3b39c147f0c Mon Sep 17 00:00:00 2001 From: Alchav <59858495+Alchav@users.noreply.github.com> Date: Sat, 26 Jul 2025 16:25:06 -0400 Subject: [PATCH] LTTP: Add Missing Crystal Switch Logic (#4638) --- worlds/alttp/Rules.py | 17 +++++++++++------ worlds/alttp/test/dungeons/TestMiseryMire.py | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/worlds/alttp/Rules.py b/worlds/alttp/Rules.py index 2d11d537..b79170da 100644 --- a/worlds/alttp/Rules.py +++ b/worlds/alttp/Rules.py @@ -463,12 +463,15 @@ def global_rules(multiworld: MultiWorld, player: int): set_rule(multiworld.get_location('Misery Mire - Big Chest', player), lambda state: state.has('Big Key (Misery Mire)', player)) set_rule(multiworld.get_location('Misery Mire - Spike Chest', player), lambda state: (world.can_take_damage and has_hearts(state, player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player)) set_rule(multiworld.get_entrance('Misery Mire Big Key Door', player), lambda state: state.has('Big Key (Misery Mire)', player)) - # How to access crystal switch: - # If have big key: then you will need 2 small keys to be able to hit switch and return to main area, as you can burn key in dark room - # If not big key: cannot burn key in dark room, hence need only 1 key. all doors immediately available lead to a crystal switch. - # The listed chests are those which can be reached if you can reach a crystal switch. - set_rule(multiworld.get_location('Misery Mire - Map Chest', player), lambda state: state._lttp_has_key('Small Key (Misery Mire)', player, 2)) - set_rule(multiworld.get_location('Misery Mire - Main Lobby', player), lambda state: state._lttp_has_key('Small Key (Misery Mire)', player, 2)) + + # The most number of keys you can burn without opening the map chest and without reaching a crystal switch is 1, + # but if you cannot activate a crystal switch except by throwing a pot, you could burn another two going through + # the conveyor crystal room. + set_rule(multiworld.get_location('Misery Mire - Map Chest', player), lambda state: (state._lttp_has_key('Small Key (Misery Mire)', player, 2) and can_activate_crystal_switch(state, player)) or state._lttp_has_key('Small Key (Misery Mire)', player, 4)) + # Using a key on the map door chest will get you the map chest but not a crystal switch. Main Lobby should require + # one more key. + set_rule(multiworld.get_location('Misery Mire - Main Lobby', player), lambda state: (state._lttp_has_key('Small Key (Misery Mire)', player, 3) and can_activate_crystal_switch(state, player)) or state._lttp_has_key('Small Key (Misery Mire)', player, 5)) + # we can place a small key in the West wing iff it also contains/blocks the Big Key, as we cannot reach and softlock with the basement key door yet set_rule(multiworld.get_location('Misery Mire - Conveyor Crystal Key Drop', player), lambda state: state._lttp_has_key('Small Key (Misery Mire)', player, 4) @@ -542,6 +545,8 @@ def global_rules(multiworld: MultiWorld, player: int): set_rule(multiworld.get_location('Ganons Tower - Bob\'s Torch', player), lambda state: state.has('Pegasus Boots', player)) set_rule(multiworld.get_entrance('Ganons Tower (Tile Room)', player), lambda state: state.has('Cane of Somaria', player)) set_rule(multiworld.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hammer', player) and (state.has('Hookshot', player) or state.has('Pegasus Boots', player))) + set_rule(multiworld.get_location('Ganons Tower - Double Switch Pot Key', player), lambda state: state.has('Cane of Somaria', player) or can_use_bombs(state, player)) + set_rule(multiworld.get_entrance('Ganons Tower (Double Switch Room)', player), lambda state: state.has('Cane of Somaria', player) or can_use_bombs(state, player)) if world.options.pot_shuffle: set_rule(multiworld.get_location('Ganons Tower - Conveyor Cross Pot Key', player), lambda state: state.has('Hammer', player) and (state.has('Hookshot', player) or state.has('Pegasus Boots', player))) set_rule(multiworld.get_entrance('Ganons Tower (Map Room)', player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 8) or ( diff --git a/worlds/alttp/test/dungeons/TestMiseryMire.py b/worlds/alttp/test/dungeons/TestMiseryMire.py index 90b7055b..b44d7d1b 100644 --- a/worlds/alttp/test/dungeons/TestMiseryMire.py +++ b/worlds/alttp/test/dungeons/TestMiseryMire.py @@ -32,8 +32,8 @@ class TestMiseryMire(TestDungeon): ["Misery Mire - Main Lobby", False, []], ["Misery Mire - Main Lobby", False, [], ['Pegasus Boots', 'Hookshot']], ["Misery Mire - Main Lobby", False, [], ['Small Key (Misery Mire)', 'Big Key (Misery Mire)']], - ["Misery Mire - Main Lobby", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Hookshot', 'Progressive Sword']], - ["Misery Mire - Main Lobby", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Pegasus Boots', 'Progressive Sword']], + ["Misery Mire - Main Lobby", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Hookshot', 'Progressive Sword']], + ["Misery Mire - Main Lobby", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Pegasus Boots', 'Progressive Sword']], ["Misery Mire - Big Key Chest", False, []], ["Misery Mire - Big Key Chest", False, [], ['Fire Rod', 'Lamp']],