Fix progressive requirements to respect overflow limits

This commit is contained in:
Kevin Cathcart 2018-01-04 01:06:22 -05:00
parent c3bdef5c6c
commit 79f1b0bbf3
6 changed files with 81 additions and 34 deletions

View File

@ -54,6 +54,7 @@ class World(object):
self.disable_music = disable_music self.disable_music = disable_music
self.keysanity = keysanity self.keysanity = keysanity
self.can_take_damage = True self.can_take_damage = True
self.difficulty_requirements = None
self.spoiler = Spoiler(self) self.spoiler = Spoiler(self)
def intialize_regions(self): def intialize_regions(self):
@ -106,13 +107,13 @@ class World(object):
if 'Sword' in item.name: if 'Sword' in item.name:
if ret.has('Golden Sword'): if ret.has('Golden Sword'):
pass pass
elif ret.has('Tempered Sword'): elif ret.has('Tempered Sword') and self.difficulty_requirements.progressive_sword_limit >= 4:
ret.prog_items.append('Golden Sword') ret.prog_items.append('Golden Sword')
elif ret.has('Master Sword'): elif ret.has('Master Sword') and self.difficulty_requirements.progressive_sword_limit >= 3:
ret.prog_items.append('Tempered Sword') ret.prog_items.append('Tempered Sword')
elif ret.has('Fighter Sword'): elif ret.has('Fighter Sword') and self.difficulty_requirements.progressive_sword_limit >= 2:
ret.prog_items.append('Master Sword') ret.prog_items.append('Master Sword')
else: elif self.difficulty_requirements.progressive_sword_limit >= 1:
ret.prog_items.append('Fighter Sword') ret.prog_items.append('Fighter Sword')
elif 'Glove' in item.name: elif 'Glove' in item.name:
if ret.has('Titans Mitts'): if ret.has('Titans Mitts'):
@ -124,13 +125,15 @@ class World(object):
elif 'Shield' in item.name: elif 'Shield' in item.name:
if ret.has('Mirror Shield'): if ret.has('Mirror Shield'):
pass pass
elif ret.has('Red Shield'): elif ret.has('Red Shield') and self.difficulty_requirements.progressive_shield_limit >= 3:
ret.prog_items.append('Mirror Shield') ret.prog_items.append('Mirror Shield')
elif ret.has('Blue Shield'): elif ret.has('Blue Shield') and self.difficulty_requirements.progressive_shield_limit >= 2:
ret.prog_items.append('Red Shield') ret.prog_items.append('Red Shield')
else: elif self.difficulty_requirements.progressive_shield_limit >= 1:
ret.prog_items.append('Blue Shield') ret.prog_items.append('Blue Shield')
elif item.name.startswith('Bottle'):
if ret.bottle_count() < self.difficulty_requirements.progressive_bottle_limit:
ret.prog_items.append(item.name)
elif item.advancement or item.key: elif item.advancement or item.key:
ret.prog_items.append(item.name) ret.prog_items.append(item.name)
@ -360,7 +363,10 @@ class CollectionState(object):
return self.has('Power Glove') or self.has('Titans Mitts') return self.has('Power Glove') or self.has('Titans Mitts')
def has_bottle(self): def has_bottle(self):
return self.has('Bottle') or self.has('Bottle (Red Potion)') or self.has('Bottle (Green Potion)') or self.has('Bottle (Blue Potion)') or self.has('Bottle (Fairy)') or self.has('Bottle (Bee)') or self.has('Bottle (Good Bee)') return self.bottle_count() > 0
def bottle_count(self):
return len([pritem for pritem in self.prog_items if pritem.startswith('Bottle')])
def can_lift_heavy_rocks(self): def can_lift_heavy_rocks(self):
return self.has('Titans Mitts') return self.has('Titans Mitts')
@ -411,16 +417,16 @@ class CollectionState(object):
if 'Sword' in item.name: if 'Sword' in item.name:
if self.has('Golden Sword'): if self.has('Golden Sword'):
pass pass
elif self.has('Tempered Sword'): elif self.has('Tempered Sword') and self.world.difficulty_requirements.progressive_sword_limit >= 4:
self.prog_items.append('Golden Sword') self.prog_items.append('Golden Sword')
changed = True changed = True
elif self.has('Master Sword'): elif self.has('Master Sword') and self.world.difficulty_requirements.progressive_sword_limit >= 3:
self.prog_items.append('Tempered Sword') self.prog_items.append('Tempered Sword')
changed = True changed = True
elif self.has('Fighter Sword'): elif self.has('Fighter Sword') and self.world.difficulty_requirements.progressive_sword_limit >= 2:
self.prog_items.append('Master Sword') self.prog_items.append('Master Sword')
changed = True changed = True
else: elif self.world.difficulty_requirements.progressive_sword_limit >= 1:
self.prog_items.append('Fighter Sword') self.prog_items.append('Fighter Sword')
changed = True changed = True
elif 'Glove' in item.name: elif 'Glove' in item.name:
@ -435,16 +441,19 @@ class CollectionState(object):
elif 'Shield' in item.name: elif 'Shield' in item.name:
if self.has('Mirror Shield'): if self.has('Mirror Shield'):
pass pass
elif self.has('Red Shield'): elif self.has('Red Shield') and self.world.difficulty_requirements.progressive_shield_limit >= 3:
self.prog_items.append('Mirror Shield') self.prog_items.append('Mirror Shield')
changed = True changed = True
elif self.has('Blue Shield'): elif self.has('Blue Shield') and self.world.difficulty_requirements.progressive_shield_limit >= 2:
self.prog_items.append('Red Shield') self.prog_items.append('Red Shield')
changed = True changed = True
else: elif self.world.difficulty_requirements.progressive_shield_limit >= 1:
self.prog_items.append('Blue Shield') self.prog_items.append('Blue Shield')
changed = True changed = True
elif item.name.startswith('Bottle'):
if self.bottle_count() < self.world.difficulty_requirements.progressive_bottle_limit:
self.prog_items.append(item.name)
changed = True
elif event or item.advancement: elif event or item.advancement:
self.prog_items.append(item.name) self.prog_items.append(item.name)
changed = True changed = True
@ -758,5 +767,4 @@ class Spoiler(object):
path_lines.append(region) path_lines.append(region)
path_listings.append("{}\n {}".format(location, "\n => ".join(path_lines))) path_listings.append("{}\n {}".format(location, "\n => ".join(path_lines)))
#["%s: \n %s" % (location, "\n => ".join(zip_longest(*[iter(path)]*2))) for location, path in self.paths.items()]
outfile.write('\n'.join(path_listings)) outfile.write('\n'.join(path_listings))

