From 06b172ee32f649e3798831d5ee083cf6a88a0a1a Mon Sep 17 00:00:00 2001 From: StructuralMike <66819228+StructuralMike@users.noreply.github.com> Date: Fri, 5 Mar 2021 20:10:21 +0100 Subject: [PATCH] Initial full rules commit --- BaseClasses.py | 5 +++ Rules.py | 93 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index e8127d65..a594331a 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1334,6 +1334,11 @@ class Door(object): self.edge_width = width return self + def kind(self, world): + if self.roomIndex != -1 and self.doorListPos != -1: + return world.get_room(self.roomIndex, self.player).kind(self) + return None + def small_key(self): self.smallKey = True return self diff --git a/Rules.py b/Rules.py index c60f3d0c..d10abf2b 100644 --- a/Rules.py +++ b/Rules.py @@ -28,6 +28,9 @@ def set_rules(world, player): else: raise NotImplementedError('Not implemented yet') + if world.futuro[player]: + bomb_rules(world, player) + if world.logic[player] == 'noglitches': no_glitches_rules(world, player) elif world.logic[player] == 'minorglitches': @@ -175,12 +178,8 @@ def global_rules(world, player): set_rule(world.get_entrance('Tower Altar NW', player), lambda state: state.has_sword(player)) set_defeat_dungeon_boss_rule(world.get_location('Agahnim 1', player)) - set_rule(world.get_entrance('PoD Arena Bonk Path', player), lambda state: state.has_Boots(player)) - for entrance in ['PoD Warp Hint SE', 'PoD Jelly Hall NW', 'PoD Jelly Hall NE', 'PoD Mimics 1 SW']: - set_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) - for entrance in ['PoD Pit Room Bomb Hole', 'PoD Map Balcony WS', 'PoD Arena Ledge ES', 'PoD Dark Maze E', 'PoD Big Chest Balcony W']: - set_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + set_rule(world.get_entrance('PoD Arena Bonk Path', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('PoD Mimics 1 NW', player), lambda state: state.can_shoot_arrows(player)) set_rule(world.get_entrance('PoD Mimics 2 NW', player), lambda state: state.can_shoot_arrows(player)) set_rule(world.get_entrance('PoD Bow Statue Down Ladder', player), lambda state: state.can_shoot_arrows(player)) @@ -226,7 +225,6 @@ def global_rules(world, player): set_defeat_dungeon_boss_rule(world.get_location('Swamp Palace - Boss', player)) set_defeat_dungeon_boss_rule(world.get_location('Swamp Palace - Prize', player)) - set_rule(world.get_entrance('Skull Pot Circle WN', player), lambda state: state.can_use_bombs(player)) set_rule(world.get_entrance('Skull Big Chest Hookpath', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Skull Torch Room WN', player), lambda state: state.has('Fire Rod', player)) set_rule(world.get_entrance('Skull Vines NW', player), lambda state: state.has_sword(player)) @@ -234,8 +232,8 @@ def global_rules(world, player): set_defeat_dungeon_boss_rule(world.get_location('Skull Woods - Prize', player)) # blind can't have the small key? - not necessarily true anymore - but likely still + set_rule(world.get_location('Thieves\' Town - Big Chest', player), lambda state: state.has('Hammer', player)) - set_rule(world.get_location('Attic Cracked Floor', player), lambda state: state.can_use_bombs(player)) for entrance in ['Thieves Basement Block Path', 'Thieves Blocked Entry Path', 'Thieves Conveyor Block Path', 'Thieves Conveyor Bridge Block Path']: set_rule(world.get_entrance(entrance, player), lambda state: state.can_lift_rocks(player)) for location in ['Thieves\' Town - Blind\'s Cell', 'Thieves\' Town - Boss']: @@ -248,7 +246,6 @@ def global_rules(world, player): set_rule(world.get_location('Thieves\' Town - Prize', player), lambda state: state.has('Maiden Unmasked', player) and world.get_location('Thieves\' Town - Prize', player).parent_region.dungeon.boss.can_defeat(state)) set_rule(world.get_entrance('Ice Lobby WS', player), lambda state: state.can_melt_things(player)) - set_rule(world.get_entrance('Ice Bomb Drop Hole', player), lambda state: state.can_use_bombs(player)) set_rule(world.get_entrance('Ice Hammer Block ES', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player)) set_rule(world.get_location('Ice Palace - Hammer Block Key Drop', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player)) set_rule(world.get_location('Ice Palace - Map Chest', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player)) @@ -275,7 +272,6 @@ def global_rules(world, player): set_rule(world.get_entrance('Mire Tile Room NW', player), lambda state: state.has_fire_source(player)) set_rule(world.get_entrance('Mire Attic Hint Hole', player), lambda state: state.has_fire_source(player)) set_rule(world.get_entrance('Mire Dark Shooters SW', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('Mire Crystal Mid NW', player), lambda state: state.can_use_bombs(player)) set_defeat_dungeon_boss_rule(world.get_location('Misery Mire - Boss', player)) set_defeat_dungeon_boss_rule(world.get_location('Misery Mire - Prize', player)) @@ -289,12 +285,8 @@ def global_rules(world, player): set_rule(world.get_entrance('TR Hub NW', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('TR Hub NE', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('TR Torches NW', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player)) - set_rule(world.get_entrance('TR Lazy Eyes SE', player), lambda state: state.can_use_bombs(player)) # ToDo: Add always true for inverted, cross-entrance, and door-variants and so on. set_rule(world.get_entrance('TR Big Chest Entrance Gap', player), lambda state: state.has('Cane of Somaria', player) or state.has('Hookshot', player)) set_rule(world.get_entrance('TR Big Chest Gap', player), lambda state: state.has('Cane of Somaria', player) or state.has_Boots(player)) - set_rule(world.get_entrance('TR Dash Room NW', player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) - set_rule(world.get_entrance('TR Crystaroller SW', player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) - set_rule(world.get_entrance('TR Dash Room ES', player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) set_rule(world.get_entrance('TR Dark Ride Up Stairs', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('TR Dark Ride SW', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('TR Crystal Maze Cane Path', player), lambda state: state.has('Cane of Somaria', player)) @@ -321,8 +313,6 @@ def global_rules(world, player): set_rule(world.get_entrance('GT Hookshot North-South Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player)) set_rule(world.get_entrance('GT Hookshot Entry Boomerang Path', player), lambda state: state.has('Blue Boomerang', player) or state.has('Red Boomerang', player)) set_rule(world.get_entrance('GT Firesnake Room Hook Path', player), lambda state: state.has('Hookshot', player)) - for entrance in ['GT Warp Maze (Rails) WS', 'GT Bob\'s Room Hole', 'GT Randomizer Room ES', 'GT Bomb Conveyor SW', 'GT Crystal Circles NW']: - set_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) # I am tempted to stick an invincibility rule for getting across falling bridge set_rule(world.get_entrance('GT Ice Armos NE', player), lambda state: world.get_region('GT Ice Armos', player).dungeon.bosses['bottom'].can_defeat(state)) @@ -408,7 +398,6 @@ def global_rules(world, player): set_rule(world.get_entrance('GT Double Switch Key Orange Path', player), lambda state: state.can_reach_orange(world.get_region('GT Double Switch Key Spot', player), player)) add_key_logic_rules(world, player) - # End of door rando rules. add_rule(world.get_location('Sunken Treasure', player), lambda state: state.has('Open Floodgate', player)) @@ -416,6 +405,75 @@ def global_rules(world, player): and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or (state.has('Silver Arrows', player) and state.can_shoot_arrows(player)) or state.has('Lamp', player) or state.can_extend_magic(player, 12))) # need to light torch a sufficient amount of times set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop +def bomb_rules(world, player): + bonkable_doors = ['Two Brothers House Exit (West)', 'Two Brothers House Exit (East)'] # Technically this is incorrectly defined, but functionally the same as what is intended. + bombable_doors = ['Ice Rod Cave', 'Light World Bomb Hut', 'Light World Death Mountain Shop', 'Hookshot Cave Exit (North)', 'Mini Moldorm Cave', + 'Dark Lake Hylia Ledge Fairy', 'Hype Cave', 'Brewery'] + for entrance in bonkable_doors: + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + for entrance in bombable_doors: + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + + bonkable_items = ["Sahasrahla's Hut - Left", "Sahasrahla's Hut - Middle", "Sahasrahla's Hut - Right"] + bombable_items = ["Blind's Hideout - Top", "Kakariko Well - Top", 'Chicken House', "Aginah's Cave", 'Graveyard Cave', + 'Paradox Cave Upper - Left', 'Paradox Cave Upper - Right', + 'Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left', 'Hype Cave - Bottom'] + for location in bonkable_items: + add_rule(world.get_location(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + for location in bombable_items: + add_rule(world.get_location(entrance, player), lambda state: state.can_use_bombs(player)) + + cave_kill_locations = ['Mini Moldorm Cave - Far Left', 'Mini Moldorm Cave - Far Right', 'Mini Moldorm Cave - Left', 'Mini Moldorm Cave - Right', 'Mini Moldorm Cave - Generous Guy'] + for location in cave_kill_locations: + add_rule(world.get_location(entrance, player), lambda state: state.can_kill_most_things(player) or state.can_use_bombs(player)) + + paradox_switch_chests = ['Paradox Cave Lower - Far Left', 'Paradox Cave Lower - Left', 'Paradox Cave Lower - Right', 'Paradox Cave Lower - Far Right', 'Paradox Cave Lower - Middle'] + for location in paradox_switch_chests: + add_rule(world.get_location(location, player), lambda state: \ + state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has_beam_sword(player) \ + or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) \ + or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) + + # Dungeon bomb logic + for _,entrances in std_kill_rooms.items(): + for entrance in entrances: + add_rule(world.get_entrance(entrance, player), lambda state: (state.can_use_bombs(player) or state.can_kill_most_things(player))) + + add_rule(world.get_location('Attic Cracked Floor', player), lambda state: state.can_use_bombs(player)) + + bombable_floors = ['PoD Pit Room Bomb Hole', 'Ice Bomb Drop Hole', 'Ice Freezors Bomb Hole', 'GT Bob\'s Room Hole'] + for entrance in bombable_floors: + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + + if world.doorShuffle[player] == 'vanilla': + add_rule(world.get_entrance('TR Lazy Eyes SE', player), lambda state: state.can_use_bombs(player)) # ToDo: Add always true for inverted, cross-entrance, and door-variants and so on. + add_rule(world.get_entrance('Turtle Rock Ledge Exit (West)', player), lambda state: state.can_use_bombs(player)) # Is this the same as above? + + dungeon_bonkable = ['PoD Warp Hint SE', 'PoD Jelly Hall NW', 'PoD Jelly Hall NE', 'PoD Mimics 1 SW', + 'Thieves Ambush E', 'Thieves Rail Ledge W', + 'TR Dash Room NW', 'TR Crystaroller SW', 'TR Dash Room ES', + 'GT Four Torches NW','GT Fairy Abyss SW' + ] + dungeon_bombable = ['PoD Map Balcony WS', 'PoD Arena Ledge ES', 'PoD Dark Maze E', 'PoD Big Chest Balcony W', + 'Swamp Pot Row WN','Swamp Map Ledge EN', 'Swamp Hammer Switch WN', 'Swamp Hub Dead Ledge EN', 'Swamp Waterway N', 'Swamp I S', + 'Skull Pot Circle WN', 'Skull Pull Switch EN', 'Skull Big Key WN', 'Skull Lone Pot EN', + 'Thieves Rail Ledge NW', 'Thieves Pot Alcove Bottom SW', + 'Ice Bomb Drop Hole', 'Ice Freezors Bomb Hole', + 'Mire Crystal Mid NW', 'Mire Tall Dark and Roomy WN', 'Mire Shooter Rupees EN', 'Mire Crystal Top SW', + 'GT Warp Maze (Rails) WS', 'GT Bob\'s Room Hole', 'GT Randomizer Room ES', 'GT Bomb Conveyor SW', 'GT Crystal Circles NW', 'GT Cannonball Bridge SE', 'GT Refill NE' + ] + for entrance in dungeon_bonkable: + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + for entrance in dungeon_bombable: + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + else: + doors_to_bomb_check = [x for x in world.doors if x.player == player and x.type in [DoorType.Normal, DoorType.Interior]] + for door in doors_to_bomb_check: + if door.kind(world) in [DoorKind.Dashable]: + add_rule(door.entrance, lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + elif door.kind(door) in [DoorKind.Bombable]: + add_rule(door.entrance, lambda state: state.can_use_bombs(player)) + def default_rules(world, player): # overworld requirements set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has_Boots(player)) @@ -844,7 +902,6 @@ std_kill_rooms = { 'GT Wizzrobes 2': ['GT Wizzrobes 2 SE', 'GT Wizzrobes 2 NE'] } # all trap rooms? - def add_connection(parent_name, target_name, entrance_name, world, player): parent = world.get_region(parent_name, player) target = world.get_region(target_name, player) @@ -880,7 +937,7 @@ def standard_rules(world, player): return loc.item and loc.item.name == 'Bombs (10)' def standard_escape_rule(state): - return state.can_kill_most_things(player) or state.can_use_bombs(player) or bomb_escape_rule() + return state.can_kill_most_things(player) or bomb_escape_rule() add_item_rule(world.get_location('Link\'s Uncle', player), uncle_item_rule)