Whitespace fixes

This commit is contained in:
Kevin Cathcart 2017-11-04 14:23:57 -04:00
parent cdf04b8a45
commit 5b3d4449c1
10 changed files with 85 additions and 83 deletions

View File

@ -96,7 +96,7 @@ class World(object):
def get_all_state(self, keys=False):
ret = CollectionState(self)
def soft_collect(item):
if item.name.startswith('Progressive '):
if 'Sword' in item.name:

View File

@ -13,6 +13,7 @@ class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
def _get_help_string(self, action):
return textwrap.dedent(action.help)
if __name__ == '__main__':
parser = argparse.ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
parser.add_argument('--create_spoiler', help='Output a Spoiler File', action='store_true')

View File

@ -668,7 +668,7 @@ def connect_entrance(world, entrancename, exitname):
# if this was already connected somewhere, remove the backreference
if entrance.connected_region is not None:
entrance.connected_region.entrances.remove(entrance)
target = exit_ids[exit.name][0] if exit is not None else exit_ids.get(region.name, None)
addresses = door_addresses[entrance.name][0][0] if exit is not None else door_addresses[entrance.name][0]
try:
@ -676,7 +676,7 @@ def connect_entrance(world, entrancename, exitname):
vanilla = exit_ids[vanilla_ref]
except IndexError:
vanilla = None
entrance.connect(region, addresses, target, vanilla)
world.spoiler.set_entrance(entrance.name, exit.name if exit is not None else region.name, 'entrance')

View File

