Individual settings: difficulty and item_functionality

This commit is contained in:
Bonta-kun 2019-12-16 17:46:21 +01:00
parent 0b999abb8a
commit 203147dda1
6 changed files with 41 additions and 41 deletions

View File

@ -14,8 +14,8 @@ class World(object):
self.logic = logic.copy() self.logic = logic.copy()
self.mode = mode.copy() self.mode = mode.copy()
self.swords = swords.copy() self.swords = swords.copy()
self.difficulty = difficulty self.difficulty = difficulty.copy()
self.difficulty_adjustments = difficulty_adjustments self.difficulty_adjustments = difficulty_adjustments.copy()
self.timer = timer self.timer = timer
self.progressive = progressive self.progressive = progressive
self.goal = goal.copy() self.goal = goal.copy()
@ -71,7 +71,7 @@ class World(object):
self.custom = custom self.custom = custom
self.customitemarray = customitemarray self.customitemarray = customitemarray
self.can_take_damage = True self.can_take_damage = True
self.difficulty_requirements = None self.difficulty_requirements = {player: None for player in range(1, players + 1)}
self.fix_fake_world = True self.fix_fake_world = True
self.boss_shuffle = boss_shuffle self.boss_shuffle = boss_shuffle
self.escape_assist = {player: [] for player in range(1, players + 1)} self.escape_assist = {player: [] for player in range(1, players + 1)}
@ -147,13 +147,13 @@ class World(object):
if 'Sword' in item.name: if 'Sword' in item.name:
if ret.has('Golden Sword', item.player): if ret.has('Golden Sword', item.player):
pass pass
elif ret.has('Tempered Sword', item.player) and self.difficulty_requirements.progressive_sword_limit >= 4: elif ret.has('Tempered Sword', item.player) and self.difficulty_requirements[item.player].progressive_sword_limit >= 4:
ret.prog_items.add(('Golden Sword', item.player)) ret.prog_items.add(('Golden Sword', item.player))
elif ret.has('Master Sword', item.player) and self.difficulty_requirements.progressive_sword_limit >= 3: elif ret.has('Master Sword', item.player) and self.difficulty_requirements[item.player].progressive_sword_limit >= 3:
ret.prog_items.add(('Tempered Sword', item.player)) ret.prog_items.add(('Tempered Sword', item.player))
elif ret.has('Fighter Sword', item.player) and self.difficulty_requirements.progressive_sword_limit >= 2: elif ret.has('Fighter Sword', item.player) and self.difficulty_requirements[item.player].progressive_sword_limit >= 2:
ret.prog_items.add(('Master Sword', item.player)) ret.prog_items.add(('Master Sword', item.player))
elif self.difficulty_requirements.progressive_sword_limit >= 1: elif self.difficulty_requirements[item.player].progressive_sword_limit >= 1:
ret.prog_items.add(('Fighter Sword', item.player)) ret.prog_items.add(('Fighter Sword', item.player))
elif 'Glove' in item.name: elif 'Glove' in item.name:
if ret.has('Titans Mitts', item.player): if ret.has('Titans Mitts', item.player):
@ -165,21 +165,21 @@ class World(object):
elif 'Shield' in item.name: elif 'Shield' in item.name:
if ret.has('Mirror Shield', item.player): if ret.has('Mirror Shield', item.player):
pass pass
elif ret.has('Red Shield', item.player) and self.difficulty_requirements.progressive_shield_limit >= 3: elif ret.has('Red Shield', item.player) and self.difficulty_requirements[item.player].progressive_shield_limit >= 3:
ret.prog_items.add(('Mirror Shield', item.player)) ret.prog_items.add(('Mirror Shield', item.player))
elif ret.has('Blue Shield', item.player) and self.difficulty_requirements.progressive_shield_limit >= 2: elif ret.has('Blue Shield', item.player) and self.difficulty_requirements[item.player].progressive_shield_limit >= 2:
ret.prog_items.add(('Red Shield', item.player)) ret.prog_items.add(('Red Shield', item.player))
elif self.difficulty_requirements.progressive_shield_limit >= 1: elif self.difficulty_requirements[item.player].progressive_shield_limit >= 1:
ret.prog_items.add(('Blue Shield', item.player)) ret.prog_items.add(('Blue Shield', item.player))
elif 'Bow' in item.name: elif 'Bow' in item.name:
if ret.has('Silver Arrows', item.player): if ret.has('Silver Arrows', item.player):
pass pass
elif ret.has('Bow', item.player) and self.difficulty_requirements.progressive_bow_limit >= 2: elif ret.has('Bow', item.player) and self.difficulty_requirements[item.player].progressive_bow_limit >= 2:
ret.prog_items.add(('Silver Arrows', item.player)) ret.prog_items.add(('Silver Arrows', item.player))
elif self.difficulty_requirements.progressive_bow_limit >= 1: elif self.difficulty_requirements[item.player].progressive_bow_limit >= 1:
ret.prog_items.add(('Bow', item.player)) ret.prog_items.add(('Bow', item.player))
elif item.name.startswith('Bottle'): elif item.name.startswith('Bottle'):
if ret.bottle_count(item.player) < self.difficulty_requirements.progressive_bottle_limit: if ret.bottle_count(item.player) < self.difficulty_requirements[item.player].progressive_bottle_limit:
ret.prog_items.add((item.name, item.player)) ret.prog_items.add((item.name, item.player))
elif item.advancement or item.smallkey or item.bigkey: elif item.advancement or item.smallkey or item.bigkey:
ret.prog_items.add((item.name, item.player)) ret.prog_items.add((item.name, item.player))
@ -413,7 +413,7 @@ class CollectionState(object):
def heart_count(self, player): def heart_count(self, player):
# Warning: This only considers items that are marked as advancement items # Warning: This only considers items that are marked as advancement items
diff = self.world.difficulty_requirements diff = self.world.difficulty_requirements[player]
return ( return (
min(self.item_count('Boss Heart Container', player), diff.boss_heart_container_limit) min(self.item_count('Boss Heart Container', player), diff.boss_heart_container_limit)
+ self.item_count('Sanctuary Heart Container', player) + self.item_count('Sanctuary Heart Container', player)
@ -431,9 +431,9 @@ class CollectionState(object):
elif self.has('Half Magic', player): elif self.has('Half Magic', player):
basemagic = 16 basemagic = 16
if self.can_buy_unlimited('Green Potion', player) or self.can_buy_unlimited('Blue Potion', player): if self.can_buy_unlimited('Green Potion', player) or self.can_buy_unlimited('Blue Potion', player):
if self.world.difficulty_adjustments == 'hard' and not fullrefill: if self.world.difficulty_adjustments[player] == 'hard' and not fullrefill:
basemagic = basemagic + int(basemagic * 0.5 * self.bottle_count(player)) basemagic = basemagic + int(basemagic * 0.5 * self.bottle_count(player))
elif self.world.difficulty_adjustments == 'expert' and not fullrefill: elif self.world.difficulty_adjustments[player] == 'expert' and not fullrefill:
basemagic = basemagic + int(basemagic * 0.25 * self.bottle_count(player)) basemagic = basemagic + int(basemagic * 0.25 * self.bottle_count(player))
else: else:
basemagic = basemagic + basemagic * self.bottle_count(player) basemagic = basemagic + basemagic * self.bottle_count(player)
@ -525,16 +525,16 @@ class CollectionState(object):
if 'Sword' in item.name: if 'Sword' in item.name:
if self.has('Golden Sword', item.player): if self.has('Golden Sword', item.player):
pass pass
elif self.has('Tempered Sword', item.player) and self.world.difficulty_requirements.progressive_sword_limit >= 4: elif self.has('Tempered Sword', item.player) and self.world.difficulty_requirements[item.player].progressive_sword_limit >= 4:
self.prog_items.add(('Golden Sword', item.player)) self.prog_items.add(('Golden Sword', item.player))
changed = True changed = True
elif self.has('Master Sword', item.player) and self.world.difficulty_requirements.progressive_sword_limit >= 3: elif self.has('Master Sword', item.player) and self.world.difficulty_requirements[item.player].progressive_sword_limit >= 3:
self.prog_items.add(('Tempered Sword', item.player)) self.prog_items.add(('Tempered Sword', item.player))
changed = True changed = True
elif self.has('Fighter Sword', item.player) and self.world.difficulty_requirements.progressive_sword_limit >= 2: elif self.has('Fighter Sword', item.player) and self.world.difficulty_requirements[item.player].progressive_sword_limit >= 2:
self.prog_items.add(('Master Sword', item.player)) self.prog_items.add(('Master Sword', item.player))
changed = True changed = True
elif self.world.difficulty_requirements.progressive_sword_limit >= 1: elif self.world.difficulty_requirements[item.player].progressive_sword_limit >= 1:
self.prog_items.add(('Fighter Sword', item.player)) self.prog_items.add(('Fighter Sword', item.player))
changed = True changed = True
elif 'Glove' in item.name: elif 'Glove' in item.name:
@ -549,13 +549,13 @@ class CollectionState(object):
elif 'Shield' in item.name: elif 'Shield' in item.name:
if self.has('Mirror Shield', item.player): if self.has('Mirror Shield', item.player):
pass pass
elif self.has('Red Shield', item.player) and self.world.difficulty_requirements.progressive_shield_limit >= 3: elif self.has('Red Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 3:
self.prog_items.add(('Mirror Shield', item.player)) self.prog_items.add(('Mirror Shield', item.player))
changed = True changed = True
elif self.has('Blue Shield', item.player) and self.world.difficulty_requirements.progressive_shield_limit >= 2: elif self.has('Blue Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 2:
self.prog_items.add(('Red Shield', item.player)) self.prog_items.add(('Red Shield', item.player))
changed = True changed = True
elif self.world.difficulty_requirements.progressive_shield_limit >= 1: elif self.world.difficulty_requirements[item.player].progressive_shield_limit >= 1:
self.prog_items.add(('Blue Shield', item.player)) self.prog_items.add(('Blue Shield', item.player))
changed = True changed = True
elif 'Bow' in item.name: elif 'Bow' in item.name:
@ -568,7 +568,7 @@ class CollectionState(object):
self.prog_items.add(('Bow', item.player)) self.prog_items.add(('Bow', item.player))
changed = True changed = True
elif item.name.startswith('Bottle'): elif item.name.startswith('Bottle'):
if self.bottle_count(item.player) < self.world.difficulty_requirements.progressive_bottle_limit: if self.bottle_count(item.player) < self.world.difficulty_requirements[item.player].progressive_bottle_limit:
self.prog_items.add((item.name, item.player)) self.prog_items.add((item.name, item.player))
changed = True changed = True
elif event or item.advancement: elif event or item.advancement:

View File

@ -278,7 +278,7 @@ def parse_arguments(argv, no_defaults=False):
for player in range(1, multiargs.multi + 1): for player in range(1, multiargs.multi + 1):
playerargs = parse_arguments(shlex.split(getattr(ret,f"p{player}")), True) playerargs = parse_arguments(shlex.split(getattr(ret,f"p{player}")), True)
for name in ['logic', 'mode', 'swords', 'goal']: for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality']:
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
if player == 1: if player == 1:
setattr(ret, name, {1: value}) setattr(ret, name, {1: value})

View File

@ -125,7 +125,7 @@ difficulties = {
} }
def generate_itempool(world, player): def generate_itempool(world, player):
if (world.difficulty not in ['normal', 'hard', 'expert'] or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'] if (world.difficulty[player] not in ['normal', 'hard', 'expert'] or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals']
or world.mode[player] not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']): or world.mode[player] not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']):
raise NotImplementedError('Not supported yet') raise NotImplementedError('Not supported yet')
@ -174,10 +174,10 @@ def generate_itempool(world, player):
# set up item pool # set up item pool
if world.custom: if world.custom:
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle, world.difficulty, world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro, world.customitemarray) (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle, world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro, world.customitemarray)
world.rupoor_cost = min(world.customitemarray[69], 9999) world.rupoor_cost = min(world.customitemarray[69], 9999)
else: else:
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle, world.difficulty, world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro) (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle, world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro)
for item in precollected_items: for item in precollected_items:
world.push_precollected(ItemFactory(item, player)) world.push_precollected(ItemFactory(item, player))
@ -227,9 +227,9 @@ def generate_itempool(world, player):
# logic has some branches where having 4 hearts is one possible requirement (of several alternatives) # logic has some branches where having 4 hearts is one possible requirement (of several alternatives)
# rather than making all hearts/heart pieces progression items (which slows down generation considerably) # rather than making all hearts/heart pieces progression items (which slows down generation considerably)
# We mark one random heart container as an advancement item (or 4 heart pieces in expert mode) # We mark one random heart container as an advancement item (or 4 heart pieces in expert mode)
if world.difficulty in ['normal', 'hard'] and not (world.custom and world.customitemarray[30] == 0): if world.difficulty[player] in ['normal', 'hard'] and not (world.custom and world.customitemarray[30] == 0):
[item for item in world.itempool if item.name == 'Boss Heart Container' and item.player == player][0].advancement = True [item for item in world.itempool if item.name == 'Boss Heart Container' and item.player == player][0].advancement = True
elif world.difficulty in ['expert'] and not (world.custom and world.customitemarray[29] < 4): elif world.difficulty[player] in ['expert'] and not (world.custom and world.customitemarray[29] < 4):
adv_heart_pieces = [item for item in world.itempool if item.name == 'Piece of Heart' and item.player == player][0:4] adv_heart_pieces = [item for item in world.itempool if item.name == 'Piece of Heart' and item.player == player][0:4]
for hp in adv_heart_pieces: for hp in adv_heart_pieces:
hp.advancement = True hp.advancement = True

