From 6bd05982ae040f1d23a94ca880e1c18bd045a512 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 12 Feb 2020 14:19:29 -0700 Subject: [PATCH] Bunny impassible rules for doorways --- DoorShuffle.py | 12 ++++ Doors.py | 14 ++++- Dungeons.py | 45 +++++++------- Main.py | 2 +- Regions.py | 17 ++++-- Rules.py | 155 +++++++++++++++++++++++++++++++++++++------------ 6 files changed, 180 insertions(+), 65 deletions(-) diff --git a/DoorShuffle.py b/DoorShuffle.py index d9e7016d..d092a6c8 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -1450,7 +1450,13 @@ logical_connections = [ ('Eastern Hint Tile Push Block', 'Eastern Hint Tile'), ('Eastern Map Balcony Hook Path', 'Eastern Map Room'), ('Eastern Map Room Drop Down', 'Eastern Map Balcony'), + ('Desert Main Lobby Left Path', 'Desert Left Alcove'), + ('Desert Main Lobby Right Path', 'Desert Right Alcove'), + ('Desert Left Alcove Path', 'Desert Main Lobby'), + ('Desert Right Alcove Path', 'Desert Main Lobby'), ('Hera Big Chest Landing Exit', 'Hera 4F'), + ('PoD Pit Room Block Path N', 'PoD Pit Room Blocked'), + ('PoD Pit Room Block Path S', 'PoD Pit Room'), ('PoD Arena Bonk Path', 'PoD Arena Bridge'), ('PoD Arena Main Crystal Path', 'PoD Arena Crystal'), ('PoD Arena Crystal Path', 'PoD Arena Main'), @@ -1459,6 +1465,8 @@ logical_connections = [ ('PoD Arena Bridge Drop Down', 'PoD Arena Main'), ('PoD Map Balcony Drop Down', 'PoD Sexy Statue'), ('PoD Basement Ledge Drop Down', 'PoD Stalfos Basement'), + ('PoD Falling Bridge Path N', 'PoD Falling Bridge Ledge'), + ('PoD Falling Bridge Path S', 'PoD Falling Bridge'), ('Swamp Lobby Moat', 'Swamp Entrance'), ('Swamp Entrance Moat', 'Swamp Lobby'), ('Swamp Trench 1 Approach Dry', 'Swamp Trench 1 Nexus'), @@ -1527,6 +1535,8 @@ logical_connections = [ ('Mire Map Spot Blue Barrier', 'Mire Crystal Dead End'), ('Mire Crystal Dead End Left Barrier', 'Mire Map Spot'), ('Mire Crystal Dead End Right Barrier', 'Mire Map Spike Side'), + ('Mire Hidden Shooters Block Path S', 'Mire Hidden Shooters'), + ('Mire Hidden Shooters Block Path N', 'Mire Hidden Shooters Blocked'), ('Mire Left Bridge Hook Path', 'Mire Right Bridge'), ('Mire Crystal Right Orange Barrier', 'Mire Crystal Mid'), ('Mire Crystal Mid Orange Barrier', 'Mire Crystal Right'), @@ -1547,6 +1557,8 @@ logical_connections = [ ('TR Crystal Maze Blue Path', 'TR Crystal Maze'), ('TR Crystal Maze Cane Path', 'TR Crystal Maze'), ('GT Blocked Stairs Block Path', 'GT Big Chest'), + ('GT Speed Torch South Path', 'GT Speed Torch'), + ('GT Speed Torch North Path', 'GT Speed Torch Upper'), ('GT Hookshot East-North Path', 'GT Hookshot North Platform'), ('GT Hookshot East-South Path', 'GT Hookshot South Platform'), ('GT Hookshot North-East Path', 'GT Hookshot East Platform'), diff --git a/Doors.py b/Doors.py index a4c33b52..82a87b38 100644 --- a/Doors.py +++ b/Doors.py @@ -182,6 +182,10 @@ def create_doors(world, player): create_door(player, 'Desert Main Lobby N Edge', Open).dir(No, 0x84, None, High), create_door(player, 'Desert Main Lobby NE Edge', Open).dir(No, 0x84, None, High), create_door(player, 'Desert Main Lobby E Edge', Open).dir(Ea, 0x84, None, High), + create_door(player, 'Desert Main Lobby Left Path', Lgcl), + create_door(player, 'Desert Main Lobby Right Path', Lgcl), + create_door(player, 'Desert Left Alcove Path', Lgcl), + create_door(player, 'Desert Right Alcove Path', Lgcl), create_door(player, 'Desert Dead End Edge', Open).dir(So, 0x74, None, High), create_door(player, 'Desert East Wing W Edge', Open).dir(We, 0x85, None, High), create_door(player, 'Desert East Wing N Edge', Open).dir(No, 0x85, None, High), @@ -321,6 +325,8 @@ def create_doors(world, player): create_door(player, 'PoD Pit Room NE', Nrml).dir(No, 0x3a, Right, High).pos(2), create_door(player, 'PoD Pit Room Freefall', Hole), create_door(player, 'PoD Pit Room Bomb Hole', Hole), + create_door(player, 'PoD Pit Room Block Path N', Lgcl), + create_door(player, 'PoD Pit Room Block Path S', Lgcl), create_door(player, 'PoD Big Key Landing Hole', Hole), create_door(player, 'PoD Big Key Landing Down Stairs', Sprl).dir(Dn, 0x3a, 0, HTH).ss(A, 0x11, 0x00).kill(), create_door(player, 'PoD Basement Ledge Up Stairs', Sprl).dir(Up, 0x0a, 0, HTH).ss(A, 0x1a, 0xec).small_key().pos(0), @@ -354,6 +360,8 @@ def create_doors(world, player): create_door(player, 'PoD Falling Bridge SW', Nrml).dir(So, 0x1a, Left, High).small_key().pos(3), create_door(player, 'PoD Falling Bridge WN', Nrml).dir(We, 0x1a, Top, High).small_key().pos(1), create_door(player, 'PoD Falling Bridge EN', Intr).dir(Ea, 0x1a, Top, High).pos(4), + create_door(player, 'PoD Falling Bridge Path N', Lgcl), + create_door(player, 'PoD Falling Bridge Path S', Lgcl), create_door(player, 'PoD Big Chest Balcony W', Nrml).dir(We, 0x1a, Mid, High).pos(2), create_door(player, 'PoD Dark Maze EN', Nrml).dir(Ea, 0x19, Top, High).small_key().pos(1), create_door(player, 'PoD Dark Maze E', Nrml).dir(Ea, 0x19, Mid, High).pos(0), @@ -658,7 +666,7 @@ def create_doors(world, player): create_door(player, 'Ice Freezors Bomb Hole', Hole), # combine these two? -- they have to lead to the same spot create_door(player, 'Ice Freezors Ledge Hole', Hole), create_door(player, 'Ice Freezors Ledge ES', Intr).dir(Ea, 0x7e, Bot, High).pos(2), - create_door(player, 'Ice Tall Hint WS', Intr).dir(We, 0x7e, Bot, High).pos(1), + create_door(player, 'Ice Tall Hint WS', Intr).dir(We, 0x7e, Bot, High).pos(2), create_door(player, 'Ice Tall Hint EN', Nrml).dir(Ea, 0x7e, Top, High).pos(1), create_door(player, 'Ice Tall Hint SE', Nrml).dir(So, 0x7e, Right, High).small_key().pos(0), create_door(player, 'Ice Hookshot Ledge WN', Nrml).dir(We, 0x7f, Top, High).no_exit().trap(0x4).pos(0).kill(), @@ -735,6 +743,8 @@ def create_doors(world, player): create_door(player, 'Mire Hidden Shooters ES', Nrml).dir(Ea, 0xb2, Bot, High).pos(7), create_door(player, 'Mire Hidden Shooters WS', Intr).dir(We, 0xb2, Bot, High).pos(1), create_door(player, 'Mire Cross ES', Intr).dir(Ea, 0xb2, Bot, High).pos(1), + create_door(player, 'Mire Hidden Shooters Block Path S', Lgcl), + create_door(player, 'Mire Hidden Shooters Block Path N', Lgcl), create_door(player, 'Mire Hidden Shooters NE', Intr).dir(No, 0xb2, Right, High).pos(2), create_door(player, 'Mire Minibridge SE', Intr).dir(So, 0xb2, Right, High).pos(2), create_door(player, 'Mire Cross SW', Nrml).dir(So, 0xb2, Left, High).pos(5), @@ -912,6 +922,8 @@ def create_doors(world, player): create_door(player, 'GT Tile Room EN', Intr).dir(Ea, 0x8d, Top, High).small_key().pos(1), create_door(player, 'GT Speed Torch WN', Intr).dir(We, 0x8d, Top, High).small_key().pos(1), create_door(player, 'GT Speed Torch NE', Nrml).dir(No, 0x8d, Right, High).pos(3), + create_door(player, 'GT Speed Torch South Path', Lgcl), + create_door(player, 'GT Speed Torch North Path', Lgcl), create_door(player, 'GT Speed Torch WS', Intr).dir(We, 0x8d, Bot, High).pos(4), create_door(player, 'GT Pots n Blocks ES', Intr).dir(Ea, 0x8d, Bot, High).pos(4), create_door(player, 'GT Speed Torch SE', Nrml).dir(So, 0x8d, Right, High).trap(0x4).pos(0), diff --git a/Dungeons.py b/Dungeons.py index d6f8acc6..1d4c898c 100644 --- a/Dungeons.py +++ b/Dungeons.py @@ -182,11 +182,12 @@ eastern_regions = [ ] desert_regions = [ - 'Desert Main Lobby', 'Desert Dead End', 'Desert East Lobby', 'Desert East Wing', 'Desert Compass Room', - 'Desert Cannonball', 'Desert Arrow Pot Corner', 'Desert Trap Room', 'Desert North Hall', 'Desert Map Room', - 'Desert Sandworm Corner', 'Desert Bonk Torch', 'Desert Circle of Pots', 'Desert Big Chest Room', 'Desert West Wing', - 'Desert West Lobby', 'Desert Fairy Fountain', 'Desert Back Lobby', 'Desert Tiles 1', - 'Desert Bridge', 'Desert Four Statues', 'Desert Beamos Hall', 'Desert Tiles 2', 'Desert Wall Slide', 'Desert Boss', + 'Desert Main Lobby', 'Desert Left Alcove', 'Desert Right Alcove', 'Desert Dead End', 'Desert East Lobby', + 'Desert East Wing', 'Desert Compass Room', 'Desert Cannonball', 'Desert Arrow Pot Corner', 'Desert Trap Room', + 'Desert North Hall', 'Desert Map Room', 'Desert Sandworm Corner', 'Desert Bonk Torch', 'Desert Circle of Pots', + 'Desert Big Chest Room', 'Desert West Wing', 'Desert West Lobby', 'Desert Fairy Fountain', 'Desert Back Lobby', + 'Desert Tiles 1', 'Desert Bridge', 'Desert Four Statues', 'Desert Beamos Hall', 'Desert Tiles 2', + 'Desert Wall Slide', 'Desert Boss' ] hera_regions = [ @@ -203,12 +204,13 @@ tower_regions = [ ] pod_regions = [ - 'PoD Lobby', 'PoD Left Cage', 'PoD Middle Cage', 'PoD Shooter Room', 'PoD Pit Room', 'PoD Arena Main', - 'PoD Arena North', 'PoD Arena Crystal', 'PoD Arena Bridge', 'PoD Arena Ledge', 'PoD Sexy Statue', 'PoD Map Balcony', - 'PoD Conveyor', 'PoD Mimics 1', 'PoD Jelly Hall', 'PoD Warp Hint', 'PoD Warp Room', 'PoD Stalfos Basement', - 'PoD Basement Ledge', 'PoD Big Key Landing', 'PoD Falling Bridge', 'PoD Dark Maze', 'PoD Big Chest Balcony', - 'PoD Compass Room', 'PoD Dark Basement', 'PoD Harmless Hellway', 'PoD Mimics 2', 'PoD Bow Statue', 'PoD Dark Pegs', - 'PoD Lonely Turtle', 'PoD Turtle Party', 'PoD Dark Alley', 'PoD Callback', 'PoD Boss' + 'PoD Lobby', 'PoD Left Cage', 'PoD Middle Cage', 'PoD Shooter Room', 'PoD Pit Room', 'PoD Pit Room Blocked', + 'PoD Arena Main', 'PoD Arena North', 'PoD Arena Crystal', 'PoD Arena Bridge', 'PoD Arena Ledge', 'PoD Sexy Statue', + 'PoD Map Balcony', 'PoD Conveyor', 'PoD Mimics 1', 'PoD Jelly Hall', 'PoD Warp Hint', 'PoD Warp Room', + 'PoD Stalfos Basement', 'PoD Basement Ledge', 'PoD Big Key Landing', 'PoD Falling Bridge', + 'PoD Falling Bridge Ledge', 'PoD Dark Maze', 'PoD Big Chest Balcony', 'PoD Compass Room', 'PoD Dark Basement', + 'PoD Harmless Hellway', 'PoD Mimics 2', 'PoD Bow Statue', 'PoD Dark Pegs', 'PoD Lonely Turtle', 'PoD Turtle Party', + 'PoD Dark Alley', 'PoD Callback', 'PoD Boss' ] swamp_regions = [ @@ -255,14 +257,15 @@ ice_regions = [ mire_regions = [ 'Mire Lobby', 'Mire Post-Gap', 'Mire 2', 'Mire Hub', 'Mire Hub Right', 'Mire Hub Top', 'Mire Lone Shooter', 'Mire Failure Bridge', 'Mire Falling Bridge', 'Mire Map Spike Side', 'Mire Map Spot', 'Mire Crystal Dead End', - 'Mire Hidden Shooters', 'Mire Cross', 'Mire Minibridge', 'Mire BK Door Room', 'Mire Spikes', 'Mire Ledgehop', - 'Mire Bent Bridge', 'Mire Over Bridge', 'Mire Right Bridge', 'Mire Left Bridge', 'Mire Fishbone', 'Mire South Fish', - 'Mire Spike Barrier', 'Mire Square Rail', 'Mire Lone Warp', 'Mire Wizzrobe Bypass', 'Mire Conveyor Crystal', - 'Mire Tile Room', 'Mire Compass Room', 'Mire Compass Chest', 'Mire Neglected Room', 'Mire Chest View', - 'Mire Conveyor Barrier', 'Mire BK Chest Ledge', 'Mire Warping Pool', 'Mire Torches Top', 'Mire Torches Bottom', - 'Mire Attic Hint', 'Mire Dark Shooters', 'Mire Key Rupees', 'Mire Block X', 'Mire Tall Dark and Roomy', - 'Mire Crystal Right', 'Mire Crystal Mid', 'Mire Crystal Left', 'Mire Crystal Top', 'Mire Shooter Rupees', - 'Mire Falling Foes', 'Mire Firesnake Skip', 'Mire Antechamber', 'Mire Boss' + 'Mire Hidden Shooters', 'Mire Hidden Shooters Blocked', 'Mire Cross', 'Mire Minibridge', 'Mire BK Door Room', + 'Mire Spikes', 'Mire Ledgehop', 'Mire Bent Bridge', 'Mire Over Bridge', 'Mire Right Bridge', 'Mire Left Bridge', + 'Mire Fishbone', 'Mire South Fish', 'Mire Spike Barrier', 'Mire Square Rail', 'Mire Lone Warp', + 'Mire Wizzrobe Bypass', 'Mire Conveyor Crystal', 'Mire Tile Room', 'Mire Compass Room', 'Mire Compass Chest', + 'Mire Neglected Room', 'Mire Chest View', 'Mire Conveyor Barrier', 'Mire BK Chest Ledge', 'Mire Warping Pool', + 'Mire Torches Top', 'Mire Torches Bottom', 'Mire Attic Hint', 'Mire Dark Shooters', 'Mire Key Rupees', + 'Mire Block X', 'Mire Tall Dark and Roomy', 'Mire Crystal Right', 'Mire Crystal Mid', 'Mire Crystal Left', + 'Mire Crystal Top', 'Mire Shooter Rupees', 'Mire Falling Foes', 'Mire Firesnake Skip', 'Mire Antechamber', + 'Mire Boss' ] tr_regions = [ @@ -276,8 +279,8 @@ tr_regions = [ gt_regions = [ 'GT Lobby', 'GT Bob\'s Torch', 'GT Hope Room', 'GT Big Chest', 'GT Blocked Stairs', 'GT Bob\'s Room', - 'GT Tile Room', 'GT Speed Torch', 'GT Pots n Blocks', 'GT Crystal Conveyor', 'GT Compass Room', - 'GT Invisible Bridges', 'GT Invisible Catwalk', 'GT Conveyor Cross', 'GT Hookshot East Platform', + 'GT Tile Room', 'GT Speed Torch', 'GT Speed Torch Upper', 'GT Pots n Blocks', 'GT Crystal Conveyor', + 'GT Compass Room', 'GT Invisible Bridges', 'GT Invisible Catwalk', 'GT Conveyor Cross', 'GT Hookshot East Platform', 'GT Hookshot North Platform', 'GT Hookshot South Platform', 'GT Hookshot South Entry', 'GT Map Room', 'GT Double Switch Entry', 'GT Double Switch Switches', 'GT Double Switch Transition', 'GT Double Switch Key Spot', 'GT Double Switch Exit', 'GT Spike Crystals', 'GT Warp Maze - Left Section', 'GT Warp Maze - Mid Section', diff --git a/Main.py b/Main.py index 2b12d179..2d96507d 100644 --- a/Main.py +++ b/Main.py @@ -23,7 +23,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute from ItemList import generate_itempool, difficulties, fill_prizes from Utils import output_path, parse_player_names -__version__ = '0.0.13pre' +__version__ = '0.0.14pre' def main(args, seed=None): diff --git a/Regions.py b/Regions.py index 011ca825..9d6cedc3 100644 --- a/Regions.py +++ b/Regions.py @@ -277,8 +277,9 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Eastern Boss', 'Eastern Palace', ['Eastern Palace - Boss', 'Eastern Palace - Prize'], ['Eastern Boss SE']), # Desert Palace - # note for later: pots in desert keep out the bunny - logically (though not practically b/c of dungeon bunny revival) - create_dungeon_region(player, 'Desert Main Lobby', 'Desert Palace', None, ['Desert Palace Exit (South)','Desert Main Lobby NW Edge', 'Desert Main Lobby N Edge', 'Desert Main Lobby NE Edge', 'Desert Main Lobby E Edge']), + create_dungeon_region(player, 'Desert Main Lobby', 'Desert Palace', None, ['Desert Palace Exit (South)', 'Desert Main Lobby N Edge', 'Desert Main Lobby Left Path', 'Desert Main Lobby Right Path']), + create_dungeon_region(player, 'Desert Left Alcove', 'Desert Palace', None, ['Desert Main Lobby NW Edge', 'Desert Left Alcove Path']), + create_dungeon_region(player, 'Desert Right Alcove', 'Desert Palace', None, ['Desert Main Lobby NE Edge', 'Desert Main Lobby E Edge', 'Desert Right Alcove Path']), create_dungeon_region(player, 'Desert Dead End', 'Desert Palace', None, ['Desert Dead End Edge']), create_dungeon_region(player, 'Desert East Lobby', 'Desert Palace', None, ['Desert East Lobby WS', 'Desert Palace Exit (East)']), create_dungeon_region(player, 'Desert East Wing', 'Desert Palace', None, ['Desert East Wing ES', 'Desert East Wing Key Door EN', 'Desert East Wing W Edge', 'Desert East Wing N Edge']), @@ -344,7 +345,8 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'PoD Left Cage', 'Palace of Darkness', None, ['PoD Left Cage SW', 'PoD Left Cage Down Stairs']), create_dungeon_region(player, 'PoD Middle Cage', 'Palace of Darkness', None, ['PoD Middle Cage S', 'PoD Middle Cage SE', 'PoD Middle Cage N', 'PoD Middle Cage Down Stairs']), create_dungeon_region(player, 'PoD Shooter Room', 'Palace of Darkness', ['Palace of Darkness - Shooter Room'], ['PoD Shooter Room Up Stairs']), - create_dungeon_region(player, 'PoD Pit Room', 'Palace of Darkness', None, ['PoD Pit Room S', 'PoD Pit Room NW', 'PoD Pit Room NE', 'PoD Pit Room Freefall', 'PoD Pit Room Bomb Hole']), + create_dungeon_region(player, 'PoD Pit Room', 'Palace of Darkness', None, ['PoD Pit Room S', 'PoD Pit Room NW', 'PoD Pit Room Bomb Hole', 'PoD Pit Room Block Path N']), + create_dungeon_region(player, 'PoD Pit Room Blocked', 'Palace of Darkness', None, ['PoD Pit Room NE', 'PoD Pit Room Freefall', 'PoD Pit Room Block Path S']), create_dungeon_region(player, 'PoD Arena Main', 'Palace of Darkness', None, ['PoD Arena Main SW', 'PoD Arena Main Crystal Path', 'PoD Arena Main Orange Barrier', 'PoD Arena Bonk Path']), create_dungeon_region(player, 'PoD Arena North', 'Palace of Darkness', None, ['PoD Arena Main NW', 'PoD Arena Main NE', 'PoD Arena North Drop Down']), create_dungeon_region(player, 'PoD Arena Crystal', 'Palace of Darkness', None, ['PoD Arena Crystals E', 'PoD Arena Crystal Path']), @@ -360,7 +362,8 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'PoD Stalfos Basement', 'Palace of Darkness', ['Palace of Darkness - Stalfos Basement'], ['PoD Stalfos Basement Warp']), create_dungeon_region(player, 'PoD Basement Ledge', 'Palace of Darkness', None, ['PoD Basement Ledge Drop Down', 'PoD Basement Ledge Up Stairs']), create_dungeon_region(player, 'PoD Big Key Landing', 'Palace of Darkness', ['Palace of Darkness - Big Key Chest'], ['PoD Big Key Landing Down Stairs', 'PoD Big Key Landing Hole']), - create_dungeon_region(player, 'PoD Falling Bridge', 'Palace of Darkness', None, ['PoD Falling Bridge SW', 'PoD Falling Bridge WN', 'PoD Falling Bridge EN']), + create_dungeon_region(player, 'PoD Falling Bridge Ledge', 'Palace of Darkness', None, ['PoD Falling Bridge WN', 'PoD Falling Bridge EN', 'PoD Falling Bridge Path S']), + create_dungeon_region(player, 'PoD Falling Bridge', 'Palace of Darkness', None, ['PoD Falling Bridge SW', 'PoD Falling Bridge Path N']), create_dungeon_region(player, 'PoD Dark Maze', 'Palace of Darkness', ['Palace of Darkness - Dark Maze - Top', 'Palace of Darkness - Dark Maze - Bottom'], ['PoD Dark Maze EN', 'PoD Dark Maze E']), create_dungeon_region(player, 'PoD Big Chest Balcony', 'Palace of Darkness', ['Palace of Darkness - Big Chest'], ['PoD Big Chest Balcony W']), create_dungeon_region(player, 'PoD Compass Room', 'Palace of Darkness', ['Palace of Darkness - Compass Chest'], ['PoD Compass Room SE', 'PoD Compass Room WN', 'PoD Compass Room W Down Stairs', 'PoD Compass Room E Down Stairs']), @@ -544,7 +547,8 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Mire Map Spike Side', 'Misery Mire', None, ['Mire Map Spike Side EN', 'Mire Map Spike Side Drop Down', 'Mire Map Spike Side Blue Barrier']), create_dungeon_region(player, 'Mire Map Spot', 'Misery Mire', ['Misery Mire - Map Chest'], ['Mire Map Spot WN', 'Mire Map Spot Blue Barrier']), create_dungeon_region(player, 'Mire Crystal Dead End', 'Misery Mire', None, ['Mire Crystal Dead End Left Barrier', 'Mire Crystal Dead End Right Barrier', 'Mire Crystal Dead End NW']), - create_dungeon_region(player, 'Mire Hidden Shooters', 'Misery Mire', None, ['Mire Hidden Shooters SE', 'Mire Hidden Shooters WS', 'Mire Hidden Shooters ES', 'Mire Hidden Shooters NE']), + create_dungeon_region(player, 'Mire Hidden Shooters', 'Misery Mire', None, ['Mire Hidden Shooters SE', 'Mire Hidden Shooters WS', 'Mire Hidden Shooters ES', 'Mire Hidden Shooters Block Path N']), + create_dungeon_region(player, 'Mire Hidden Shooters Blocked', 'Misery Mire', None, ['Mire Hidden Shooters NE', 'Mire Hidden Shooters Block Path S']), create_dungeon_region(player, 'Mire Cross', 'Misery Mire', None, ['Mire Cross ES', 'Mire Cross SW']), create_dungeon_region(player, 'Mire Minibridge', 'Misery Mire', None, ['Mire Minibridge SE', 'Mire Minibridge NE']), create_dungeon_region(player, 'Mire BK Door Room', 'Misery Mire', None, ['Mire BK Door Room EN', 'Mire BK Door Room N']), @@ -633,7 +637,8 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'GT Blocked Stairs', 'Ganon\'s Tower', None, ['GT Blocked Stairs Down Stairs', 'GT Blocked Stairs Block Path']), create_dungeon_region(player, 'GT Bob\'s Room', 'Ganon\'s Tower', ['Ganons Tower - Bob\'s Chest'], ['GT Bob\'s Room SE', 'GT Bob\'s Room Hole']), create_dungeon_region(player, 'GT Tile Room', 'Ganon\'s Tower', ['Ganons Tower - Tile Room'], ['GT Tile Room WN', 'GT Tile Room EN']), - create_dungeon_region(player, 'GT Speed Torch', 'Ganon\'s Tower', None, ['GT Speed Torch WN', 'GT Speed Torch NE', 'GT Speed Torch WS', 'GT Speed Torch SE']), + create_dungeon_region(player, 'GT Speed Torch', 'Ganon\'s Tower', None, ['GT Speed Torch WS', 'GT Speed Torch SE', 'GT Speed Torch North Path']), + create_dungeon_region(player, 'GT Speed Torch Upper', 'Ganon\'s Tower', None, ['GT Speed Torch WN', 'GT Speed Torch NE', 'GT Speed Torch South Path']), create_dungeon_region(player, 'GT Pots n Blocks', 'Ganon\'s Tower', None, ['GT Pots n Blocks ES']), create_dungeon_region(player, 'GT Crystal Conveyor', 'Ganon\'s Tower', None, ['GT Crystal Conveyor NE', 'GT Crystal Conveyor WN']), create_dungeon_region(player, 'GT Compass Room', 'Ganon\'s Tower', ['Ganons Tower - Compass Room - Top Left', 'Ganons Tower - Compass Room - Top Right', 'Ganons Tower - Compass Room - Bottom Left', 'Ganons Tower - Compass Room - Bottom Right'], diff --git a/Rules.py b/Rules.py index 9d3317bb..c243ce2d 100644 --- a/Rules.py +++ b/Rules.py @@ -1,6 +1,7 @@ import logging -from BaseClasses import CollectionState, RegionType +from BaseClasses import CollectionState, RegionType, DoorType from Regions import key_only_locations +from RoomData import DoorKind from collections import deque @@ -1252,7 +1253,7 @@ def set_inverted_big_bomb_rules(world, player): set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('East Dark World', 'Region', player) and state.can_reach('Inverted Big Bomb Shop', 'Region', player) and state.has('Crystal 5', player) and state.has('Crystal 6', player)) - #crossing peg bridge starting from the southern dark world + # crossing peg bridge starting from the southern dark world def cross_peg_bridge(state): return state.has('Hammer', player) @@ -1313,23 +1314,18 @@ def set_bunny_rules(world, player): # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)'] - # todo: bunny impassable caves - # sewers drop may or may not be - maybe just new terminology - # desert pots are impassible by bunny - need rules for those transitions - # skull woods drops tend to soft lock bunny - # tr too - dark ride, chest gap, entrance gap, pots in lazy eyes, etc - - bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins'] - + bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', + 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', + 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins'] def path_to_access_rule(path, entrance): - return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) + return lambda state: state.can_reach(entrance) and all(rule_func(state) for rule_func in path) def options_to_access_rule(options): - return lambda state: any(rule(state) for rule in options) + return lambda state: any(rule_func(state) for rule_func in options) - def get_rule_to_add(region): - if not region.is_light_world: + def get_rule_to_add(start_region): + if not start_region.is_light_world: return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. @@ -1342,8 +1338,8 @@ def set_bunny_rules(world, player): # for each such entrance a new option is added that consist of: # a) being able to reach it, and # b) being able to access all entrances from there to `region` - seen = set([region]) - queue = deque([(region, [])]) + seen = {start_region} + queue = deque([(start_region, [])]) while queue: (current, path) = queue.popleft() for entrance in current.entrances: @@ -1353,7 +1349,7 @@ def set_bunny_rules(world, player): new_path = path + [entrance.access_rule] seen.add(new_region) if not new_region.is_light_world: - continue # we don't care about pure dark world entrances + continue # we don't care about pure dark world entrances if new_region.is_dark_world: queue.append((new_region, new_path)) else: @@ -1367,13 +1363,25 @@ def set_bunny_rules(world, player): if not region.is_dark_world: continue rule = get_rule_to_add(region) - for exit in region.exits: - add_rule(exit, rule) + for ext in region.exits: + add_rule(ext, rule) paradox_shop = world.get_region('Light World Death Mountain Shop', player) if paradox_shop.is_dark_world: add_rule(paradox_shop.entrances[0], get_rule_to_add(paradox_shop)) + for ent_name in bunny_impassible_doors: + bunny_exit = world.get_entrance(ent_name, player) + if bunny_exit.parent_region.is_dark_world: + add_rule(bunny_exit, get_rule_to_add(bunny_exit.parent_region)) + + doors_to_check = [x for x in world.doors if x.player == player and x not in bunny_impassible_doors] + doors_to_check = [x for x in doors_to_check if x.type in [DoorType.Normal, DoorType.Interior] and not x.blocked] + for door in doors_to_check: + room = world.get_room(door.roomIndex, player) + if door.entrance.parent_region.is_dark_world and room.kind(door) in [DoorKind.Dashable, DoorKind.Bombable, DoorKind.Hidden]: + add_rule(door.entrance, get_rule_to_add(door.entrance.parent_region)) + # Add requirements for all locations that are actually in the dark world, except those available to the bunny for location in world.get_locations(): if location.player == player and location.parent_region.is_dark_world: @@ -1383,29 +1391,26 @@ def set_bunny_rules(world, player): add_rule(location, get_rule_to_add(location.parent_region)) + def set_inverted_bunny_rules(world, player): # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)', 'The Sky'] - # todo: bunny impassable caves - # sewers drop may or may not be - maybe just new terminology - # desert pots are impassible by bunny - need rules for those transitions - # skull woods drops tend to soft lock bunny - # tr too - dark ride, chest gap, entrance gap, pots in lazy eyes, etc - - bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest'] - + bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', + 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', + 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', + 'Bombos Tablet', 'Ether Tablet', 'Purple Chest'] def path_to_access_rule(path, entrance): - return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) + return lambda state: state.can_reach(entrance) and all(rule_func(state) for rule_func in path) def options_to_access_rule(options): - return lambda state: any(rule(state) for rule in options) + return lambda state: any(rule_func(state) for rule_func in options) - def get_rule_to_add(region): - if not region.is_dark_world: + def get_rule_to_add(start_region): + if not start_region.is_dark_world: return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. @@ -1418,8 +1423,8 @@ def set_inverted_bunny_rules(world, player): # for each such entrance a new option is added that consist of: # a) being able to reach it, and # b) being able to access all entrances from there to `region` - seen = set([region]) - queue = deque([(region, [])]) + seen = {start_region} + queue = deque([(start_region, [])]) while queue: (current, path) = queue.popleft() for entrance in current.entrances: @@ -1429,7 +1434,7 @@ def set_inverted_bunny_rules(world, player): new_path = path + [entrance.access_rule] seen.add(new_region) if not new_region.is_dark_world: - continue # we don't care about pure light world entrances + continue # we don't care about pure light world entrances if new_region.is_light_world: queue.append((new_region, new_path)) else: @@ -1443,13 +1448,25 @@ def set_inverted_bunny_rules(world, player): if not region.is_light_world: continue rule = get_rule_to_add(region) - for exit in region.exits: - add_rule(exit, rule) + for ext in region.exits: + add_rule(ext, rule) paradox_shop = world.get_region('Light World Death Mountain Shop', player) if paradox_shop.is_light_world: add_rule(paradox_shop.entrances[0], get_rule_to_add(paradox_shop)) + for ent_name in bunny_impassible_doors: + bunny_exit = world.get_entrance(ent_name, player) + if bunny_exit.parent_region.is_light_world: + add_rule(bunny_exit, get_rule_to_add(bunny_exit.parent_region)) + + doors_to_check = [x for x in world.doors if x.player == player and x not in bunny_impassible_doors] + doors_to_check = [x for x in doors_to_check if x.type in [DoorType.Normal, DoorType.Interior] and not x.blocked] + for door in doors_to_check: + room = world.get_room(door.roomIndex, player) + if door.entrance.parent_region.is_light_world and room.kind(door) in [DoorKind.Dashable, DoorKind.Bombable, DoorKind.Hidden]: + add_rule(door.entrance, get_rule_to_add(door.entrance.parent_region)) + # Add requirements for all locations that are actually in the light world, except those available to the bunny for location in world.get_locations(): if location.player == player and location.parent_region.is_light_world: @@ -1460,6 +1477,72 @@ def set_inverted_bunny_rules(world, player): add_rule(location, get_rule_to_add(location.parent_region)) +bunny_impassible_doors = { + 'Hyrule Dungeon Armory S', 'Hyrule Dungeon Armory ES', 'Sewers Secret Room Push Block', 'Sewers Pull Switch S', + 'Eastern Lobby N', 'Eastern Courtyard Ledge W', 'Eastern Courtyard Ledge E', 'Eastern Pot Switch SE', + 'Eastern Map Balcony Hook Path', 'Eastern Stalfos Spawn ES', 'Eastern Stalfos Spawn NW', + 'Eastern Hint Tile Push Block', 'Eastern Darkness S', 'Eastern Darkness NE', 'Eastern Darkness Up Stairs', + 'Eastern Attic Start WS', 'Eastern Single Eyegore NE', 'Eastern Duo Eyegores NE', 'Desert Main Lobby Left Path', + 'Desert Main Lobby Right Path', 'Desert Left Alcove Path', 'Desert Right Alcove Path', 'Desert Compass NW', + 'Desert West Lobby NW', 'Desert Back Lobby NW', 'Desert Four Statues NW', 'Desert Four Statues ES', + 'Desert Beamos Hall WS', 'Desert Beamos Hall NE', 'Desert Wall Slide NW', 'Hera Lobby Down Stairs', + 'Hera Lobby Key Stairs', 'Hera Lobby Up Stairs', 'Hera Tile Room EN', 'Hera Tridorm SE', 'Hera Beetles WS', + 'Hera 4F Down Stairs', 'Tower Gold Knights SW', 'Tower Dark Maze EN', 'Tower Dark Pits ES', 'Tower Dark Archers WN', + 'Tower Red Spears WN', 'Tower Red Guards EN', 'Tower Red Guards SW', 'Tower Circle of Pots NW', 'Tower Altar NW', + 'PoD Left Cage SW', 'PoD Middle Cage SE', 'PoD Pit Room Bomb Hole', 'PoD Pit Room Block Path N', + 'PoD Pit Room Block Path S', 'PoD Stalfos Basement Warp', 'PoD Arena Main SW', 'PoD Arena Main Crystal Path', + 'PoD Arena Bonk Path', 'PoD Arena Crystal Path', 'PoD Sexy Statue NW', 'PoD Map Balcony Drop Down', + 'PoD Mimics 1 NW', 'PoD Warp Hint Warp', 'PoD Falling Bridge Path N', 'PoD Falling Bridge Path S', + 'PoD Mimics 2 NW', 'PoD Bow Statue Down Ladder', 'PoD Dark Pegs Up Ladder', 'PoD Dark Pegs WN', + 'PoD Turtle Party ES', 'PoD Turtle Party NW', 'PoD Callback Warp', 'Swamp Lobby Moat', 'Swamp Entrance Moat', + 'Swamp Trench 1 Approach Swim Depart', 'Swamp Trench 1 Approach Key', 'Swamp Trench 1 Key Approach', + 'Swamp Trench 1 Key Ledge Depart', 'Swamp Trench 1 Departure Approach', 'Swamp Trench 1 Departure Key', + 'Swamp Hub Hook Path', 'Swamp Compass Donut Push Block', + 'Swamp Shortcut Blue Barrier', 'Swamp Trench 2 Pots Blue Barrier', 'Swamp Trench 2 Pots Wet', + 'Swamp Trench 2 Departure Wet', 'Swamp West Shallows Push Blocks', 'Swamp West Ledge Hook Path', + 'Swamp Barrier Ledge Hook Path', 'Swamp Attic Left Pit', 'Swamp Attic Right Pit', 'Swamp Push Statue NW', + 'Swamp Push Statue NE', 'Swamp Drain Right Switch', 'Swamp Waterway NE', 'Swamp Waterway N', 'Swamp Waterway NW', + 'Skull Pot Circle WN', 'Skull Pot Circle Star Path', 'Skull Pull Switch S', 'Skull Big Chest N', + 'Skull Big Chest Hookpath', 'Skull 2 East Lobby NW', 'Skull Back Drop Star Path', 'Skull 2 West Lobby NW', + 'Skull 3 Lobby EN', 'Skull Star Pits SW', 'Skull Star Pits ES', 'Skull Torch Room WN', 'Skull Vines NW', + 'Thieves Conveyor Maze EN', 'Thieves Triple Bypass EN', 'Thieves Triple Bypass SE', 'Thieves Triple Bypass WN', + 'Thieves Hellway Blue Barrier', 'Thieves Hellway Crystal Blue Barrier', 'Thieves Attic ES', + 'Thieves Basement Block Path', 'Thieves Blocked Entry Path', 'Thieves Conveyor Bridge Block Path', + 'Thieves Conveyor Block Path', 'Ice Lobby WS', 'Ice Cross Left Push Block', 'Ice Cross Bottom Push Block Left', + 'Ice Cross Bottom Push Block Right', 'Ice Cross Right Push Block Top', 'Ice Cross Right Push Block Bottom', + 'Ice Cross Top Push Block Bottom', 'Ice Cross Top Push Block Right', 'Ice Bomb Drop Hole', 'Ice Pengator Switch WS', + 'Ice Pengator Switch ES', 'Ice Big Key Push Block', 'Ice Stalfos Hint SE', 'Ice Bomb Jump EN', + 'Ice Pengator Trap NE', 'Ice Hammer Block ES', 'Ice Tongue Pull WS', 'Ice Freezors Bomb Hole', 'Ice Tall Hint WS', + 'Ice Hookshot Ledge Path', 'Ice Hookshot Balcony Path', 'Ice Many Pots SW', 'Ice Many Pots WS', + 'Ice Crystal Right Blue Hole', 'Ice Crystal Left Blue Barrier', 'Ice Big Chest Landing Push Blocks', + 'Ice Backwards Room Hole', 'Ice Switch Room SE', 'Ice Antechamber NE', 'Ice Antechamber Hole', 'Mire Lobby Gap', + 'Mire Post-Gap Gap', 'Mire 2 NE', 'Mire Hub Upper Blue Barrier', 'Mire Hub Lower Blue Barrier', + 'Mire Hub Right Blue Barrier', 'Mire Hub Top Blue Barrier', 'Mire Falling Bridge WN', + 'Mire Map Spike Side Blue Barrier', 'Mire Map Spot Blue Barrier', 'Mire Crystal Dead End Left Barrier', + 'Mire Crystal Dead End Right Barrier', 'Mire Cross ES', 'Mire Hidden Shooters Block Path S', + 'Mire Hidden Shooters Block Path N', 'Mire Left Bridge Hook Path', 'Mire Fishbone Blue Barrier', + 'Mire South Fish Blue Barrier', 'Mire Tile Room NW', 'Mire Compass Blue Barrier', 'Mire Attic Hint Hole', + 'Mire Dark Shooters SW', 'Mire Crystal Mid Blue Barrier', 'Mire Crystal Left Blue Barrier', 'TR Main Lobby Gap', + 'TR Lobby Ledge Gap', 'TR Hub SW', 'TR Hub SE', 'TR Hub ES', 'TR Hub EN', 'TR Hub NW', 'TR Hub NE', 'TR Torches NW', + 'TR Pokey 2 EN', 'TR Pokey 2 ES', 'TR Twin Pokeys SW', 'TR Twin Pokeys EN', 'TR Big Chest Gap', + 'TR Big Chest Entrance Gap', 'TR Lazy Eyes ES', 'TR Tongue Pull WS', 'TR Tongue Pull NE', 'TR Dark Ride Up Stairs', + 'TR Dark Ride SW', 'TR Crystal Maze Forwards Path', 'TR Crystal Maze Blue Path', 'TR Crystal Maze Cane Path', + 'TR Final Abyss South Stairs', 'TR Final Abyss NW', 'GT Hope Room EN', 'GT Blocked Stairs Block Path', + 'GT Bob\'s Room Hole', 'GT Speed Torch SE', 'GT Speed Torch South Path', 'GT Speed Torch North Path', + 'GT Crystal Conveyor NE', 'GT Crystal Conveyor WN', 'GT Conveyor Cross EN', 'GT Conveyor Cross WN', + 'GT Hookshot East-North Path', 'GT Hookshot East-South Path', 'GT Hookshot North-East Path', + 'GT Hookshot North-South Path', 'GT Hookshot South-East Path', 'GT Hookshot South-North Path', + 'GT Hookshot Platform Blue Barrier', 'GT Hookshot Entry Blue Barrier', 'GT Double Switch Blue Path', + 'GT Double Switch Key Blue Path', 'GT Double Switch Blue Barrier', 'GT Double Switch Transition Blue', + 'GT Firesnake Room Hook Path', 'GT Falling Bridge WN', 'GT Falling Bridge WS', 'GT Ice Armos NE', 'GT Ice Armos WS', + 'GT Crystal Paths SW', 'GT Mimics 1 NW', 'GT Mimics 1 ES', 'GT Mimics 2 WS', 'GT Mimics 2 NE', + 'GT Hidden Spikes EN', 'GT Cannonball Bridge SE', 'GT Gauntlet 1 WN', 'GT Gauntlet 2 EN', 'GT Gauntlet 2 SW', + 'GT Gauntlet 3 NW', 'GT Gauntlet 3 SW', 'GT Gauntlet 4 NW', 'GT Gauntlet 4 SW', 'GT Gauntlet 5 NW', + 'GT Gauntlet 5 WS', 'GT Lanmolas 2 ES', 'GT Lanmolas 2 NW', 'GT Wizzrobes 1 SW', 'GT Wizzrobes 2 SE', + 'GT Wizzrobes 2 NE', 'GT Torch Cross ES', 'GT Falling Torches NE', 'GT Moldorm Gap', 'GT Validation Block Path' +} + + def add_key_logic_rules(world, player): key_logic = world.key_logic[player] for d_name, d_logic in key_logic.items():