@ -1,6 +1,7 @@
import random
import logging
def distribute_items_cutoff(world, cutoffrate=0.33):
# get list of locations to fill in
fill_locations = world.get_unfilled_locations()
@ -55,7 +56,7 @@ def distribute_items_cutoff(world, cutoffrate=0.33):
raise RuntimeError('No more progress items left to place.')
spot_to_fill = None
for location in (fill_locations if placed_advancement_items/total_advancement_items < cutoffrate else reversed(fill_locations)):
for location in (fill_locations if placed_advancement_items / total_advancement_items < cutoffrate else reversed(fill_locations)):
if world.state.can_reach(location) and location.can_fill(item_to_place):
spot_to_fill = location
break
@ -199,7 +200,7 @@ def fill_restrictive(world, base_state, locations, itempool):
spot_to_fill.event = True
def distribute_items_restrictive(world, gftower_trash_count=0,fill_locations=None):
def distribute_items_restrictive(world, gftower_trash_count=0, fill_locations=None):
# If not passed in, then get a shuffled list of locations to fill in
if not fill_locations:
fill_locations = world.get_unfilled_locations()
@ -223,7 +224,7 @@ def distribute_items_restrictive(world, gftower_trash_count=0,fill_locations=Non
trashcnt += 1
random.shuffle(fill_locations)
fill_locations.reverse()
fill_locations.reverse()
fill_restrictive(world, world.state, fill_locations, progitempool)
@ -242,7 +243,7 @@ def fast_fill(world, item_pool, fill_locations):
item_to_place = item_pool.pop()
world.push_item(spot_to_fill, item_to_place, False)
def flood_items(world):
# get items to distribute
random.shuffle(world.itempool)

21
Gui.py
View File

@ -38,18 +38,19 @@ def guiMain(args=None):
dungeonItemsCheckbutton.pack(expand=True, anchor=W)
beatableOnlyCheckbutton.pack(expand=True, anchor=W)
shuffleGanonCheckbutton.pack(expand=True, anchor=W)
fileDialogFrame = Frame(rightHalfFrame)
romDialogFrame = Frame(fileDialogFrame)
baseRomLabel = Label(romDialogFrame, text='Base Rom')
romVar = StringVar()
romEntry = Entry(romDialogFrame, textvariable=romVar)
def RomSelect():
rom = filedialog.askopenfilename()
romVar.set(rom)
romSelectButton = Button(romDialogFrame, text='Select Rom', command=RomSelect)
baseRomLabel.pack(side=LEFT)
romEntry.pack(side=LEFT)
romSelectButton.pack(side=LEFT)
@ -68,7 +69,7 @@ def guiMain(args=None):
baseSpriteLabel.pack(side=LEFT)
spriteEntry.pack(side=LEFT)
spriteSelectButton.pack(side=LEFT)
romDialogFrame.pack()
spriteDialogFrame.pack()
@ -84,7 +85,7 @@ def guiMain(args=None):
modeOptionMenu.pack(side=RIGHT)
modeLabel = Label(modeFrame, text='Game Mode')
modeLabel.pack(side=LEFT)
logicFrame = Frame(drowDownFrame)
logicVar = StringVar()
logicVar.set('noglitches')
@ -92,7 +93,7 @@ def guiMain(args=None):
logicOptionMenu.pack(side=RIGHT)
logicLabel = Label(logicFrame, text='Game logic')
logicLabel.pack(side=LEFT)
goalFrame = Frame(drowDownFrame)
goalVar = StringVar()
goalVar.set('ganon')
@ -100,7 +101,7 @@ def guiMain(args=None):
goalOptionMenu.pack(side=RIGHT)
goalLabel = Label(goalFrame, text='Game goal')
goalLabel.pack(side=LEFT)
difficultyFrame = Frame(drowDownFrame)
difficultyVar = StringVar()
difficultyVar.set('normal')
@ -108,7 +109,7 @@ def guiMain(args=None):
difficultyOptionMenu.pack(side=RIGHT)
difficultyLabel = Label(difficultyFrame, text='Game difficulty')
difficultyLabel.pack(side=LEFT)
algorithmFrame = Frame(drowDownFrame)
algorithmVar = StringVar()
algorithmVar.set('vt26')
@ -116,7 +117,7 @@ def guiMain(args=None):
algorithmOptionMenu.pack(side=RIGHT)
algorithmLabel = Label(algorithmFrame, text='Item distribution algorithm')
algorithmLabel.pack(side=LEFT)
shuffleFrame = Frame(drowDownFrame)
shuffleVar = StringVar()
shuffleVar.set('full')
@ -124,7 +125,7 @@ def guiMain(args=None):
shuffleOptionMenu.pack(side=RIGHT)
shuffleLabel = Label(shuffleFrame, text='Entrance shuffle algorithm')
shuffleLabel.pack(side=LEFT)
heartbeepFrame = Frame(drowDownFrame)
heartbeepVar = StringVar()
heartbeepVar.set('normal')
@ -140,7 +141,7 @@ def guiMain(args=None):
algorithmFrame.pack(expand=True, anchor=E)
shuffleFrame.pack(expand=True, anchor=E)
heartbeepFrame.pack(expand=True, anchor=E)
bottomFrame = Frame(mainWindow)
seedLabel = Label(bottomFrame, text='Seed #')

View File

@ -19,7 +19,7 @@ def ItemFactory(items):
else:
logging.getLogger('').warning('Unknown Item: %s' % item)
return None
if singleton:
return ret[0]
else:

View File

@ -40,8 +40,8 @@ def main(args, seed=None):
logger.info('ALttP Entrance Randomizer Version %s - Seed: %s\n\n' % (__version__, world.seed))
create_regions(world)
create_dungeons(world);
create_dungeons(world)
logger.info('Shuffling the World about.')
@ -91,7 +91,7 @@ def main(args, seed=None):
else:
sprite = None
outfilebase = 'ER_%s_%s-%s-%s_%s-%s%s%s%s%s_%s' % (world.logic, world.difficulty, world.mode, world.goal, world.shuffle, world.algorithm, "-keysanity" if world.keysanity else "", "-fastmenu" if world.fastmenu else "","-quickswap" if world.quickswap else "", "-shuffleganon" if world.shuffle_ganon else "", world.seed)
outfilebase = 'ER_%s_%s-%s-%s_%s-%s%s%s%s%s_%s' % (world.logic, world.difficulty, world.mode, world.goal, world.shuffle, world.algorithm, "-keysanity" if world.keysanity else "", "-fastmenu" if world.fastmenu else "", "-quickswap" if world.quickswap else "", "-shuffleganon" if world.shuffle_ganon else "", world.seed)
if not args.suppress_rom:
if args.jsonout:
@ -182,7 +182,7 @@ def generate_itempool(world):
world.treasure_hunt_icon = 'Triforce Piece'
world.itempool.extend(ItemFactory(['Triforce Piece'] * 30))
world.itempool.append(ItemFactory('Magic Upgrade (1/2)'))
world.itempool.append(ItemFactory('Magic Upgrade (1/2)'))
# shuffle medallions
mm_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)]
@ -315,4 +315,3 @@ def create_playthrough(world):
# we can finally output our playthrough
old_world.spoiler.playthrough = OrderedDict([(str(i + 1), {str(location): str(location.item) for location in sphere}) for i, sphere in enumerate(collection_spheres)])

View File

@ -16,10 +16,10 @@ def create_regions(world):
'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Swamp Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid']),
create_region('Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Teleporter']),
create_region('Blinds Hideout', ["Blind\'s Hideout - Top",
"Blind\'s Hideout - Left",
"Blind\'s Hideout - Right",
"Blind\'s Hideout - Far Left",
"Blind\'s Hideout - Far Right"]),
"Blind\'s Hideout - Left",
"Blind\'s Hideout - Right",
"Blind\'s Hideout - Far Left",
"Blind\'s Hideout - Far Right"]),
create_region('Hyrule Castle Secret Entrance', ['Link\'s Uncle', 'Secret Passage'], ['Hyrule Castle Secret Entrance Exit']),
create_region('Zoras River', ['King Zora', 'Zora\'s Ledge']),
create_region('Waterfall of Wishing', ['Waterfall Fairy - Left', 'Waterfall Fairy - Right']),
@ -60,7 +60,7 @@ def create_regions(world):
create_region('Checkerboard Cave', ['Checkerboard Cave']),
create_region('Long Fairy Cave'),
create_region('Mini Moldorm Cave', ['Mini Moldorm Cave - Far Left', 'Mini Moldorm Cave - Left', 'Mini Moldorm Cave - Right',
'Mini Moldorm Cave - Far Right', 'Mini Moldorm Cave - Generous Guy']),
'Mini Moldorm Cave - Far Right', 'Mini Moldorm Cave - Generous Guy']),
create_region('Ice Rod Cave', ['Ice Rod Cave']),
create_region('Good Bee Cave'),
create_region('20 Rupee Cave'),
@ -110,12 +110,12 @@ def create_regions(world):
create_region('Hookshot Fairy'),
create_region('Paradox Cave Front', None, ['Paradox Cave Push Block Reverse', 'Paradox Cave Exit (Bottom)']),
create_region('Paradox Cave Chest Area', ['Paradox Cave Lower - Far Left',
'Paradox Cave Lower - Left',
'Paradox Cave Lower - Right',
'Paradox Cave Lower - Far Right',
'Paradox Cave Lower - Middle',
'Paradox Cave Upper - Left',
'Paradox Cave Upper - Right'],
'Paradox Cave Lower - Left',
'Paradox Cave Lower - Right',
'Paradox Cave Lower - Far Right',
'Paradox Cave Lower - Middle',
'Paradox Cave Upper - Left',
'Paradox Cave Upper - Right'],
['Paradox Cave Push Block', 'Paradox Cave Bomb Jump']),
create_region('Paradox Cave', None, ['Paradox Cave Exit (Middle)', 'Paradox Cave Exit (Top)', 'Paradox Cave Drop']),
create_region('East Death Mountain (Top)', None, ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'Turtle Rock Teleporter', 'Fairy Ascension Ledge']),
@ -136,7 +136,7 @@ def create_regions(world):
create_region('Palace of Darkness Hint'),
create_region('East Dark World Hint'),
create_region('South Dark World', ['Stumpy', 'Digging Game', 'Bombos Tablet'], ['Dark Lake Hylia Drop (South)', 'Dark Swamp Cave', 'Swamp Palace', 'Village of Outcasts Heavy Rock',
'Maze Race Mirror Spot', 'Cave 45', 'East Dark World Bridge', 'Big Bomb Shop', 'Archery Game', 'Bonk Fairy (Dark)', 'Dark Lake Hylia Shop']),
'Maze Race Mirror Spot', 'Cave 45', 'East Dark World Bridge', 'Big Bomb Shop', 'Archery Game', 'Bonk Fairy (Dark)', 'Dark Lake Hylia Shop']),
create_region('Big Bomb Shop'),
create_region('Archery Game'),
create_region('Dark Lake Hylia', None, ['Lake Hylia Island Mirror Spot', 'East Dark World Pier', 'Dark Lake Hylia Ledge']),
@ -261,8 +261,8 @@ def create_regions(world):
create_region('Pyramid', ['Ganon'], ['Ganon Drop']),
create_region('Bottom of Pyramid', None, ['Pyramid Exit']),
create_region('Pyramid Ledge', None, ['Pyramid Entrance', 'Pyramid Drop'])
]
]
world.intialize_regions()

62
Rom.py
View File

@ -64,7 +64,7 @@ class LocalRom(object):
patchedmd5 = hashlib.md5()
patchedmd5.update(self.buffer)
if not RANDOMIZERBASEHASH == patchedmd5.hexdigest():
raise RuntimeError('Provided Base Rom unsuitable for patching. Please provide a JAP(1.0) "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc" rom to use as a base.')
raise RuntimeError('Provided Base Rom unsuitable for patching. Please provide a JAP(1.0) "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc" rom to use as a base.')
def write_crc(self):
# this does not seem to work
@ -83,12 +83,14 @@ def patch_rom(world, rom, hashtable, beep='normal', sprite=None):
locationaddress = location.address
if not location.crystal:
#Keys in their native dungeon should use the orignal item code for keys
# Keys in their native dungeon should use the orignal item code for keys
if location.parent_region.dungeon:
dungeon=location.parent_region.dungeon
dungeon = location.parent_region.dungeon
if location.item.key and dungeon.is_dungeon_item(location.item):
if location.item.type == "BigKey": itemid = 0x32
if location.item.type == "SmallKey": itemid = 0x24
if location.item.type == "BigKey":
itemid = 0x32
if location.item.type == "SmallKey":
itemid = 0x24
rom.write_byte(locationaddress, itemid)
else:
# crystals
@ -103,9 +105,9 @@ def patch_rom(world, rom, hashtable, beep='normal', sprite=None):
music = 0x11 if 'Pendant' in location.item.name else 0x16
for music_address in music_addresses:
rom.write_byte(music_address, music)
if world.keysanity:
rom.write_byte(0x155C9, random.choice([0x11, 0x16])) #Randomize GT music too in keysanity mode
rom.write_byte(0x155C9, random.choice([0x11, 0x16])) # Randomize GT music too in keysanity mode
# patch entrances
for region in world.regions:
@ -316,15 +318,15 @@ def patch_rom(world, rom, hashtable, beep='normal', sprite=None):
rom.write_byte(0x18003E, 0x04) # make ganon invincible until all crystals
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
# compasses showing dungeon count
if world.clock_mode != 'off':
rom.write_byte(0x18003C, 0x00) #Currently must be off if timer is on, because they use same HUD location
rom.write_byte(0x18003C, 0x00) # Currently must be off if timer is on, because they use same HUD location
elif world.keysanity:
rom.write_byte(0x18003C, 0x01) #show on pickup
rom.write_byte(0x18003C, 0x01) # show on pickup
else:
rom.write_byte(0x18003C, 0x00)
rom.write_byte(0x180045, 0x01 if world.keysanity else 0x00) # free roaming items in menu
digging_game_rng = random.randint(1, 30) # set rng for digging game
rom.write_byte(0x180020, digging_game_rng)
@ -375,29 +377,29 @@ def patch_rom(world, rom, hashtable, beep='normal', sprite=None):
rom.write_byte(0x15E25, 0xA4)
# todo fix screen scrolling
#enable instant item menu
if world.fastmenu:
# enable instant item menu
if world.fastmenu:
rom.write_byte(0x180048, 0x01)
# Sound twekas for fastmenu:
rom.write_byte(0x6DD9A, 0x20)
rom.write_byte(0x6DF2A, 0x20)
rom.write_byte(0x6E0E9, 0x20)
# enable quick item swapping with L and R (ported by Amazing Ampharos)
if world.quickswap:
rom.write_bytes(0x107fb, [0x22, 0x50, 0xFF, 0x1F])
rom.write_bytes(0x12451, [0x22, 0x50, 0xFF, 0x1F])
rom.write_bytes(0xfff50, [0x20, 0x58, 0xFF, 0xA5, 0xF6, 0x29, 0x40, 0x6B, 0xA5, 0xF6, 0x89, 0x10, 0xF0, 0x03, 0x4C, 0x69,
0xFF, 0x89, 0x20, 0xF0, 0x03, 0x4C, 0xAA, 0xFF, 0x60, 0xAD, 0x02, 0x02, 0xF0, 0x3B, 0xDA, 0xAA,
0xE0, 0x0F, 0xF0, 0x14, 0xE0, 0x10, 0xF0, 0x14, 0xE0, 0x14, 0xD0, 0x02, 0xA2, 0x00, 0xE8, 0xBF,
0x3F, 0xF3, 0x7E, 0xF0, 0xEB, 0x4C, 0xEB, 0xFF, 0xA2, 0x01, 0x80, 0x0A, 0xAF, 0x4F, 0xF3, 0x7E,
0xAA, 0xE0, 0x04, 0xF0, 0x10, 0xE8, 0xBF, 0x5B, 0xF3, 0x7E, 0xF0, 0xF5, 0x8A, 0x8F, 0x4F, 0xF3,
0x7E, 0xA2, 0x10, 0x80, 0xE0, 0xA2, 0x11, 0x80, 0xD6, 0x60, 0xAD, 0x02, 0x02, 0xF0, 0x3B, 0xDA,
0xAA, 0xE0, 0x11, 0xF0, 0x14, 0xE0, 0x10, 0xF0, 0x14, 0xE0, 0x01, 0xD0, 0x02, 0xA2, 0x15, 0xCA,
0xBF, 0x3F, 0xF3, 0x7E, 0xF0, 0xEB, 0x4C, 0xEB, 0xFF, 0xA2, 0x04, 0x80, 0x0A, 0xAF, 0x4F, 0xF3,
0x7E, 0xAA, 0xE0, 0x01, 0xF0, 0x10, 0xCA, 0xBF, 0x5B, 0xF3, 0x7E, 0xF0, 0xF5, 0x8A, 0x8F, 0x4F,
0xF3, 0x7E, 0xA2, 0x10, 0x80, 0xE0, 0xA2, 0x0F, 0x80, 0xD6, 0x60, 0xA9, 0x20, 0x8D, 0x2F, 0x01,
0x8E, 0x02, 0x02, 0x22, 0x7F, 0xDB, 0x0D, 0xFA, 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
0xFF, 0x89, 0x20, 0xF0, 0x03, 0x4C, 0xAA, 0xFF, 0x60, 0xAD, 0x02, 0x02, 0xF0, 0x3B, 0xDA, 0xAA,
0xE0, 0x0F, 0xF0, 0x14, 0xE0, 0x10, 0xF0, 0x14, 0xE0, 0x14, 0xD0, 0x02, 0xA2, 0x00, 0xE8, 0xBF,
0x3F, 0xF3, 0x7E, 0xF0, 0xEB, 0x4C, 0xEB, 0xFF, 0xA2, 0x01, 0x80, 0x0A, 0xAF, 0x4F, 0xF3, 0x7E,
0xAA, 0xE0, 0x04, 0xF0, 0x10, 0xE8, 0xBF, 0x5B, 0xF3, 0x7E, 0xF0, 0xF5, 0x8A, 0x8F, 0x4F, 0xF3,
0x7E, 0xA2, 0x10, 0x80, 0xE0, 0xA2, 0x11, 0x80, 0xD6, 0x60, 0xAD, 0x02, 0x02, 0xF0, 0x3B, 0xDA,
0xAA, 0xE0, 0x11, 0xF0, 0x14, 0xE0, 0x10, 0xF0, 0x14, 0xE0, 0x01, 0xD0, 0x02, 0xA2, 0x15, 0xCA,
0xBF, 0x3F, 0xF3, 0x7E, 0xF0, 0xEB, 0x4C, 0xEB, 0xFF, 0xA2, 0x04, 0x80, 0x0A, 0xAF, 0x4F, 0xF3,
0x7E, 0xAA, 0xE0, 0x01, 0xF0, 0x10, 0xCA, 0xBF, 0x5B, 0xF3, 0x7E, 0xF0, 0xF5, 0x8A, 0x8F, 0x4F,
0xF3, 0x7E, 0xA2, 0x10, 0x80, 0xE0, 0xA2, 0x0F, 0x80, 0xD6, 0x60, 0xA9, 0x20, 0x8D, 0x2F, 0x01,
0x8E, 0x02, 0x02, 0x22, 0x7F, 0xDB, 0x0D, 0xFA, 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
write_strings(rom, world)
@ -502,16 +504,16 @@ def write_strings(rom, world):
sickkiditem = world.get_location('Sick Kid').item
sickkiditem_text = SickKid_texts[random.randint(0, len(SickKid_texts) - 1)] if sickkiditem is None or sickkiditem.sickkid_credit_text is None else sickkiditem.sickkid_credit_text
write_credits_string_to_rom(rom, 'SickKid', sickkiditem_text)
write_credits_string_to_rom(rom, 'SickKid', sickkiditem_text)
zoraitem = world.get_location('King Zora').item
zoraitem_text = Zora_texts[random.randint(0, len(Zora_texts) - 1)] if zoraitem is None or zoraitem.zora_credit_text is None else zoraitem.zora_credit_text
write_credits_string_to_rom(rom, 'Zora', zoraitem_text)
write_credits_string_to_rom(rom, 'Zora', zoraitem_text)
magicshopitem = world.get_location('Potion Shop').item
magicshopitem_text = MagicShop_texts[random.randint(0, len(MagicShop_texts) - 1)] if magicshopitem is None or magicshopitem.magicshop_credit_text is None else magicshopitem.magicshop_credit_text
write_credits_string_to_rom(rom, 'MagicShop', magicshopitem_text)
write_credits_string_to_rom(rom, 'MagicShop', magicshopitem_text)
fluteboyitem = world.get_location('Stumpy').item
fluteboyitem_text = FluteBoy_texts[random.randint(0, len(FluteBoy_texts) - 1)] if fluteboyitem is None or fluteboyitem.fluteboy_credit_text is None else fluteboyitem.fluteboy_credit_text
write_credits_string_to_rom(rom, 'FluteBoy', fluteboyitem_text)

View File

@ -3,7 +3,7 @@ import logging
def set_rules(world):
global_rules(world)
if world.mode == 'open':
open_rules(world)
elif world.mode == 'standard':
@ -20,8 +20,6 @@ def set_rules(world):
else:
raise NotImplementedError('Not implemented yet')
if world.goal == 'dungeons':
# require all dungeons to beat ganon
add_rule(world.get_location('Ganon'), lambda state: state.can_reach('Master Sword Pedestal', 'Location') and state.has('Beat Agahnim 1') and state.has('Beat Agahnim 2'))
@ -55,10 +53,11 @@ def add_lamp_requirement(spot):
def forbid_item(location, item):
old_rule = location.item_rule
location.item_rule = lambda i: i.name != item and old_rule(i)
def item_in_locations(state, item, locations):
for location in locations:
loc=state.world.get_location(location)
loc = state.world.get_location(location)
if loc.item is not None and loc.item.name == item:
return True
return False
@ -205,10 +204,9 @@ def global_rules(world):
(state.has_blunt_weapon() or state.has('Fire Rod') or state.has('Ice Rod') or state.has('Bow')))
for location in ['Desert Palace - Lanmolas', 'Desert Palace - Big Chest']:
forbid_item(world.get_location(location), 'Big Key (Desert Palace)')
for location in ['Desert Palace - Lanmolas', 'Desert Palace - Big Key Chest', 'Desert Palace - Compass Chest']:
forbid_item(world.get_location(location), 'Small Key (Desert Palace)')
set_rule(world.get_entrance('Tower of Hera Small Key Door'), lambda state: state.has('Small Key (Tower of Hera)'))
set_rule(world.get_entrance('Tower of Hera Big Key Door'), lambda state: state.has('Big Key (Tower of Hera)'))
@ -242,7 +240,7 @@ def global_rules(world):
set_rule(world.get_entrance('Skull Woods First Section South Door'), lambda state: state.has('Small Key (Skull Woods)'))
set_rule(world.get_entrance('Skull Woods First Section (Right) North Door'), lambda state: state.has('Small Key (Skull Woods)'))
set_rule(world.get_entrance('Skull Woods First Section West Door'), lambda state: state.has('Small Key (Skull Woods)', 2)) #ideally would only be one key, but we may have spent thst key already on escaping the right section
set_rule(world.get_entrance('Skull Woods First Section West Door'), lambda state: state.has('Small Key (Skull Woods)', 2)) # ideally would only be one key, but we may have spent thst key already on escaping the right section
set_rule(world.get_entrance('Skull Woods First Section (Left) Door to Exit'), lambda state: state.has('Small Key (Skull Woods)', 2))
set_rule(world.get_location('Skull Woods - Big Chest'), lambda state: state.has('Big Key (Skull Woods)'))
set_rule(world.get_entrance('Skull Woods Torch Room'), lambda state: state.has('Small Key (Skull Woods)', 3) and state.has('Fire Rod') and state.has_sword()) # sword required for curtain
@ -254,7 +252,7 @@ def global_rules(world):
set_rule(world.get_entrance('Ice Palace Entrance Room'), lambda state: state.has('Fire Rod') or (state.has('Bombos') and state.has_sword()))
set_rule(world.get_location('Ice Palace - Big Chest'), lambda state: state.has('Big Key (Ice Palace)'))
set_rule(world.get_entrance('Ice Palace (Kholdstare)'), lambda state: state.can_lift_rocks() and state.has('Hammer') and state.has('Big Key (Ice Palace)') and (state.has('Small Key (Ice Palace)', 2) or (state.has('Cane of Somaria') and state.has('Small Key (Ice Palace)', 1))))
set_rule(world.get_entrance('Ice Palace (East)'), lambda state: (state.has('Hookshot') or (item_in_locations(state,'Big Key (Ice Palace)',['Ice Palace - Spike Room','Ice Palace - Big Key Chest','Ice Palace - Map Chest']) and state.has('Small Key (Ice Palace)')) or state.has('Small Key (Ice Palace)',2)) and (state.has('Hookshot') or state.has('Cape') or state.has('Cane of Byrna')))
set_rule(world.get_entrance('Ice Palace (East)'), lambda state: (state.has('Hookshot') or (item_in_locations(state, 'Big Key (Ice Palace)', ['Ice Palace - Spike Room', 'Ice Palace - Big Key Chest', 'Ice Palace - Map Chest']) and state.has('Small Key (Ice Palace)')) or state.has('Small Key (Ice Palace)', 2)) and (state.has('Hookshot') or state.has('Cape') or state.has('Cane of Byrna')))
set_rule(world.get_entrance('Ice Palace (East Top)'), lambda state: state.can_lift_rocks() and state.has('Hammer'))
for location in ['Ice Palace - Big Chest', 'Ice Palace - Kholdstare']:
forbid_item(world.get_location(location), 'Big Key (Ice Palace)')
@ -270,7 +268,7 @@ def global_rules(world):
set_rule(world.get_location('Misery Mire - Main Lobby'), lambda state: state.has('Small Key (Misery Mire)', 2) or state.has('Big Key (Misery Mire)'))
# we can place a small key in the West wing iff it also contains/blocks the Big Key, as we cannot reach and softlock with the basement key door yet
set_rule(world.get_entrance('Misery Mire (West)'), lambda state: state.has('Small Key (Misery Mire)', 2) if ((state.world.get_location('Misery Mire - Compass Chest').item is not None and state.world.get_location('Misery Mire - Compass Chest').item.name in ['Big Key (Misery Mire)']) or
(state.world.get_location('Misery Mire - Big Key Chest').item is not None and state.world.get_location('Misery Mire - Big Key Chest').item.name in ['Big Key (Misery Mire)'])) else state.has('Small Key (Misery Mire)', 3))
(state.world.get_location('Misery Mire - Big Key Chest').item is not None and state.world.get_location('Misery Mire - Big Key Chest').item.name in ['Big Key (Misery Mire)'])) else state.has('Small Key (Misery Mire)', 3))
set_rule(world.get_location('Misery Mire - Compass Chest'), lambda state: state.has_fire_source())
set_rule(world.get_location('Misery Mire - Big Key Chest'), lambda state: state.has_fire_source())
set_rule(world.get_entrance('Misery Mire (Vitreous)'), lambda state: state.has('Cane of Somaria') and (state.has('Bow') or state.has_blunt_weapon()))
@ -293,7 +291,7 @@ def global_rules(world):
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 Right'), lambda state: state.has('Cane of Byrna') or state.has('Cape') or state.has('Mirror Shield'))
set_rule(world.get_entrance('Turtle Rock (Trinexx)'), lambda state: state.has('Small Key (Turtle Rock)', 4) and state.has('Big Key (Turtle Rock)') and state.has('Cane of Somaria') and state.has('Fire Rod') and state.has('Ice Rod') and
(state.has('Hammer') or state.has_beam_sword() or state.has('Bottle') or state.has('Half Magic') or state.has('Quarter Magic')))
(state.has('Hammer') or state.has_beam_sword() or state.has('Bottle') or state.has('Half Magic') or state.has('Quarter Magic')))
set_trock_key_rules(world)
set_rule(world.get_entrance('Palace of Darkness Bonk Wall'), lambda state: state.has('Bow'))
@ -307,7 +305,7 @@ def global_rules(world):
set_rule(world.get_location('Palace of Darkness - Big Chest'), lambda state: state.has('Big Key (Palace of Darkness)'))
for location in ['Palace of Darkness - Big Chest', 'Palace of Darkness - Helmasaur']:
forbid_item(world.get_location(location), 'Big Key (Palace of Darkness)')
for location in ['Palace of Darkness - Big Chest', 'Palace of Darkness - Dark Maze - Top', 'Palace of Darkness - Dark Maze - Bottom']:
forbid_item(world.get_location(location), 'Small Key (Palace of Darkness)')
@ -351,7 +349,7 @@ def no_glitches_rules(world):
add_rule(world.get_entrance('Ganons Tower (Hookshot Room)'), lambda state: state.has('Hookshot'))
set_rule(world.get_entrance('Paradox Cave Push Block Reverse'), lambda state: False) # no glitches does not require block override
set_rule(world.get_entrance('Paradox Cave Bomb Jump'), lambda state: False)
set_rule(world.get_entrance('Skull Woods First Section Bomb Jump'), lambda state: False)
set_rule(world.get_entrance('Skull Woods First Section Bomb Jump'), lambda state: False)
# Light cones in standard depend on which world we actually are in, not which one the location would normally be
# We add Lamp requirements only to those locations which lie in the dark world (or everything if open
@ -462,7 +460,7 @@ def set_trock_key_rules(world):
for location in non_big_key_locations:
forbid_item(world.get_location(location), 'Big Key (Turtle Rock)')
# small key restriction
for location in ['Turtle Rock - Trinexx']:
forbid_item(world.get_location(location), 'Small Key (Turtle Rock)')
@ -531,8 +529,8 @@ def set_big_bomb_rules(world):
'Cave Shop (Dark Death Mountain)',
'Dark Death Mountain Fairy',
'Mimic Cave Mirror Spot']
Isolated_LW_entrances =['Capacity Upgrade',
'Hookshot Fairy']
Isolated_LW_entrances = ['Capacity Upgrade',
'Hookshot Fairy']
set_rule(world.get_entrance('Pyramid Fairy'), lambda state: state.has_Pearl() and state.can_reach('Big Bomb Shop', 'Region') and state.has('Crystal 5') and state.has('Crystal 6'))
if bombshop_entrance.name in Normal_LW_entrances:
add_rule(world.get_entrance('Pyramid Fairy'), lambda state: state.can_reach('Top of Pyramid', 'Entrance') or (state.has('Hammer') and state.can_lift_rocks()) or state.has_Mirror())