Make "Prize" shuffling an option

This commit is contained in:
Fabian Dill 2020-09-20 04:35:45 +02:00
parent 37a3c8f0d5
commit a668aa3b23
7 changed files with 93 additions and 60 deletions

View File

@ -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"])}: '

View File

@ -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})

15
Gui.py
View File

@ -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()),

View File

@ -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)}

View File

@ -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():

115
Rom.py
View File

@ -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, [

View File

@ -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.