diff --git a/BaseClasses.py b/BaseClasses.py index 2466a3b7..09fdba1d 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -71,6 +71,8 @@ class World(object): self.fix_fake_world = True self.boss_shuffle = boss_shuffle self.hints = hints + self.crystals_needed_for_ganon = 7 + self.crystals_needed_for_gt = 7 self.dynamic_regions = [] self.dynamic_locations = [] self.spoiler = Spoiler(self) @@ -367,6 +369,10 @@ class CollectionState(object): def item_count(self, item, player): return self.prog_items.count((item, player)) + def has_crystals(self, count, player): + crystals = ['Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'] + return len([crystal for crystal in crystals if self.has(crystal, player)]) >= count + def can_lift_rocks(self, player): return self.has('Power Glove', player) or self.has('Titans Mitts', player) diff --git a/Rom.py b/Rom.py index c425169c..066897fe 100644 --- a/Rom.py +++ b/Rom.py @@ -929,6 +929,9 @@ def patch_rom(world, player, rom): else: rom.write_byte(0x18003E, 0x03) # make ganon invincible until all crystals and aga 2 are collected + rom.write_byte(0x18005E, world.crystals_needed_for_gt) + rom.write_byte(0x18005F, world.crystals_needed_for_ganon) + rom.write_byte(0x18016A, 0x01 if world.keysanity else 0x00) # free roaming item text boxes rom.write_byte(0x18003B, 0x01 if world.keysanity else 0x00) # maps showing crystals on overworld @@ -1739,114 +1742,114 @@ InsanityEntrances = {'Sanctuary': 'Sanctuary', 'Hookshot Cave Back Entrance': 'The stairs on the floating island' } -HintLocations = ['telepathic_tile_eastern_palace', - 'telepathic_tile_tower_of_hera_floor_4', - 'telepathic_tile_spectacle_rock', - 'telepathic_tile_swamp_entrance', - 'telepathic_tile_thieves_town_upstairs', - 'telepathic_tile_misery_mire', - 'telepathic_tile_palace_of_darkness', - 'telepathic_tile_desert_bonk_torch_room', - 'telepathic_tile_castle_tower', - 'telepathic_tile_ice_large_room', - 'telepathic_tile_turtle_rock', - 'telepathic_tile_ice_entrace', - 'telepathic_tile_ice_stalfos_knights_room', - 'telepathic_tile_tower_of_hera_entrance', - 'telepathic_tile_south_east_darkworld_cave', - 'dark_palace_tree_dude', - 'dark_sanctuary_hint_0', - 'dark_sanctuary_hint_1', - 'dark_sanctuary_yes', - 'dark_sanctuary_hint_2'] - -InconvenientLocations = ['Spike Cave', - 'Sahasrahla', - 'Purple Chest', - 'Swamp Left', - 'Mire Left', - 'Tower of Hera - Big Key Chest', - 'Eastern Palace - Big Key Chest', - 'Thieves\' Town - Big Chest', - 'Ice Palace - Big Chest', - 'Ganons Tower - Big Chest', - 'Magic Bat'] -RelevantItems = ['Bow', - 'Book of Mudora', - 'Hammer', - 'Hookshot', - 'Magic Mirror', - 'Ocarina', - 'Pegasus Boots', - 'Power Glove', - 'Cape', - 'Mushroom', - 'Shovel', - 'Lamp', - 'Magic Powder', - 'Moon Pearl', - 'Cane of Somaria', - 'Fire Rod', - 'Flippers', - 'Ice Rod', - 'Titans Mitts', - 'Ether', - 'Bombos', - 'Quake', - 'Bottle', - 'Bottle (Red Potion)', - 'Bottle (Green Potion)', - 'Bottle (Blue Potion)', - 'Bottle (Fairy)', - 'Bottle (Bee)', - 'Bottle (Good Bee)', - 'Master Sword', - 'Tempered Sword', - 'Fighter Sword', - 'Golden Sword', - 'Progressive Sword', - 'Progressive Glove', - 'Master Sword', - 'Power Star', - 'Triforce Piece', - 'Single Arrow', - 'Blue Mail', - 'Red Mail', - 'Progressive Armor', - 'Blue Boomerang', - 'Red Boomerang', - 'Blue Shield', - 'Red Shield', - 'Mirror Shield', - 'Progressive Shield', - 'Bug Catching Net', - 'Cane of Byrna', - 'Magic Upgrade (1/2)', - 'Magic Upgrade (1/4)' - ] - -KeysanityItems = ['Small Key (Eastern Palace)', - 'Big Key (Eastern Palace)', - 'Small Key (Escape)', - 'Small Key (Desert Palace)', - 'Big Key (Desert Palace)', - 'Small Key (Tower of Hera)', - 'Big Key (Tower of Hera)', - 'Small Key (Agahnims Tower)', - 'Small Key (Palace of Darkness)', - 'Big Key (Palace of Darkness)', - 'Small Key (Thieves Town)', - 'Big Key (Thieves Town)', - 'Small Key (Swamp Palace)', - 'Big Key (Swamp Palace)', - 'Small Key (Skull Woods)', - 'Big Key (Skull Woods)', - 'Small Key (Ice Palace)', - 'Big Key (Ice Palace)', - 'Small Key (Misery Mire)', - 'Big Key (Misery Mire)', - 'Small Key (Turtle Rock)', - 'Big Key (Turtle Rock)', - 'Small Key (Ganons Tower)', - 'Big Key (Ganons Tower)' - ] +HintLocations = ['telepathic_tile_eastern_palace', + 'telepathic_tile_tower_of_hera_floor_4', + 'telepathic_tile_spectacle_rock', + 'telepathic_tile_swamp_entrance', + 'telepathic_tile_thieves_town_upstairs', + 'telepathic_tile_misery_mire', + 'telepathic_tile_palace_of_darkness', + 'telepathic_tile_desert_bonk_torch_room', + 'telepathic_tile_castle_tower', + 'telepathic_tile_ice_large_room', + 'telepathic_tile_turtle_rock', + 'telepathic_tile_ice_entrace', + 'telepathic_tile_ice_stalfos_knights_room', + 'telepathic_tile_tower_of_hera_entrance', + 'telepathic_tile_south_east_darkworld_cave', + 'dark_palace_tree_dude', + 'dark_sanctuary_hint_0', + 'dark_sanctuary_hint_1', + 'dark_sanctuary_yes', + 'dark_sanctuary_hint_2'] + +InconvenientLocations = ['Spike Cave', + 'Sahasrahla', + 'Purple Chest', + 'Swamp Left', + 'Mire Left', + 'Tower of Hera - Big Key Chest', + 'Eastern Palace - Big Key Chest', + 'Thieves\' Town - Big Chest', + 'Ice Palace - Big Chest', + 'Ganons Tower - Big Chest', + 'Magic Bat'] +RelevantItems = ['Bow', + 'Book of Mudora', + 'Hammer', + 'Hookshot', + 'Magic Mirror', + 'Ocarina', + 'Pegasus Boots', + 'Power Glove', + 'Cape', + 'Mushroom', + 'Shovel', + 'Lamp', + 'Magic Powder', + 'Moon Pearl', + 'Cane of Somaria', + 'Fire Rod', + 'Flippers', + 'Ice Rod', + 'Titans Mitts', + 'Ether', + 'Bombos', + 'Quake', + 'Bottle', + 'Bottle (Red Potion)', + 'Bottle (Green Potion)', + 'Bottle (Blue Potion)', + 'Bottle (Fairy)', + 'Bottle (Bee)', + 'Bottle (Good Bee)', + 'Master Sword', + 'Tempered Sword', + 'Fighter Sword', + 'Golden Sword', + 'Progressive Sword', + 'Progressive Glove', + 'Master Sword', + 'Power Star', + 'Triforce Piece', + 'Single Arrow', + 'Blue Mail', + 'Red Mail', + 'Progressive Armor', + 'Blue Boomerang', + 'Red Boomerang', + 'Blue Shield', + 'Red Shield', + 'Mirror Shield', + 'Progressive Shield', + 'Bug Catching Net', + 'Cane of Byrna', + 'Magic Upgrade (1/2)', + 'Magic Upgrade (1/4)' + ] + +KeysanityItems = ['Small Key (Eastern Palace)', + 'Big Key (Eastern Palace)', + 'Small Key (Escape)', + 'Small Key (Desert Palace)', + 'Big Key (Desert Palace)', + 'Small Key (Tower of Hera)', + 'Big Key (Tower of Hera)', + 'Small Key (Agahnims Tower)', + 'Small Key (Palace of Darkness)', + 'Big Key (Palace of Darkness)', + 'Small Key (Thieves Town)', + 'Big Key (Thieves Town)', + 'Small Key (Swamp Palace)', + 'Big Key (Swamp Palace)', + 'Small Key (Skull Woods)', + 'Big Key (Skull Woods)', + 'Small Key (Ice Palace)', + 'Big Key (Ice Palace)', + 'Small Key (Misery Mire)', + 'Big Key (Misery Mire)', + 'Small Key (Turtle Rock)', + 'Big Key (Turtle Rock)', + 'Small Key (Ganons Tower)', + 'Big Key (Ganons Tower)' + ] diff --git a/Rules.py b/Rules.py index 17b6f4e9..6d2d7767 100644 --- a/Rules.py +++ b/Rules.py @@ -43,7 +43,7 @@ def set_rules(world, player): if world.goal == 'dungeons': # require all dungeons to beat ganon - add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player) and state.has('Beat Agahnim 1', player) and state.has('Beat Agahnim 2', player)) + add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player) and state.has('Beat Agahnim 1', player) and state.has('Beat Agahnim 2', player) and state.has_crystals(7, player)) elif world.goal == 'ganon': # require aga2 to beat ganon add_rule(world.get_location('Ganon', player), lambda state: state.has('Beat Agahnim 2', player)) @@ -427,8 +427,7 @@ def global_rules(world, player): 'Ganons Tower - Pre-Moldorm Chest', 'Ganons Tower - Validation Chest']: forbid_item(world.get_location(location, player), 'Big Key (Ganons Tower)', player) - set_rule(world.get_location('Ganon', player), lambda state: state.has_beam_sword(player) and state.has_fire_source(player) and state.has('Crystal 1', player) and state.has('Crystal 2', player) - and state.has('Crystal 3', player) and state.has('Crystal 4', player) and state.has('Crystal 5', player) and state.has('Crystal 6', player) and state.has('Crystal 7', player) + set_rule(world.get_location('Ganon', player), lambda state: state.has_beam_sword(player) and state.has_fire_source(player) and state.has_crystals(world.crystals_needed_for_ganon, 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 @@ -436,7 +435,7 @@ def global_rules(world, player): set_trock_key_rules(world, player) - set_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has('Crystal 1', player) and state.has('Crystal 2', player) and state.has('Crystal 3', player) and state.has('Crystal 4', player) and state.has('Crystal 5', player) and state.has('Crystal 6', player) and state.has('Crystal 7', player)) + set_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt, player)) def inverted_rules(world, player): world.get_location('Ganon', player).item_rule = lambda item: item.name == 'Triforce' and item.player == player @@ -901,8 +900,7 @@ def swordless_rules(world, player): set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_Pearl(player) and state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock (Top)', 'Region', player)) # sword not required to use medallion for opening in swordless (!) set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state.has_key('Small Key (Skull Woods)', player, 3) and state.has('Fire Rod', player)) # no curtain set_rule(world.get_entrance('Ice Palace Entrance Room', player), lambda state: state.has('Fire Rod', player) or state.has('Bombos', player)) #in swordless mode bombos pads are present in the relevant parts of ice palace - set_rule(world.get_location('Ganon', player), lambda state: state.has('Hammer', player) and state.has_fire_source(player) and state.has('Silver Arrows', player) and state.can_shoot_arrows(player) and state.has('Crystal 1', player) and state.has('Crystal 2', player) - and state.has('Crystal 3', player) and state.has('Crystal 4', player) and state.has('Crystal 5', player) and state.has('Crystal 6', player) and state.has('Crystal 7', player)) + set_rule(world.get_location('Ganon', player), lambda state: state.has('Hammer', player) and state.has_fire_source(player) and state.has('Silver Arrows', player) and state.can_shoot_arrows(player) and state.has_crystals(world.crystals_needed_for_ganon, player)) set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has('Hammer', player)) # need to damage ganon to get tiles to drop