diff --git a/Bosses.py b/Bosses.py index 70464da8..b2e0dcaa 100644 --- a/Bosses.py +++ b/Bosses.py @@ -119,6 +119,8 @@ boss_table = { 'Agahnim2': ('Agahnim2', AgahnimDefeatRule) } +anywhere_bosses = ["Moldorm", "Helmasaur King", "Mothula", "Vitreous"] + def can_place_boss(world, player, boss, dungeon_name, level=None): if world.swords[player] in ['swordless'] and boss == 'Kholdstare' and dungeon_name != 'Ice Palace': return False @@ -178,7 +180,7 @@ def place_bosses(world, player): ['Inverted Ganons Tower', 'bottom'], ] - all_bosses = sorted(boss_table.keys()) #s orted to be deterministic on older pythons + all_bosses = sorted(boss_table.keys()) #sorted to be deterministic on older pythons placeable_bosses = [boss for boss in all_bosses if boss not in ['Agahnim', 'Agahnim2', 'Ganon']] if world.boss_shuffle[player] in ["basic", "normal"]: @@ -194,7 +196,7 @@ def place_bosses(world, player): else: # all bosses present, the three duplicates chosen at random bosses = all_bosses + [world.random.choice(placeable_bosses) for _ in range(3)] - logging.getLogger('').debug('Bosses chosen %s', bosses) + logging.debug('Bosses chosen %s', bosses) world.random.shuffle(bosses) for [loc, level] in boss_locations: @@ -204,7 +206,7 @@ def place_bosses(world, player): raise FillError('Could not place boss for location %s' % loc_text) bosses.remove(boss) - logging.getLogger('').debug('Placing boss %s at %s', boss, loc_text) + logging.debug('Placing boss %s at %s', boss, loc_text) world.get_dungeon(loc, player).bosses[level] = BossFactory(boss, player) elif world.boss_shuffle[player] == "chaos": #all bosses chosen at random for [loc, level] in boss_locations: @@ -215,5 +217,26 @@ def place_bosses(world, player): except IndexError: raise FillError('Could not place boss for location %s' % loc_text) - logging.getLogger('').debug('Placing boss %s at %s', boss, loc_text) + logging.debug('Placing boss %s at %s', boss, loc_text) world.get_dungeon(loc, player).bosses[level] = BossFactory(boss, player) + elif world.boss_shuffle[player] == "singularity": + if world.swords[player] == 'swordless': + boss = world.random.choice(anywhere_bosses) + else: + boss = world.random.choice(anywhere_bosses + ["Kholdstare"]) + for [loc, level] in boss_locations: + logging.debug('Placing boss %s at %s', boss, loc + (' ('+level+')' if level else '')) + world.get_dungeon(loc, player).bosses[level] = BossFactory(boss, player) + elif world.boss_shuffle[player] == "duality": + if world.swords[player] == 'swordless': + used_anywhere_bosses = anywhere_bosses + else: + used_anywhere_bosses = anywhere_bosses + ["Kholdstare"] + + limited_boss = world.random.choice([boss for boss in placeable_bosses if boss not in used_anywhere_bosses]) + anywhere_boss = world.random.choice(used_anywhere_bosses) + + for [loc, level] in boss_locations: + boss = limited_boss if can_place_boss(world, player, limited_boss, loc, level) else anywhere_boss + logging.debug('Placing boss %s at %s', boss, loc + (' ('+level+')' if level else '')) + world.get_dungeon(loc, player).bosses[level] = BossFactory(boss, player) \ No newline at end of file diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index ef2f53aa..d207e148 100755 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -290,7 +290,8 @@ def parse_arguments(argv, no_defaults=False): help="Skip Multiworld Progression balancing.") parser.add_argument('--skip_playthrough', action='store_true', default=defval(False)) parser.add_argument('--enemizercli', default=defval('EnemizerCLI/EnemizerCLI.Core')) - parser.add_argument('--shufflebosses', default=defval('none'), choices=['none', 'basic', 'normal', 'chaos']) + parser.add_argument('--shufflebosses', default=defval('none'), choices=['none', 'basic', 'normal', 'chaos', + "singularity", "duality"]) parser.add_argument('--shuffleenemies', default=defval('none'), choices=['none', 'shuffled', 'chaos', 'chaosthieves']) parser.add_argument('--enemy_health', default=defval('default'), diff --git a/Gui.py b/Gui.py index a251be0f..46826409 100755 --- a/Gui.py +++ b/Gui.py @@ -384,7 +384,8 @@ def guiMain(args=None): enemizerBossLabel.pack(side=LEFT) enemizerBossVar = StringVar() enemizerBossVar.set('none') - enemizerBossOption = OptionMenu(enemizerBossFrame, enemizerBossVar, 'none', 'basic', 'normal', 'chaos') + enemizerBossOption = OptionMenu(enemizerBossFrame, enemizerBossVar, 'none', 'basic', 'normal', 'chaos', + "singularity", "duality") enemizerBossOption.pack(side=LEFT) enemizerDamageFrame = Frame(enemizerFrame) diff --git a/Mystery.py b/Mystery.py index c8c58102..c93b287b 100644 --- a/Mystery.py +++ b/Mystery.py @@ -329,7 +329,9 @@ def roll_settings(weights): ret.shufflebosses = {'none': 'none', 'simple': 'basic', 'full': 'normal', - 'random': 'chaos' + 'random': 'chaos', + 'singularity': 'singularity', + 'duality': 'duality' }[get_choice('boss_shuffle', weights)] ret.shuffleenemies = {'none': 'none', diff --git a/easy.yaml b/easy.yaml index 22eb1209..f6290e6f 100644 --- a/easy.yaml +++ b/easy.yaml @@ -147,6 +147,8 @@ boss_shuffle: simple: 0 # Existing bosses except Ganon and Agahnim are shuffled throughout dungeons full: 0 # 3 bosses can occur twice random: 0 # Any boss can appear any amount of times + singularity: 0 # picks any boss that can appear anywhere and puts that boss into every arena + duality: 0 # picks a boss that can only appear in some places and a boss that can appear anywhere, then attempts to put both in that order in every arena enemy_shuffle: none: 1 # Vanilla enemy placement chaos: 0 # Enemies are randomized