diff --git a/BaseClasses.py b/BaseClasses.py index 40342687..fb692305 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -14,8 +14,8 @@ class World(object): self.logic = logic.copy() self.mode = mode.copy() self.swords = swords.copy() - self.difficulty = difficulty - self.difficulty_adjustments = difficulty_adjustments + self.difficulty = difficulty.copy() + self.difficulty_adjustments = difficulty_adjustments.copy() self.timer = timer self.progressive = progressive self.goal = goal.copy() @@ -71,7 +71,7 @@ class World(object): self.custom = custom self.customitemarray = customitemarray 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.boss_shuffle = boss_shuffle self.escape_assist = {player: [] for player in range(1, players + 1)} @@ -147,13 +147,13 @@ class World(object): if 'Sword' in item.name: if ret.has('Golden Sword', item.player): 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)) - 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)) - 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)) - 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)) elif 'Glove' in item.name: if ret.has('Titans Mitts', item.player): @@ -165,21 +165,21 @@ class World(object): elif 'Shield' in item.name: if ret.has('Mirror Shield', item.player): 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)) - 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)) - 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)) elif 'Bow' in item.name: if ret.has('Silver Arrows', item.player): 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)) - 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)) 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)) elif item.advancement or item.smallkey or item.bigkey: ret.prog_items.add((item.name, item.player)) @@ -413,7 +413,7 @@ class CollectionState(object): def heart_count(self, player): # Warning: This only considers items that are marked as advancement items - diff = self.world.difficulty_requirements + diff = self.world.difficulty_requirements[player] return ( min(self.item_count('Boss Heart Container', player), diff.boss_heart_container_limit) + self.item_count('Sanctuary Heart Container', player) @@ -431,9 +431,9 @@ class CollectionState(object): elif self.has('Half Magic', player): basemagic = 16 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)) - 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)) else: basemagic = basemagic + basemagic * self.bottle_count(player) @@ -525,16 +525,16 @@ class CollectionState(object): if 'Sword' in item.name: if self.has('Golden Sword', item.player): 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)) 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)) 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)) 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)) changed = True elif 'Glove' in item.name: @@ -549,13 +549,13 @@ class CollectionState(object): elif 'Shield' in item.name: if self.has('Mirror Shield', item.player): 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)) 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)) 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)) changed = True elif 'Bow' in item.name: @@ -568,7 +568,7 @@ class CollectionState(object): self.prog_items.add(('Bow', item.player)) changed = True 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)) changed = True elif event or item.advancement: diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index 6e3871cd..a16f25b5 100755 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -278,7 +278,7 @@ def parse_arguments(argv, no_defaults=False): for player in range(1, multiargs.multi + 1): 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) if player == 1: setattr(ret, name, {1: value}) diff --git a/ItemList.py b/ItemList.py index 85f549a7..f947a450 100644 --- a/ItemList.py +++ b/ItemList.py @@ -125,7 +125,7 @@ difficulties = { } 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']): raise NotImplementedError('Not supported yet') @@ -174,10 +174,10 @@ def generate_itempool(world, player): # set up item pool 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) 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: 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) # 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) - 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 - 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] for hp in adv_heart_pieces: hp.advancement = True diff --git a/Main.py b/Main.py index 07c37b26..86ac1a4c 100644 --- a/Main.py +++ b/Main.py @@ -55,9 +55,9 @@ def main(args, seed=None): 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): + 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']): 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) 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 '', - world.logic[player], world.difficulty, world.difficulty_adjustments, + world.logic[player], world.difficulty[player], world.difficulty_adjustments[player], world.mode[player], world.goal[player], "" if world.timer in ['none', 'display'] else "-" + world.timer, 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_middle = world.can_access_trock_middle 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.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms ret.mapshuffle = world.mapshuffle diff --git a/Plando.py b/Plando.py index c559c0d9..90b2b891 100755 --- a/Plando.py +++ b/Plando.py @@ -36,7 +36,7 @@ def main(args): 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_dungeons(world, 1) diff --git a/Rom.py b/Rom.py index a8a3db22..a732b6d7 100644 --- a/Rom.py +++ b/Rom.py @@ -611,7 +611,7 @@ def patch_rom(world, player, rom, enemized): rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on # handle difficulty_adjustments - if world.difficulty_adjustments == 'hard': + if world.difficulty_adjustments[player] == 'hard': # Powdered Fairies Prize rom.write_byte(0x36DD0, 0xD8) # One Heart # potion heal amount @@ -629,7 +629,7 @@ def patch_rom(world, player, rom, enemized): write_int16(rom, 0x180036, world.rupoor_cost) # Set stun items rom.write_byte(0x180180, 0x02) # Hookshot only - elif world.difficulty_adjustments == 'expert': + elif world.difficulty_adjustments[player] == 'expert': # Powdered Fairies Prize rom.write_byte(0x36DD0, 0xD8) # One Heart # potion heal amount @@ -676,7 +676,7 @@ def patch_rom(world, player, rom, enemized): #Byrna residual magic cost rom.write_bytes(0x45C42, [0x04, 0x02, 0x01]) - difficulty = world.difficulty_requirements + difficulty = world.difficulty_requirements[player] #Set overflow items for progressive equipment mw_sword_replacements = {0: overflow_replacement, @@ -737,7 +737,7 @@ def patch_rom(world, player, rom, enemized): random.shuffle(packs) 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 0xE3: 0xD8} # Big magic -> small magic 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 - 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(0x3493B, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x48][random.randint(0, 5)]) 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, 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) - if world.difficulty_adjustments == 'normal': + if world.difficulty_adjustments[player] == 'normal': write_int32(rom, 0x18020C, (10 + ERtimeincrease) * 60 * 60) # starting time (in frames, sint32) else: write_int32(rom, 0x18020C, int((5 + ERtimeincrease / 2) * 60 * 60)) # starting time (in frames, sint32)