From 1e644836bb647412ce72836337f69cd59a752d09 Mon Sep 17 00:00:00 2001 From: LLCoolDave Date: Mon, 17 Jul 2017 22:28:29 +0200 Subject: [PATCH] Add --shuffleganon option to include Ganon's Tower and Pyramid in shuffle pool. --- BaseClasses.py | 5 +++-- EntranceRandomizer.py | 13 +++++++++---- Gui.py | 7 ++++++- Main.py | 4 ++-- Plando.py | 2 +- README.md | 8 ++++++++ 6 files changed, 29 insertions(+), 10 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index fe7bfc02..d49b12f5 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -4,7 +4,7 @@ import logging class World(object): - def __init__(self, shuffle, logic, mode, difficulty, goal, algorithm, place_dungeon_items, check_beatable_only): + def __init__(self, shuffle, logic, mode, difficulty, goal, algorithm, place_dungeon_items, check_beatable_only, shuffle_ganon): self.shuffle = shuffle self.logic = logic self.mode = mode @@ -41,7 +41,8 @@ class World(object): self.fix_skullwoods_exit = self.shuffle not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'] self.fix_palaceofdarkness_exit = self.shuffle not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'] self.fix_trock_exit = self.shuffle not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'] - self.fix_gtower_exit = self.goal != 'ganon' + self.shuffle_ganon = shuffle_ganon + self.fix_gtower_exit = self.shuffle_ganon def get_region(self, regionname): if isinstance(regionname, Region): diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index 61c63bf8..8199a7bf 100644 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -26,7 +26,7 @@ if __name__ == '__main__': parser.add_argument('--mode', default='open', const='open', nargs='?', choices=['standard', 'open', 'swordless'], help='''\ Select game mode. (default: %(default)s) - Open: + Open: World starts with Zelda rescued. Standard: Fixes Hyrule Castle Secret Entrance and Front Door but may lead to weird rain state issues if you exit through the Hyrule Castle side exits before rescuing @@ -42,10 +42,11 @@ if __name__ == '__main__': parser.add_argument('--goal', default='ganon', const='ganon', nargs='?', choices=['ganon', 'pedestal', 'dungeons', 'starhunt', 'triforcehunt'], help='''\ Select completion goal. (default: %(default)s) - Ganon: Defeat Ganon. + Ganon: Collect all crystals, beat Agahnim 2 then + defeat Ganon. Pedestal: Places the Triforce at the Master Sword Pedestal. - All Dungeons: Not enforced ingame but considered in the - playthrough. + All Dungeons: Collect all crystals, pendants, beat both + Agahnim fights and then defeat Ganon. Star Hunt: Places 15 Power Stars in the world, collect 10 of them to beat the game. Triforce Hunt: Places 3 Triforce Pieces in the world, collect @@ -130,6 +131,10 @@ if __name__ == '__main__': ensure all locations are reachable. This only has an effect on the restrictive algorithm currently. ''', action='store_true') + parser.add_argument('--shuffleganon', help='''\ + If set, include the Pyramid Hole and Ganon's Tower in the + entrance shuffle pool. + ''', action='store_true') parser.add_argument('--heartbeep', default='normal', const='normal', nargs='?', choices=['normal', 'half', 'quarter', 'off'], help='''\ Select the rate at which the heart beep sound is played at diff --git a/Gui.py b/Gui.py index 19b0af09..60a0668b 100644 --- a/Gui.py +++ b/Gui.py @@ -23,12 +23,15 @@ def guiMain(args=None): dungeonItemsCheckbutton = Checkbutton(checkBoxFrame, text="Place Dungeon Items (Compasses/Maps)", onvalue=0, offvalue=1, variable=dungeonItemsVar) beatableOnlyVar = IntVar() beatableOnlyCheckbutton = Checkbutton(checkBoxFrame, text="Only ensure seed is beatable, not all items must be reachable", variable=beatableOnlyVar) + shuffleGanonVar = IntVar() + shuffleGanonCheckbutton = Checkbutton(checkBoxFrame, text="Include Ganon's Tower and Pyramid Hole in shuffle pool", variable=shuffleGanonVar) createSpoilerCheckbutton.pack(expand=True, anchor=W) suppressRomCheckbutton.pack(expand=True, anchor=W) quickSwapCheckbutton.pack(expand=True, anchor=W) dungeonItemsCheckbutton.pack(expand=True, anchor=W) - beatableOnlyCheckbutton.pack(expand=True, anchor=W) + beatableOnlyCheckbutton.pack(expand=True, anchor=W) + shuffleGanonCheckbutton.pack(expand=True, anchor=W) fileDialogFrame = Frame(rightHalfFrame) @@ -157,6 +160,7 @@ def guiMain(args=None): guiargs.nodungeonitems = bool(dungeonItemsVar.get()) guiargs.beatableonly = bool(beatableOnlyVar.get()) guiargs.quickswap = bool(quickSwapVar.get()) + guiargs.shuffleganon = bool(shuffleGanonVar.get()) guiargs.rom = romVar.get() guiargs.jsonout = None guiargs.sprite = spriteVar.get() if spriteVar.get() else None @@ -206,6 +210,7 @@ def guiMain(args=None): heartbeepVar.set(args.heartbeep) logicVar.set(args.logic) romVar.set(args.rom) + shuffleGanonVar.set(args.shuffleganon) if args.sprite is not None: spriteVar.set(args.sprite) diff --git a/Main.py b/Main.py index d0ea3b05..868ecb1d 100644 --- a/Main.py +++ b/Main.py @@ -26,7 +26,7 @@ def main(args, seed=None): start = time.clock() # initialize the world - world = World(args.shuffle, args.logic, args.mode, args.difficulty, args.goal, args.algorithm, not args.nodungeonitems, args.beatableonly) + world = World(args.shuffle, args.logic, args.mode, args.difficulty, args.goal, args.algorithm, not args.nodungeonitems, args.beatableonly, args.shuffleganon) logger = logging.getLogger('') if seed is None: @@ -502,7 +502,7 @@ def generate_itempool(world): def copy_world(world): # ToDo: Not good yet - ret = World(world.shuffle, world.logic, world.mode, world.difficulty, world.goal, world.algorithm, world.place_dungeon_items, world.check_beatable_only) + ret = World(world.shuffle, world.logic, world.mode, world.difficulty, world.goal, world.algorithm, world.place_dungeon_items, world.check_beatable_only, world.shuffle_ganon) ret.required_medallions = list(world.required_medallions) ret.swamp_patch_required = world.swamp_patch_required ret.treasure_hunt_count = world.treasure_hunt_count diff --git a/Plando.py b/Plando.py index a4ab418b..3420f70a 100644 --- a/Plando.py +++ b/Plando.py @@ -28,7 +28,7 @@ def main(args, seed=None): start = time.clock() # initialize the world - world = World('vanilla', 'noglitches', 'standard', 'normal', 'ganon', 'freshness', False, False) + world = World('vanilla', 'noglitches', 'standard', 'normal', 'ganon', 'freshness', False, False, False) logger = logging.getLogger('') hasher = hashlib.md5() diff --git a/README.md b/README.md index afa38d24..958f1941 100644 --- a/README.md +++ b/README.md @@ -206,6 +206,14 @@ Use to select a different sprite sheet to use for Link. Path to a binary file of If set, will only ensure the goal can be achieved, but not necessarily that all locations are reachable. Currently only affects restrictive algorithm. +``` +--shuffleganon +``` + +If set, Ganon's Tower is included in the dungeon shuffle pool and the Pyramid Hole/Exit pair is included in the Holes shuffle pool. Ganon can not be defeated until the primary goal is fulfilled. + +Note: This option is under development and may sometimes lead to dungeon and crystal distributions that cannot be solved. If this is the case, the generation will fail. Simply retry with a different seed number if you run into this issue. + ``` --suppress_rom ```