View File

@ -55,9 +55,9 @@ def main(args, seed=None):
logger.info('ALttP Entrance Randomizer Version %s - Seed: %s\n\n', __version__, world.seed) logger.info('ALttP Entrance Randomizer Version %s - Seed: %s\n\n', __version__, world.seed)
world.difficulty_requirements = difficulties[world.difficulty]
for player in range(1, world.players + 1): for player in range(1, world.players + 1):
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
if world.mode[player] == 'standard' and (args.shuffleenemies != 'none' or args.enemy_health not in ['default', 'easy']): if world.mode[player] == 'standard' and (args.shuffleenemies != 'none' or args.enemy_health not in ['default', 'easy']):
world.escape_assist[player].append(['bombs']) # enemized escape assumes infinite bombs available and will likely be unbeatable without it world.escape_assist[player].append(['bombs']) # enemized escape assumes infinite bombs available and will likely be unbeatable without it
@ -184,7 +184,7 @@ def main(args, seed=None):
apply_rom_settings(rom, args.heartbeep, args.heartcolor, world.quickswap, world.fastmenu, world.disable_music, sprite, player_names) apply_rom_settings(rom, args.heartbeep, args.heartcolor, world.quickswap, world.fastmenu, world.disable_music, sprite, player_names)
outfilesuffix = ('%s%s_%s_%s-%s-%s-%s%s_%s-%s%s%s%s%s' % (f'_P{player}' if world.players > 1 else '', outfilesuffix = ('%s%s_%s_%s-%s-%s-%s%s_%s-%s%s%s%s%s' % (f'_P{player}' if world.players > 1 else '',
f'_{player_names[player]}' if player in player_names else '', f'_{player_names[player]}' if player in player_names else '',
world.logic[player], world.difficulty, world.difficulty_adjustments, world.logic[player], world.difficulty[player], world.difficulty_adjustments[player],
world.mode[player], world.goal[player], world.mode[player], world.goal[player],
"" if world.timer in ['none', 'display'] else "-" + world.timer, "" if world.timer in ['none', 'display'] else "-" + world.timer,
world.shuffle, world.algorithm, mcsb_name, world.shuffle, world.algorithm, mcsb_name,
@ -232,7 +232,7 @@ def copy_world(world):
ret.can_access_trock_big_chest = world.can_access_trock_big_chest ret.can_access_trock_big_chest = world.can_access_trock_big_chest
ret.can_access_trock_middle = world.can_access_trock_middle ret.can_access_trock_middle = world.can_access_trock_middle
ret.can_take_damage = world.can_take_damage ret.can_take_damage = world.can_take_damage
ret.difficulty_requirements = world.difficulty_requirements ret.difficulty_requirements = world.difficulty_requirements.copy()
ret.fix_fake_world = world.fix_fake_world ret.fix_fake_world = world.fix_fake_world
ret.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms ret.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms
ret.mapshuffle = world.mapshuffle ret.mapshuffle = world.mapshuffle

View File

@ -36,7 +36,7 @@ def main(args):
logger.info('ALttP Plandomizer Version %s - Seed: %s\n\n', __version__, args.plando) logger.info('ALttP Plandomizer Version %s - Seed: %s\n\n', __version__, args.plando)
world.difficulty_requirements = difficulties[world.difficulty] world.difficulty_requirements[1] = difficulties[world.difficulty[1]]
create_regions(world, 1) create_regions(world, 1)
create_dungeons(world, 1) create_dungeons(world, 1)

12
Rom.py
View File

@ -611,7 +611,7 @@ def patch_rom(world, player, rom, enemized):
rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on
# handle difficulty_adjustments # handle difficulty_adjustments
if world.difficulty_adjustments == 'hard': if world.difficulty_adjustments[player] == 'hard':
# Powdered Fairies Prize # Powdered Fairies Prize
rom.write_byte(0x36DD0, 0xD8) # One Heart rom.write_byte(0x36DD0, 0xD8) # One Heart
# potion heal amount # potion heal amount
@ -629,7 +629,7 @@ def patch_rom(world, player, rom, enemized):
write_int16(rom, 0x180036, world.rupoor_cost) write_int16(rom, 0x180036, world.rupoor_cost)
# Set stun items # Set stun items
rom.write_byte(0x180180, 0x02) # Hookshot only rom.write_byte(0x180180, 0x02) # Hookshot only
elif world.difficulty_adjustments == 'expert': elif world.difficulty_adjustments[player] == 'expert':
# Powdered Fairies Prize # Powdered Fairies Prize
rom.write_byte(0x36DD0, 0xD8) # One Heart rom.write_byte(0x36DD0, 0xD8) # One Heart
# potion heal amount # potion heal amount
@ -676,7 +676,7 @@ def patch_rom(world, player, rom, enemized):
#Byrna residual magic cost #Byrna residual magic cost
rom.write_bytes(0x45C42, [0x04, 0x02, 0x01]) rom.write_bytes(0x45C42, [0x04, 0x02, 0x01])
difficulty = world.difficulty_requirements difficulty = world.difficulty_requirements[player]
#Set overflow items for progressive equipment #Set overflow items for progressive equipment
mw_sword_replacements = {0: overflow_replacement, mw_sword_replacements = {0: overflow_replacement,
@ -737,7 +737,7 @@ def patch_rom(world, player, rom, enemized):
random.shuffle(packs) random.shuffle(packs)
prizes[:56] = [drop for pack in packs for drop in pack] prizes[:56] = [drop for pack in packs for drop in pack]
if world.difficulty_adjustments in ['hard', 'expert']: if world.difficulty_adjustments[player] in ['hard', 'expert']:
prize_replacements = {0xE0: 0xDF, # Fairy -> heart prize_replacements = {0xE0: 0xDF, # Fairy -> heart
0xE3: 0xD8} # Big magic -> small magic 0xE3: 0xD8} # Big magic -> small magic
prizes = [prize_replacements.get(prize, prize) for prize in prizes] prizes = [prize_replacements.get(prize, prize) for prize in prizes]
@ -793,7 +793,7 @@ def patch_rom(world, player, rom, enemized):
]) ])
# set Fountain bottle exchange items # set Fountain bottle exchange items
if world.difficulty in ['hard', 'expert']: if world.difficulty[player] in ['hard', 'expert']:
rom.write_byte(0x348FF, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x48][random.randint(0, 5)]) rom.write_byte(0x348FF, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x48][random.randint(0, 5)])
rom.write_byte(0x3493B, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x48][random.randint(0, 5)]) rom.write_byte(0x3493B, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x48][random.randint(0, 5)])
else: else:
@ -858,7 +858,7 @@ def patch_rom(world, player, rom, enemized):
write_int32(rom, 0x180200, -100 * 60 * 60 * 60) # red clock adjustment time (in frames, sint32) write_int32(rom, 0x180200, -100 * 60 * 60 * 60) # red clock adjustment time (in frames, sint32)
write_int32(rom, 0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32) write_int32(rom, 0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32)
write_int32(rom, 0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32) write_int32(rom, 0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32)
if world.difficulty_adjustments == 'normal': if world.difficulty_adjustments[player] == 'normal':
write_int32(rom, 0x18020C, (10 + ERtimeincrease) * 60 * 60) # starting time (in frames, sint32) write_int32(rom, 0x18020C, (10 + ERtimeincrease) * 60 * 60) # starting time (in frames, sint32)
else: else:
write_int32(rom, 0x18020C, int((5 + ERtimeincrease / 2) * 60 * 60)) # starting time (in frames, sint32) write_int32(rom, 0x18020C, int((5 + ERtimeincrease / 2) * 60 * 60)) # starting time (in frames, sint32)