From 5b3d4449c137c0fb025b5ac6a3e72fd9d864fe5b Mon Sep 17 00:00:00 2001 From: Kevin Cathcart Date: Sat, 4 Nov 2017 14:23:57 -0400 Subject: [PATCH] Whitespace fixes --- BaseClasses.py | 2 +- EntranceRandomizer.py | 1 + EntranceShuffle.py | 4 +-- Fill.py | 9 ++++--- Gui.py | 21 ++++++++------- Items.py | 2 +- Main.py | 9 +++---- Regions.py | 28 +++++++++---------- Rom.py | 62 ++++++++++++++++++++++--------------------- Rules.py | 30 ++++++++++----------- 10 files changed, 85 insertions(+), 83 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index c8cf551d..55aa1ba6 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -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: diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index f824a4ee..5d9a47b4 100644 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -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') diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 8a230e52..2ddd5463 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -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') diff --git a/Fill.py b/Fill.py index 512229b3..983a3279 100644 --- a/Fill.py +++ b/Fill.py @@ -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) diff --git a/Gui.py b/Gui.py index d2171e08..3a815344 100644 --- a/Gui.py +++ b/Gui.py @@ -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 #') diff --git a/Items.py b/Items.py index a2dd2ae7..9d0becff 100644 --- a/Items.py +++ b/Items.py @@ -19,7 +19,7 @@ def ItemFactory(items): else: logging.getLogger('').warning('Unknown Item: %s' % item) return None - + if singleton: return ret[0] else: diff --git a/Main.py b/Main.py index 9f4baef5..d1a145fd 100644 --- a/Main.py +++ b/Main.py @@ -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)]) - diff --git a/Regions.py b/Regions.py index e85eee73..33f40306 100644 --- a/Regions.py +++ b/Regions.py @@ -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() diff --git a/Rom.py b/Rom.py index 3e27dad1..76dcfdfb 100644 --- a/Rom.py +++ b/Rom.py @@ -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) diff --git a/Rules.py b/Rules.py index 7c9541ff..9b09f87e 100644 --- a/Rules.py +++ b/Rules.py @@ -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())