Partially implement variable crystal requirements

This commit is contained in:
Kevin Cathcart 2019-07-25 18:25:14 -04:00
parent 18f1275050
commit 90e5f522d8
3 changed files with 124 additions and 117 deletions

View File

@ -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)

225
Rom.py
View File

@ -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)'
]

View File

@ -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