From a668aa3b23d1802448a4e2284f935b59cbd03d0d Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 20 Sep 2020 04:35:45 +0200 Subject: [PATCH] Make "Prize" shuffling an option --- BaseClasses.py | 11 ++-- EntranceRandomizer.py | 3 +- Gui.py | 15 +++++- Main.py | 1 + Mystery.py | 3 ++ Rom.py | 115 ++++++++++++++++++++++-------------------- playerSettings.yaml | 5 ++ 7 files changed, 93 insertions(+), 60 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 9e8da063..6b81e207 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -59,7 +59,6 @@ class World(object): self._entrance_cache = {} self._location_cache = {} self.required_locations = [] - self.shuffle_bonk_prizes = False self.light_world_light_cone = False self.dark_world_light_cone = False self.rupoor_cost = 10 @@ -125,6 +124,7 @@ class World(object): set_player_attr('triforce_pieces_available', 30) set_player_attr('triforce_pieces_required', 20) set_player_attr('shop_shuffle', 'off') + set_player_attr('shuffle_prizes', "g") def secure(self): self.random = secrets.SystemRandom() @@ -1290,7 +1290,8 @@ class Spoiler(object): 'progression_balancing': self.world.progression_balancing, 'triforce_pieces_available': self.world.triforce_pieces_available, 'triforce_pieces_required': self.world.triforce_pieces_required, - 'shop_shuffle': self.world.shop_shuffle + 'shop_shuffle': self.world.shop_shuffle, + 'shuffle_prizes': self.world.shuffle_prizes } def to_json(self): @@ -1381,8 +1382,10 @@ class Spoiler(object): outfile.write( 'Hints: %s\n' % ('Yes' if self.metadata['hints'][player] else 'No')) outfile.write('Beemizer: %s\n' % self.metadata['beemizer'][player]) - outfile.write( - 'Pot shuffle %s\n' % ('Yes' if self.metadata['shufflepots'][player] else 'No')) + outfile.write('Pot shuffle %s\n' + % ('Yes' if self.metadata['shufflepots'][player] else 'No')) + outfile.write('Prize shuffle %s\n' % + self.metadata['shuffle_prizes'][player]) if self.entrances: outfile.write('\n\nEntrances:\n\n') outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index f72001f0..d74c9aaa 100755 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -314,6 +314,7 @@ def parse_arguments(argv, no_defaults=False): p: randomize the prices of the items in shop inventories u: shuffle capacity upgrades into the item pool ''') + parser.add_argument('--shuffle_prizes', default=defval('g'), choices=['', 'g', 'b', 'gb']) parser.add_argument('--remote_items', default=defval(False), action='store_true') parser.add_argument('--multi', default=defval(1), type=lambda value: min(max(int(value), 1), 255)) parser.add_argument('--names', default=defval('')) @@ -359,7 +360,7 @@ def parse_arguments(argv, no_defaults=False): 'heartbeep', "skip_progression_balancing", "triforce_pieces_available", "triforce_pieces_required", "shop_shuffle", 'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves', - 'tile_shuffle', 'bush_shuffle']: + 'tile_shuffle', 'bush_shuffle', 'shuffle_prizes']: value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) if player == 1: setattr(ret, name, {1: value}) diff --git a/Gui.py b/Gui.py index de25c062..284be31b 100755 --- a/Gui.py +++ b/Gui.py @@ -349,9 +349,17 @@ def guiMain(args=None): 'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy', 'dungeonsfull', 'dungeonssimple') shuffleOptionMenu.pack(side=RIGHT) - shuffleLabel = Label(shuffleFrame, text='Entrance shuffle algorithm') + shuffleLabel = Label(shuffleFrame, text='Entrance shuffle') shuffleLabel.pack(side=LEFT) + prizeFrame = Frame(drowDownFrame) + prizeVar = StringVar() + prizeVar.set('general') + prizeOptionMenu = OptionMenu(prizeFrame, prizeVar, 'none', 'general', 'bonk', 'both') + prizeOptionMenu.pack(side=RIGHT) + prizeLabel = Label(prizeFrame, text='Shuffle Prices/Drops') + prizeLabel.pack(side=LEFT) + modeFrame.pack(expand=True, anchor=E) logicFrame.pack(expand=True, anchor=E) @@ -367,6 +375,7 @@ def guiMain(args=None): accessibilityFrame.pack(expand=True, anchor=E) algorithmFrame.pack(expand=True, anchor=E) shuffleFrame.pack(expand=True, anchor=E) + prizeFrame.pack(expand=True, anchor=E) enemizerFrame = LabelFrame(randomizerWindow, text="Enemizer", padx=5, pady=2) @@ -534,6 +543,10 @@ def guiMain(args=None): guiargs.shop_shuffle += "p" if shopUpgradeShuffleVar.get(): guiargs.shop_shuffle += "u" + guiargs.shuffle_prizes = {"none": "", + "bonk": "b", + "general": "g", + "both": "bg"}[prizeVar.get()] guiargs.customitemarray = [int(bowVar.get()), int(silverarrowVar.get()), int(boomerangVar.get()), int(magicboomerangVar.get()), int(hookshotVar.get()), int(mushroomVar.get()), int(magicpowderVar.get()), int(firerodVar.get()), diff --git a/Main.py b/Main.py index 53f72a04..8f1fcfa1 100644 --- a/Main.py +++ b/Main.py @@ -80,6 +80,7 @@ def main(args, seed=None): world.triforce_pieces_required = args.triforce_pieces_required.copy() world.shop_shuffle = args.shop_shuffle.copy() world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()} + world.shuffle_prizes = args.shuffle_prizes.copy() world.rom_seeds = {player: random.Random(world.random.randint(0, 999999999)) for player in range(1, world.players + 1)} diff --git a/Mystery.py b/Mystery.py index a22e44ea..0dea4de2 100644 --- a/Mystery.py +++ b/Mystery.py @@ -411,6 +411,9 @@ def roll_settings(weights): ret.dungeon_counters = get_choice('dungeon_counters', weights, 'default') ret.progressive = convert_to_on_off(get_choice('progressive', weights, 'on')) + + ret.shuffle_prizes = get_choice('shuffle_prizes', weights, "g") + inventoryweights = weights.get('startinventory', {}) startitems = [] for item in inventoryweights.keys(): diff --git a/Rom.py b/Rom.py index df8f5d22..5c17b472 100644 --- a/Rom.py +++ b/Rom.py @@ -805,72 +805,79 @@ def patch_rom(world, rom, player, team, enemized): # set up game internal RNG seed rom.write_bytes(0x178000, local_random.getrandbits(8 * 1024).to_bytes(1024, 'big')) + if "g" in world.shuffle_prizes[player]: + # shuffle prize packs + prizes = [0xD8, 0xD8, 0xD8, 0xD8, 0xD9, 0xD8, 0xD8, 0xD9, 0xDA, 0xD9, 0xDA, 0xDB, 0xDA, 0xD9, 0xDA, 0xDA, 0xE0, 0xDF, 0xDF, 0xDA, 0xE0, 0xDF, 0xD8, 0xDF, + 0xDC, 0xDC, 0xDC, 0xDD, 0xDC, 0xDC, 0xDE, 0xDC, 0xE1, 0xD8, 0xE1, 0xE2, 0xE1, 0xD8, 0xE1, 0xE2, 0xDF, 0xD9, 0xD8, 0xE1, 0xDF, 0xDC, 0xD9, 0xD8, + 0xD8, 0xE3, 0xE0, 0xDB, 0xDE, 0xD8, 0xDB, 0xE2, 0xD9, 0xDA, 0xDB, 0xD9, 0xDB, 0xD9, 0xDB] + dig_prizes = [0xB2, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, + 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, + 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, + 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, + 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, + 0xE3, 0xE3, 0xE3, 0xE3, 0xE3] - # shuffle prize packs - prizes = [0xD8, 0xD8, 0xD8, 0xD8, 0xD9, 0xD8, 0xD8, 0xD9, 0xDA, 0xD9, 0xDA, 0xDB, 0xDA, 0xD9, 0xDA, 0xDA, 0xE0, 0xDF, 0xDF, 0xDA, 0xE0, 0xDF, 0xD8, 0xDF, - 0xDC, 0xDC, 0xDC, 0xDD, 0xDC, 0xDC, 0xDE, 0xDC, 0xE1, 0xD8, 0xE1, 0xE2, 0xE1, 0xD8, 0xE1, 0xE2, 0xDF, 0xD9, 0xD8, 0xE1, 0xDF, 0xDC, 0xD9, 0xD8, - 0xD8, 0xE3, 0xE0, 0xDB, 0xDE, 0xD8, 0xDB, 0xE2, 0xD9, 0xDA, 0xDB, 0xD9, 0xDB, 0xD9, 0xDB] - dig_prizes = [0xB2, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, - 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, - 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, - 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, - 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, - 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, - 0xE3, 0xE3, 0xE3, 0xE3, 0xE3] + def chunk(l,n): + return [l[i:i+n] for i in range(0, len(l), n)] - def chunk(l,n): - return [l[i:i+n] for i in range(0, len(l), n)] + # randomize last 7 slots + prizes [-7:] = local_random.sample(prizes, 7) - # randomize last 7 slots - prizes [-7:] = local_random.sample(prizes, 7) + #shuffle order of 7 main packs + packs = chunk(prizes[:56], 8) + local_random.shuffle(packs) + prizes[:56] = [drop for pack in packs for drop in pack] - #shuffle order of 7 main packs - packs = chunk(prizes[:56], 8) - local_random.shuffle(packs) - prizes[:56] = [drop for pack in packs for drop in pack] + if world.difficulty_adjustments[player] in ['hard', 'expert']: + prize_replacements = {0xE0: 0xDF, # Fairy -> heart + 0xE3: 0xD8} # Big magic -> small magic + prizes = [prize_replacements.get(prize, prize) for prize in prizes] + dig_prizes = [prize_replacements.get(prize, prize) for prize in dig_prizes] - if world.difficulty_adjustments[player] in ['hard', 'expert']: - prize_replacements = {0xE0: 0xDF, # Fairy -> heart - 0xE3: 0xD8} # Big magic -> small magic - prizes = [prize_replacements.get(prize, prize) for prize in prizes] - dig_prizes = [prize_replacements.get(prize, prize) for prize in dig_prizes] + if world.retro[player]: + prize_replacements = {0xE1: 0xDA, #5 Arrows -> Blue Rupee + 0xE2: 0xDB} #10 Arrows -> Red Rupee + prizes = [prize_replacements.get(prize, prize) for prize in prizes] + dig_prizes = [prize_replacements.get(prize, prize) for prize in dig_prizes] + rom.write_bytes(0x180100, dig_prizes) - if world.retro[player]: - prize_replacements = {0xE1: 0xDA, #5 Arrows -> Blue Rupee - 0xE2: 0xDB} #10 Arrows -> Red Rupee - prizes = [prize_replacements.get(prize, prize) for prize in prizes] - dig_prizes = [prize_replacements.get(prize, prize) for prize in dig_prizes] - rom.write_bytes(0x180100, dig_prizes) + # write tree pull prizes + rom.write_byte(0xEFBD4, prizes.pop()) + rom.write_byte(0xEFBD5, prizes.pop()) + rom.write_byte(0xEFBD6, prizes.pop()) - # write tree pull prizes - rom.write_byte(0xEFBD4, prizes.pop()) - rom.write_byte(0xEFBD5, prizes.pop()) - rom.write_byte(0xEFBD6, prizes.pop()) + # rupee crab prizes + rom.write_byte(0x329C8, prizes.pop()) # first prize + rom.write_byte(0x329C4, prizes.pop()) # final prize - # rupee crab prizes - rom.write_byte(0x329C8, prizes.pop()) # first prize - rom.write_byte(0x329C4, prizes.pop()) # final prize + # stunned enemy prize + rom.write_byte(0x37993, prizes.pop()) - # stunned enemy prize - rom.write_byte(0x37993, prizes.pop()) + # saved fish prize + rom.write_byte(0xE82CC, prizes.pop()) - # saved fish prize - rom.write_byte(0xE82CC, prizes.pop()) + # fill enemy prize packs + rom.write_bytes(0x37A78, prizes) - # fill enemy prize packs - rom.write_bytes(0x37A78, prizes) - - # set bonk prizes - bonk_prizes = [0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xAC, 0xE3, 0xE3, 0xDA, 0xE3, 0xDA, 0xD8, 0xAC, 0xAC, 0xE3, 0xD8, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xDC, 0xDB, 0xE3, 0xDA, 0x79, 0x79, 0xE3, 0xE3, - 0xDA, 0x79, 0xAC, 0xAC, 0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xE3, 0x79, 0xDE, 0xE3, 0xAC, 0xDB, 0x79, 0xE3, 0xD8, 0xAC, 0x79, 0xE3, 0xDB, 0xDB, 0xE3, 0xE3, 0x79, 0xD8, 0xDD] - bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028, 0x4D03C, 0x4D059, 0x4D07A, 0x4D09E, 0x4D0A8, 0x4D0AB, 0x4D0AE, 0x4D0BE, 0x4D0DD, - 0x4D16A, 0x4D1E5, 0x4D1EE, 0x4D20B, 0x4CBBF, 0x4CBBF, 0x4CC17, 0x4CC1A, 0x4CC4A, 0x4CC4D, 0x4CC53, 0x4CC69, 0x4CC6F, 0x4CC7C, 0x4CCEF, 0x4CD51, - 0x4CDC0, 0x4CDC3, 0x4CDC6, 0x4CE37, 0x4D2DE, 0x4D32F, 0x4D355, 0x4D367, 0x4D384, 0x4D387, 0x4D397, 0x4D39E, 0x4D3AB, 0x4D3AE, 0x4D3D1, 0x4D3D7, - 0x4D3F8, 0x4D416, 0x4D420, 0x4D423, 0x4D42D, 0x4D449, 0x4D48C, 0x4D4D9, 0x4D4DC, 0x4D4E3, 0x4D504, 0x4D507, 0x4D55E, 0x4D56A] - if world.shuffle_bonk_prizes: + if "b" in world.shuffle_prizes[player]: + # set bonk prizes + bonk_prizes = [0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xAC, 0xE3, 0xE3, 0xDA, 0xE3, 0xDA, 0xD8, 0xAC, + 0xAC, 0xE3, 0xD8, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xDC, 0xDB, 0xE3, 0xDA, 0x79, 0x79, + 0xE3, 0xE3, + 0xDA, 0x79, 0xAC, 0xAC, 0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xE3, 0x79, 0xDE, 0xE3, + 0xAC, 0xDB, 0x79, 0xE3, 0xD8, 0xAC, 0x79, 0xE3, 0xDB, 0xDB, 0xE3, 0xE3, 0x79, 0xD8, 0xDD] + bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028, 0x4D03C, 0x4D059, 0x4D07A, + 0x4D09E, 0x4D0A8, 0x4D0AB, 0x4D0AE, 0x4D0BE, 0x4D0DD, + 0x4D16A, 0x4D1E5, 0x4D1EE, 0x4D20B, 0x4CBBF, 0x4CBBF, 0x4CC17, 0x4CC1A, 0x4CC4A, 0x4CC4D, + 0x4CC53, 0x4CC69, 0x4CC6F, 0x4CC7C, 0x4CCEF, 0x4CD51, + 0x4CDC0, 0x4CDC3, 0x4CDC6, 0x4CE37, 0x4D2DE, 0x4D32F, 0x4D355, 0x4D367, 0x4D384, 0x4D387, + 0x4D397, 0x4D39E, 0x4D3AB, 0x4D3AE, 0x4D3D1, 0x4D3D7, + 0x4D3F8, 0x4D416, 0x4D420, 0x4D423, 0x4D42D, 0x4D449, 0x4D48C, 0x4D4D9, 0x4D4DC, 0x4D4E3, + 0x4D504, 0x4D507, 0x4D55E, 0x4D56A] local_random.shuffle(bonk_prizes) - for prize, address in zip(bonk_prizes, bonk_addresses): - rom.write_byte(address, prize) + for prize, address in zip(bonk_prizes, bonk_addresses): + rom.write_byte(address, prize) # Fill in item substitutions table rom.write_bytes(0x184000, [ diff --git a/playerSettings.yaml b/playerSettings.yaml index a4cc06ec..e52a7f5a 100644 --- a/playerSettings.yaml +++ b/playerSettings.yaml @@ -194,6 +194,11 @@ shop_shuffle: ip: 0 # Shuffle inventories and randomize prices uip: 0 # Shuffle inventories, randomize prices and shuffle capacity upgrades into the item pool # You can add more combos +shuffle_prizes: # aka drops + none: 0 # do not shuffle prize packs + g: 50 # shuffle "general" price packs, as in enemy, tree pull, dig etc. + b: 0 # shuffle "bonk" price packs + bg: 0 # shuffle both timer: none: 50 # No timer will be displayed. timed: 0 # Starts with clock at zero. Green clocks subtract 4 minutes (total 20). Blue clocks subtract 2 minutes (total 10). Red clocks add two minutes (total 10). Winner is the player with the lowest time at the end.