View File

@ -62,7 +62,8 @@ Difficulty = namedtuple('Difficulty',
'basicshield', 'progressivearmor', 'basicarmor', 'swordless', 'basicshield', 'progressivearmor', 'basicarmor', 'swordless',
'progressivesword', 'basicsword', 'timedohko', 'timedother', 'progressivesword', 'basicsword', 'timedohko', 'timedother',
'triforcehunt', 'triforce_pieces_required', 'conditional_extras', 'triforcehunt', 'triforce_pieces_required', 'conditional_extras',
'extras']) 'extras', 'progressive_sword_limit', 'progressive_shield_limit',
'progressive_armor_limit', 'progressive_bottle_limit'])
total_items_to_place = 153 total_items_to_place = 153
@ -77,7 +78,7 @@ def easy_conditional_extras(timer, _goal, _mode, pool, placed_items):
def no_conditonal_extras(*_args): def no_conditonal_extras(*_args):
return [] return []
# pylint: disable=
difficulties = { difficulties = {
'normal': Difficulty( 'normal': Difficulty(
baseitems = normalbaseitems, baseitems = normalbaseitems,
@ -96,7 +97,11 @@ difficulties = {
triforcehunt = ['Triforce Piece'] * 30, triforcehunt = ['Triforce Piece'] * 30,
triforce_pieces_required = 20, triforce_pieces_required = 20,
conditional_extras = no_conditonal_extras, conditional_extras = no_conditonal_extras,
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra] extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
progressive_sword_limit = 4,
progressive_shield_limit = 3,
progressive_armor_limit = 2,
progressive_bottle_limit = 4,
), ),
'easy': Difficulty( 'easy': Difficulty(
baseitems = easybaseitems, baseitems = easybaseitems,
@ -116,6 +121,10 @@ difficulties = {
triforce_pieces_required = 10, triforce_pieces_required = 10,
conditional_extras = easy_conditional_extras, conditional_extras = easy_conditional_extras,
extras = [easyextra, easyfirst15extra, easysecond10extra, easythird5extra, easyfinal25extra], extras = [easyextra, easyfirst15extra, easysecond10extra, easythird5extra, easyfinal25extra],
progressive_sword_limit = 4,
progressive_shield_limit = 3,
progressive_armor_limit = 2,
progressive_bottle_limit = 4,
), ),
'hard': Difficulty( 'hard': Difficulty(
baseitems = hardbaseitems, baseitems = hardbaseitems,
@ -135,6 +144,10 @@ difficulties = {
triforce_pieces_required = 30, triforce_pieces_required = 30,
conditional_extras = no_conditonal_extras, conditional_extras = no_conditonal_extras,
extras = [hardfirst20extra, hardsecond20extra, hardthird20extra, hardfinal20extra], extras = [hardfirst20extra, hardsecond20extra, hardthird20extra, hardfinal20extra],
progressive_sword_limit = 3,
progressive_shield_limit = 2,
progressive_armor_limit = 1,
progressive_bottle_limit = 2,
), ),
'expert': Difficulty( 'expert': Difficulty(
baseitems = expertbaseitems, baseitems = expertbaseitems,
@ -154,6 +167,10 @@ difficulties = {
triforce_pieces_required = 40, triforce_pieces_required = 40,
conditional_extras = no_conditonal_extras, conditional_extras = no_conditonal_extras,
extras = [expertfirst15extra, expertsecond25extra, expertthird15extra, expertfinal25extra], extras = [expertfirst15extra, expertsecond25extra, expertthird15extra, expertfinal25extra],
progressive_sword_limit = 2,
progressive_shield_limit = 0,
progressive_armor_limit = 0,
progressive_bottle_limit = 1,
), ),
'insane': Difficulty( 'insane': Difficulty(
baseitems = insanebaseitems, baseitems = insanebaseitems,
@ -173,6 +190,10 @@ difficulties = {
triforce_pieces_required = 50, triforce_pieces_required = 50,
conditional_extras = no_conditonal_extras, conditional_extras = no_conditonal_extras,
extras = [insanefirst15extra, insanesecond25extra, insanethird10extra, insanefourth15extra, insanefinal25extra], extras = [insanefirst15extra, insanesecond25extra, insanethird10extra, insanefourth15extra, insanefinal25extra],
progressive_sword_limit = 2,
progressive_shield_limit = 0,
progressive_armor_limit = 0,
progressive_bottle_limit = 1,
), ),
} }

View File

@ -11,7 +11,7 @@ from Rom import patch_rom, Sprite, LocalRom, JsonRom
from Rules import set_rules from Rules import set_rules
from Dungeons import create_dungeons, fill_dungeons, fill_dungeons_restrictive from Dungeons import create_dungeons, fill_dungeons, fill_dungeons_restrictive
from Fill import distribute_items_cutoff, distribute_items_staleness, distribute_items_restrictive, flood_items from Fill import distribute_items_cutoff, distribute_items_staleness, distribute_items_restrictive, flood_items
from ItemList import generate_itempool from ItemList import generate_itempool, difficulties
from Utils import output_path from Utils import output_path
__version__ = '0.5.1-dev' __version__ = '0.5.1-dev'
@ -41,6 +41,8 @@ def main(args, seed=None):
logger.info('ALttP Entrance Randomizer Version %s - Seed: %s\n\n', __version__, world.seed) logger.info('ALttP Entrance Randomizer Version %s - Seed: %s\n\n', __version__, world.seed)
world.difficulty_requirements = difficulties[world.difficulty]
create_regions(world) create_regions(world)
create_dungeons(world) create_dungeons(world)
@ -134,6 +136,7 @@ def copy_world(world):
ret.seed = world.seed ret.seed = world.seed
ret.can_access_trock_eyebridge = world.can_access_trock_eyebridge ret.can_access_trock_eyebridge = world.can_access_trock_eyebridge
ret.can_take_damage = world.can_take_damage ret.can_take_damage = world.can_take_damage
ret.difficulty_requirements = world.difficulty_requirements
create_regions(ret) create_regions(ret)
create_dungeons(ret) create_dungeons(ret)

View File

@ -14,6 +14,7 @@ from Rom import patch_rom, LocalRom, Sprite, write_string_to_rom
from Rules import set_rules from Rules import set_rules
from Dungeons import create_dungeons from Dungeons import create_dungeons
from Items import ItemFactory from Items import ItemFactory
from ItemList import difficulties
from Main import create_playthrough from Main import create_playthrough
__version__ = '0.2-dev' __version__ = '0.2-dev'
@ -45,6 +46,8 @@ def main(args):
logger.info('ALttP Plandomizer Version %s - Seed: %s\n\n', __version__, args.plando) logger.info('ALttP Plandomizer Version %s - Seed: %s\n\n', __version__, args.plando)
world.difficulty_requirements = difficulties[world.difficulty]
create_regions(world) create_regions(world)
create_dungeons(world) create_dungeons(world)

28
Rom.py
View File

@ -11,6 +11,7 @@ from Text import string_to_alttp_text, text_addresses, Credits
from Text import Uncle_texts, Ganon1_texts, PyramidFairy_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts from Text import Uncle_texts, Ganon1_texts, PyramidFairy_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
from Utils import local_path from Utils import local_path
from Items import ItemFactory
JAP10HASH = '03a63945398191337e896e5771f77173' JAP10HASH = '03a63945398191337e896e5771f77173'
@ -345,6 +346,10 @@ def patch_rom(world, rom, hashtable, beep='normal', sprite=None):
rom.write_byte(0x180039, 0x01 if world.light_world_light_cone else 0x00) rom.write_byte(0x180039, 0x01 if world.light_world_light_cone else 0x00)
rom.write_byte(0x18003A, 0x01 if world.dark_world_light_cone else 0x00) rom.write_byte(0x18003A, 0x01 if world.dark_world_light_cone else 0x00)
GREEN_TWENTY_RUPEES = 0x47
TRIFORCE_PIECE = ItemFactory('Triforce Piece').code
GREEN_CLOCK = ItemFactory('Green Clock').code
# handle difficulty # handle difficulty
if world.difficulty == 'hard': if world.difficulty == 'hard':
# Powdered Fairies Prize # Powdered Fairies Prize
@ -359,8 +364,7 @@ def patch_rom(world, rom, hashtable, beep='normal', sprite=None):
rom.write_bytes(0x45C42, [0x08, 0x08, 0x08]) rom.write_bytes(0x45C42, [0x08, 0x08, 0x08])
#Disable catching fairies #Disable catching fairies
rom.write_byte(0x34FD6, 0x80) rom.write_byte(0x34FD6, 0x80)
#Set overflow items for progressive equipment overflow_replacement = GREEN_TWENTY_RUPEES
rom.write_bytes(0x180090, [0x03, 0x47, 0x02, 0x47, 0x01, 0x47, 0x02, 0x47])
# Rupoor negative value # Rupoor negative value
rom.write_int16_to_rom(0x180036, 10) rom.write_int16_to_rom(0x180036, 10)
#Make Blue Shield more expensive #Make Blue Shield more expensive
@ -394,8 +398,7 @@ def patch_rom(world, rom, hashtable, beep='normal', sprite=None):
rom.write_bytes(0x45C42, [0x08, 0x08, 0x08]) rom.write_bytes(0x45C42, [0x08, 0x08, 0x08])
#Disable catching fairies #Disable catching fairies
rom.write_byte(0x34FD6, 0x80) rom.write_byte(0x34FD6, 0x80)
#Set overflow items for progressive equipment overflow_replacement = GREEN_TWENTY_RUPEES
rom.write_bytes(0x180090, [0x02, 0x47, 0x00, 0x47, 0x00, 0x47, 0x01, 0x47])
# Rupoor negative value # Rupoor negative value
rom.write_int16_to_rom(0x180036, 20) rom.write_int16_to_rom(0x180036, 20)
#Make Blue Shield more expensive #Make Blue Shield more expensive
@ -429,8 +432,7 @@ def patch_rom(world, rom, hashtable, beep='normal', sprite=None):
rom.write_bytes(0x45C42, [0x08, 0x08, 0x08]) rom.write_bytes(0x45C42, [0x08, 0x08, 0x08])
#Disable catching fairies #Disable catching fairies
rom.write_byte(0x34FD6, 0x80) rom.write_byte(0x34FD6, 0x80)
#Set overflow items for progressive equipment overflow_replacement = GREEN_TWENTY_RUPEES
rom.write_bytes(0x180090, [0x02, 0x47, 0x00, 0x47, 0x00, 0x47, 0x01, 0x47])
# Rupoor negative value # Rupoor negative value
rom.write_int16_to_rom(0x180036, 9999) rom.write_int16_to_rom(0x180036, 9999)
#Make Blue Shield more expensive #Make Blue Shield more expensive
@ -466,11 +468,19 @@ def patch_rom(world, rom, hashtable, beep='normal', sprite=None):
rom.write_byte(0x34FD6, 0xF0) rom.write_byte(0x34FD6, 0xF0)
#Set overflow items for progressive equipment #Set overflow items for progressive equipment
if world.goal == 'triforcehunt': if world.goal == 'triforcehunt':
rom.write_bytes(0x180090, [0x04, 0x6C, 0x03, 0x6C, 0x02, 0x6C, 0x04, 0x6C]) overflow_replacement = TRIFORCE_PIECE
elif world.timer in ['timed', 'timed-countdown', 'timed-ohko']: elif world.timer in ['timed', 'timed-countdown', 'timed-ohko']:
rom.write_bytes(0x180090, [0x04, 0x5D, 0x03, 0x5D, 0x02, 0x5D, 0x04, 0x5D]) overflow_replacement = GREEN_CLOCK
else: else:
rom.write_bytes(0x180090, [0x04, 0x47, 0x03, 0x47, 0x02, 0x47, 0x04, 0x47]) overflow_replacement = GREEN_TWENTY_RUPEES
difficulty = world.difficulty_requirements
#Set overflow items for progressive equipment
rom.write_bytes(0x180090,
[difficulty.progressive_sword_limit, overflow_replacement,
difficulty.progressive_shield_limit, overflow_replacement,
difficulty.progressive_armor_limit, overflow_replacement,
difficulty.progressive_bottle_limit, overflow_replacement])
# set up game internal RNG seed # set up game internal RNG seed
for i in range(1024): for i in range(1024):

View File

@ -187,7 +187,7 @@ def global_rules(world):
set_rule(world.get_entrance('Superbunny Cave Exit (Bottom)'), lambda state: False) # Cannot get to bottom exit from top. Just exists for shuffling set_rule(world.get_entrance('Superbunny Cave Exit (Bottom)'), lambda state: False) # Cannot get to bottom exit from top. Just exists for shuffling
set_rule(world.get_location('Spike Cave'), lambda state: state.has('Hammer') and state.can_lift_rocks() and (state.has('Cane of Byrna') or state.has('Cape')) and state.can_extend_magic()) set_rule(world.get_location('Spike Cave'), lambda state: state.has('Hammer') and state.can_lift_rocks() and (state.has('Cane of Byrna') or state.has('Cape')) and state.can_extend_magic())
# TODO: Current-VT logic is: hammer and lift_rocks and ((cape and extend) or (byrna and (can-take-damage OR canextend))) # TODO: Current-VT logic is: hammer and lift_rocks and ((cape and extend) or (byrna and (can-take-damage OR canextend)))
# Is that really good enough? Can you really get through with byrna, single magic w/o refills and only 3 hearts? (answer: probnably but seems to requires tas-like timing.) # Is that really good enough? Can you really get through with byrna, single magic w/o refills and only 3 hearts? (answer: probably but seems to requires tas-like timing.)
set_rule(world.get_location('Hookshot Cave - Top Right'), lambda state: state.has('Hookshot')) set_rule(world.get_location('Hookshot Cave - Top Right'), lambda state: state.has('Hookshot'))
set_rule(world.get_location('Hookshot Cave - Top Left'), lambda state: state.has('Hookshot')) set_rule(world.get_location('Hookshot Cave - Top Left'), lambda state: state.has('Hookshot'))
set_rule(world.get_location('Hookshot Cave - Bottom Right'), lambda state: state.has('Hookshot') or state.has('Pegasus Boots')) set_rule(world.get_location('Hookshot Cave - Bottom Right'), lambda state: state.has('Hookshot') or state.has('Pegasus Boots'))
@ -298,7 +298,6 @@ def global_rules(world):
set_rule(world.get_entrance('Turtle Rock Dark Room Staircase'), lambda state: state.has('Small Key (Turtle Rock)', 3)) set_rule(world.get_entrance('Turtle Rock Dark Room Staircase'), lambda state: state.has('Small Key (Turtle Rock)', 3))
set_rule(world.get_entrance('Turtle Rock (Dark Room) (North)'), lambda state: state.has('Cane of Somaria')) set_rule(world.get_entrance('Turtle Rock (Dark Room) (North)'), lambda state: state.has('Cane of Somaria'))
set_rule(world.get_entrance('Turtle Rock (Dark Room) (South)'), lambda state: state.has('Cane of Somaria')) set_rule(world.get_entrance('Turtle Rock (Dark Room) (South)'), lambda state: state.has('Cane of Somaria'))
# FIXME: should shield overflow count check to the progrssive logic stuff, so we don't get false mirror shields which would cause problems here
set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Left'), lambda state: state.has('Cane of Byrna') or state.has('Cape') or state.has('Mirror Shield')) set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Left'), lambda state: state.has('Cane of Byrna') or state.has('Cape') or state.has('Mirror Shield'))
set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Right'), lambda state: state.has('Cane of Byrna') or state.has('Cape') or state.has('Mirror Shield')) set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Right'), lambda state: state.has('Cane of Byrna') or state.has('Cape') or state.has('Mirror Shield'))
set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Left'), lambda state: state.has('Cane of Byrna') or state.has('Cape') or state.has('Mirror Shield')) set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Left'), lambda state: state.has('Cane of Byrna') or state.has('Cape') or state.has('Mirror Shield'))
@ -312,17 +311,20 @@ def global_rules(world):
set_rule(world.get_entrance('Palace of Darkness Hammer Peg Drop'), lambda state: state.has('Hammer')) set_rule(world.get_entrance('Palace of Darkness Hammer Peg Drop'), lambda state: state.has('Hammer'))
set_rule(world.get_entrance('Palace of Darkness Bridge Room'), lambda state: state.has('Small Key (Palace of Darkness)', 1)) # If we can reach any other small key door, we already have back door access to this area set_rule(world.get_entrance('Palace of Darkness Bridge Room'), lambda state: state.has('Small Key (Palace of Darkness)', 1)) # If we can reach any other small key door, we already have back door access to this area
set_rule(world.get_entrance('Palace of Darkness Big Key Door'), lambda state: state.has('Small Key (Palace of Darkness)', 6) and state.has('Big Key (Palace of Darkness)') and state.has('Bow') and state.has('Hammer')) set_rule(world.get_entrance('Palace of Darkness Big Key Door'), lambda state: state.has('Small Key (Palace of Darkness)', 6) and state.has('Big Key (Palace of Darkness)') and state.has('Bow') and state.has('Hammer'))
set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase'), lambda state: state.has('Small Key (Palace of Darkness)', 5) or (item_name(state.world.get_location('Palace of Darkness - Big Key Chest')) in ['Small Key (Palace of Darkness)']))
set_rule(world.get_entrance('Palace of Darkness (North)'), lambda state: state.has('Small Key (Palace of Darkness)', 4)) set_rule(world.get_entrance('Palace of Darkness (North)'), lambda state: state.has('Small Key (Palace of Darkness)', 4))
set_rule(world.get_location('Palace of Darkness - Big Chest'), lambda state: state.has('Big Key (Palace of Darkness)')) set_rule(world.get_location('Palace of Darkness - Big Chest'), lambda state: state.has('Big Key (Palace of Darkness)'))
if world.keysanity: if world.keysanity:
set_rule(world.get_entrance('Palace of Darkness Spike Statue Room Door'), lambda state: state.has('Small Key (Palace of Darkness)', 6) or (item_name(state.world.get_location('Palace of Darkness - Harmless Hellway')) in ['Small Key (Palace of Darkness)'])) set_rule(world.get_entrance('Palace of Darkness Spike Statue Room Door'), lambda state: state.has('Small Key (Palace of Darkness)', 6) or (item_name(state.world.get_location('Palace of Darkness - Harmless Hellway')) in ['Small Key (Palace of Darkness)']))
# TODO: add an always_allow rule for this to permit key for a key
set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase'), lambda state: state.has('Small Key (Palace of Darkness)', 6) or (item_name(state.world.get_location('Palace of Darkness - Big Key Chest')) in ['Small Key (Palace of Darkness)'])) set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase'), lambda state: state.has('Small Key (Palace of Darkness)', 6) or (item_name(state.world.get_location('Palace of Darkness - Big Key Chest')) in ['Small Key (Palace of Darkness)']))
# TODO: add an always_allow rule for this to permit key for a key
set_rule(world.get_entrance('Palace of Darkness Maze Door'), lambda state: state.has('Small Key (Palace of Darkness)', 6)) set_rule(world.get_entrance('Palace of Darkness Maze Door'), lambda state: state.has('Small Key (Palace of Darkness)', 6))
else: else:
set_rule(world.get_entrance('Palace of Darkness Spike Statue Room Door'), lambda state: state.has('Small Key (Palace of Darkness)', 5) or (item_name(state.world.get_location('Palace of Darkness - Harmless Hellway')) in ['Small Key (Palace of Darkness)'])) set_rule(world.get_entrance('Palace of Darkness Spike Statue Room Door'), lambda state: state.has('Small Key (Palace of Darkness)', 5) or (item_name(state.world.get_location('Palace of Darkness - Harmless Hellway')) in ['Small Key (Palace of Darkness)']))
# TODO: add an always_allow rule for this to permit key for a key
set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase'), lambda state: state.has('Small Key (Palace of Darkness)', 5) or (item_name(state.world.get_location('Palace of Darkness - Big Key Chest')) in ['Small Key (Palace of Darkness)'])) set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase'), lambda state: state.has('Small Key (Palace of Darkness)', 5) or (item_name(state.world.get_location('Palace of Darkness - Big Key Chest')) in ['Small Key (Palace of Darkness)']))
# TODO: add an always_allow rule for this to permit key for a key
set_rule(world.get_entrance('Palace of Darkness Maze Door'), lambda state: state.has('Small Key (Palace of Darkness)', 5)) set_rule(world.get_entrance('Palace of Darkness Maze Door'), lambda state: state.has('Small Key (Palace of Darkness)', 5))
for location in ['Palace of Darkness - Big Chest', 'Palace of Darkness - Helmasaur']: for location in ['Palace of Darkness - Big Chest', 'Palace of Darkness - Helmasaur']: