diff --git a/BaseClasses.py b/BaseClasses.py index 40028001..25e4e707 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -159,11 +159,11 @@ class MultiWorld(): self.fix_trock_doors = self.AttributeProxy( lambda player: self.shuffle[player] != 'vanilla' or self.mode[player] == 'inverted') self.fix_skullwoods_exit = self.AttributeProxy( - lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple']) + lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeons_simple']) self.fix_palaceofdarkness_exit = self.AttributeProxy( - lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple']) + lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeons_simple']) self.fix_trock_exit = self.AttributeProxy( - lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple']) + lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeons_simple']) for player in range(1, players + 1): def set_player_attr(attr, val): diff --git a/Generate.py b/Generate.py index e19a7a97..fd4a5a7e 100644 --- a/Generate.py +++ b/Generate.py @@ -315,20 +315,6 @@ def prefer_int(input_data: str) -> Union[str, int]: return input_data -goals = { - 'ganon': 'ganon', - 'crystals': 'crystals', - 'bosses': 'bosses', - 'pedestal': 'pedestal', - 'ganon_pedestal': 'ganonpedestal', - 'triforce_hunt': 'triforcehunt', - 'local_triforce_hunt': 'localtriforcehunt', - 'ganon_triforce_hunt': 'ganontriforcehunt', - 'local_ganon_triforce_hunt': 'localganontriforcehunt', - 'ice_rod_hunt': 'icerodhunt', -} - - def roll_percentage(percentage: Union[int, float]) -> bool: """Roll a percentage chance. percentage is expected to be in range [0, 100]""" @@ -357,15 +343,6 @@ def roll_meta_option(option_key, game: str, category_dict: Dict) -> Any: if options[option_key].supports_weighting: return get_choice(option_key, category_dict) return category_dict[option_key] - if game == "A Link to the Past": # TODO wow i hate this - if option_key in {"glitches_required", "dark_room_logic", "entrance_shuffle", "goals", "triforce_pieces_mode", - "triforce_pieces_percentage", "triforce_pieces_available", "triforce_pieces_extra", - "triforce_pieces_required", "shop_shuffle", "mode", "item_pool", "item_functionality", - "boss_shuffle", "enemy_damage", "enemy_health", "timer", "countdown_start_time", - "red_clock_time", "blue_clock_time", "green_clock_time", "dungeon_counters", "shuffle_prizes", - "misery_mire_medallion", "turtle_rock_medallion", "sprite_pool", "sprite", - "random_sprite_on_event"}: - return get_choice(option_key, category_dict) raise Exception(f"Error generating meta option {option_key} for {game}.") @@ -504,101 +481,6 @@ def roll_settings(weights: dict, plando_options: PlandoOptions = PlandoOptions.b def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options): - if "dungeon_items" in weights and get_choice_legacy('dungeon_items', weights, "none") != "none": - raise Exception(f"dungeon_items key in A Link to the Past was removed, but is present in these weights as {get_choice_legacy('dungeon_items', weights, False)}.") - glitches_required = get_choice_legacy('glitches_required', weights) - if glitches_required not in [None, 'none', 'no_logic', 'overworld_glitches', 'hybrid_major_glitches', 'minor_glitches']: - logging.warning("Only NMG, OWG, HMG and No Logic supported") - glitches_required = 'none' - ret.logic = {None: 'noglitches', 'none': 'noglitches', 'no_logic': 'nologic', 'overworld_glitches': 'owglitches', - 'minor_glitches': 'minorglitches', 'hybrid_major_glitches': 'hybridglitches'}[ - glitches_required] - - ret.dark_room_logic = get_choice_legacy("dark_room_logic", weights, "lamp") - if not ret.dark_room_logic: # None/False - ret.dark_room_logic = "none" - if ret.dark_room_logic == "sconces": - ret.dark_room_logic = "torches" - if ret.dark_room_logic not in {"lamp", "torches", "none"}: - raise ValueError(f"Unknown Dark Room Logic: \"{ret.dark_room_logic}\"") - - entrance_shuffle = get_choice_legacy('entrance_shuffle', weights, 'vanilla') - if entrance_shuffle.startswith('none-'): - ret.shuffle = 'vanilla' - else: - ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla' - - goal = get_choice_legacy('goals', weights, 'ganon') - - ret.goal = goals[goal] - - - extra_pieces = get_choice_legacy('triforce_pieces_mode', weights, 'available') - - ret.triforce_pieces_required = LttPOptions.TriforcePieces.from_any(get_choice_legacy('triforce_pieces_required', weights, 20)) - - # sum a percentage to required - if extra_pieces == 'percentage': - percentage = max(100, float(get_choice_legacy('triforce_pieces_percentage', weights, 150))) / 100 - ret.triforce_pieces_available = int(round(ret.triforce_pieces_required * percentage, 0)) - # vanilla mode (specify how many pieces are) - elif extra_pieces == 'available': - ret.triforce_pieces_available = LttPOptions.TriforcePieces.from_any( - get_choice_legacy('triforce_pieces_available', weights, 30)) - # required pieces + fixed extra - elif extra_pieces == 'extra': - extra_pieces = max(0, int(get_choice_legacy('triforce_pieces_extra', weights, 10))) - ret.triforce_pieces_available = ret.triforce_pieces_required + extra_pieces - - # change minimum to required pieces to avoid problems - ret.triforce_pieces_available = min(max(ret.triforce_pieces_required, int(ret.triforce_pieces_available)), 90) - - ret.shop_shuffle = get_choice_legacy('shop_shuffle', weights, '') - if not ret.shop_shuffle: - ret.shop_shuffle = '' - - ret.mode = get_choice_legacy("mode", weights) - - ret.difficulty = get_choice_legacy('item_pool', weights) - - ret.item_functionality = get_choice_legacy('item_functionality', weights) - - - ret.enemy_damage = {None: 'default', - 'default': 'default', - 'shuffled': 'shuffled', - 'random': 'chaos', # to be removed - 'chaos': 'chaos', - }[get_choice_legacy('enemy_damage', weights)] - - ret.enemy_health = get_choice_legacy('enemy_health', weights) - - ret.timer = {'none': False, - None: False, - False: False, - 'timed': 'timed', - 'timed_ohko': 'timed-ohko', - 'ohko': 'ohko', - 'timed_countdown': 'timed-countdown', - 'display': 'display'}[get_choice_legacy('timer', weights, False)] - - ret.countdown_start_time = int(get_choice_legacy('countdown_start_time', weights, 10)) - ret.red_clock_time = int(get_choice_legacy('red_clock_time', weights, -2)) - ret.blue_clock_time = int(get_choice_legacy('blue_clock_time', weights, 2)) - ret.green_clock_time = int(get_choice_legacy('green_clock_time', weights, 4)) - - ret.dungeon_counters = get_choice_legacy('dungeon_counters', weights, 'default') - - ret.shuffle_prizes = get_choice_legacy('shuffle_prizes', weights, "g") - - ret.required_medallions = [get_choice_legacy("misery_mire_medallion", weights, "random"), - get_choice_legacy("turtle_rock_medallion", weights, "random")] - - for index, medallion in enumerate(ret.required_medallions): - ret.required_medallions[index] = {"ether": "Ether", "quake": "Quake", "bombos": "Bombos", "random": "random"} \ - .get(medallion.lower(), None) - if not ret.required_medallions[index]: - raise Exception(f"unknown Medallion {medallion} for {'misery mire' if index == 0 else 'turtle rock'}") ret.plando_texts = {} if PlandoOptions.texts in plando_options: diff --git a/data/basepatch.bsdiff4 b/data/basepatch.bsdiff4 index a578b248..aa8f1375 100644 Binary files a/data/basepatch.bsdiff4 and b/data/basepatch.bsdiff4 differ diff --git a/setup.py b/setup.py index 9b28715a..272e6de0 100644 --- a/setup.py +++ b/setup.py @@ -396,8 +396,6 @@ class BuildExeCommand(cx_Freeze.command.build_exe.BuildEXE): folders_to_remove.append(file_name) shutil.rmtree(world_directory) shutil.copyfile("meta.yaml", self.buildfolder / "Players" / "Templates" / "meta.yaml") - # TODO: fix LttP options one day - shutil.copyfile("playerSettings.yaml", self.buildfolder / "Players" / "Templates" / "A Link to the Past.yaml") try: from maseya import z3pr except ImportError: diff --git a/worlds/alttp/Bosses.py b/worlds/alttp/Bosses.py index 90ffe9dc..965a86db 100644 --- a/worlds/alttp/Bosses.py +++ b/worlds/alttp/Bosses.py @@ -6,7 +6,7 @@ from typing import Optional, Union, List, Tuple, Callable, Dict, TYPE_CHECKING from Fill import FillError from .Options import LTTPBosses as Bosses from .StateHelpers import can_shoot_arrows, can_extend_magic, can_get_good_bee, has_sword, has_beam_sword, \ - has_melee_weapon, has_fire_source + has_melee_weapon, has_fire_source, can_use_bombs if TYPE_CHECKING: from . import ALTTPWorld @@ -62,7 +62,8 @@ def MoldormDefeatRule(state, player: int) -> bool: def HelmasaurKingDefeatRule(state, player: int) -> bool: # TODO: technically possible with the hammer - return has_sword(state, player) or can_shoot_arrows(state, player) + return (can_use_bombs(state, player, 5) or state.has("Hammer", player)) and (has_sword(state, player) + or can_shoot_arrows(state, player)) def ArrghusDefeatRule(state, player: int) -> bool: @@ -143,7 +144,7 @@ def GanonDefeatRule(state, player: int) -> bool: can_hurt = has_beam_sword(state, player) common = can_hurt and has_fire_source(state, player) # silverless ganon may be needed in anything higher than no glitches - if state.multiworld.logic[player] != 'noglitches': + if state.multiworld.glitches_required[player] != 'no_glitches': # need to light torch a sufficient amount of times return common and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or ( state.has('Silver Bow', player) and can_shoot_arrows(state, player)) or diff --git a/worlds/alttp/Dungeons.py b/worlds/alttp/Dungeons.py index b456174f..c886fce9 100644 --- a/worlds/alttp/Dungeons.py +++ b/worlds/alttp/Dungeons.py @@ -9,7 +9,7 @@ from Fill import fill_restrictive from .Bosses import BossFactory, Boss from .Items import ItemFactory from .Regions import lookup_boss_drops, key_drop_data -from .Options import smallkey_shuffle +from .Options import small_key_shuffle if typing.TYPE_CHECKING: from .SubClasses import ALttPLocation, ALttPItem @@ -66,7 +66,7 @@ def create_dungeons(world: "ALTTPWorld"): def make_dungeon(name, default_boss, dungeon_regions, big_key, small_keys, dungeon_items): dungeon = Dungeon(name, dungeon_regions, big_key, - [] if multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal else small_keys, + [] if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal else small_keys, dungeon_items, player) for item in dungeon.all_items: item.dungeon = dungeon diff --git a/worlds/alttp/EntranceRandomizer.py b/worlds/alttp/EntranceRandomizer.py index 47c36b6c..37486a9c 100644 --- a/worlds/alttp/EntranceRandomizer.py +++ b/worlds/alttp/EntranceRandomizer.py @@ -23,7 +23,7 @@ def parse_arguments(argv, no_defaults=False): multiargs, _ = parser.parse_known_args(argv) parser = argparse.ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) - parser.add_argument('--logic', default=defval('noglitches'), const='noglitches', nargs='?', choices=['noglitches', 'minorglitches', 'owglitches', 'hybridglitches', 'nologic'], + parser.add_argument('--logic', default=defval('no_glitches'), const='no_glitches', nargs='?', choices=['no_glitches', 'minor_glitches', 'overworld_glitches', 'hybrid_major_glitches', 'no_logic'], help='''\ Select Enforcement of Item Requirements. (default: %(default)s) No Glitches: @@ -49,7 +49,7 @@ def parse_arguments(argv, no_defaults=False): instead of a bunny. ''') parser.add_argument('--goal', default=defval('ganon'), const='ganon', nargs='?', - choices=['ganon', 'pedestal', 'bosses', 'triforcehunt', 'localtriforcehunt', 'ganontriforcehunt', 'localganontriforcehunt', 'crystals', 'ganonpedestal'], + choices=['ganon', 'pedestal', 'bosses', 'triforce_hunt', 'local_triforce_hunt', 'ganon_triforce_hunt', 'local_ganon_triforce_hunt', 'crystals', 'ganon_pedestal'], help='''\ Select completion goal. (default: %(default)s) Ganon: Collect all crystals, beat Agahnim 2 then @@ -92,7 +92,7 @@ def parse_arguments(argv, no_defaults=False): Hard: Reduced functionality. Expert: Greatly reduced functionality. ''') - parser.add_argument('--timer', default=defval('none'), const='normal', nargs='?', choices=['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'], + parser.add_argument('--timer', default=defval('none'), const='normal', nargs='?', choices=['none', 'display', 'timed', 'timed_ohko', 'ohko', 'timed_countdown'], help='''\ Select game timer setting. Affects available itempool. (default: %(default)s) None: No timer. @@ -151,7 +151,7 @@ def parse_arguments(argv, no_defaults=False): slightly biased to placing progression items with less restrictions. ''') - parser.add_argument('--shuffle', default=defval('vanilla'), const='vanilla', nargs='?', choices=['vanilla', 'simple', 'restricted', 'full', 'crossed', 'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy', 'dungeonsfull', 'dungeonssimple', 'dungeonscrossed'], + parser.add_argument('--shuffle', default=defval('vanilla'), const='vanilla', nargs='?', choices=['vanilla', 'simple', 'restricted', 'full', 'crossed', 'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy', 'dungeons_full', 'dungeons_simple', 'dungeons_crossed'], help='''\ Select Entrance Shuffling Algorithm. (default: %(default)s) Full: Mix cave and dungeon entrances freely while limiting @@ -178,9 +178,9 @@ def parse_arguments(argv, no_defaults=False): parser.add_argument('--open_pyramid', default=defval('auto'), help='''\ Pre-opens the pyramid hole, this removes the Agahnim 2 requirement for it. Depending on goal, you might still need to beat Agahnim 2 in order to beat ganon. - fast ganon goals are crystals, ganontriforcehunt, localganontriforcehunt, pedestalganon + fast ganon goals are crystals, ganon_triforce_hunt, local_ganon_triforce_hunt, pedestalganon auto - Only opens pyramid hole if the goal specifies a fast ganon, and entrance shuffle - is vanilla, dungeonssimple or dungeonsfull. + is vanilla, dungeons_simple or dungeons_full. goal - Opens pyramid hole if the goal specifies a fast ganon. yes - Always opens the pyramid hole. no - Never opens the pyramid hole. diff --git a/worlds/alttp/EntranceShuffle.py b/worlds/alttp/EntranceShuffle.py index 07bb587e..fceba86a 100644 --- a/worlds/alttp/EntranceShuffle.py +++ b/worlds/alttp/EntranceShuffle.py @@ -21,17 +21,17 @@ def link_entrances(world, player): connect_simple(world, exitname, regionname, player) # if we do not shuffle, set default connections - if world.shuffle[player] == 'vanilla': + if world.entrance_shuffle[player] == 'vanilla': for exitname, regionname in default_connections: connect_simple(world, exitname, regionname, player) for exitname, regionname in default_dungeon_connections: connect_simple(world, exitname, regionname, player) - elif world.shuffle[player] == 'dungeonssimple': + elif world.entrance_shuffle[player] == 'dungeons_simple': for exitname, regionname in default_connections: connect_simple(world, exitname, regionname, player) simple_shuffle_dungeons(world, player) - elif world.shuffle[player] == 'dungeonsfull': + elif world.entrance_shuffle[player] == 'dungeons_full': for exitname, regionname in default_connections: connect_simple(world, exitname, regionname, player) @@ -63,9 +63,9 @@ def link_entrances(world, player): connect_mandatory_exits(world, lw_entrances, dungeon_exits, list(LW_Dungeon_Entrances_Must_Exit), player) connect_mandatory_exits(world, dw_entrances, dungeon_exits, list(DW_Dungeon_Entrances_Must_Exit), player) connect_caves(world, lw_entrances, dw_entrances, dungeon_exits, player) - elif world.shuffle[player] == 'dungeonscrossed': + elif world.entrance_shuffle[player] == 'dungeons_crossed': crossed_shuffle_dungeons(world, player) - elif world.shuffle[player] == 'simple': + elif world.entrance_shuffle[player] == 'simple': simple_shuffle_dungeons(world, player) old_man_entrances = list(Old_Man_Entrances) @@ -136,7 +136,7 @@ def link_entrances(world, player): # place remaining doors connect_doors(world, single_doors, door_targets, player) - elif world.shuffle[player] == 'restricted': + elif world.entrance_shuffle[player] == 'restricted': simple_shuffle_dungeons(world, player) lw_entrances = list(LW_Entrances + LW_Single_Cave_Doors + Old_Man_Entrances) @@ -207,62 +207,8 @@ def link_entrances(world, player): # place remaining doors connect_doors(world, doors, door_targets, player) - elif world.shuffle[player] == 'restricted_legacy': - simple_shuffle_dungeons(world, player) - lw_entrances = list(LW_Entrances) - dw_entrances = list(DW_Entrances) - dw_must_exits = list(DW_Entrances_Must_Exit) - old_man_entrances = list(Old_Man_Entrances) - caves = list(Cave_Exits) - three_exit_caves = list(Cave_Three_Exits) - single_doors = list(Single_Cave_Doors) - bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors) - blacksmith_doors = list(Blacksmith_Single_Cave_Doors) - door_targets = list(Single_Cave_Targets) - - # only use two exit caves to do mandatory dw connections - connect_mandatory_exits(world, dw_entrances, caves, dw_must_exits, player) - # add three exit doors to pool for remainder - caves.extend(three_exit_caves) - - # place old man, has limited options - # exit has to come from specific set of doors, the entrance is free to move about - world.random.shuffle(old_man_entrances) - old_man_exit = old_man_entrances.pop() - lw_entrances.extend(old_man_entrances) - world.random.shuffle(lw_entrances) - old_man_entrance = lw_entrances.pop() - connect_two_way(world, old_man_entrance, 'Old Man Cave Exit (West)', player) - connect_two_way(world, old_man_exit, 'Old Man Cave Exit (East)', player) - - # place Old Man House in Light World - connect_caves(world, lw_entrances, [], Old_Man_House, player) - - # connect rest. There's 2 dw entrances remaining, so we will not run into parity issue placing caves - connect_caves(world, lw_entrances, dw_entrances, caves, player) - - # scramble holes - scramble_holes(world, player) - - # place blacksmith, has limited options - world.random.shuffle(blacksmith_doors) - blacksmith_hut = blacksmith_doors.pop() - connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player) - bomb_shop_doors.extend(blacksmith_doors) - - # place dam and pyramid fairy, have limited options - world.random.shuffle(bomb_shop_doors) - bomb_shop = bomb_shop_doors.pop() - connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) - single_doors.extend(bomb_shop_doors) - - # tavern back door cannot be shuffled yet - connect_doors(world, ['Tavern North'], ['Tavern'], player) - - # place remaining doors - connect_doors(world, single_doors, door_targets, player) - elif world.shuffle[player] == 'full': + elif world.entrance_shuffle[player] == 'full': skull_woods_shuffle(world, player) lw_entrances = list(LW_Entrances + LW_Dungeon_Entrances + LW_Single_Cave_Doors + Old_Man_Entrances) @@ -368,7 +314,7 @@ def link_entrances(world, player): # place remaining doors connect_doors(world, doors, door_targets, player) - elif world.shuffle[player] == 'crossed': + elif world.entrance_shuffle[player] == 'crossed': skull_woods_shuffle(world, player) entrances = list(LW_Entrances + LW_Dungeon_Entrances + LW_Single_Cave_Doors + Old_Man_Entrances + DW_Entrances + DW_Dungeon_Entrances + DW_Single_Cave_Doors) @@ -445,337 +391,8 @@ def link_entrances(world, player): # place remaining doors connect_doors(world, entrances, door_targets, player) - elif world.shuffle[player] == 'full_legacy': - skull_woods_shuffle(world, player) - lw_entrances = list(LW_Entrances + LW_Dungeon_Entrances + Old_Man_Entrances) - dw_entrances = list(DW_Entrances + DW_Dungeon_Entrances) - dw_must_exits = list(DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit) - lw_must_exits = list(LW_Dungeon_Entrances_Must_Exit) - old_man_entrances = list(Old_Man_Entrances + ['Tower of Hera']) - caves = list(Cave_Exits + Dungeon_Exits + Cave_Three_Exits) # don't need to consider three exit caves, have one exit caves to avoid parity issues - single_doors = list(Single_Cave_Doors) - bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors) - blacksmith_doors = list(Blacksmith_Single_Cave_Doors) - door_targets = list(Single_Cave_Targets) - - if world.mode[player] == 'standard': - # must connect front of hyrule castle to do escape - connect_two_way(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player) - else: - caves.append(tuple(world.random.sample( - ['Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'], 3))) - lw_entrances.append('Hyrule Castle Entrance (South)') - - if not world.shuffle_ganon: - connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit', player) - else: - dw_entrances.append('Ganons Tower') - caves.append('Ganons Tower Exit') - - # we randomize which world requirements we fulfill first so we get better dungeon distribution - if world.random.randint(0, 1) == 0: - connect_mandatory_exits(world, lw_entrances, caves, lw_must_exits, player) - connect_mandatory_exits(world, dw_entrances, caves, dw_must_exits, player) - else: - connect_mandatory_exits(world, dw_entrances, caves, dw_must_exits, player) - connect_mandatory_exits(world, lw_entrances, caves, lw_must_exits, player) - if world.mode[player] == 'standard': - # rest of hyrule castle must be in light world - connect_caves(world, lw_entrances, [], [('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')], player) - - # place old man, has limited options - # exit has to come from specific set of doors, the entrance is free to move about - old_man_entrances = [door for door in old_man_entrances if door in lw_entrances] - world.random.shuffle(old_man_entrances) - old_man_exit = old_man_entrances.pop() - lw_entrances.remove(old_man_exit) - - world.random.shuffle(lw_entrances) - old_man_entrance = lw_entrances.pop() - connect_two_way(world, old_man_entrance, 'Old Man Cave Exit (West)', player) - connect_two_way(world, old_man_exit, 'Old Man Cave Exit (East)', player) - - # place Old Man House in Light World - connect_caves(world, lw_entrances, [], list(Old_Man_House), player) #need this to avoid badness with multiple seeds - - # now scramble the rest - connect_caves(world, lw_entrances, dw_entrances, caves, player) - - # scramble holes - scramble_holes(world, player) - - # place blacksmith, has limited options - world.random.shuffle(blacksmith_doors) - blacksmith_hut = blacksmith_doors.pop() - connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player) - bomb_shop_doors.extend(blacksmith_doors) - - # place bomb shop, has limited options - world.random.shuffle(bomb_shop_doors) - bomb_shop = bomb_shop_doors.pop() - connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) - single_doors.extend(bomb_shop_doors) - - # tavern back door cannot be shuffled yet - connect_doors(world, ['Tavern North'], ['Tavern'], player) - - # place remaining doors - connect_doors(world, single_doors, door_targets, player) - elif world.shuffle[player] == 'madness_legacy': - # here lie dragons, connections are no longer two way - lw_entrances = list(LW_Entrances + LW_Dungeon_Entrances + Old_Man_Entrances) - dw_entrances = list(DW_Entrances + DW_Dungeon_Entrances) - dw_entrances_must_exits = list(DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit) - - lw_doors = list(LW_Entrances + LW_Dungeon_Entrances + LW_Dungeon_Entrances_Must_Exit) + ['Kakariko Well Cave', - 'Bat Cave Cave', - 'North Fairy Cave', - 'Sanctuary', - 'Lost Woods Hideout Stump', - 'Lumberjack Tree Cave'] + list( - Old_Man_Entrances) - dw_doors = list( - DW_Entrances + DW_Dungeon_Entrances + DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit) + [ - 'Skull Woods First Section Door', 'Skull Woods Second Section Door (East)', - 'Skull Woods Second Section Door (West)'] - - world.random.shuffle(lw_doors) - world.random.shuffle(dw_doors) - - dw_entrances_must_exits.append('Skull Woods Second Section Door (West)') - dw_entrances.append('Skull Woods Second Section Door (East)') - dw_entrances.append('Skull Woods First Section Door') - - lw_entrances.extend( - ['Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', - 'Lumberjack Tree Cave']) - - lw_entrances_must_exits = list(LW_Dungeon_Entrances_Must_Exit) - - old_man_entrances = list(Old_Man_Entrances) + ['Tower of Hera'] - - mandatory_light_world = ['Old Man House Exit (Bottom)', 'Old Man House Exit (Top)'] - mandatory_dark_world = [] - caves = list(Cave_Exits + Dungeon_Exits + Cave_Three_Exits) - - # shuffle up holes - - lw_hole_entrances = ['Kakariko Well Drop', 'Bat Cave Drop', 'North Fairy Cave Drop', 'Lost Woods Hideout Drop', 'Lumberjack Tree Tree', 'Sanctuary Grave'] - dw_hole_entrances = ['Skull Woods First Section Hole (East)', 'Skull Woods First Section Hole (West)', 'Skull Woods First Section Hole (North)', 'Skull Woods Second Section Hole'] - - hole_targets = [('Kakariko Well Exit', 'Kakariko Well (top)'), - ('Bat Cave Exit', 'Bat Cave (right)'), - ('North Fairy Cave Exit', 'North Fairy Cave'), - ('Lost Woods Hideout Exit', 'Lost Woods Hideout (top)'), - ('Lumberjack Tree Exit', 'Lumberjack Tree (top)'), - (('Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)'), 'Skull Woods Second Section (Drop)')] - - if world.mode[player] == 'standard': - # cannot move uncle cave - connect_entrance(world, 'Hyrule Castle Secret Entrance Drop', 'Hyrule Castle Secret Entrance', player) - connect_exit(world, 'Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance Stairs', player) - connect_entrance(world, 'Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Secret Entrance Exit', player) - else: - lw_hole_entrances.append('Hyrule Castle Secret Entrance Drop') - hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance')) - lw_doors.append('Hyrule Castle Secret Entrance Stairs') - lw_entrances.append('Hyrule Castle Secret Entrance Stairs') - - if not world.shuffle_ganon: - connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit', player) - connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player) - connect_entrance(world, 'Pyramid Hole', 'Pyramid', player) - else: - dw_entrances.append('Ganons Tower') - caves.append('Ganons Tower Exit') - dw_hole_entrances.append('Pyramid Hole') - hole_targets.append(('Pyramid Exit', 'Pyramid')) - dw_entrances_must_exits.append('Pyramid Entrance') - dw_doors.extend(['Ganons Tower', 'Pyramid Entrance']) - - world.random.shuffle(lw_hole_entrances) - world.random.shuffle(dw_hole_entrances) - world.random.shuffle(hole_targets) - - # decide if skull woods first section should be in light or dark world - sw_light = world.random.randint(0, 1) == 0 - if sw_light: - sw_hole_pool = lw_hole_entrances - mandatory_light_world.append('Skull Woods First Section Exit') - else: - sw_hole_pool = dw_hole_entrances - mandatory_dark_world.append('Skull Woods First Section Exit') - for target in ['Skull Woods First Section (Left)', 'Skull Woods First Section (Right)', - 'Skull Woods First Section (Top)']: - connect_entrance(world, sw_hole_pool.pop(), target, player) - - # sanctuary has to be in light world - connect_entrance(world, lw_hole_entrances.pop(), 'Sewer Drop', player) - mandatory_light_world.append('Sanctuary Exit') - - # fill up remaining holes - for hole in dw_hole_entrances: - exits, target = hole_targets.pop() - mandatory_dark_world.append(exits) - connect_entrance(world, hole, target, player) - - for hole in lw_hole_entrances: - exits, target = hole_targets.pop() - mandatory_light_world.append(exits) - connect_entrance(world, hole, target, player) - - # hyrule castle handling - if world.mode[player] == 'standard': - # must connect front of hyrule castle to do escape - connect_entrance(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player) - connect_exit(world, 'Hyrule Castle Exit (South)', 'Hyrule Castle Entrance (South)', player) - mandatory_light_world.append(('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')) - else: - lw_doors.append('Hyrule Castle Entrance (South)') - lw_entrances.append('Hyrule Castle Entrance (South)') - caves.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')) - - # now let's deal with mandatory reachable stuff - def extract_reachable_exit(cavelist): - world.random.shuffle(cavelist) - candidate = None - for cave in cavelist: - if isinstance(cave, tuple) and len(cave) > 1: - # special handling: TRock and Spectracle Rock cave have two entries that we should consider entrance only - # ToDo this should be handled in a more sensible manner - if cave[0] in ['Turtle Rock Exit (Front)', 'Spectacle Rock Cave Exit (Peak)'] and len(cave) == 2: - continue - candidate = cave - break - if candidate is None: - raise KeyError('No suitable cave.') - cavelist.remove(candidate) - return candidate - - def connect_reachable_exit(entrance, general, worldspecific, worldoors): - # select which one is the primary option - if world.random.randint(0, 1) == 0: - primary = general - secondary = worldspecific - else: - primary = worldspecific - secondary = general - - try: - cave = extract_reachable_exit(primary) - except KeyError: - cave = extract_reachable_exit(secondary) - - exit = cave[-1] - cave = cave[:-1] - connect_exit(world, exit, entrance, player) - connect_entrance(world, worldoors.pop(), exit, player) - # rest of cave now is forced to be in this world - worldspecific.append(cave) - - # we randomize which world requirements we fulfill first so we get better dungeon distribution - if world.random.randint(0, 1) == 0: - for entrance in lw_entrances_must_exits: - connect_reachable_exit(entrance, caves, mandatory_light_world, lw_doors) - for entrance in dw_entrances_must_exits: - connect_reachable_exit(entrance, caves, mandatory_dark_world, dw_doors) - else: - for entrance in dw_entrances_must_exits: - connect_reachable_exit(entrance, caves, mandatory_dark_world, dw_doors) - for entrance in lw_entrances_must_exits: - connect_reachable_exit(entrance, caves, mandatory_light_world, lw_doors) - - # place old man, has limited options - # exit has to come from specific set of doors, the entrance is free to move about - old_man_entrances = [entrance for entrance in old_man_entrances if entrance in lw_entrances] - world.random.shuffle(old_man_entrances) - old_man_exit = old_man_entrances.pop() - lw_entrances.remove(old_man_exit) - - connect_exit(world, 'Old Man Cave Exit (East)', old_man_exit, player) - connect_entrance(world, lw_doors.pop(), 'Old Man Cave Exit (East)', player) - mandatory_light_world.append('Old Man Cave Exit (West)') - - # we connect up the mandatory associations we have found - for mandatory in mandatory_light_world: - if not isinstance(mandatory, tuple): - mandatory = (mandatory,) - for exit in mandatory: - # point out somewhere - connect_exit(world, exit, lw_entrances.pop(), player) - # point in from somewhere - connect_entrance(world, lw_doors.pop(), exit, player) - - for mandatory in mandatory_dark_world: - if not isinstance(mandatory, tuple): - mandatory = (mandatory,) - for exit in mandatory: - # point out somewhere - connect_exit(world, exit, dw_entrances.pop(), player) - # point in from somewhere - connect_entrance(world, dw_doors.pop(), exit, player) - - # handle remaining caves - while caves: - # connect highest exit count caves first, prevent issue where we have 2 or 3 exits accross worlds left to fill - cave_candidate = (None, 0) - for i, cave in enumerate(caves): - if isinstance(cave, str): - cave = (cave,) - if len(cave) > cave_candidate[1]: - cave_candidate = (i, len(cave)) - cave = caves.pop(cave_candidate[0]) - - place_lightworld = world.random.randint(0, 1) == 0 - if place_lightworld: - target_doors = lw_doors - target_entrances = lw_entrances - else: - target_doors = dw_doors - target_entrances = dw_entrances - - if isinstance(cave, str): - cave = (cave,) - - # check if we can still fit the cave into our target group - if len(target_doors) < len(cave): - if not place_lightworld: - target_doors = lw_doors - target_entrances = lw_entrances - else: - target_doors = dw_doors - target_entrances = dw_entrances - - for exit in cave: - connect_exit(world, exit, target_entrances.pop(), player) - connect_entrance(world, target_doors.pop(), exit, player) - - # handle simple doors - - single_doors = list(Single_Cave_Doors) - bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors) - blacksmith_doors = list(Blacksmith_Single_Cave_Doors) - door_targets = list(Single_Cave_Targets) - - # place blacksmith, has limited options - world.random.shuffle(blacksmith_doors) - blacksmith_hut = blacksmith_doors.pop() - connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player) - bomb_shop_doors.extend(blacksmith_doors) - - # place dam and pyramid fairy, have limited options - world.random.shuffle(bomb_shop_doors) - bomb_shop = bomb_shop_doors.pop() - connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) - single_doors.extend(bomb_shop_doors) - - # tavern back door cannot be shuffled yet - connect_doors(world, ['Tavern North'], ['Tavern'], player) - - # place remaining doors - connect_doors(world, single_doors, door_targets, player) - elif world.shuffle[player] == 'insanity': + elif world.entrance_shuffle[player] == 'insanity': # beware ye who enter here entrances = LW_Entrances + LW_Dungeon_Entrances + DW_Entrances + DW_Dungeon_Entrances + Old_Man_Entrances + ['Skull Woods Second Section Door (East)', 'Skull Woods First Section Door', 'Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave'] @@ -922,157 +539,15 @@ def link_entrances(world, player): # place remaining doors connect_doors(world, doors, door_targets, player) - elif world.shuffle[player] == 'insanity_legacy': - world.fix_fake_world[player] = False - # beware ye who enter here - entrances = LW_Entrances + LW_Dungeon_Entrances + DW_Entrances + DW_Dungeon_Entrances + Old_Man_Entrances + ['Skull Woods Second Section Door (East)', 'Skull Woods First Section Door', 'Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave'] - entrances_must_exits = DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit + LW_Dungeon_Entrances_Must_Exit + ['Skull Woods Second Section Door (West)'] - - doors = LW_Entrances + LW_Dungeon_Entrances + LW_Dungeon_Entrances_Must_Exit + ['Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave'] + Old_Man_Entrances +\ - DW_Entrances + DW_Dungeon_Entrances + DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit + ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)', 'Skull Woods Second Section Door (West)'] - - world.random.shuffle(doors) - - old_man_entrances = list(Old_Man_Entrances) + ['Tower of Hera'] - - caves = Cave_Exits + Dungeon_Exits + Cave_Three_Exits + ['Old Man House Exit (Bottom)', 'Old Man House Exit (Top)', 'Skull Woods First Section Exit', 'Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)', - 'Kakariko Well Exit', 'Bat Cave Exit', 'North Fairy Cave Exit', 'Lost Woods Hideout Exit', 'Lumberjack Tree Exit', 'Sanctuary Exit'] - - # shuffle up holes - - hole_entrances = ['Kakariko Well Drop', 'Bat Cave Drop', 'North Fairy Cave Drop', 'Lost Woods Hideout Drop', 'Lumberjack Tree Tree', 'Sanctuary Grave', - 'Skull Woods First Section Hole (East)', 'Skull Woods First Section Hole (West)', 'Skull Woods First Section Hole (North)', 'Skull Woods Second Section Hole'] - - hole_targets = ['Kakariko Well (top)', 'Bat Cave (right)', 'North Fairy Cave', 'Lost Woods Hideout (top)', 'Lumberjack Tree (top)', 'Sewer Drop', 'Skull Woods Second Section (Drop)', - 'Skull Woods First Section (Left)', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Top)'] - - if world.mode[player] == 'standard': - # cannot move uncle cave - connect_entrance(world, 'Hyrule Castle Secret Entrance Drop', 'Hyrule Castle Secret Entrance', player) - connect_exit(world, 'Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance Stairs', player) - connect_entrance(world, 'Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Secret Entrance Exit', player) - else: - hole_entrances.append('Hyrule Castle Secret Entrance Drop') - hole_targets.append('Hyrule Castle Secret Entrance') - doors.append('Hyrule Castle Secret Entrance Stairs') - entrances.append('Hyrule Castle Secret Entrance Stairs') - caves.append('Hyrule Castle Secret Entrance Exit') - - if not world.shuffle_ganon: - connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit', player) - connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player) - connect_entrance(world, 'Pyramid Hole', 'Pyramid', player) - else: - entrances.append('Ganons Tower') - caves.extend(['Ganons Tower Exit', 'Pyramid Exit']) - hole_entrances.append('Pyramid Hole') - hole_targets.append('Pyramid') - entrances_must_exits.append('Pyramid Entrance') - doors.extend(['Ganons Tower', 'Pyramid Entrance']) - - world.random.shuffle(hole_entrances) - world.random.shuffle(hole_targets) - world.random.shuffle(entrances) - - # fill up holes - for hole in hole_entrances: - connect_entrance(world, hole, hole_targets.pop(), player) - - # hyrule castle handling - if world.mode[player] == 'standard': - # must connect front of hyrule castle to do escape - connect_entrance(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player) - connect_exit(world, 'Hyrule Castle Exit (South)', 'Hyrule Castle Entrance (South)', player) - caves.append(('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')) - else: - doors.append('Hyrule Castle Entrance (South)') - entrances.append('Hyrule Castle Entrance (South)') - caves.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')) - - # now let's deal with mandatory reachable stuff - def extract_reachable_exit(cavelist): - world.random.shuffle(cavelist) - candidate = None - for cave in cavelist: - if isinstance(cave, tuple) and len(cave) > 1: - # special handling: TRock has two entries that we should consider entrance only - # ToDo this should be handled in a more sensible manner - if cave[0] in ['Turtle Rock Exit (Front)', 'Spectacle Rock Cave Exit (Peak)'] and len(cave) == 2: - continue - candidate = cave - break - if candidate is None: - raise KeyError('No suitable cave.') - cavelist.remove(candidate) - return candidate - - def connect_reachable_exit(entrance, caves, doors): - cave = extract_reachable_exit(caves) - - exit = cave[-1] - cave = cave[:-1] - connect_exit(world, exit, entrance, player) - connect_entrance(world, doors.pop(), exit, player) - # rest of cave now is forced to be in this world - caves.append(cave) - - # connect mandatory exits - for entrance in entrances_must_exits: - connect_reachable_exit(entrance, caves, doors) - - # place old man, has limited options - # exit has to come from specific set of doors, the entrance is free to move about - old_man_entrances = [entrance for entrance in old_man_entrances if entrance in entrances] - world.random.shuffle(old_man_entrances) - old_man_exit = old_man_entrances.pop() - entrances.remove(old_man_exit) - - connect_exit(world, 'Old Man Cave Exit (East)', old_man_exit, player) - connect_entrance(world, doors.pop(), 'Old Man Cave Exit (East)', player) - caves.append('Old Man Cave Exit (West)') - - # handle remaining caves - for cave in caves: - if isinstance(cave, str): - cave = (cave,) - - for exit in cave: - connect_exit(world, exit, entrances.pop(), player) - connect_entrance(world, doors.pop(), exit, player) - - # handle simple doors - - single_doors = list(Single_Cave_Doors) - bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors) - blacksmith_doors = list(Blacksmith_Single_Cave_Doors) - door_targets = list(Single_Cave_Targets) - - # place blacksmith, has limited options - world.random.shuffle(blacksmith_doors) - blacksmith_hut = blacksmith_doors.pop() - connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player) - bomb_shop_doors.extend(blacksmith_doors) - - # place dam and pyramid fairy, have limited options - world.random.shuffle(bomb_shop_doors) - bomb_shop = bomb_shop_doors.pop() - connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) - single_doors.extend(bomb_shop_doors) - - # tavern back door cannot be shuffled yet - connect_doors(world, ['Tavern North'], ['Tavern'], player) - - # place remaining doors - connect_doors(world, single_doors, door_targets, player) else: raise NotImplementedError( - f'{world.shuffle[player]} Shuffling not supported yet. Player {world.get_player_name(player)}') + f'{world.entrance_shuffle[player]} Shuffling not supported yet. Player {world.get_player_name(player)}') - if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']: + if world.glitches_required[player] in ['overworld_glitches', 'hybrid_major_glitches', 'no_logic']: overworld_glitch_connections(world, player) # mandatory hybrid major glitches connections - if world.logic[player] in ['hybridglitches', 'nologic']: + if world.glitches_required[player] in ['hybrid_major_glitches', 'no_logic']: underworld_glitch_connections(world, player) # check for swamp palace fix @@ -1106,17 +581,17 @@ def link_inverted_entrances(world, player): connect_simple(world, exitname, regionname, player) # if we do not shuffle, set default connections - if world.shuffle[player] == 'vanilla': + if world.entrance_shuffle[player] == 'vanilla': for exitname, regionname in inverted_default_connections: connect_simple(world, exitname, regionname, player) for exitname, regionname in inverted_default_dungeon_connections: connect_simple(world, exitname, regionname, player) - elif world.shuffle[player] == 'dungeonssimple': + elif world.entrance_shuffle[player] == 'dungeons_simple': for exitname, regionname in inverted_default_connections: connect_simple(world, exitname, regionname, player) simple_shuffle_dungeons(world, player) - elif world.shuffle[player] == 'dungeonsfull': + elif world.entrance_shuffle[player] == 'dungeons_full': for exitname, regionname in inverted_default_connections: connect_simple(world, exitname, regionname, player) @@ -1171,9 +646,9 @@ def link_inverted_entrances(world, player): connect_mandatory_exits(world, lw_entrances, dungeon_exits, lw_dungeon_entrances_must_exit, player) connect_caves(world, lw_entrances, dw_entrances, dungeon_exits, player) - elif world.shuffle[player] == 'dungeonscrossed': + elif world.entrance_shuffle[player] == 'dungeons_crossed': inverted_crossed_shuffle_dungeons(world, player) - elif world.shuffle[player] == 'simple': + elif world.entrance_shuffle[player] == 'simple': simple_shuffle_dungeons(world, player) old_man_entrances = list(Inverted_Old_Man_Entrances) @@ -1270,7 +745,7 @@ def link_inverted_entrances(world, player): # place remaining doors connect_doors(world, single_doors, door_targets, player) - elif world.shuffle[player] == 'restricted': + elif world.entrance_shuffle[player] == 'restricted': simple_shuffle_dungeons(world, player) lw_entrances = list(Inverted_LW_Entrances + Inverted_LW_Single_Cave_Doors) @@ -1355,7 +830,7 @@ def link_inverted_entrances(world, player): doors = lw_entrances + dw_entrances # place remaining doors connect_doors(world, doors, door_targets, player) - elif world.shuffle[player] == 'full': + elif world.entrance_shuffle[player] == 'full': skull_woods_shuffle(world, player) lw_entrances = list(Inverted_LW_Entrances + Inverted_LW_Dungeon_Entrances + Inverted_LW_Single_Cave_Doors) @@ -1506,7 +981,7 @@ def link_inverted_entrances(world, player): # place remaining doors connect_doors(world, doors, door_targets, player) - elif world.shuffle[player] == 'crossed': + elif world.entrance_shuffle[player] == 'crossed': skull_woods_shuffle(world, player) entrances = list(Inverted_LW_Entrances + Inverted_LW_Dungeon_Entrances + Inverted_LW_Single_Cave_Doors + Inverted_Old_Man_Entrances + Inverted_DW_Entrances + Inverted_DW_Dungeon_Entrances + Inverted_DW_Single_Cave_Doors) @@ -1617,7 +1092,7 @@ def link_inverted_entrances(world, player): # place remaining doors connect_doors(world, entrances, door_targets, player) - elif world.shuffle[player] == 'insanity': + elif world.entrance_shuffle[player] == 'insanity': # beware ye who enter here entrances = Inverted_LW_Entrances + Inverted_LW_Dungeon_Entrances + Inverted_DW_Entrances + Inverted_DW_Dungeon_Entrances + Inverted_Old_Man_Entrances + Old_Man_Entrances + ['Skull Woods Second Section Door (East)', 'Skull Woods Second Section Door (West)', 'Skull Woods First Section Door', 'Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave', 'Hyrule Castle Entrance (South)'] @@ -1776,10 +1251,10 @@ def link_inverted_entrances(world, player): else: raise NotImplementedError('Shuffling not supported yet') - if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']: + if world.glitches_required[player] in ['overworld_glitches', 'hybrid_major_glitches', 'no_logic']: overworld_glitch_connections(world, player) # mandatory hybrid major glitches connections - if world.logic[player] in ['hybridglitches', 'nologic']: + if world.glitches_required[player] in ['hybrid_major_glitches', 'no_logic']: underworld_glitch_connections(world, player) # patch swamp drain @@ -1880,14 +1355,14 @@ def scramble_holes(world, player): hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance')) # do not shuffle sanctuary into pyramid hole unless shuffle is crossed - if world.shuffle[player] == 'crossed': + if world.entrance_shuffle[player] == 'crossed': hole_targets.append(('Sanctuary Exit', 'Sewer Drop')) if world.shuffle_ganon: world.random.shuffle(hole_targets) exit, target = hole_targets.pop() connect_two_way(world, 'Pyramid Entrance', exit, player) connect_entrance(world, 'Pyramid Hole', target, player) - if world.shuffle[player] != 'crossed': + if world.entrance_shuffle[player] != 'crossed': hole_targets.append(('Sanctuary Exit', 'Sewer Drop')) world.random.shuffle(hole_targets) @@ -1922,14 +1397,14 @@ def scramble_inverted_holes(world, player): hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance')) # do not shuffle sanctuary into pyramid hole unless shuffle is crossed - if world.shuffle[player] == 'crossed': + if world.entrance_shuffle[player] == 'crossed': hole_targets.append(('Sanctuary Exit', 'Sewer Drop')) if world.shuffle_ganon: world.random.shuffle(hole_targets) exit, target = hole_targets.pop() connect_two_way(world, 'Inverted Pyramid Entrance', exit, player) connect_entrance(world, 'Inverted Pyramid Hole', target, player) - if world.shuffle[player] != 'crossed': + if world.entrance_shuffle[player] != 'crossed': hole_targets.append(('Sanctuary Exit', 'Sewer Drop')) world.random.shuffle(hole_targets) @@ -1958,7 +1433,7 @@ def connect_mandatory_exits(world, entrances, caves, must_be_exits, player): invalid_connections = Must_Exit_Invalid_Connections.copy() invalid_cave_connections = defaultdict(set) - if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']: + if world.glitches_required[player] in ['overworld_glitches', 'hybrid_major_glitches', 'no_logic']: from worlds.alttp import OverworldGlitchRules for entrance in OverworldGlitchRules.get_non_mandatory_exits(world.mode[player] == 'inverted'): invalid_connections[entrance] = set() @@ -3038,6 +2513,7 @@ mandatory_connections = [('Links House S&Q', 'Links House'), ('Sanctuary Push Door', 'Sanctuary'), ('Sewer Drop', 'Sewers'), ('Sewers Back Door', 'Sewers (Dark)'), + ('Sewers Secret Room', 'Sewers Secret Room'), ('Agahnim 1', 'Agahnim 1'), ('Flute Spot 1', 'Death Mountain'), ('Death Mountain Entrance Rock', 'Death Mountain Entrance'), @@ -3053,6 +2529,8 @@ mandatory_connections = [('Links House S&Q', 'Links House'), ('Spiral Cave Ledge Access', 'Spiral Cave Ledge'), ('Spiral Cave Ledge Drop', 'East Death Mountain (Bottom)'), ('Spiral Cave (top to bottom)', 'Spiral Cave (Bottom)'), + ('Hookshot Cave Bomb Wall (South)', 'Hookshot Cave (Upper)'), + ('Hookshot Cave Bomb Wall (North)', 'Hookshot Cave'), ('East Death Mountain (Top)', 'East Death Mountain (Top)'), ('Death Mountain (Top)', 'Death Mountain (Top)'), ('Death Mountain Drop', 'Death Mountain'), @@ -3227,6 +2705,7 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'), ('Sanctuary Push Door', 'Sanctuary'), ('Sewer Drop', 'Sewers'), ('Sewers Back Door', 'Sewers (Dark)'), + ('Sewers Secret Room', 'Sewers Secret Room'), ('Agahnim 1', 'Agahnim 1'), ('Death Mountain Entrance Rock', 'Death Mountain Entrance'), ('Death Mountain Entrance Drop', 'Light World'), @@ -3241,6 +2720,8 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'), ('Spiral Cave Ledge Access', 'Spiral Cave Ledge'), ('Spiral Cave Ledge Drop', 'East Death Mountain (Bottom)'), ('Spiral Cave (top to bottom)', 'Spiral Cave (Bottom)'), + ('Hookshot Cave Bomb Wall (South)', 'Hookshot Cave (Upper)'), + ('Hookshot Cave Bomb Wall (North)', 'Hookshot Cave'), ('East Death Mountain (Top)', 'East Death Mountain (Top)'), ('Death Mountain (Top)', 'Death Mountain (Top)'), ('Death Mountain Drop', 'Death Mountain'), @@ -3572,7 +3053,7 @@ default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'), ('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'), ('Hookshot Cave Exit (South)', 'Dark Death Mountain (Top)'), ('Hookshot Cave Exit (North)', 'Death Mountain Floating Island (Dark World)'), - ('Hookshot Cave Back Entrance', 'Hookshot Cave'), + ('Hookshot Cave Back Entrance', 'Hookshot Cave (Upper)'), ('Mimic Cave', 'Mimic Cave'), ('Pyramid Hole', 'Pyramid'), @@ -3703,7 +3184,7 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing' ('Superbunny Cave (Bottom)', 'Superbunny Cave (Bottom)'), ('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'), ('Hookshot Cave Exit (North)', 'Death Mountain Floating Island (Dark World)'), - ('Hookshot Cave Back Entrance', 'Hookshot Cave'), + ('Hookshot Cave Back Entrance', 'Hookshot Cave (Upper)'), ('Mimic Cave', 'Mimic Cave'), ('Inverted Pyramid Hole', 'Pyramid'), ('Inverted Links House', 'Inverted Links House'), diff --git a/worlds/alttp/InvertedRegions.py b/worlds/alttp/InvertedRegions.py index f89eebec..2e30fde8 100644 --- a/worlds/alttp/InvertedRegions.py +++ b/worlds/alttp/InvertedRegions.py @@ -133,7 +133,7 @@ def create_inverted_regions(world, player): create_cave_region(world, player, 'Kakariko Gamble Game', 'a game of chance'), create_cave_region(world, player, 'Potion Shop', 'the potion shop', ['Potion Shop']), create_lw_region(world, player, 'Lake Hylia Island', ['Lake Hylia Island']), - create_cave_region(world, player, 'Capacity Upgrade', 'the queen of fairies'), + create_cave_region(world, player, 'Capacity Upgrade', 'the queen of fairies', ['Capacity Upgrade Shop']), create_cave_region(world, player, 'Two Brothers House', 'a connector', None, ['Two Brothers House Exit (East)', 'Two Brothers House Exit (West)']), create_lw_region(world, player, 'Maze Race Ledge', ['Maze Race'], @@ -176,8 +176,9 @@ def create_inverted_regions(world, player): 'Throne Room']), create_dungeon_region(world, player, 'Sewer Drop', 'a drop\'s exit', None, ['Sewer Drop']), # This exists only to be referenced for access checks create_dungeon_region(world, player, 'Sewers (Dark)', 'a drop\'s exit', ['Sewers - Dark Cross', 'Sewers - Key Rat Key Drop'], ['Sewers Door']), - create_dungeon_region(world, player, 'Sewers', 'a drop\'s exit', ['Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle', - 'Sewers - Secret Room - Right'], ['Sanctuary Push Door', 'Sewers Back Door']), + create_dungeon_region(world, player, 'Sewers', 'a drop\'s exit', None, ['Sanctuary Push Door', 'Sewers Back Door', 'Sewers Secret Room']), + create_dungeon_region(world, player, 'Sewers Secret Room', 'a drop\'s exit', ['Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle', + 'Sewers - Secret Room - Right']), create_dungeon_region(world, player, 'Sanctuary', 'a drop\'s exit', ['Sanctuary'], ['Sanctuary Exit']), create_dungeon_region(world, player, 'Inverted Agahnims Tower', 'Castle Tower', ['Castle Tower - Room 03', 'Castle Tower - Dark Maze', 'Castle Tower - Dark Archer Key Drop', 'Castle Tower - Circle of Pots Key Drop'], ['Agahnim 1', 'Inverted Agahnims Tower Exit']), create_dungeon_region(world, player, 'Agahnim 1', 'Castle Tower', ['Agahnim 1'], None), @@ -346,7 +347,9 @@ def create_inverted_regions(world, player): create_cave_region(world, player, 'Hookshot Cave', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', 'Hookshot Cave - Bottom Left'], - ['Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)']), + ['Hookshot Cave Exit (South)', 'Hookshot Cave Bomb Wall (South)']), + create_cave_region(world, player, 'Hookshot Cave (Upper)', 'a connector', None, ['Hookshot Cave Exit (North)', + 'Hookshot Cave Bomb Wall (North)']), create_dw_region(world, player, 'Death Mountain Floating Island (Dark World)', None, ['Floating Island Drop', 'Hookshot Cave Back Entrance']), create_cave_region(world, player, 'Mimic Cave', 'Mimic Cave', ['Mimic Cave']), @@ -380,8 +383,8 @@ def create_inverted_regions(world, player): create_dungeon_region(world, player, 'Skull Woods Second Section', 'Skull Woods', ['Skull Woods - Big Key Chest', 'Skull Woods - West Lobby Pot Key'], ['Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)']), create_dungeon_region(world, player, 'Skull Woods Final Section (Entrance)', 'Skull Woods', ['Skull Woods - Bridge Room', 'Skull Woods - Spike Corner Key Drop'], ['Skull Woods Torch Room', 'Skull Woods Final Section Exit']), create_dungeon_region(world, player, 'Skull Woods Final Section (Mothula)', 'Skull Woods', ['Skull Woods - Boss', 'Skull Woods - Prize']), - create_dungeon_region(world, player, 'Ice Palace (Entrance)', 'Ice Palace', ['Ice Palace - Jelly Key Drop'], ['Ice Palace (Second Section)', 'Ice Palace Exit']), - create_dungeon_region(world, player, 'Ice Palace (Second Section)', 'Ice Palace', ['Ice Palace - Conveyor Key Drop', 'Ice Palace - Compass Chest'], ['Ice Palace (Main)']), + create_dungeon_region(world, player, 'Ice Palace (Entrance)', 'Ice Palace', ['Ice Palace - Jelly Key Drop', 'Ice Palace - Compass Chest'], ['Ice Palace (Second Section)', 'Ice Palace Exit']), + create_dungeon_region(world, player, 'Ice Palace (Second Section)', 'Ice Palace', ['Ice Palace - Conveyor Key Drop'], ['Ice Palace (Main)']), create_dungeon_region(world, player, 'Ice Palace (Main)', 'Ice Palace', ['Ice Palace - Freezor Chest', 'Ice Palace - Many Pots Pot Key', 'Ice Palace - Big Chest', 'Ice Palace - Iced T Room'], ['Ice Palace (East)', 'Ice Palace (Kholdstare)']), diff --git a/worlds/alttp/ItemPool.py b/worlds/alttp/ItemPool.py index 1c3f3e44..bb5bbaa6 100644 --- a/worlds/alttp/ItemPool.py +++ b/worlds/alttp/ItemPool.py @@ -5,12 +5,12 @@ from BaseClasses import ItemClassification from Fill import FillError from .SubClasses import ALttPLocation, LTTPRegion, LTTPRegionType -from .Shops import TakeAny, total_shop_slots, set_up_shops, shuffle_shops, create_dynamic_shop_locations +from .Shops import TakeAny, total_shop_slots, set_up_shops, shop_table_by_location, ShopType from .Bosses import place_bosses from .Dungeons import get_dungeon_item_pool_player from .EntranceShuffle import connect_entrance -from .Items import ItemFactory, GetBeemizerItem -from .Options import smallkey_shuffle, compass_shuffle, bigkey_shuffle, map_shuffle, LTTPBosses +from .Items import ItemFactory, GetBeemizerItem, trap_replaceable, item_name_groups +from .Options import small_key_shuffle, compass_shuffle, big_key_shuffle, map_shuffle, TriforcePiecesMode from .StateHelpers import has_triforce_pieces, has_melee_weapon from .Regions import key_drop_data @@ -189,104 +189,62 @@ difficulties = { ), } -ice_rod_hunt_difficulties = dict() -for diff in {'easy', 'normal', 'hard', 'expert'}: - ice_rod_hunt_difficulties[diff] = Difficulty( - baseitems=['Nothing'] * 41, - bottles=['Nothing'] * 4, - bottle_count=difficulties[diff].bottle_count, - same_bottle=difficulties[diff].same_bottle, - progressiveshield=['Nothing'] * 3, - basicshield=['Nothing'] * 3, - progressivearmor=['Nothing'] * 2, - basicarmor=['Nothing'] * 2, - swordless=['Nothing'] * 4, - progressivemagic=['Nothing'] * 2, - basicmagic=['Nothing'] * 2, - progressivesword=['Nothing'] * 4, - basicsword=['Nothing'] * 4, - progressivebow=['Nothing'] * 2, - basicbow=['Nothing'] * 2, - timedohko=difficulties[diff].timedohko, - timedother=difficulties[diff].timedother, - progressiveglove=['Nothing'] * 2, - basicglove=['Nothing'] * 2, - alwaysitems=['Ice Rod'] + ['Nothing'] * 19, - legacyinsanity=['Nothing'] * 2, - universal_keys=['Nothing'] * 29, - extras=[['Nothing'] * 15, ['Nothing'] * 15, ['Nothing'] * 10, ['Nothing'] * 5, ['Nothing'] * 25], - progressive_sword_limit=difficulties[diff].progressive_sword_limit, - progressive_shield_limit=difficulties[diff].progressive_shield_limit, - progressive_armor_limit=difficulties[diff].progressive_armor_limit, - progressive_bow_limit=difficulties[diff].progressive_bow_limit, - progressive_bottle_limit=difficulties[diff].progressive_bottle_limit, - boss_heart_container_limit=difficulties[diff].boss_heart_container_limit, - heart_piece_limit=difficulties[diff].heart_piece_limit, - ) + +items_reduction_table = ( + ("Piece of Heart", "Boss Heart Container", 4, 1), + # the order of the upgrades is important + ("Arrow Upgrade (+5)", "Arrow Upgrade (+10)", 8, 4), + ("Arrow Upgrade (+5)", "Arrow Upgrade (+10)", 7, 4), + ("Arrow Upgrade (+5)", "Arrow Upgrade (+10)", 6, 3), + ("Arrow Upgrade (+10)", "Arrow Upgrade (70)", 4, 1), + ("Bomb Upgrade (+5)", "Bomb Upgrade (+10)", 8, 4), + ("Bomb Upgrade (+5)", "Bomb Upgrade (+10)", 7, 4), + ("Bomb Upgrade (+5)", "Bomb Upgrade (+10)", 6, 3), + ("Bomb Upgrade (+10)", "Bomb Upgrade (50)", 5, 1), + ("Bomb Upgrade (+10)", "Bomb Upgrade (50)", 4, 1), + ("Progressive Sword", 4), + ("Fighter Sword", 1), + ("Master Sword", 1), + ("Tempered Sword", 1), + ("Golden Sword", 1), + ("Progressive Shield", 3), + ("Blue Shield", 1), + ("Red Shield", 1), + ("Mirror Shield", 1), + ("Progressive Mail", 2), + ("Blue Mail", 1), + ("Red Mail", 1), + ("Progressive Bow", 2), + ("Bow", 1), + ("Silver Bow", 1), + ("Lamp", 1), + ("Bottles",) +) def generate_itempool(world): player = world.player multiworld = world.multiworld - if multiworld.difficulty[player] not in difficulties: - raise NotImplementedError(f"Diffulty {multiworld.difficulty[player]}") - if multiworld.goal[player] not in {'ganon', 'pedestal', 'bosses', 'triforcehunt', 'localtriforcehunt', 'icerodhunt', - 'ganontriforcehunt', 'localganontriforcehunt', 'crystals', 'ganonpedestal'}: + if multiworld.item_pool[player].current_key not in difficulties: + raise NotImplementedError(f"Diffulty {multiworld.item_pool[player]}") + if multiworld.goal[player] not in ('ganon', 'pedestal', 'bosses', 'triforce_hunt', 'local_triforce_hunt', + 'ganon_triforce_hunt', 'local_ganon_triforce_hunt', 'crystals', + 'ganon_pedestal'): raise NotImplementedError(f"Goal {multiworld.goal[player]} for player {player}") - if multiworld.mode[player] not in {'open', 'standard', 'inverted'}: + if multiworld.mode[player] not in ('open', 'standard', 'inverted'): raise NotImplementedError(f"Mode {multiworld.mode[player]} for player {player}") - if multiworld.timer[player] not in {False, 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'}: + if multiworld.timer[player] not in {False, 'display', 'timed', 'timed_ohko', 'ohko', 'timed_countdown'}: raise NotImplementedError(f"Timer {multiworld.mode[player]} for player {player}") - if multiworld.timer[player] in ['ohko', 'timed-ohko']: + if multiworld.timer[player] in ['ohko', 'timed_ohko']: multiworld.can_take_damage[player] = False - if multiworld.goal[player] in ['pedestal', 'triforcehunt', 'localtriforcehunt', 'icerodhunt']: + if multiworld.goal[player] in ['pedestal', 'triforce_hunt', 'local_triforce_hunt']: multiworld.push_item(multiworld.get_location('Ganon', player), ItemFactory('Nothing', player), False) else: multiworld.push_item(multiworld.get_location('Ganon', player), ItemFactory('Triforce', player), False) - if multiworld.goal[player] == 'icerodhunt': - multiworld.progression_balancing[player].value = 0 - loc = multiworld.get_location('Turtle Rock - Boss', player) - multiworld.push_item(loc, ItemFactory('Triforce Piece', player), False) - multiworld.treasure_hunt_count[player] = 1 - if multiworld.boss_shuffle[player] != 'none': - if isinstance(multiworld.boss_shuffle[player].value, str) and 'turtle rock-' not in multiworld.boss_shuffle[player].value: - multiworld.boss_shuffle[player] = LTTPBosses.from_text(f'Turtle Rock-Trinexx;{multiworld.boss_shuffle[player].current_key}') - elif isinstance(multiworld.boss_shuffle[player].value, int): - multiworld.boss_shuffle[player] = LTTPBosses.from_text(f'Turtle Rock-Trinexx;{multiworld.boss_shuffle[player].current_key}') - else: - logging.warning(f'Cannot guarantee that Trinexx is the boss of Turtle Rock for player {player}') - loc.event = True - loc.locked = True - itemdiff = difficulties[multiworld.difficulty[player]] - itempool = [] - itempool.extend(itemdiff.alwaysitems) - itempool.remove('Ice Rod') - - itempool.extend(['Single Arrow', 'Sanctuary Heart Container']) - itempool.extend(['Boss Heart Container'] * itemdiff.boss_heart_container_limit) - itempool.extend(['Piece of Heart'] * itemdiff.heart_piece_limit) - itempool.extend(itemdiff.bottles) - itempool.extend(itemdiff.basicbow) - itempool.extend(itemdiff.basicarmor) - if not multiworld.swordless[player]: - itempool.extend(itemdiff.basicsword) - itempool.extend(itemdiff.basicmagic) - itempool.extend(itemdiff.basicglove) - itempool.extend(itemdiff.basicshield) - itempool.extend(itemdiff.legacyinsanity) - itempool.extend(['Rupees (300)'] * 34) - itempool.extend(['Bombs (10)'] * 5) - itempool.extend(['Arrows (10)'] * 7) - if multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal: - itempool.extend(itemdiff.universal_keys) - - for item in itempool: - multiworld.push_precollected(ItemFactory(item, player)) - - if multiworld.goal[player] in ['triforcehunt', 'localtriforcehunt', 'icerodhunt']: + if multiworld.goal[player] in ['triforce_hunt', 'local_triforce_hunt']: region = multiworld.get_region('Light World', player) loc = ALttPLocation(player, "Murahdahla", parent=region) @@ -308,7 +266,8 @@ def generate_itempool(world): ('Missing Smith', 'Return Smith'), ('Floodgate', 'Open Floodgate'), ('Agahnim 1', 'Beat Agahnim 1'), - ('Flute Activation Spot', 'Activated Flute') + ('Flute Activation Spot', 'Activated Flute'), + ('Capacity Upgrade Shop', 'Capacity Upgrade Shop') ] for location_name, event_name in event_pairs: location = multiworld.get_location(location_name, player) @@ -340,17 +299,31 @@ def generate_itempool(world): if not found_sword: found_sword = True possible_weapons.append(item) - if item in ['Progressive Bow', 'Bow'] and not found_bow: + elif item in ['Progressive Bow', 'Bow'] and not found_bow: found_bow = True possible_weapons.append(item) - if item in ['Hammer', 'Bombs (10)', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']: + elif item in ['Hammer', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']: if item not in possible_weapons: possible_weapons.append(item) + elif (item == 'Bombs (10)' and (not multiworld.bombless_start[player]) and item not in + possible_weapons): + possible_weapons.append(item) + elif (item in ['Bomb Upgrade (+10)', 'Bomb Upgrade (50)'] and multiworld.bombless_start[player] and item + not in possible_weapons): + possible_weapons.append(item) + starting_weapon = multiworld.random.choice(possible_weapons) placed_items["Link's Uncle"] = starting_weapon pool.remove(starting_weapon) - if placed_items["Link's Uncle"] in ['Bow', 'Progressive Bow', 'Bombs (10)', 'Cane of Somaria', 'Cane of Byrna'] and multiworld.enemy_health[player] not in ['default', 'easy']: - multiworld.escape_assist[player].append('bombs') + if (placed_items["Link's Uncle"] in ['Bow', 'Progressive Bow', 'Bombs (10)', 'Bomb Upgrade (+10)', + 'Bomb Upgrade (50)', 'Cane of Somaria', 'Cane of Byrna'] and multiworld.enemy_health[player] not in ['default', 'easy']): + if multiworld.bombless_start[player] and "Bomb Upgrade" not in placed_items["Link's Uncle"]: + if 'Bow' in placed_items["Link's Uncle"]: + multiworld.escape_assist[player].append('arrows') + elif 'Cane' in placed_items["Link's Uncle"]: + multiworld.escape_assist[player].append('magic') + else: + multiworld.escape_assist[player].append('bombs') for (location, item) in placed_items.items(): multiworld.get_location(location, player).place_locked_item(ItemFactory(item, player)) @@ -377,7 +350,7 @@ def generate_itempool(world): for key_loc in key_drop_data: key_data = key_drop_data[key_loc] drop_item = ItemFactory(key_data[3], player) - if multiworld.goal[player] == 'icerodhunt' or not multiworld.key_drop_shuffle[player]: + if not multiworld.key_drop_shuffle[player]: if drop_item in dungeon_items: dungeon_items.remove(drop_item) else: @@ -391,88 +364,151 @@ def generate_itempool(world): world.dungeons[dungeon].small_keys.remove(drop_item) elif world.dungeons[dungeon].big_key is not None and world.dungeons[dungeon].big_key == drop_item: world.dungeons[dungeon].big_key = None - if not multiworld.key_drop_shuffle[player]: - # key drop item was removed from the pool because key drop shuffle is off - # and it will now place the removed key into its original location + loc = multiworld.get_location(key_loc, player) loc.place_locked_item(drop_item) loc.address = None - elif multiworld.goal[player] == 'icerodhunt': - # key drop item removed because of icerodhunt - multiworld.itempool.append(ItemFactory(GetBeemizerItem(world, player, 'Nothing'), player)) - multiworld.push_precollected(drop_item) - elif "Small" in key_data[3] and multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal: + elif "Small" in key_data[3] and multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal: # key drop shuffle and universal keys are on. Add universal keys in place of key drop keys. - multiworld.itempool.append(ItemFactory(GetBeemizerItem(world, player, 'Small Key (Universal)'), player)) + multiworld.itempool.append(ItemFactory(GetBeemizerItem(multiworld, player, 'Small Key (Universal)'), player)) dungeon_item_replacements = sum(difficulties[multiworld.difficulty[player]].extras, []) * 2 multiworld.random.shuffle(dungeon_item_replacements) - if multiworld.goal[player] == 'icerodhunt': - for item in dungeon_items: - multiworld.itempool.append(ItemFactory(GetBeemizerItem(multiworld, player, 'Nothing'), player)) + + for x in range(len(dungeon_items)-1, -1, -1): + item = dungeon_items[x] + if ((multiworld.small_key_shuffle[player] == small_key_shuffle.option_start_with and item.type == 'SmallKey') + or (multiworld.big_key_shuffle[player] == big_key_shuffle.option_start_with and item.type == 'BigKey') + or (multiworld.compass_shuffle[player] == compass_shuffle.option_start_with and item.type == 'Compass') + or (multiworld.map_shuffle[player] == map_shuffle.option_start_with and item.type == 'Map')): + dungeon_items.pop(x) multiworld.push_precollected(item) - else: - for x in range(len(dungeon_items)-1, -1, -1): - item = dungeon_items[x] - if ((multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_start_with and item.type == 'SmallKey') - or (multiworld.bigkey_shuffle[player] == bigkey_shuffle.option_start_with and item.type == 'BigKey') - or (multiworld.compass_shuffle[player] == compass_shuffle.option_start_with and item.type == 'Compass') - or (multiworld.map_shuffle[player] == map_shuffle.option_start_with and item.type == 'Map')): - dungeon_items.pop(x) - multiworld.push_precollected(item) - multiworld.itempool.append(ItemFactory(dungeon_item_replacements.pop(), player)) - multiworld.itempool.extend([item for item in dungeon_items]) - # 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 multiworld.goal[player] != 'icerodhunt' and multiworld.difficulty[player] in ['easy', 'normal', 'hard'] and not (multiworld.custom and multiworld.customitemarray[30] == 0): - next(item for item in items if item.name == 'Boss Heart Container').classification = ItemClassification.progression - elif multiworld.goal[player] != 'icerodhunt' and multiworld.difficulty[player] in ['expert'] and not (multiworld.custom and multiworld.customitemarray[29] < 4): - adv_heart_pieces = (item for item in items if item.name == 'Piece of Heart') - for i in range(4): - next(adv_heart_pieces).classification = ItemClassification.progression + multiworld.itempool.append(ItemFactory(dungeon_item_replacements.pop(), player)) + multiworld.itempool.extend([item for item in dungeon_items]) - - progressionitems = [] - nonprogressionitems = [] - for item in items: - if item.advancement or item.type: - progressionitems.append(item) - else: - nonprogressionitems.append(GetBeemizerItem(multiworld, item.player, item)) - multiworld.random.shuffle(nonprogressionitems) - - if additional_triforce_pieces: - if additional_triforce_pieces > len(nonprogressionitems): - raise FillError(f"Not enough non-progression items to replace with Triforce pieces found for player " - f"{multiworld.get_player_name(player)}.") - progressionitems += [ItemFactory("Triforce Piece", player) for _ in range(additional_triforce_pieces)] - nonprogressionitems.sort(key=lambda item: int("Heart" in item.name)) # try to keep hearts in the pool - nonprogressionitems = nonprogressionitems[additional_triforce_pieces:] - multiworld.random.shuffle(nonprogressionitems) - - # shuffle medallions - if multiworld.required_medallions[player][0] == "random": - mm_medallion = multiworld.random.choice(['Ether', 'Quake', 'Bombos']) - else: - mm_medallion = multiworld.required_medallions[player][0] - if multiworld.required_medallions[player][1] == "random": - tr_medallion = multiworld.random.choice(['Ether', 'Quake', 'Bombos']) - else: - tr_medallion = multiworld.required_medallions[player][1] - multiworld.required_medallions[player] = (mm_medallion, tr_medallion) - - place_bosses(world) set_up_shops(multiworld, player) - if multiworld.shop_shuffle[player]: - shuffle_shops(multiworld, nonprogressionitems, player) + if multiworld.retro_bow[player]: + shop_items = 0 + shop_locations = [location for shop_locations in (shop.region.locations for shop in multiworld.shops if + shop.type == ShopType.Shop and shop.region.player == player) for location in shop_locations if + location.shop_slot is not None] + for location in shop_locations: + if location.shop.inventory[location.shop_slot]["item"] == "Single Arrow": + location.place_locked_item(ItemFactory("Single Arrow", player)) + else: + shop_items += 1 + else: + shop_items = min(multiworld.shop_item_slots[player], 30 if multiworld.include_witch_hut[player] else 27) - multiworld.itempool += progressionitems + nonprogressionitems + if multiworld.shuffle_capacity_upgrades[player]: + shop_items += 2 + chance_100 = int(multiworld.retro_bow[player]) * 0.25 + int( + multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal) * 0.5 + for _ in range(shop_items): + if multiworld.random.random() < chance_100: + items.append(ItemFactory(GetBeemizerItem(multiworld, player, "Rupees (100)"), player)) + else: + items.append(ItemFactory(GetBeemizerItem(multiworld, player, "Rupees (50)"), player)) + + multiworld.random.shuffle(items) + pool_count = len(items) + new_items = ["Triforce Piece" for _ in range(additional_triforce_pieces)] + if multiworld.shuffle_capacity_upgrades[player] or multiworld.bombless_start[player]: + progressive = multiworld.progressive[player] + progressive = multiworld.random.choice([True, False]) if progressive == 'grouped_random' else progressive == 'on' + if multiworld.shuffle_capacity_upgrades[player] == "on_combined": + new_items.append("Bomb Upgrade (50)") + elif multiworld.shuffle_capacity_upgrades[player] == "on": + new_items += ["Bomb Upgrade (+5)"] * 6 + new_items.append("Bomb Upgrade (+5)" if progressive else "Bomb Upgrade (+10)") + if multiworld.shuffle_capacity_upgrades[player] != "on_combined" and multiworld.bombless_start[player]: + new_items.append("Bomb Upgrade (+5)" if progressive else "Bomb Upgrade (+10)") + + if multiworld.shuffle_capacity_upgrades[player] and not multiworld.retro_bow[player]: + if multiworld.shuffle_capacity_upgrades[player] == "on_combined": + new_items += ["Arrow Upgrade (70)"] + else: + new_items += ["Arrow Upgrade (+5)"] * 6 + new_items.append("Arrow Upgrade (+5)" if progressive else "Arrow Upgrade (+10)") + + items += [ItemFactory(item, player) for item in new_items] + removed_filler = [] + + multiworld.random.shuffle(items) # Decide what gets tossed randomly. + + while len(items) > pool_count: + for i, item in enumerate(items): + if item.classification in (ItemClassification.filler, ItemClassification.trap): + removed_filler.append(items.pop(i)) + break + else: + # no more junk to remove, condense progressive items + def condense_items(items, small_item, big_item, rem, add): + small_item = ItemFactory(small_item, player) + # while (len(items) >= pool_count + rem - 1 # minus 1 to account for the replacement item + # and items.count(small_item) >= rem): + if items.count(small_item) >= rem: + for _ in range(rem): + items.remove(small_item) + removed_filler.append(ItemFactory(small_item.name, player)) + items += [ItemFactory(big_item, player) for _ in range(add)] + return True + return False + + def cut_item(items, item_to_cut, minimum_items): + item_to_cut = ItemFactory(item_to_cut, player) + if items.count(item_to_cut) > minimum_items: + items.remove(item_to_cut) + removed_filler.append(ItemFactory(item_to_cut.name, player)) + return True + return False + + while len(items) > pool_count: + items_were_cut = False + for reduce_item in items_reduction_table: + if len(items) <= pool_count: + break + if len(reduce_item) == 2: + items_were_cut = items_were_cut or cut_item(items, *reduce_item) + elif len(reduce_item) == 4: + items_were_cut = items_were_cut or condense_items(items, *reduce_item) + elif len(reduce_item) == 1: # Bottles + bottles = [item for item in items if item.name in item_name_groups["Bottles"]] + if len(bottles) > 4: + bottle = multiworld.random.choice(bottles) + items.remove(bottle) + removed_filler.append(bottle) + items_were_cut = True + assert items_were_cut, f"Failed to limit item pool size for player {player}" + if len(items) < pool_count: + items += removed_filler[len(items) - pool_count:] + + if multiworld.randomize_cost_types[player]: + # Heart and Arrow costs require all Heart Container/Pieces and Arrow Upgrades to be advancement items for logic + for item in items: + if (item.name in ("Boss Heart Container", "Sanctuary Heart Container", "Piece of Heart") + or "Arrow Upgrade" in item.name): + item.classification = ItemClassification.progression + else: + # Otherwise, 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 multiworld.item_pool[player] in ['easy', 'normal', 'hard'] and not (multiworld.custom and multiworld.customitemarray[30] == 0): + next(item for item in items if item.name == 'Boss Heart Container').classification = ItemClassification.progression + elif multiworld.item_pool[player] in ['expert'] and not (multiworld.custom and multiworld.customitemarray[29] < 4): + adv_heart_pieces = (item for item in items if item.name == 'Piece of Heart') + for i in range(4): + next(adv_heart_pieces).classification = ItemClassification.progression + + multiworld.required_medallions[player] = (multiworld.misery_mire_medallion[player].current_key.title(), + multiworld.turtle_rock_medallion[player].current_key.title()) + + place_bosses(world) + + multiworld.itempool += items if multiworld.retro_caves[player]: set_up_take_anys(multiworld, player) # depends on world.itempool to be set - # set_up_take_anys needs to run first - create_dynamic_shop_locations(multiworld, player) take_any_locations = { @@ -516,9 +552,14 @@ def set_up_take_anys(world, player): sword = world.random.choice(swords) world.itempool.remove(sword) world.itempool.append(ItemFactory('Rupees (20)', player)) - old_man_take_any.shop.add_inventory(0, sword.name, 0, 0, create_location=True) + old_man_take_any.shop.add_inventory(0, sword.name, 0, 0) + loc_name = "Old Man Sword Cave" + location = ALttPLocation(player, loc_name, shop_table_by_location[loc_name], parent=old_man_take_any) + location.shop_slot = 0 + old_man_take_any.locations.append(location) + location.place_locked_item(sword) else: - old_man_take_any.shop.add_inventory(0, 'Rupees (300)', 0, 0, create_location=True) + old_man_take_any.shop.add_inventory(0, 'Rupees (300)', 0, 0) for num in range(4): take_any = LTTPRegion("Take-Any #{}".format(num+1), LTTPRegionType.Cave, 'a cave of choice', player, world) @@ -532,18 +573,22 @@ def set_up_take_anys(world, player): take_any.shop = TakeAny(take_any, room_id, 0xE3, True, True, total_shop_slots + num + 1) world.shops.append(take_any.shop) take_any.shop.add_inventory(0, 'Blue Potion', 0, 0) - take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 0, create_location=True) + take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 0) + location = ALttPLocation(player, take_any.name, shop_table_by_location[take_any.name], parent=take_any) + location.shop_slot = 1 + take_any.locations.append(location) + location.place_locked_item(ItemFactory("Boss Heart Container", player)) def get_pool_core(world, player: int): - shuffle = world.shuffle[player] - difficulty = world.difficulty[player] - timer = world.timer[player] - goal = world.goal[player] - mode = world.mode[player] + shuffle = world.entrance_shuffle[player].current_key + difficulty = world.item_pool[player].current_key + timer = world.timer[player].current_key + goal = world.goal[player].current_key + mode = world.mode[player].current_key swordless = world.swordless[player] retro_bow = world.retro_bow[player] - logic = world.logic[player] + logic = world.glitches_required[player] pool = [] placed_items = {} @@ -552,7 +597,7 @@ def get_pool_core(world, player: int): treasure_hunt_count = None treasure_hunt_icon = None - diff = ice_rod_hunt_difficulties[difficulty] if goal == 'icerodhunt' else difficulties[difficulty] + diff = difficulties[difficulty] pool.extend(diff.alwaysitems) def place_item(loc, item): @@ -560,7 +605,7 @@ def get_pool_core(world, player: int): placed_items[loc] = item # provide boots to major glitch dependent seeds - if logic in {'owglitches', 'hybridglitches', 'nologic'} and world.glitch_boots[player] and goal != 'icerodhunt': + if logic in {'overworld_glitches', 'hybrid_major_glitches', 'no_logic'} and world.glitch_boots[player]: precollected_items.append('Pegasus Boots') pool.remove('Pegasus Boots') pool.append('Rupees (20)') @@ -611,7 +656,7 @@ def get_pool_core(world, player: int): if want_progressives(world.random): pool.extend(diff.progressivebow) world.worlds[player].has_progressive_bows = True - elif (swordless or logic == 'noglitches') and goal != 'icerodhunt': + elif (swordless or logic == 'no_glitches'): swordless_bows = ['Bow', 'Silver Bow'] if difficulty == "easy": swordless_bows *= 2 @@ -627,21 +672,32 @@ def get_pool_core(world, player: int): extraitems = total_items_to_place - len(pool) - len(placed_items) - if timer in ['timed', 'timed-countdown']: + if timer in ['timed', 'timed_countdown']: pool.extend(diff.timedother) extraitems -= len(diff.timedother) clock_mode = 'stopwatch' if timer == 'timed' else 'countdown' - elif timer == 'timed-ohko': + elif timer == 'timed_ohko': pool.extend(diff.timedohko) extraitems -= len(diff.timedohko) clock_mode = 'countdown-ohko' additional_pieces_to_place = 0 - if 'triforcehunt' in goal: - pieces_in_core = min(extraitems, world.triforce_pieces_available[player]) - additional_pieces_to_place = world.triforce_pieces_available[player] - pieces_in_core + if 'triforce_hunt' in goal: + + if world.triforce_pieces_mode[player].value == TriforcePiecesMode.option_extra: + triforce_pieces = world.triforce_pieces_available[player].value + world.triforce_pieces_extra[player].value + elif world.triforce_pieces_mode[player].value == TriforcePiecesMode.option_percentage: + percentage = float(max(100, world.triforce_pieces_percentage[player].value)) / 100 + triforce_pieces = int(round(world.triforce_pieces_required[player].value * percentage, 0)) + else: # available + triforce_pieces = world.triforce_pieces_available[player].value + + triforce_pieces = max(triforce_pieces, world.triforce_pieces_required[player].value) + + pieces_in_core = min(extraitems, triforce_pieces) + additional_pieces_to_place = triforce_pieces - pieces_in_core pool.extend(["Triforce Piece"] * pieces_in_core) extraitems -= pieces_in_core - treasure_hunt_count = world.triforce_pieces_required[player] + treasure_hunt_count = world.triforce_pieces_required[player].value treasure_hunt_icon = 'Triforce Piece' for extra in diff.extras: @@ -659,12 +715,12 @@ def get_pool_core(world, player: int): pool.remove("Rupees (20)") if retro_bow: - replace = {'Single Arrow', 'Arrows (10)', 'Arrow Upgrade (+5)', 'Arrow Upgrade (+10)'} + replace = {'Single Arrow', 'Arrows (10)', 'Arrow Upgrade (+5)', 'Arrow Upgrade (+10)', 'Arrow Upgrade (50)'} pool = ['Rupees (5)' if item in replace else item for item in pool] - if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal: + if world.small_key_shuffle[player] == small_key_shuffle.option_universal: pool.extend(diff.universal_keys) if mode == 'standard': - if world.key_drop_shuffle[player] and world.goal[player] != 'icerodhunt': + if world.key_drop_shuffle[player]: key_locations = ['Secret Passage', 'Hyrule Castle - Map Guard Key Drop'] key_location = world.random.choice(key_locations) key_locations.remove(key_location) @@ -688,8 +744,8 @@ def get_pool_core(world, player: int): def make_custom_item_pool(world, player): - shuffle = world.shuffle[player] - difficulty = world.difficulty[player] + shuffle = world.entrance_shuffle[player] + difficulty = world.item_pool[player] timer = world.timer[player] goal = world.goal[player] mode = world.mode[player] @@ -798,9 +854,9 @@ def make_custom_item_pool(world, player): treasure_hunt_count = world.triforce_pieces_required[player] treasure_hunt_icon = 'Triforce Piece' - if timer in ['display', 'timed', 'timed-countdown']: - clock_mode = 'countdown' if timer == 'timed-countdown' else 'stopwatch' - elif timer == 'timed-ohko': + if timer in ['display', 'timed', 'timed_countdown']: + clock_mode = 'countdown' if timer == 'timed_countdown' else 'stopwatch' + elif timer == 'timed_ohko': clock_mode = 'countdown-ohko' elif timer == 'ohko': clock_mode = 'ohko' @@ -810,7 +866,7 @@ def make_custom_item_pool(world, player): itemtotal = itemtotal + 1 if mode == 'standard': - if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal: + if world.small_key_shuffle[player] == small_key_shuffle.option_universal: key_location = world.random.choice( ['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest', 'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross']) @@ -833,7 +889,7 @@ def make_custom_item_pool(world, player): pool.extend(['Magic Mirror'] * customitemarray[22]) pool.extend(['Moon Pearl'] * customitemarray[28]) - if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal: + if world.small_key_shuffle[player] == small_key_shuffle.option_universal: itemtotal = itemtotal - 28 # Corrects for small keys not being in item pool in universal Mode if world.key_drop_shuffle[player]: itemtotal = itemtotal - (len(key_drop_data) - 1) diff --git a/worlds/alttp/Items.py b/worlds/alttp/Items.py index 18f96b2d..8e513552 100644 --- a/worlds/alttp/Items.py +++ b/worlds/alttp/Items.py @@ -112,13 +112,15 @@ item_table = {'Bow': ItemData(IC.progression, None, 0x0B, 'You have\nchosen the\ 'Crystal 7': ItemData(IC.progression, 'Crystal', (0x08, 0x34, 0x64, 0x40, 0x7C, 0x06), None, None, None, None, None, None, "a blue crystal"), 'Single Arrow': ItemData(IC.filler, None, 0x43, 'a lonely arrow\nsits here.', 'and the arrow', 'stick-collecting kid', 'sewing needle for sale', 'fungus for arrow', 'archer boy sews again', 'an arrow'), 'Arrows (10)': ItemData(IC.filler, None, 0x44, 'This will give\nyou ten shots\nwith your bow!', 'and the arrow pack','stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again','ten arrows'), - 'Arrow Upgrade (+10)': ItemData(IC.filler, None, 0x54, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'), - 'Arrow Upgrade (+5)': ItemData(IC.filler, None, 0x53, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'), + 'Arrow Upgrade (+10)': ItemData(IC.useful, None, 0x54, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'), + 'Arrow Upgrade (+5)': ItemData(IC.useful, None, 0x53, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'), + 'Arrow Upgrade (70)': ItemData(IC.useful, None, 0x4D, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'), 'Single Bomb': ItemData(IC.filler, None, 0x27, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'), 'Bombs (3)': ItemData(IC.filler, None, 0x28, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'), 'Bombs (10)': ItemData(IC.filler, None, 0x31, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'), - 'Bomb Upgrade (+10)': ItemData(IC.filler, None, 0x52, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'), - 'Bomb Upgrade (+5)': ItemData(IC.filler, None, 0x51, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'), + 'Bomb Upgrade (+10)': ItemData(IC.progression, None, 0x52, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'), + 'Bomb Upgrade (+5)': ItemData(IC.progression, None, 0x51, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'), + 'Bomb Upgrade (50)': ItemData(IC.progression, None, 0x4C, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'), 'Blue Mail': ItemData(IC.useful, None, 0x22, 'Now you\'re a\nblue elf!', 'and the banana hat', 'the protected kid', 'banana hat for sale', 'the clothing store', 'tailor boy banana hatted again', 'the Blue Mail'), 'Red Mail': ItemData(IC.useful, None, 0x23, 'Now you\'re a\nred elf!', 'and the eggplant hat', 'well-protected kid', 'purple hat for sale', 'the nice clothing store', 'tailor boy fears nothing again', 'the Red Mail'), 'Progressive Mail': ItemData(IC.useful, None, 0x60, 'time for a\nchange of\nclothes?', 'and the unknown hat', 'the protected kid', 'new hat for sale', 'the clothing store', 'tailor boy has threads again', 'some armor'), @@ -222,6 +224,7 @@ item_table = {'Bow': ItemData(IC.progression, None, 0x0B, 'You have\nchosen the\ 'Return Smith': ItemData(IC.progression, 'Event', None, None, None, None, None, None, None, None), 'Pick Up Purple Chest': ItemData(IC.progression, 'Event', None, None, None, None, None, None, None, None), 'Open Floodgate': ItemData(IC.progression, 'Event', None, None, None, None, None, None, None, None), + 'Capacity Upgrade Shop': ItemData(IC.progression, 'Event', None, None, None, None, None, None, None, None), } item_init_table = {name: data.as_init_dict() for name, data in item_table.items()} @@ -287,5 +290,5 @@ progression_items = {name for name in everything if item_table[name].classification in {IC.progression, IC.progression_skip_balancing}} item_name_groups['Progression Items'] = progression_items item_name_groups['Non Progression Items'] = everything - progression_items - +item_name_groups['Upgrades'] = {name for name in everything if 'Upgrade' in name} trap_replaceable = item_name_groups['Rupees'] | {'Arrows (10)', 'Single Bomb', 'Bombs (3)', 'Bombs (10)', 'Nothing'} diff --git a/worlds/alttp/Options.py b/worlds/alttp/Options.py index a89a9adb..ed6af6dd 100644 --- a/worlds/alttp/Options.py +++ b/worlds/alttp/Options.py @@ -1,10 +1,18 @@ import typing from BaseClasses import MultiWorld -from Options import Choice, Range, Option, Toggle, DefaultOnToggle, DeathLink, StartInventoryPool, PlandoBosses +from Options import Choice, Range, Option, Toggle, DefaultOnToggle, DeathLink, StartInventoryPool, PlandoBosses,\ + FreeText -class Logic(Choice): +class GlitchesRequired(Choice): + """Determine the logic required to complete the seed + None: No glitches required + Minor Glitches: Puts fake flipper, waterwalk, super bunny shenanigans, and etc into logic + Overworld Glitches: Assumes the player has knowledge of both overworld major glitches (boots clips, mirror clips) and minor glitches + Hybrid Major Glitches: In addition to overworld glitches, also requires underworld clips between dungeons. + No Logic: Your own items are placed with no regard to any logic; such as your Fire Rod can be on your Trinexx.""" + display_name = "Glitches Required" option_no_glitches = 0 option_minor_glitches = 1 option_overworld_glitches = 2 @@ -12,20 +20,122 @@ class Logic(Choice): option_no_logic = 4 alias_owg = 2 alias_hmg = 3 + alias_none = 0 -class Objective(Choice): - option_crystals = 0 - # option_pendants = 1 - option_triforce_pieces = 2 - option_pedestal = 3 - option_bingo = 4 +class DarkRoomLogic(Choice): + """Logic for unlit dark rooms. Lamp: require the Lamp for these rooms to be considered accessible. + Torches: in addition to lamp, allow the fire rod and presence of easily accessible torches for access. + None: all dark rooms are always considered doable, meaning this may force completion of rooms in complete darkness.""" + display_name = "Dark Room Logic" + option_lamp = 0 + option_torches = 1 + option_none = 2 + default = 0 class Goal(Choice): - option_kill_ganon = 0 - option_kill_ganon_and_gt_agahnim = 1 - option_hand_in = 2 + """Ganon: Climb GT, defeat Agahnim 2, and then kill Ganon + Crystals: Only killing Ganon is required. However, items may still be placed in GT + Bosses: Defeat the boss of all dungeons, including Agahnim's tower and GT (Aga 2) + Pedestal: Pull the Triforce from the Master Sword pedestal + Ganon Pedestal: Pull the Master Sword pedestal, then kill Ganon + Triforce Hunt: Collect Triforce pieces spread throughout the worlds, then turn them in to Murahadala in front of Hyrule Castle + Local Triforce Hunt: Collect Triforce pieces spread throughout your world, then turn them in to Murahadala in front of Hyrule Castle + Ganon Triforce Hunt: Collect Triforce pieces spread throughout the worlds, then kill Ganon + Local Ganon Triforce Hunt: Collect Triforce pieces spread throughout your world, then kill Ganon + Ice Rod Hunt: You start with everything except Ice Rod. Find the Ice rod, then kill Trinexx at Turtle rock.""" + display_name = "Goal" + default = 0 + option_ganon = 0 + option_crystals = 1 + option_bosses = 2 + option_pedestal = 3 + option_ganon_pedestal = 4 + option_triforce_hunt = 5 + option_local_triforce_hunt = 6 + option_ganon_triforce_hunt = 7 + option_local_ganon_triforce_hunt = 8 + + +class EntranceShuffle(Choice): + """Dungeons Simple: Shuffle just dungeons amongst each other, swapping dungeons entirely, so Hyrule Castle is always 1 dungeon. + Dungeons Full: Shuffle any dungeon entrance with any dungeon interior, so Hyrule Castle can be 4 different dungeons, but keep dungeons to a specific world. + Dungeons Crossed: like dungeons_full, but allow cross-world traversal through a dungeon. Warning: May force repeated dungeon traversal. + Simple: Entrances are grouped together before being randomized. Interiors with two entrances are grouped shuffled together with each other, + and Death Mountain entrances are shuffled only on Death Mountain. Dungeons are swapped entirely. + Restricted: Like Simple, but single entrance interiors, multi entrance interiors, and Death Mountain interior entrances are all shuffled with each other. + Full: Like Restricted, but all Dungeon entrances are shuffled with all non-Dungeon entrances. + Crossed: Like Full, but interiors with multiple entrances are no longer confined to the same world, which may allow crossing worlds. + Insanity: Like Crossed, but entrances and exits may be decoupled from each other, so that leaving through an exit may not return you to the entrance you entered from.""" + display_name = "Entrance Shuffle" + default = 0 + alias_none = 0 + option_vanilla = 0 + option_dungeons_simple = 1 + option_dungeons_full = 2 + option_dungeons_crossed = 3 + option_simple = 4 + option_restricted = 5 + option_full = 6 + option_crossed = 7 + option_insanity = 8 + alias_dungeonssimple = 1 + alias_dungeonsfull = 2 + alias_dungeonscrossed = 3 + + +class EntranceShuffleSeed(FreeText): + """You can specify a number to use as an entrance shuffle seed, or a group name. Everyone with the same group name + will get the same entrance shuffle result as long as their Entrance Shuffle, Mode, Retro Caves, and Glitches + Required options are the same.""" + default = "random" + display_name = "Entrance Shuffle Seed" + + +class TriforcePiecesMode(Choice): + """Determine how to calculate the extra available triforce pieces. + Extra: available = triforce_pieces_extra + triforce_pieces_required + Percentage: available = (triforce_pieces_percentage /100) * triforce_pieces_required + Available: available = triforce_pieces_available""" + display_name = "Triforce Pieces Mode" + default = 2 + option_extra = 0 + option_percentage = 1 + option_available = 2 + + +class TriforcePiecesPercentage(Range): + """Set to how many triforce pieces according to a percentage of the required ones, are available to collect in the world.""" + display_name = "Triforce Pieces Percentage" + range_start = 100 + range_end = 1000 + default = 150 + + +class TriforcePiecesAvailable(Range): + """Set to how many triforces pieces are available to collect in the world. Default is 30. Max is 90, Min is 1""" + display_name = "Triforce Pieces Available" + range_start = 1 + range_end = 90 + default = 30 + + +class TriforcePiecesRequired(Range): + """Set to how many out of X triforce pieces you need to win the game in a triforce hunt. + Default is 20. Max is 90, Min is 1.""" + display_name = "Triforce Pieces Required" + range_start = 1 + range_end = 90 + default = 20 + + +class TriforcePiecesExtra(Range): + """Set to how many extra triforces pieces are available to collect in the world.""" + display_name = "Triforce Pieces Extra" + range_start = 0 + range_end = 89 + default = 10 class OpenPyramid(Choice): @@ -44,10 +154,10 @@ class OpenPyramid(Choice): def to_bool(self, world: MultiWorld, player: int) -> bool: if self.value == self.option_goal: - return world.goal[player] in {'crystals', 'ganontriforcehunt', 'localganontriforcehunt', 'ganonpedestal'} + return world.goal[player] in {'crystals', 'ganon_triforce_hunt', 'local_ganon_triforce_hunt', 'ganon_pedestal'} elif self.value == self.option_auto: - return world.goal[player] in {'crystals', 'ganontriforcehunt', 'localganontriforcehunt', 'ganonpedestal'} \ - and (world.shuffle[player] in {'vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed'} or not + return world.goal[player] in {'crystals', 'ganon_triforce_hunt', 'local_ganon_triforce_hunt', 'ganon_pedestal'} \ + and (world.entrance_shuffle[player] in {'vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed'} or not world.shuffle_ganon) elif self.value == self.option_open: return True @@ -76,13 +186,13 @@ class DungeonItem(Choice): return self.value in {1, 2, 3, 4} -class bigkey_shuffle(DungeonItem): +class big_key_shuffle(DungeonItem): """Big Key Placement""" item_name_group = "Big Keys" display_name = "Big Key Shuffle" -class smallkey_shuffle(DungeonItem): +class small_key_shuffle(DungeonItem): """Small Key Placement""" option_universal = 5 item_name_group = "Small Keys" @@ -107,6 +217,149 @@ class key_drop_shuffle(Toggle): display_name = "Key Drop Shuffle" + +class DungeonCounters(Choice): + """On: Always display amount of items checked in a dungeon. Pickup: Show when compass is picked up. + Default: Show when compass is picked up if the compass itself is shuffled. Off: Never show item count in dungeons.""" + display_name = "Dungeon Counters" + default = 1 + option_on = 0 + option_pickup = 1 + option_default = 2 + option_off = 4 + + +class Mode(Choice): + """Standard: Begin the game by rescuing Zelda from her cell and escorting her to the Sanctuary + Open: Begin the game from your choice of Link's House or the Sanctuary + Inverted: Begin in the Dark World. The Moon Pearl is required to avoid bunny-state in Light World, and the Light World game map is altered""" + option_standard = 0 + option_open = 1 + option_inverted = 2 + default = 1 + display_name = "Mode" + + +class ItemPool(Choice): + """Easy: Doubled upgrades, progressives, and etc. Normal: Item availability remains unchanged from vanilla game. + Hard: Reduced upgrade availability (max: 14 hearts, blue mail, tempered sword, fire shield, no silvers unless swordless). + Expert: Minimum upgrade availability (max: 8 hearts, green mail, master sword, fighter shield, no silvers unless swordless).""" + display_name = "Item Pool" + default = 1 + option_easy = 0 + option_normal = 1 + option_hard = 2 + option_expert = 3 + + +class ItemFunctionality(Choice): + """Easy: Allow Hammer to damage ganon, Allow Hammer tablet collection, Allow swordless medallion use everywhere. + Normal: Vanilla item functionality + Hard: Reduced helpfulness of items (potions less effective, can't catch faeries, cape uses double magic, byrna does not grant invulnerability, boomerangs do not stun, silvers disabled outside ganon) + Expert: Vastly reduces the helpfulness of items (potions barely effective, can't catch faeries, cape uses double magic, byrna does not grant invulnerability, boomerangs and hookshot do not stun, silvers disabled outside ganon)""" + display_name = "Item Functionality" + default = 1 + option_easy = 0 + option_normal = 1 + option_hard = 2 + option_expert = 3 + + +class EnemyHealth(Choice): + """Default: Vanilla enemy HP. Easy: Enemies have reduced health. Hard: Enemies have increased health. + Expert: Enemies have greatly increased health.""" + display_name = "Enemy Health" + default = 1 + option_easy = 0 + option_default = 1 + option_hard = 2 + option_expert = 3 + + +class EnemyDamage(Choice): + """Default: Vanilla enemy damage. Shuffled: 0 # Enemies deal 0 to 4 hearts and armor helps. + Chaos: Enemies deal 0 to 8 hearts and armor just reshuffles the damage.""" + display_name = "Enemy Damage" + default = 0 + option_default = 0 + option_shuffled = 2 + option_chaos = 3 + + +class ShufflePrizes(Choice): + """Shuffle "general" prize packs, as in enemy, tree pull, dig etc.; "bonk" prizes; or both.""" + display_name = "Shuffle Prizes" + default = 1 + option_off = 0 + option_general = 1 + option_bonk = 2 + option_both = 3 + + +class Medallion(Choice): + default = "random" + option_ether = 0 + option_bombos = 1 + option_quake = 2 + + +class MiseryMireMedallion(Medallion): + """Required medallion to open Misery Mire front entrance.""" + display_name = "Misery Mire Medallion" + + +class TurtleRockMedallion(Medallion): + """Required medallion to open Turtle Rock front entrance.""" + display_name = "Turtle Rock Medallion" + + +class Timer(Choice): + """None: No timer will be displayed. OHKO: Timer always at zero. Permanent OHKO. + Timed: 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. + Timed OHKO: Starts the clock at ten minutes. Green clocks add five minutes (total 25). As long as the clock as at zero, Link will die in one hit. + Timed Countdown: Starts the clock with forty minutes. Same clocks as timed mode, but if the clock hits zero you lose. You can still keep playing, though. + Display: Displays a timer, but otherwise does not affect gameplay or the item pool.""" + display_name = "Timer" + option_none = 0 + option_timed = 1 + option_timed_ohko = 2 + option_ohko = 3 + option_timed_countdown = 4 + option_display = 5 + default = 0 + + +class CountdownStartTime(Range): + """For Timed OHKO and Timed Countdown timer modes, the amount of time in minutes to start with.""" + display_name = "Countdown Start Time" + range_start = 0 + range_end = 480 + default = 10 + + +class ClockTime(Range): + range_start = -60 + range_end = 60 + + +class RedClockTime(ClockTime): + """For all timer modes, the amount of time in minutes to gain or lose when picking up a red clock.""" + display_name = "Red Clock Time" + default = -2 + + +class BlueClockTime(ClockTime): + """For all timer modes, the amount of time in minutes to gain or lose when picking up a blue clock.""" + display_name = "Blue Clock Time" + default = 2 + + +class GreenClockTime(ClockTime): + """For all timer modes, the amount of time in minutes to gain or lose when picking up a green clock.""" + display_name = "Green Clock Time" + default = 4 + + class Crystals(Range): range_start = 0 range_end = 7 @@ -137,18 +390,52 @@ class ShopItemSlots(Range): range_end = 30 +class RandomizeShopInventories(Choice): + """Generate new default inventories for overworld/underworld shops, and unique shops; or each shop independently""" + display_name = "Randomize Shop Inventories" + default = 0 + option_default = 0 + option_randomize_by_shop_type = 1 + option_randomize_each = 2 + + +class ShuffleShopInventories(Toggle): + """Shuffle default inventories of the shops around""" + display_name = "Shuffle Shop Inventories" + + +class RandomizeShopPrices(Toggle): + """Randomize the prices of the items in shop inventories""" + display_name = "Randomize Shop Prices" + + +class RandomizeCostTypes(Toggle): + """Prices of the items in shop inventories may cost hearts, arrow, or bombs instead of rupees""" + display_name = "Randomize Cost Types" + + class ShopPriceModifier(Range): """Percentage modifier for shuffled item prices in shops""" - display_name = "Shop Price Cost Percent" + display_name = "Shop Price Modifier" range_start = 0 default = 100 range_end = 400 -class WorldState(Choice): - option_standard = 1 - option_open = 0 - option_inverted = 2 +class IncludeWitchHut(Toggle): + """Consider witch's hut like any other shop and shuffle/randomize it too""" + display_name = "Include Witch's Hut" + + +class ShuffleCapacityUpgrades(Choice): + """Shuffle capacity upgrades into the item pool (and allow them to traverse the multiworld). + On Combined will shuffle only a single bomb upgrade and arrow upgrade each which bring you to the maximum capacity.""" + display_name = "Shuffle Capacity Upgrades" + option_off = 0 + option_on = 1 + option_on_combined = 2 + alias_false = 0 + alias_true = 1 class LTTPBosses(PlandoBosses): @@ -236,6 +523,11 @@ class Swordless(Toggle): display_name = "Swordless" +class BomblessStart(Toggle): + """Start with a max of 0 bombs available, requiring Bomb Upgrade items in order to use bombs""" + display_name = "Bombless Start" + + # Might be a decent idea to split "Bow" into its own option with choices of # Defer to Progressive Option (default), Progressive, Non-Progressive, Bow + Silvers, Retro class RetroBow(Toggle): @@ -433,29 +725,66 @@ class AllowCollect(Toggle): alttp_options: typing.Dict[str, type(Option)] = { + "start_inventory_from_pool": StartInventoryPool, + "goal": Goal, + "mode": Mode, + "glitches_required": GlitchesRequired, + "dark_room_logic": DarkRoomLogic, + "open_pyramid": OpenPyramid, "crystals_needed_for_gt": CrystalsTower, "crystals_needed_for_ganon": CrystalsGanon, - "open_pyramid": OpenPyramid, - "bigkey_shuffle": bigkey_shuffle, - "smallkey_shuffle": smallkey_shuffle, + "triforce_pieces_mode": TriforcePiecesMode, + "triforce_pieces_percentage": TriforcePiecesPercentage, + "triforce_pieces_required": TriforcePiecesRequired, + "triforce_pieces_available": TriforcePiecesAvailable, + "triforce_pieces_extra": TriforcePiecesExtra, + "entrance_shuffle": EntranceShuffle, + "entrance_shuffle_seed": EntranceShuffleSeed, + "big_key_shuffle": big_key_shuffle, + "small_key_shuffle": small_key_shuffle, "key_drop_shuffle": key_drop_shuffle, "compass_shuffle": compass_shuffle, "map_shuffle": map_shuffle, + "restrict_dungeon_item_on_boss": RestrictBossItem, + "item_pool": ItemPool, + "item_functionality": ItemFunctionality, + "enemy_health": EnemyHealth, + "enemy_damage": EnemyDamage, "progressive": Progressive, "swordless": Swordless, + "dungeon_counters": DungeonCounters, "retro_bow": RetroBow, "retro_caves": RetroCaves, "hints": Hints, "scams": Scams, - "restrict_dungeon_item_on_boss": RestrictBossItem, "boss_shuffle": LTTPBosses, "pot_shuffle": PotShuffle, "enemy_shuffle": EnemyShuffle, "killable_thieves": KillableThieves, "bush_shuffle": BushShuffle, "shop_item_slots": ShopItemSlots, + "randomize_shop_inventories": RandomizeShopInventories, + "shuffle_shop_inventories": ShuffleShopInventories, + "include_witch_hut": IncludeWitchHut, + "randomize_shop_prices": RandomizeShopPrices, + "randomize_cost_types": RandomizeCostTypes, "shop_price_modifier": ShopPriceModifier, + "shuffle_capacity_upgrades": ShuffleCapacityUpgrades, + "bombless_start": BomblessStart, + "shuffle_prizes": ShufflePrizes, "tile_shuffle": TileShuffle, + "misery_mire_medallion": MiseryMireMedallion, + "turtle_rock_medallion": TurtleRockMedallion, + "glitch_boots": GlitchBoots, + "beemizer_total_chance": BeemizerTotalChance, + "beemizer_trap_chance": BeemizerTrapChance, + "timer": Timer, + "countdown_start_time": CountdownStartTime, + "red_clock_time": RedClockTime, + "blue_clock_time": BlueClockTime, + "green_clock_time": GreenClockTime, + "death_link": DeathLink, + "allow_collect": AllowCollect, "ow_palettes": OWPalette, "uw_palettes": UWPalette, "hud_palettes": HUDPalette, @@ -469,10 +798,4 @@ alttp_options: typing.Dict[str, type(Option)] = { "music": Music, "reduceflashing": ReduceFlashing, "triforcehud": TriforceHud, - "glitch_boots": GlitchBoots, - "beemizer_total_chance": BeemizerTotalChance, - "beemizer_trap_chance": BeemizerTrapChance, - "death_link": DeathLink, - "allow_collect": AllowCollect, - "start_inventory_from_pool": StartInventoryPool, } diff --git a/worlds/alttp/Regions.py b/worlds/alttp/Regions.py index 0cc8a3d6..dc3adb10 100644 --- a/worlds/alttp/Regions.py +++ b/worlds/alttp/Regions.py @@ -94,7 +94,7 @@ def create_regions(world, player): create_cave_region(world, player, 'Kakariko Gamble Game', 'a game of chance'), create_cave_region(world, player, 'Potion Shop', 'the potion shop', ['Potion Shop']), create_lw_region(world, player, 'Lake Hylia Island', ['Lake Hylia Island']), - create_cave_region(world, player, 'Capacity Upgrade', 'the queen of fairies'), + create_cave_region(world, player, 'Capacity Upgrade', 'the queen of fairies', ['Capacity Upgrade Shop']), create_cave_region(world, player, 'Two Brothers House', 'a connector', None, ['Two Brothers House Exit (East)', 'Two Brothers House Exit (West)']), create_lw_region(world, player, 'Maze Race Ledge', ['Maze Race'], ['Two Brothers House (West)']), create_cave_region(world, player, '50 Rupee Cave', 'a cave with some cash'), @@ -121,8 +121,9 @@ def create_regions(world, player): ['Hyrule Castle Exit (East)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (South)', 'Throne Room']), create_dungeon_region(world, player, 'Sewer Drop', 'a drop\'s exit', None, ['Sewer Drop']), # This exists only to be referenced for access checks create_dungeon_region(world, player, 'Sewers (Dark)', 'a drop\'s exit', ['Sewers - Dark Cross', 'Sewers - Key Rat Key Drop'], ['Sewers Door']), - create_dungeon_region(world, player, 'Sewers', 'a drop\'s exit', ['Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle', - 'Sewers - Secret Room - Right'], ['Sanctuary Push Door', 'Sewers Back Door']), + create_dungeon_region(world, player, 'Sewers', 'a drop\'s exit', None, ['Sanctuary Push Door', 'Sewers Back Door', 'Sewers Secret Room']), + create_dungeon_region(world, player, 'Sewers Secret Room', 'a drop\'s exit', ['Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle', + 'Sewers - Secret Room - Right']), create_dungeon_region(world, player, 'Sanctuary', 'a drop\'s exit', ['Sanctuary'], ['Sanctuary Exit']), create_dungeon_region(world, player, 'Agahnims Tower', 'Castle Tower', ['Castle Tower - Room 03', 'Castle Tower - Dark Maze', 'Castle Tower - Dark Archer Key Drop', 'Castle Tower - Circle of Pots Key Drop'], ['Agahnim 1', 'Agahnims Tower Exit']), create_dungeon_region(world, player, 'Agahnim 1', 'Castle Tower', ['Agahnim 1'], None), @@ -275,7 +276,9 @@ def create_regions(world, player): create_cave_region(world, player, 'Hookshot Cave', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', 'Hookshot Cave - Bottom Left'], - ['Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)']), + ['Hookshot Cave Exit (South)', 'Hookshot Cave Bomb Wall (South)']), + create_cave_region(world, player, 'Hookshot Cave (Upper)', 'a connector', None, ['Hookshot Cave Exit (North)', + 'Hookshot Cave Bomb Wall (North)']), create_dw_region(world, player, 'Death Mountain Floating Island (Dark World)', None, ['Floating Island Drop', 'Hookshot Cave Back Entrance', 'Floating Island Mirror Spot']), create_lw_region(world, player, 'Death Mountain Floating Island (Light World)', ['Floating Island']), @@ -311,8 +314,8 @@ def create_regions(world, player): create_dungeon_region(world, player, 'Skull Woods Second Section', 'Skull Woods', ['Skull Woods - Big Key Chest', 'Skull Woods - West Lobby Pot Key'], ['Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)']), create_dungeon_region(world, player, 'Skull Woods Final Section (Entrance)', 'Skull Woods', ['Skull Woods - Bridge Room'], ['Skull Woods Torch Room', 'Skull Woods Final Section Exit']), create_dungeon_region(world, player, 'Skull Woods Final Section (Mothula)', 'Skull Woods', ['Skull Woods - Spike Corner Key Drop', 'Skull Woods - Boss', 'Skull Woods - Prize']), - create_dungeon_region(world, player, 'Ice Palace (Entrance)', 'Ice Palace', ['Ice Palace - Jelly Key Drop'], ['Ice Palace (Second Section)', 'Ice Palace Exit']), - create_dungeon_region(world, player, 'Ice Palace (Second Section)', 'Ice Palace', ['Ice Palace - Conveyor Key Drop', 'Ice Palace - Compass Chest'], ['Ice Palace (Main)']), + create_dungeon_region(world, player, 'Ice Palace (Entrance)', 'Ice Palace', ['Ice Palace - Jelly Key Drop', 'Ice Palace - Compass Chest'], ['Ice Palace (Second Section)', 'Ice Palace Exit']), + create_dungeon_region(world, player, 'Ice Palace (Second Section)', 'Ice Palace', ['Ice Palace - Conveyor Key Drop'], ['Ice Palace (Main)']), create_dungeon_region(world, player, 'Ice Palace (Main)', 'Ice Palace', ['Ice Palace - Freezor Chest', 'Ice Palace - Many Pots Pot Key', 'Ice Palace - Big Chest', 'Ice Palace - Iced T Room'], ['Ice Palace (East)', 'Ice Palace (Kholdstare)']), @@ -735,6 +738,7 @@ location_table: typing.Dict[str, 'Missing Smith': (None, None, False, None), 'Dark Blacksmith Ruins': (None, None, False, None), 'Flute Activation Spot': (None, None, False, None), + 'Capacity Upgrade Shop': (None, None, False, None), 'Eastern Palace - Prize': ([0x1209D, 0x53EF8, 0x53EF9, 0x180052, 0x18007C, 0xC6FE], None, True, 'Eastern Palace'), 'Desert Palace - Prize': ([0x1209E, 0x53F1C, 0x53F1D, 0x180053, 0x180078, 0xC6FF], None, True, 'Desert Palace'), 'Tower of Hera - Prize': ( diff --git a/worlds/alttp/Rom.py b/worlds/alttp/Rom.py index b80cec57..ff4947bb 100644 --- a/worlds/alttp/Rom.py +++ b/worlds/alttp/Rom.py @@ -4,7 +4,7 @@ import Utils import worlds.Files LTTPJPN10HASH: str = "03a63945398191337e896e5771f77173" -RANDOMIZERBASEHASH: str = "9952c2a3ec1b421e408df0d20c8f0c7f" +RANDOMIZERBASEHASH: str = "35d010bc148e0ea0ee68e81e330223f1" ROM_PLAYER_LIMIT: int = 255 import io @@ -36,7 +36,7 @@ from .Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmith SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names from .Items import ItemFactory, item_table, item_name_groups, progression_items from .EntranceShuffle import door_addresses -from .Options import smallkey_shuffle +from .Options import small_key_shuffle try: from maseya import z3pr @@ -294,7 +294,7 @@ def patch_enemizer(world, rom: LocalRom, enemizercli, output_directory): 'RandomizeBushEnemyChance': multiworld.bush_shuffle[player].value, 'RandomizeEnemyHealthRange': multiworld.enemy_health[player] != 'default', 'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[ - multiworld.enemy_health[player]], + multiworld.enemy_health[player].current_key], 'OHKO': False, 'RandomizeEnemyDamage': multiworld.enemy_damage[player] != 'default', 'AllowEnemyZeroDamage': True, @@ -858,13 +858,13 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): # Thanks to Zarby89 for originally finding these values # todo fix screen scrolling - if world.shuffle[player] not in {'insanity', 'insanity_legacy', 'madness_legacy'} and \ + if world.entrance_shuffle[player] != 'insanity' and \ exit.name in {'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Swamp Palace Exit', 'Ganons Tower Exit', 'Desert Palace Exit (North)', 'Agahnims Tower Exit', 'Spiral Cave Exit (Top)', 'Superbunny Cave Exit (Bottom)', 'Turtle Rock Ledge Exit (East)'} and \ - (world.logic[player] not in ['hybridglitches', 'nologic'] or + (world.glitches_required[player] not in ['hybrid_major_glitches', 'no_logic'] or exit.name not in {'Palace of Darkness Exit', 'Tower of Hera Exit', 'Swamp Palace Exit'}): # For exits that connot be reached from another, no need to apply offset fixes. rom.write_int16(0x15DB5 + 2 * offset, link_y) # same as final else @@ -907,7 +907,9 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): if world.retro_caves[player]: # Old man cave and Take any caves will count towards collection rate. credits_total += 5 if world.shop_item_slots[player]: # Potion shop only counts towards collection rate if included in the shuffle. - credits_total += 30 if 'w' in world.shop_shuffle[player] else 27 + credits_total += 30 if world.include_witch_hut[player] else 27 + if world.shuffle_capacity_upgrades[player]: + credits_total += 2 rom.write_byte(0x187010, credits_total) # dynamic credits @@ -1059,7 +1061,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): # Set stun items rom.write_byte(0x180180, 0x03) # All standard items # Set overflow items for progressive equipment - if world.timer[player] in ['timed', 'timed-countdown', 'timed-ohko']: + if world.timer[player] in ['timed', 'timed_countdown', 'timed_ohko']: overflow_replacement = GREEN_CLOCK else: overflow_replacement = GREEN_TWENTY_RUPEES @@ -1079,7 +1081,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): difficulty.progressive_bow_limit, item_table[difficulty.basicbow[-1]].item_code]) if difficulty.progressive_bow_limit < 2 and ( - world.swordless[player] or world.logic[player] == 'noglitches'): + world.swordless[player] or world.glitches_required[player] == 'no_glitches'): rom.write_bytes(0x180098, [2, item_table["Silver Bow"].item_code]) rom.write_byte(0x180181, 0x01) # Make silver arrows work only on ganon rom.write_byte(0x180182, 0x00) # Don't auto equip silvers on pickup @@ -1095,7 +1097,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): prize_replacements[0xE1] = 0xDA # 5 Arrows -> Blue Rupee prize_replacements[0xE2] = 0xDB # 10 Arrows -> Red Rupee - if "g" in world.shuffle_prizes[player]: + if world.shuffle_prizes[player] in ("general", "both"): # 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, @@ -1157,7 +1159,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): byte = int(rom.read_byte(address)) rom.write_byte(address, prize_replacements.get(byte, byte)) - if "b" in world.shuffle_prizes[player]: + if world.shuffle_prizes[player] in ("bonk", "both"): # 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, @@ -1274,7 +1276,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed gametype = 0x04 # item - if world.shuffle[player] != 'vanilla': + if world.entrance_shuffle[player] != 'vanilla': gametype |= 0x02 # entrance if enemized: gametype |= 0x01 # enemizer @@ -1312,7 +1314,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): equip[0x36C] = 0x18 equip[0x36D] = 0x18 equip[0x379] = 0x68 - starting_max_bombs = 10 + starting_max_bombs = 0 if world.bombless_start[player] else 10 starting_max_arrows = 30 startingstate = CollectionState(world) @@ -1430,8 +1432,8 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): 'Bottle (Fairy)': 6, 'Bottle (Bee)': 7, 'Bottle (Good Bee)': 8} rupees = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)': 50, 'Rupees (100)': 100, 'Rupees (300)': 300} - bomb_caps = {'Bomb Upgrade (+5)': 5, 'Bomb Upgrade (+10)': 10} - arrow_caps = {'Arrow Upgrade (+5)': 5, 'Arrow Upgrade (+10)': 10} + bomb_caps = {'Bomb Upgrade (+5)': 5, 'Bomb Upgrade (+10)': 10, 'Bomb Upgrade (50)': 50} + arrow_caps = {'Arrow Upgrade (+5)': 5, 'Arrow Upgrade (+10)': 10, 'Arrow Upgrade (70)': 70} bombs = {'Single Bomb': 1, 'Bombs (3)': 3, 'Bombs (10)': 10} arrows = {'Single Arrow': 1, 'Arrows (10)': 10} @@ -1498,7 +1500,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): rom.write_byte(0x3A96D, 0xF0 if world.mode[ player] != 'inverted' else 0xD0) # Residual Portal: Normal (F0= Light Side, D0=Dark Side, 42 = both (Darth Vader)) rom.write_byte(0x3A9A7, 0xD0) # Residual Portal: Normal (D0= Light Side, F0=Dark Side, 42 = both (Darth Vader)) - if 'u' in world.shop_shuffle[player]: + if world.shuffle_capacity_upgrades[player]: rom.write_bytes(0x180080, [5, 10, 5, 10]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10) else: @@ -1509,11 +1511,11 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): (0x02 if 'bombs' in world.escape_assist[player] else 0x00) | (0x04 if 'magic' in world.escape_assist[player] else 0x00))) # Escape assist - if world.goal[player] in ['pedestal', 'triforcehunt', 'localtriforcehunt', 'icerodhunt']: + if world.goal[player] in ['pedestal', 'triforce_hunt', 'local_triforce_hunt']: rom.write_byte(0x18003E, 0x01) # make ganon invincible - elif world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']: + elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']: rom.write_byte(0x18003E, 0x05) # make ganon invincible until enough triforce pieces are collected - elif world.goal[player] in ['ganonpedestal']: + elif world.goal[player] in ['ganon_pedestal']: rom.write_byte(0x18003E, 0x06) elif world.goal[player] in ['bosses']: rom.write_byte(0x18003E, 0x02) # make ganon invincible until all bosses are beat @@ -1534,12 +1536,12 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): # c - enabled for inside compasses # s - enabled for inside small keys # block HC upstairs doors in rain state in standard mode - rom.write_byte(0x18008A, 0x01 if world.mode[player] == "standard" and world.shuffle[player] != 'vanilla' else 0x00) + rom.write_byte(0x18008A, 0x01 if world.mode[player] == "standard" and world.entrance_shuffle[player] != 'vanilla' else 0x00) - rom.write_byte(0x18016A, 0x10 | ((0x01 if world.smallkey_shuffle[player] else 0x00) + rom.write_byte(0x18016A, 0x10 | ((0x01 if world.small_key_shuffle[player] else 0x00) | (0x02 if world.compass_shuffle[player] else 0x00) | (0x04 if world.map_shuffle[player] else 0x00) - | (0x08 if world.bigkey_shuffle[ + | (0x08 if world.big_key_shuffle[ player] else 0x00))) # free roaming item text boxes rom.write_byte(0x18003B, 0x01 if world.map_shuffle[player] else 0x00) # maps showing crystals on overworld @@ -1561,9 +1563,9 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): # b - Big Key # a - Small Key # - rom.write_byte(0x180045, ((0x00 if (world.smallkey_shuffle[player] == smallkey_shuffle.option_original_dungeon or - world.smallkey_shuffle[player] == smallkey_shuffle.option_universal) else 0x01) - | (0x02 if world.bigkey_shuffle[player] else 0x00) + rom.write_byte(0x180045, ((0x00 if (world.small_key_shuffle[player] == small_key_shuffle.option_original_dungeon or + world.small_key_shuffle[player] == small_key_shuffle.option_universal) else 0x01) + | (0x02 if world.big_key_shuffle[player] else 0x00) | (0x04 if world.map_shuffle[player] else 0x00) | (0x08 if world.compass_shuffle[player] else 0x00))) # free roaming items in menu @@ -1595,8 +1597,8 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): rom.write_int16(0x18017C, get_reveal_bytes('Crystal 5') | get_reveal_bytes('Crystal 6') if world.map_shuffle[ player] else 0x0000) # Bomb Shop Reveal - rom.write_byte(0x180172, 0x01 if world.smallkey_shuffle[ - player] == smallkey_shuffle.option_universal else 0x00) # universal keys + rom.write_byte(0x180172, 0x01 if world.small_key_shuffle[ + player] == small_key_shuffle.option_universal else 0x00) # universal keys rom.write_byte(0x18637E, 0x01 if world.retro_bow[player] else 0x00) # Skip quiver in item shops once bought rom.write_byte(0x180175, 0x01 if world.retro_bow[player] else 0x00) # rupee bow rom.write_byte(0x180176, 0x0A if world.retro_bow[player] else 0x00) # wood arrow cost @@ -1613,9 +1615,9 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): rom.write_byte(0x180020, digging_game_rng) rom.write_byte(0xEFD95, digging_game_rng) rom.write_byte(0x1800A3, 0x01) # enable correct world setting behaviour after agahnim kills - rom.write_byte(0x1800A4, 0x01 if world.logic[player] != 'nologic' else 0x00) # enable POD EG fix - rom.write_byte(0x186383, 0x01 if world.glitch_triforce or world.logic[ - player] == 'nologic' else 0x00) # disable glitching to Triforce from Ganons Room + rom.write_byte(0x1800A4, 0x01 if world.glitches_required[player] != 'no_logic' else 0x00) # enable POD EG fix + rom.write_byte(0x186383, 0x01 if world.glitch_triforce or world.glitches_required[ + player] == 'no_logic' else 0x00) # disable glitching to Triforce from Ganons Room rom.write_byte(0x180042, 0x01 if world.save_and_quit_from_boss else 0x00) # Allow Save and Quit after boss kill # remove shield from uncle @@ -1660,8 +1662,8 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): 0x4F]) # allow smith into multi-entrance caves in appropriate shuffles - if world.shuffle[player] in ['restricted', 'full', 'crossed', 'insanity', 'madness'] or ( - world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'): + if world.entrance_shuffle[player] in ['restricted', 'full', 'crossed', 'insanity'] or ( + world.entrance_shuffle[player] == 'simple' and world.mode[player] == 'inverted'): rom.write_byte(0x18004C, 0x01) # set correct flag for hera basement item @@ -1758,8 +1760,8 @@ def write_custom_shops(rom, world, player): if item is None: break if world.shop_item_slots[player] or shop.type == ShopType.TakeAny: - count_shop = (shop.region.name != 'Potion Shop' or 'w' in world.shop_shuffle[player]) and \ - shop.region.name != 'Capacity Upgrade' + count_shop = (shop.region.name != 'Potion Shop' or world.include_witch_hut[player]) and \ + (shop.region.name != 'Capacity Upgrade' or world.shuffle_capacity_upgrades[player]) rom.write_byte(0x186560 + shop.sram_offset + slot, 1 if count_shop else 0) if item['item'] == 'Single Arrow' and item['player'] == 0: arrow_mask |= 1 << index @@ -2201,7 +2203,7 @@ def write_strings(rom, world, player): tt.removeUnwantedText() # Let's keep this guy's text accurate to the shuffle setting. - if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple', 'dungeonscrossed']: + if world.entrance_shuffle[player] in ['vanilla', 'dungeons_full', 'dungeons_simple', 'dungeons_crossed']: tt['kakariko_flophouse_man_no_flippers'] = 'I really hate mowing my yard.\n{PAGEBREAK}\nI should move.' tt['kakariko_flophouse_man'] = 'I really hate mowing my yard.\n{PAGEBREAK}\nI should move.' @@ -2255,7 +2257,7 @@ def write_strings(rom, world, player): entrances_to_hint.update({'Inverted Ganons Tower': 'The sealed castle door'}) else: entrances_to_hint.update({'Ganons Tower': 'Ganon\'s Tower'}) - if world.shuffle[player] in ['simple', 'restricted', 'restricted_legacy']: + if world.entrance_shuffle[player] in ['simple', 'restricted']: for entrance in all_entrances: if entrance.name in entrances_to_hint: this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text( @@ -2265,9 +2267,9 @@ def write_strings(rom, world, player): break # Now we write inconvenient locations for most shuffles and finish taking care of the less chaotic ones. entrances_to_hint.update(InconvenientOtherEntrances) - if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']: + if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']: hint_count = 0 - elif world.shuffle[player] in ['simple', 'restricted', 'restricted_legacy']: + elif world.entrance_shuffle[player] in ['simple', 'restricted']: hint_count = 2 else: hint_count = 4 @@ -2284,14 +2286,14 @@ def write_strings(rom, world, player): # Next we handle hints for randomly selected other entrances, # curating the selection intelligently based on shuffle. - if world.shuffle[player] not in ['simple', 'restricted', 'restricted_legacy']: + if world.entrance_shuffle[player] not in ['simple', 'restricted']: entrances_to_hint.update(ConnectorEntrances) entrances_to_hint.update(DungeonEntrances) if world.mode[player] == 'inverted': entrances_to_hint.update({'Inverted Agahnims Tower': 'The dark mountain tower'}) else: entrances_to_hint.update({'Agahnims Tower': 'The sealed castle door'}) - elif world.shuffle[player] == 'restricted': + elif world.entrance_shuffle[player] == 'restricted': entrances_to_hint.update(ConnectorEntrances) entrances_to_hint.update(OtherEntrances) if world.mode[player] == 'inverted': @@ -2301,15 +2303,15 @@ def write_strings(rom, world, player): else: entrances_to_hint.update({'Dark Sanctuary Hint': 'The dark sanctuary cave'}) entrances_to_hint.update({'Big Bomb Shop': 'The old bomb shop'}) - if world.shuffle[player] in ['insanity', 'madness_legacy', 'insanity_legacy']: + if world.entrance_shuffle[player] != 'insanity': entrances_to_hint.update(InsanityEntrances) if world.shuffle_ganon: if world.mode[player] == 'inverted': entrances_to_hint.update({'Inverted Pyramid Entrance': 'The extra castle passage'}) else: entrances_to_hint.update({'Pyramid Ledge': 'The pyramid ledge'}) - hint_count = 4 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', - 'dungeonscrossed'] else 0 + hint_count = 4 if world.entrance_shuffle[player] not in ['vanilla', 'dungeons_simple', 'dungeons_full', + 'dungeons_crossed'] else 0 for entrance in all_entrances: if entrance.name in entrances_to_hint: if hint_count: @@ -2323,11 +2325,11 @@ def write_strings(rom, world, player): # Next we write a few hints for specific inconvenient locations. We don't make many because in entrance this is highly unpredictable. locations_to_hint = InconvenientLocations.copy() - if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']: + if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']: locations_to_hint.extend(InconvenientVanillaLocations) local_random.shuffle(locations_to_hint) - hint_count = 3 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', - 'dungeonscrossed'] else 5 + hint_count = 3 if world.entrance_shuffle[player] not in ['vanilla', 'dungeons_simple', 'dungeons_full', + 'dungeons_crossed'] else 5 for location in locations_to_hint[:hint_count]: if location == 'Swamp Left': if local_random.randint(0, 1): @@ -2381,16 +2383,16 @@ def write_strings(rom, world, player): # Lastly we write hints to show where certain interesting items are. items_to_hint = RelevantItems.copy() - if world.smallkey_shuffle[player].hints_useful: + if world.small_key_shuffle[player].hints_useful: items_to_hint |= item_name_groups["Small Keys"] - if world.bigkey_shuffle[player].hints_useful: + if world.big_key_shuffle[player].hints_useful: items_to_hint |= item_name_groups["Big Keys"] if world.hints[player] == "full": hint_count = len(hint_locations) # fill all remaining hint locations with Item hints. else: - hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', - 'dungeonscrossed'] else 8 + hint_count = 5 if world.entrance_shuffle[player] not in ['vanilla', 'dungeons_simple', 'dungeons_full', + 'dungeons_crossed'] else 8 hint_count = min(hint_count, len(items_to_hint), len(hint_locations)) if hint_count: locations = world.find_items_in_locations(items_to_hint, player, True) @@ -2417,7 +2419,7 @@ def write_strings(rom, world, player): tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint if world.worlds[player].has_progressive_bows and (world.difficulty_requirements[player].progressive_bow_limit >= 2 or ( - world.swordless[player] or world.logic[player] == 'noglitches')): + world.swordless[player] or world.glitches_required[player] == 'no_glitches')): prog_bow_locs = world.find_item_locations('Progressive Bow', player, True) world.per_slot_randoms[player].shuffle(prog_bow_locs) found_bow = False @@ -2448,7 +2450,7 @@ def write_strings(rom, world, player): if world.goal[player] == 'bosses': tt['sign_ganon'] = 'You need to kill all bosses, Ganon last.' - elif world.goal[player] == 'ganonpedestal': + elif world.goal[player] == 'ganon_pedestal': tt['sign_ganon'] = 'You need to pull the pedestal to defeat Ganon.' elif world.goal[player] == "ganon": if world.crystals_needed_for_ganon[player] == 1: @@ -2456,14 +2458,6 @@ def write_strings(rom, world, player): else: tt['sign_ganon'] = f'You need {world.crystals_needed_for_ganon[player]} crystals to beat Ganon and ' \ f'have beaten Agahnim atop Ganons Tower' - elif world.goal[player] == "icerodhunt": - tt['sign_ganon'] = 'Go find the Ice Rod and Kill Trinexx, then talk to Murahdahla... Ganon is invincible!' - tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Go kill Trinexx instead.' - tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.' - tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\n" \ - "invisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\n" \ - "hidden in a hollow tree. " \ - "If you bring me the Triforce piece from Turtle Rock, I can reassemble it." else: if world.crystals_needed_for_ganon[player] == 1: tt['sign_ganon'] = 'You need a crystal to beat Ganon.' @@ -2478,10 +2472,10 @@ def write_strings(rom, world, player): tt['sahasrahla_quest_have_master_sword'] = Sahasrahla2_texts[local_random.randint(0, len(Sahasrahla2_texts) - 1)] tt['blind_by_the_light'] = Blind_texts[local_random.randint(0, len(Blind_texts) - 1)] - if world.goal[player] in ['triforcehunt', 'localtriforcehunt', 'icerodhunt']: + if world.goal[player] in ['triforce_hunt', 'local_triforce_hunt']: tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.' tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.' - if world.goal[player] == 'triforcehunt' and world.players > 1: + if world.goal[player] == 'triforce_hunt' and world.players > 1: tt['sign_ganon'] = 'Go find the Triforce pieces with your friends... Ganon is invincible!' else: tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!' @@ -2504,17 +2498,17 @@ def write_strings(rom, world, player): tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!' tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!' if world.treasure_hunt_count[player] > 1: - if world.goal[player] == 'ganontriforcehunt' and world.players > 1: + if world.goal[player] == 'ganon_triforce_hunt' and world.players > 1: tt['sign_ganon'] = 'You need to find %d Triforce pieces out of %d with your friends to defeat Ganon.' % \ (world.treasure_hunt_count[player], world.triforce_pieces_available[player]) - elif world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']: + elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']: tt['sign_ganon'] = 'You need to find %d Triforce pieces out of %d to defeat Ganon.' % \ (world.treasure_hunt_count[player], world.triforce_pieces_available[player]) else: - if world.goal[player] == 'ganontriforcehunt' and world.players > 1: + if world.goal[player] == 'ganon_triforce_hunt' and world.players > 1: tt['sign_ganon'] = 'You need to find %d Triforce piece out of %d with your friends to defeat Ganon.' % \ (world.treasure_hunt_count[player], world.triforce_pieces_available[player]) - elif world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']: + elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']: tt['sign_ganon'] = 'You need to find %d Triforce piece out of %d to defeat Ganon.' % \ (world.treasure_hunt_count[player], world.triforce_pieces_available[player]) @@ -2614,12 +2608,12 @@ def set_inverted_mode(world, player, rom): rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph proof # the following bytes should only be written in vanilla # or they'll overwrite the randomizer's shuffles - if world.shuffle[player] == 'vanilla': + if world.entrance_shuffle[player] == 'vanilla': rom.write_byte(0xDBB73 + 0x23, 0x37) # switch AT and GT rom.write_byte(0xDBB73 + 0x36, 0x24) rom.write_int16(0x15AEE + 2 * 0x38, 0x00E0) rom.write_int16(0x15AEE + 2 * 0x25, 0x000C) - if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']: + if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']: rom.write_byte(0x15B8C, 0x6C) rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house rom.write_byte(0xDBB73 + 0x52, 0x01) @@ -2677,7 +2671,7 @@ def set_inverted_mode(world, player, rom): rom.write_int16(snes_to_pc(0x02D9A6), 0x005A) rom.write_byte(snes_to_pc(0x02D9B3), 0x12) # keep the old man spawn point at old man house unless shuffle is vanilla - if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple', 'dungeonscrossed']: + if world.entrance_shuffle[player] in ['vanilla', 'dungeons_full', 'dungeons_simple', 'dungeons_crossed']: rom.write_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01]) rom.write_int16(snes_to_pc(0x02D8DE), 0x00F1) rom.write_bytes(snes_to_pc(0x02D910), [0x1F, 0x1E, 0x1F, 0x1F, 0x03, 0x02, 0x03, 0x03]) @@ -2740,7 +2734,7 @@ def set_inverted_mode(world, player, rom): rom.write_int16s(snes_to_pc(0x1bb836), [0x001B, 0x001B, 0x001B]) rom.write_int16(snes_to_pc(0x308300), 0x0140) # new pyramid hole entrance rom.write_int16(snes_to_pc(0x308320), 0x001B) - if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']: + if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']: rom.write_byte(snes_to_pc(0x308340), 0x7B) rom.write_int16(snes_to_pc(0x1af504), 0x148B) rom.write_int16(snes_to_pc(0x1af50c), 0x149B) @@ -2777,10 +2771,10 @@ def set_inverted_mode(world, player, rom): rom.write_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82]) rom.write_int16(0xDB96F + 2 * 0x35, 0x001B) # move pyramid exit door rom.write_int16(0xDBA71 + 2 * 0x35, 0x06A4) - if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']: + if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']: rom.write_byte(0xDBB73 + 0x35, 0x36) rom.write_byte(snes_to_pc(0x09D436), 0xF3) # remove castle gate warp - if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']: + if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']: rom.write_int16(0x15AEE + 2 * 0x37, 0x0010) # pyramid exit to new hc area rom.write_byte(0x15B8C + 0x37, 0x1B) rom.write_int16(0x15BDB + 2 * 0x37, 0x0418) diff --git a/worlds/alttp/Rules.py b/worlds/alttp/Rules.py index 98ab805b..17061842 100644 --- a/worlds/alttp/Rules.py +++ b/worlds/alttp/Rules.py @@ -9,25 +9,25 @@ from worlds.generic.Rules import (add_item_rule, add_rule, forbid_item, from . import OverworldGlitchRules from .Bosses import GanonDefeatRule from .Items import ItemFactory, item_name_groups, item_table, progression_items -from .Options import smallkey_shuffle +from .Options import small_key_shuffle from .OverworldGlitchRules import no_logic_rules, overworld_glitches_rules from .Regions import LTTPRegionType, location_table from .StateHelpers import (can_extend_magic, can_kill_most_things, can_lift_heavy_rocks, can_lift_rocks, can_melt_things, can_retrieve_tablet, can_shoot_arrows, has_beam_sword, has_crystals, - has_fire_source, has_hearts, + has_fire_source, has_hearts, has_melee_weapon, has_misery_mire_medallion, has_sword, has_turtle_rock_medallion, - has_triforce_pieces) + has_triforce_pieces, can_use_bombs, can_bomb_or_bonk) from .UnderworldGlitchRules import underworld_glitches_rules def set_rules(world): player = world.player world = world.multiworld - if world.logic[player] == 'nologic': + if world.glitches_required[player] == 'no_logic': if player == next(player_id for player_id in world.get_game_players("A Link to the Past") - if world.logic[player_id] == 'nologic'): # only warn one time + if world.glitches_required[player_id] == 'no_logic'): # only warn one time logging.info( 'WARNING! Seeds generated under this logic often require major glitches and may be impossible!') @@ -45,8 +45,8 @@ def set_rules(world): else: world.completion_condition[player] = lambda state: state.has('Triforce', player) - global_rules(world, player) dungeon_boss_rules(world, player) + global_rules(world, player) if world.mode[player] != 'inverted': default_rules(world, player) @@ -61,24 +61,24 @@ def set_rules(world): else: raise NotImplementedError(f'World state {world.mode[player]} is not implemented yet') - if world.logic[player] == 'noglitches': + if world.glitches_required[player] == 'no_glitches': no_glitches_rules(world, player) - elif world.logic[player] == 'owglitches': + elif world.glitches_required[player] == 'overworld_glitches': # Initially setting no_glitches_rules to set the baseline rules for some # entrances. The overworld_glitches_rules set is primarily additive. no_glitches_rules(world, player) fake_flipper_rules(world, player) overworld_glitches_rules(world, player) - elif world.logic[player] in ['hybridglitches', 'nologic']: + elif world.glitches_required[player] in ['hybrid_major_glitches', 'no_logic']: no_glitches_rules(world, player) fake_flipper_rules(world, player) overworld_glitches_rules(world, player) underworld_glitches_rules(world, player) - elif world.logic[player] == 'minorglitches': + elif world.glitches_required[player] == 'minor_glitches': no_glitches_rules(world, player) fake_flipper_rules(world, player) else: - raise NotImplementedError(f'Not implemented yet: Logic - {world.logic[player]}') + raise NotImplementedError(f'Not implemented yet: Logic - {world.glitches_required[player]}') if world.goal[player] == 'bosses': # require all bosses to beat ganon @@ -89,7 +89,7 @@ def set_rules(world): if world.mode[player] != 'inverted': set_big_bomb_rules(world, player) - if world.logic[player] in {'owglitches', 'hybridglitches', 'nologic'} and world.shuffle[player] not in {'insanity', 'insanity_legacy', 'madness'}: + if world.glitches_required[player] in {'overworld_glitches', 'hybrid_major_glitches', 'no_logic'} and world.entrance_shuffle[player] not in {'insanity', 'insanity_legacy', 'madness'}: path_to_courtyard = mirrorless_path_to_castle_courtyard(world, player) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.multiworld.get_entrance('Dark Death Mountain Offset Mirror', player).can_reach(state) and all(rule(state) for rule in path_to_courtyard), 'or') else: @@ -97,18 +97,18 @@ def set_rules(world): # if swamp and dam have not been moved we require mirror for swamp palace # however there is mirrorless swamp in hybrid MG, so we don't necessarily want this. HMG handles this requirement itself. - if not world.swamp_patch_required[player] and world.logic[player] not in ['hybridglitches', 'nologic']: + if not world.swamp_patch_required[player] and world.glitches_required[player] not in ['hybrid_major_glitches', 'no_logic']: add_rule(world.get_entrance('Swamp Palace Moat', player), lambda state: state.has('Magic Mirror', player)) # GT Entrance may be required for Turtle Rock for OWG and < 7 required ganons_tower = world.get_entrance('Inverted Ganons Tower' if world.mode[player] == 'inverted' else 'Ganons Tower', player) - if world.crystals_needed_for_gt[player] == 7 and not (world.logic[player] in ['owglitches', 'hybridglitches', 'nologic'] and world.mode[player] != 'inverted'): + if world.crystals_needed_for_gt[player] == 7 and not (world.glitches_required[player] in ['overworld_glitches', 'hybrid_major_glitches', 'no_logic'] and world.mode[player] != 'inverted'): set_rule(ganons_tower, lambda state: False) set_trock_key_rules(world, player) set_rule(ganons_tower, lambda state: has_crystals(state, state.multiworld.crystals_needed_for_gt[player], player)) - if world.mode[player] != 'inverted' and world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']: + if world.mode[player] != 'inverted' and world.glitches_required[player] in ['overworld_glitches', 'hybrid_major_glitches', 'no_logic']: add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.multiworld.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or') set_bunny_rules(world, player, world.mode[player] == 'inverted') @@ -139,6 +139,7 @@ def set_defeat_dungeon_boss_rule(location): add_rule(location, lambda state: location.parent_region.dungeon.boss.can_defeat(state)) + def set_always_allow(spot, rule): spot.always_allow = rule @@ -184,6 +185,7 @@ def dungeon_boss_rules(world, player): for location in boss_locations: set_defeat_dungeon_boss_rule(world.get_location(location, player)) + def global_rules(world, player): # ganon can only carry triforce add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player) @@ -213,14 +215,61 @@ def global_rules(world, player): set_rule(world.get_location('Ether Tablet', player), lambda state: can_retrieve_tablet(state, player)) set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) - set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith + set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith set_rule(world.get_location('Blacksmith', player), lambda state: state.has('Return Smith', player)) set_rule(world.get_location('Magic Bat', player), lambda state: state.has('Magic Powder', player)) set_rule(world.get_location('Sick Kid', player), lambda state: state.has_group("Bottles", player)) set_rule(world.get_location('Library', player), lambda state: state.has('Pegasus Boots', player)) - set_rule(world.get_location('Mimic Cave', player), lambda state: state.has('Hammer', player)) + + if world.enemy_shuffle[player]: + set_rule(world.get_location('Mimic Cave', player), lambda state: state.has('Hammer', player) and + can_kill_most_things(state, player, 4)) + else: + set_rule(world.get_location('Mimic Cave', player), lambda state: state.has('Hammer', player) + and ((state.multiworld.enemy_health[player] in ("easy", "default") and can_use_bombs(state, player, 4)) + or can_shoot_arrows(state, player) or state.has("Cane of Somaria", player) + or has_beam_sword(state, player))) + set_rule(world.get_location('Sahasrahla', player), lambda state: state.has('Green Pendant', player)) + set_rule(world.get_location('Aginah\'s Cave', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_location('Blind\'s Hideout - Top', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_location('Chicken House', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_location('Kakariko Well - Top', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_location('Graveyard Cave', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_location('Sahasrahla\'s Hut - Left', player), lambda state: can_bomb_or_bonk(state, player)) + set_rule(world.get_location('Sahasrahla\'s Hut - Middle', player), lambda state: can_bomb_or_bonk(state, player)) + set_rule(world.get_location('Sahasrahla\'s Hut - Right', player), lambda state: can_bomb_or_bonk(state, player)) + set_rule(world.get_location('Paradox Cave Lower - Left', player), lambda state: can_use_bombs(state, player) + or has_beam_sword(state, player) or can_shoot_arrows(state, player) + or state.has_any(["Fire Rod", "Cane of Somaria"], player)) + set_rule(world.get_location('Paradox Cave Lower - Right', player), lambda state: can_use_bombs(state, player) + or has_beam_sword(state, player) or can_shoot_arrows(state, player) + or state.has_any(["Fire Rod", "Cane of Somaria"], player)) + set_rule(world.get_location('Paradox Cave Lower - Far Right', player), lambda state: can_use_bombs(state, player) + or has_beam_sword(state, player) or can_shoot_arrows(state, player) + or state.has_any(["Fire Rod", "Cane of Somaria"], player)) + set_rule(world.get_location('Paradox Cave Lower - Middle', player), lambda state: can_use_bombs(state, player) + or has_beam_sword(state, player) or can_shoot_arrows(state, player) + or state.has_any(["Fire Rod", "Cane of Somaria"], player)) + set_rule(world.get_location('Paradox Cave Lower - Far Left', player), lambda state: can_use_bombs(state, player) + or has_beam_sword(state, player) or can_shoot_arrows(state, player) + or state.has_any(["Fire Rod", "Cane of Somaria"], player)) + set_rule(world.get_location('Paradox Cave Upper - Left', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_location('Paradox Cave Upper - Right', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_location('Mini Moldorm Cave - Far Left', player), lambda state: can_kill_most_things(state, player, 4)) + set_rule(world.get_location('Mini Moldorm Cave - Left', player), lambda state: can_kill_most_things(state, player, 4)) + set_rule(world.get_location('Mini Moldorm Cave - Far Right', player), lambda state: can_kill_most_things(state, player, 4)) + set_rule(world.get_location('Mini Moldorm Cave - Right', player), lambda state: can_kill_most_things(state, player, 4)) + set_rule(world.get_location('Mini Moldorm Cave - Generous Guy', player), lambda state: can_kill_most_things(state, player, 4)) + set_rule(world.get_location('Hype Cave - Bottom', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_location('Hype Cave - Middle Left', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_location('Hype Cave - Middle Right', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_location('Hype Cave - Top', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_entrance('Light World Death Mountain Shop', player), lambda state: can_use_bombs(state, player)) + + set_rule(world.get_entrance('Two Brothers House Exit (West)', player), lambda state: can_bomb_or_bonk(state, player)) + set_rule(world.get_entrance('Two Brothers House Exit (East)', player), lambda state: can_bomb_or_bonk(state, player)) set_rule(world.get_location('Spike Cave', player), lambda state: state.has('Hammer', player) and can_lift_rocks(state, player) and @@ -238,61 +287,81 @@ def global_rules(world, player): set_rule(world.get_entrance('Sewers Door', player), lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4) or ( - world.smallkey_shuffle[player] == smallkey_shuffle.option_universal and world.mode[ + world.small_key_shuffle[player] == small_key_shuffle.option_universal and world.mode[ player] == 'standard')) # standard universal small keys cannot access the shop set_rule(world.get_entrance('Sewers Back Door', player), lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4)) + set_rule(world.get_entrance('Sewers Secret Room', player), lambda state: can_bomb_or_bonk(state, player)) + set_rule(world.get_entrance('Agahnim 1', player), lambda state: has_sword(state, player) and state._lttp_has_key('Small Key (Agahnims Tower)', player, 4)) - set_rule(world.get_location('Castle Tower - Room 03', player), lambda state: can_kill_most_things(state, player, 8)) + set_rule(world.get_location('Castle Tower - Room 03', player), lambda state: can_kill_most_things(state, player, 4)) set_rule(world.get_location('Castle Tower - Dark Maze', player), - lambda state: can_kill_most_things(state, player, 8) and state._lttp_has_key('Small Key (Agahnims Tower)', + lambda state: can_kill_most_things(state, player, 4) and state._lttp_has_key('Small Key (Agahnims Tower)', player)) set_rule(world.get_location('Castle Tower - Dark Archer Key Drop', player), - lambda state: can_kill_most_things(state, player, 8) and state._lttp_has_key('Small Key (Agahnims Tower)', + lambda state: can_kill_most_things(state, player, 4) and state._lttp_has_key('Small Key (Agahnims Tower)', player, 2)) set_rule(world.get_location('Castle Tower - Circle of Pots Key Drop', player), - lambda state: can_kill_most_things(state, player, 8) and state._lttp_has_key('Small Key (Agahnims Tower)', + lambda state: can_kill_most_things(state, player, 4) and state._lttp_has_key('Small Key (Agahnims Tower)', player, 3)) set_always_allow(world.get_location('Eastern Palace - Big Key Chest', player), lambda state, item: item.name == 'Big Key (Eastern Palace)' and item.player == player) set_rule(world.get_location('Eastern Palace - Big Key Chest', player), - lambda state: state._lttp_has_key('Small Key (Eastern Palace)', player, 2) or - ((location_item_name(state, 'Eastern Palace - Big Key Chest', player) == ('Big Key (Eastern Palace)', player) - and state.has('Small Key (Eastern Palace)', player)))) + lambda state: can_kill_most_things(state, player, 5) and (state._lttp_has_key('Small Key (Eastern Palace)', + player, 2) or ((location_item_name(state, 'Eastern Palace - Big Key Chest', player) + == ('Big Key (Eastern Palace)', player) and state.has('Small Key (Eastern Palace)', + player))))) set_rule(world.get_location('Eastern Palace - Dark Eyegore Key Drop', player), - lambda state: state.has('Big Key (Eastern Palace)', player)) + lambda state: state.has('Big Key (Eastern Palace)', player) and can_kill_most_things(state, player, 1)) set_rule(world.get_location('Eastern Palace - Big Chest', player), lambda state: state.has('Big Key (Eastern Palace)', player)) + # not bothering to check for can_kill_most_things in the rooms leading to boss, as if you can kill a boss you should + # be able to get through these rooms ep_boss = world.get_location('Eastern Palace - Boss', player) - set_rule(ep_boss, lambda state: state.has('Big Key (Eastern Palace)', player) and + add_rule(ep_boss, lambda state: state.has('Big Key (Eastern Palace)', player) and state._lttp_has_key('Small Key (Eastern Palace)', player, 2) and ep_boss.parent_region.dungeon.boss.can_defeat(state)) ep_prize = world.get_location('Eastern Palace - Prize', player) - set_rule(ep_prize, lambda state: state.has('Big Key (Eastern Palace)', player) and + add_rule(ep_prize, lambda state: state.has('Big Key (Eastern Palace)', player) and state._lttp_has_key('Small Key (Eastern Palace)', player, 2) and ep_prize.parent_region.dungeon.boss.can_defeat(state)) if not world.enemy_shuffle[player]: add_rule(ep_boss, lambda state: can_shoot_arrows(state, player)) add_rule(ep_prize, lambda state: can_shoot_arrows(state, player)) + # You can always kill the Stalfos' with the pots on easy/normal + if world.enemy_health[player] in ("hard", "expert") or world.enemy_shuffle[player]: + stalfos_rule = lambda state: can_kill_most_things(state, player, 4) + for location in ['Eastern Palace - Compass Chest', 'Eastern Palace - Big Chest', + 'Eastern Palace - Dark Square Pot Key', 'Eastern Palace - Dark Eyegore Key Drop', + 'Eastern Palace - Big Key Chest', 'Eastern Palace - Boss', 'Eastern Palace - Prize']: + add_rule(world.get_location(location, player), stalfos_rule) + set_rule(world.get_location('Desert Palace - Big Chest', player), lambda state: state.has('Big Key (Desert Palace)', player)) set_rule(world.get_location('Desert Palace - Torch', player), lambda state: state.has('Pegasus Boots', player)) set_rule(world.get_entrance('Desert Palace East Wing', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 4)) - set_rule(world.get_location('Desert Palace - Big Key Chest', player), lambda state: can_kill_most_things(state, player)) - set_rule(world.get_location('Desert Palace - Beamos Hall Pot Key', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 2) and can_kill_most_things(state, player)) - set_rule(world.get_location('Desert Palace - Desert Tiles 2 Pot Key', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 3) and can_kill_most_things(state, player)) - set_rule(world.get_location('Desert Palace - Prize', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 4) and state.has('Big Key (Desert Palace)', player) and has_fire_source(state, player) and state.multiworld.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) - set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 4) and state.has('Big Key (Desert Palace)', player) and has_fire_source(state, player) and state.multiworld.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) + set_rule(world.get_location('Desert Palace - Big Key Chest', player), lambda state: can_kill_most_things(state, player, 3)) + set_rule(world.get_location('Desert Palace - Beamos Hall Pot Key', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 2) and can_kill_most_things(state, player, 4)) + set_rule(world.get_location('Desert Palace - Desert Tiles 2 Pot Key', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 3) and can_kill_most_things(state, player, 4)) + add_rule(world.get_location('Desert Palace - Prize', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 4) and state.has('Big Key (Desert Palace)', player) and has_fire_source(state, player) and state.multiworld.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) + add_rule(world.get_location('Desert Palace - Boss', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 4) and state.has('Big Key (Desert Palace)', player) and has_fire_source(state, player) and state.multiworld.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) # logic patch to prevent placing a crystal in Desert that's required to reach the required keys - if not (world.smallkey_shuffle[player] and world.bigkey_shuffle[player]): + if not (world.small_key_shuffle[player] and world.big_key_shuffle[player]): add_rule(world.get_location('Desert Palace - Prize', player), lambda state: state.multiworld.get_region('Desert Palace Main (Outer)', player).can_reach(state)) set_rule(world.get_entrance('Tower of Hera Small Key Door', player), lambda state: state._lttp_has_key('Small Key (Tower of Hera)', player) or location_item_name(state, 'Tower of Hera - Big Key Chest', player) == ('Small Key (Tower of Hera)', player)) set_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: state.has('Big Key (Tower of Hera)', player)) + if world.enemy_shuffle[player]: + add_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: can_kill_most_things(state, player, 3)) + else: + add_rule(world.get_entrance('Tower of Hera Big Key Door', player), + lambda state: (has_melee_weapon(state, player) or (state.has('Silver Bow', player) + and can_shoot_arrows(state, player)) or state.has("Cane of Byrna", player) + or state.has("Cane of Somaria", player))) set_rule(world.get_location('Tower of Hera - Big Chest', player), lambda state: state.has('Big Key (Tower of Hera)', player)) set_rule(world.get_location('Tower of Hera - Big Key Chest', player), lambda state: has_fire_source(state, player)) if world.accessibility[player] != 'locations': @@ -300,9 +369,13 @@ def global_rules(world, player): set_rule(world.get_entrance('Swamp Palace Moat', player), lambda state: state.has('Flippers', player) and state.has('Open Floodgate', player)) set_rule(world.get_entrance('Swamp Palace Small Key Door', player), lambda state: state._lttp_has_key('Small Key (Swamp Palace)', player)) + set_rule(world.get_location('Swamp Palace - Map Chest', player), lambda state: can_use_bombs(state, player)) set_rule(world.get_location('Swamp Palace - Trench 1 Pot Key', player), lambda state: state._lttp_has_key('Small Key (Swamp Palace)', player, 2)) set_rule(world.get_entrance('Swamp Palace (Center)', player), lambda state: state.has('Hammer', player) and state._lttp_has_key('Small Key (Swamp Palace)', player, 3)) set_rule(world.get_location('Swamp Palace - Hookshot Pot Key', player), lambda state: state.has('Hookshot', player)) + if world.pot_shuffle[player]: + # it could move the key to the top right platform which can only be reached with bombs + add_rule(world.get_location('Swamp Palace - Hookshot Pot Key', player), lambda state: can_use_bombs(state, player)) set_rule(world.get_entrance('Swamp Palace (West)', player), lambda state: state._lttp_has_key('Small Key (Swamp Palace)', player, 6) if state.has('Hookshot', player) else state._lttp_has_key('Small Key (Swamp Palace)', player, 4)) @@ -310,15 +383,18 @@ def global_rules(world, player): if world.accessibility[player] != 'locations': allow_self_locking_items(world.get_location('Swamp Palace - Big Chest', player), 'Big Key (Swamp Palace)') set_rule(world.get_entrance('Swamp Palace (North)', player), lambda state: state.has('Hookshot', player) and state._lttp_has_key('Small Key (Swamp Palace)', player, 5)) - if not world.smallkey_shuffle[player] and world.logic[player] not in ['hybridglitches', 'nologic']: + if not world.small_key_shuffle[player] and world.glitches_required[player] not in ['hybrid_major_glitches', 'no_logic']: forbid_item(world.get_location('Swamp Palace - Entrance', player), 'Big Key (Swamp Palace)', player) set_rule(world.get_location('Swamp Palace - Prize', player), lambda state: state._lttp_has_key('Small Key (Swamp Palace)', player, 6)) set_rule(world.get_location('Swamp Palace - Boss', player), lambda state: state._lttp_has_key('Small Key (Swamp Palace)', player, 6)) + if world.pot_shuffle[player]: + # key can (and probably will) be moved behind bombable wall + set_rule(world.get_location('Swamp Palace - Waterway Pot Key', player), lambda state: can_use_bombs(state, player)) set_rule(world.get_entrance('Thieves Town Big Key Door', player), lambda state: state.has('Big Key (Thieves Town)', player)) if world.worlds[player].dungeons["Thieves Town"].boss.enemizer_name == "Blind": - set_rule(world.get_entrance('Blind Fight', player), lambda state: state._lttp_has_key('Small Key (Thieves Town)', player, 3)) + set_rule(world.get_entrance('Blind Fight', player), lambda state: state._lttp_has_key('Small Key (Thieves Town)', player, 3) and can_use_bombs(state, player)) set_rule(world.get_location('Thieves\' Town - Big Chest', player), lambda state: (state._lttp_has_key('Small Key (Thieves Town)', player, 3)) and state.has('Hammer', player)) @@ -334,7 +410,7 @@ def global_rules(world, player): set_rule(world.get_entrance('Skull Woods First Section (Right) North Door', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 5)) set_rule(world.get_entrance('Skull Woods First Section West Door', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 5)) set_rule(world.get_entrance('Skull Woods First Section (Left) Door to Exit', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 5)) - set_rule(world.get_location('Skull Woods - Big Chest', player), lambda state: state.has('Big Key (Skull Woods)', player)) + set_rule(world.get_location('Skull Woods - Big Chest', player), lambda state: state.has('Big Key (Skull Woods)', player) and can_use_bombs(state, player)) if world.accessibility[player] != 'locations': allow_self_locking_items(world.get_location('Skull Woods - Big Chest', player), 'Big Key (Skull Woods)') set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 4) and state.has('Fire Rod', player) and has_sword(state, player)) # sword required for curtain @@ -342,7 +418,13 @@ def global_rules(world, player): add_rule(world.get_location('Skull Woods - Boss', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 5)) set_rule(world.get_location('Ice Palace - Jelly Key Drop', player), lambda state: can_melt_things(state, player)) - set_rule(world.get_entrance('Ice Palace (Second Section)', player), lambda state: can_melt_things(state, player) and state._lttp_has_key('Small Key (Ice Palace)', player)) + set_rule(world.get_location('Ice Palace - Compass Chest', player), lambda state: can_melt_things(state, player) and state._lttp_has_key('Small Key (Ice Palace)', player)) + set_rule(world.get_entrance('Ice Palace (Second Section)', player), lambda state: can_melt_things(state, player) and state._lttp_has_key('Small Key (Ice Palace)', player) and can_use_bombs(state, player)) + if not world.enemy_shuffle[player]: + # Stalfos Knights can be killed by damaging them repeatedly with boomerang, swords, etc. if bombs are + # unavailable. If bombs are available, the pots can be thrown at them, so no other weapons are needed + add_rule(world.get_entrance('Ice Palace (Second Section)', player), lambda state: (can_use_bombs(state, player) + or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) or has_sword(state, player) or state.has("Hammer", player))) set_rule(world.get_entrance('Ice Palace (Main)', player), lambda state: state._lttp_has_key('Small Key (Ice Palace)', player, 2)) set_rule(world.get_location('Ice Palace - Big Chest', player), lambda state: state.has('Big Key (Ice Palace)', player)) set_rule(world.get_entrance('Ice Palace (Kholdstare)', player), lambda state: can_lift_rocks(state, player) and state.has('Hammer', player) and state.has('Big Key (Ice Palace)', player) and (state._lttp_has_key('Small Key (Ice Palace)', player, 6) or (state.has('Cane of Somaria', player) and state._lttp_has_key('Small Key (Ice Palace)', player, 5)))) @@ -387,16 +469,21 @@ def global_rules(world, player): else state._lttp_has_key('Small Key (Misery Mire)', player, 6)) set_rule(world.get_location('Misery Mire - Compass Chest', player), lambda state: has_fire_source(state, player)) set_rule(world.get_location('Misery Mire - Big Key Chest', player), lambda state: has_fire_source(state, player)) - set_rule(world.get_entrance('Misery Mire (Vitreous)', player), lambda state: state.has('Cane of Somaria', player)) + set_rule(world.get_entrance('Misery Mire (Vitreous)', player), lambda state: state.has('Cane of Somaria', player) and can_use_bombs(state, player)) set_rule(world.get_entrance('Turtle Rock Entrance Gap', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('Turtle Rock Entrance Gap Reverse', player), lambda state: state.has('Cane of Somaria', player)) + set_rule(world.get_location('Turtle Rock - Pokey 1 Key Drop', player), lambda state: can_kill_most_things(state, player, 5)) + set_rule(world.get_location('Turtle Rock - Pokey 2 Key Drop', player), lambda state: can_kill_most_things(state, player, 5)) set_rule(world.get_location('Turtle Rock - Compass Chest', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_location('Turtle Rock - Roller Room - Left', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player)) set_rule(world.get_location('Turtle Rock - Roller Room - Right', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player)) set_rule(world.get_location('Turtle Rock - Big Chest', player), lambda state: state.has('Big Key (Turtle Rock)', player) and (state.has('Cane of Somaria', player) or state.has('Hookshot', player))) set_rule(world.get_entrance('Turtle Rock (Big Chest) (North)', player), lambda state: state.has('Cane of Somaria', player) or state.has('Hookshot', player)) - set_rule(world.get_entrance('Turtle Rock Big Key Door', player), lambda state: state.has('Big Key (Turtle Rock)', player)) + set_rule(world.get_entrance('Turtle Rock Big Key Door', player), lambda state: state.has('Big Key (Turtle Rock)', player) and can_kill_most_things(state, player, 10)) + set_rule(world.get_entrance('Turtle Rock Ledge Exit (West)', player), lambda state: can_use_bombs(state, player) and can_kill_most_things(state, player, 10)) + set_rule(world.get_location('Turtle Rock - Chain Chomps', player), lambda state: can_use_bombs(state, player) or can_shoot_arrows(state, player) + or has_beam_sword(state, player) or state.has_any(["Blue Boomerang", "Red Boomerang", "Hookshot", "Cane of Somaria", "Fire Rod", "Ice Rod"], player)) set_rule(world.get_entrance('Turtle Rock (Dark Room) (North)', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('Turtle Rock (Dark Room) (South)', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) @@ -405,16 +492,22 @@ def global_rules(world, player): set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player)) set_rule(world.get_entrance('Turtle Rock (Trinexx)', player), lambda state: state._lttp_has_key('Small Key (Turtle Rock)', player, 6) and state.has('Big Key (Turtle Rock)', player) and state.has('Cane of Somaria', player)) - if not world.enemy_shuffle[player]: - set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: can_shoot_arrows(state, player)) + if world.enemy_shuffle[player]: + set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: can_bomb_or_bonk(state, player) and can_kill_most_things(state, player, 3)) + else: + set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: can_bomb_or_bonk(state, player) and can_shoot_arrows(state, player)) set_rule(world.get_entrance('Palace of Darkness Hammer Peg Drop', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Palace of Darkness Bridge Room', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 1)) # If we can reach any other small key door, we already have back door access to this area set_rule(world.get_entrance('Palace of Darkness Big Key Door', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 6) and state.has('Big Key (Palace of Darkness)', player) and can_shoot_arrows(state, player) and state.has('Hammer', player)) set_rule(world.get_entrance('Palace of Darkness (North)', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 4)) - set_rule(world.get_location('Palace of Darkness - Big Chest', player), lambda state: state.has('Big Key (Palace of Darkness)', player)) + set_rule(world.get_location('Palace of Darkness - Big Chest', player), lambda state: can_use_bombs(state, player) and state.has('Big Key (Palace of Darkness)', player)) + set_rule(world.get_location('Palace of Darkness - The Arena - Ledge', player), lambda state: can_use_bombs(state, player)) + if world.pot_shuffle[player]: + # chest switch may be up on ledge where bombs are required + set_rule(world.get_location('Palace of Darkness - Stalfos Basement', player), lambda state: can_use_bombs(state, player)) - set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 6) or ( - location_item_name(state, 'Palace of Darkness - Big Key Chest', player) in [('Small Key (Palace of Darkness)', player)] and state._lttp_has_key('Small Key (Palace of Darkness)', player, 3))) + set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase', player), lambda state: can_use_bombs(state, player) and (state._lttp_has_key('Small Key (Palace of Darkness)', player, 6) or ( + location_item_name(state, 'Palace of Darkness - Big Key Chest', player) in [('Small Key (Palace of Darkness)', player)] and state._lttp_has_key('Small Key (Palace of Darkness)', player, 3)))) if world.accessibility[player] != 'locations': set_always_allow(world.get_location('Palace of Darkness - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Palace of Darkness)' and item.player == player and state._lttp_has_key('Small Key (Palace of Darkness)', player, 5)) @@ -430,13 +523,9 @@ def global_rules(world, player): compass_room_chests = ['Ganons Tower - Compass Room - Top Left', 'Ganons Tower - Compass Room - Top Right', 'Ganons Tower - Compass Room - Bottom Left', 'Ganons Tower - Compass Room - Bottom Right', 'Ganons Tower - Conveyor Star Pits Pot Key'] back_chests = ['Ganons Tower - Bob\'s Chest', 'Ganons Tower - Big Chest', 'Ganons Tower - Big Key Room - Left', 'Ganons Tower - Big Key Room - Right', 'Ganons Tower - Big Key Chest'] - set_rule(world.get_location('Ganons Tower - Bob\'s Torch', player), lambda state: state.has('Pegasus Boots', player)) set_rule(world.get_entrance('Ganons Tower (Tile Room)', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hammer', player) and (state.has('Hookshot', player) or state.has('Pegasus Boots', player))) - if world.pot_shuffle[player]: - # Pot Shuffle can move this check into the hookshot room - set_rule(world.get_location('Ganons Tower - Conveyor Cross Pot Key', player), lambda state: state.has('Hammer', player) and (state.has('Hookshot', player) or state.has('Pegasus Boots', player))) set_rule(world.get_entrance('Ganons Tower (Map Room)', player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 8) or ( location_item_name(state, 'Ganons Tower - Map Chest', player) in [('Big Key (Ganons Tower)', player)] and state._lttp_has_key('Small Key (Ganons Tower)', player, 6))) @@ -465,17 +554,17 @@ def global_rules(world, player): item_name_in_location_names(state, 'Big Key (Ganons Tower)', player, zip(back_chests, [player] * len(back_chests))) and state._lttp_has_key('Small Key (Ganons Tower)', player, 5))) # Actual requirements for location in compass_room_chests: - set_rule(world.get_location(location, player), lambda state: state.has('Fire Rod', player) and (state._lttp_has_key('Small Key (Ganons Tower)', player, 7) or ( + set_rule(world.get_location(location, player), lambda state: (can_use_bombs(state, player) or state.has("Cane of Somaria", player)) and state.has('Fire Rod', player) and (state._lttp_has_key('Small Key (Ganons Tower)', player, 7) or ( item_name_in_location_names(state, 'Big Key (Ganons Tower)', player, zip(compass_room_chests, [player] * len(compass_room_chests))) and state._lttp_has_key('Small Key (Ganons Tower)', player, 5)))) set_rule(world.get_location('Ganons Tower - Big Chest', player), lambda state: state.has('Big Key (Ganons Tower)', player)) set_rule(world.get_location('Ganons Tower - Big Key Room - Left', player), - lambda state: state.multiworld.get_location('Ganons Tower - Big Key Room - Left', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) + lambda state: can_use_bombs(state, player) and state.multiworld.get_location('Ganons Tower - Big Key Room - Left', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) set_rule(world.get_location('Ganons Tower - Big Key Chest', player), - lambda state: state.multiworld.get_location('Ganons Tower - Big Key Chest', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) + lambda state: can_use_bombs(state, player) and state.multiworld.get_location('Ganons Tower - Big Key Chest', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) set_rule(world.get_location('Ganons Tower - Big Key Room - Right', player), - lambda state: state.multiworld.get_location('Ganons Tower - Big Key Room - Right', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) + lambda state: can_use_bombs(state, player) and state.multiworld.get_location('Ganons Tower - Big Key Room - Right', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) if world.enemy_shuffle[player]: set_rule(world.get_entrance('Ganons Tower Big Key Door', player), lambda state: state.has('Big Key (Ganons Tower)', player)) @@ -483,7 +572,8 @@ def global_rules(world, player): set_rule(world.get_entrance('Ganons Tower Big Key Door', player), lambda state: state.has('Big Key (Ganons Tower)', player) and can_shoot_arrows(state, player)) set_rule(world.get_entrance('Ganons Tower Torch Rooms', player), - lambda state: has_fire_source(state, player) and state.multiworld.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state)) + lambda state: can_kill_most_things(state, player, 8) and has_fire_source(state, player) and state.multiworld.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state)) + set_rule(world.get_location('Ganons Tower - Mini Helmasaur Key Drop', player), lambda state: can_kill_most_things(state, player, 1)) set_rule(world.get_location('Ganons Tower - Pre-Moldorm Chest', player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 7)) set_rule(world.get_entrance('Ganons Tower Moldorm Door', player), @@ -493,9 +583,9 @@ def global_rules(world, player): set_defeat_dungeon_boss_rule(world.get_location('Agahnim 2', player)) ganon = world.get_location('Ganon', player) set_rule(ganon, lambda state: GanonDefeatRule(state, player)) - if world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']: + if world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']: add_rule(ganon, lambda state: has_triforce_pieces(state, player)) - elif world.goal[player] == 'ganonpedestal': + elif world.goal[player] == 'ganon_pedestal': add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player)) else: add_rule(ganon, lambda state: has_crystals(state, state.multiworld.crystals_needed_for_ganon[player], player)) @@ -507,6 +597,12 @@ def global_rules(world, player): def default_rules(world, player): """Default world rules when world state is not inverted.""" # overworld requirements + + set_rule(world.get_entrance('Light World Bomb Hut', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_entrance('Ice Rod Cave', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has('Pegasus Boots', player)) set_rule(world.get_entrance('Kings Grave Outer Rocks', player), lambda state: can_lift_heavy_rocks(state, player)) set_rule(world.get_entrance('Kings Grave Inner Rocks', player), lambda state: can_lift_heavy_rocks(state, player)) @@ -562,12 +658,12 @@ def default_rules(world, player): set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: (state.has('Moon Pearl', player) and state.has('Flippers', player) or state.has('Magic Mirror', player))) # Overworld Bunny Revival set_rule(world.get_location('Bombos Tablet', player), lambda state: can_retrieve_tablet(state, player)) set_rule(world.get_entrance('Dark Lake Hylia Drop (South)', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) # ToDo any fake flipper set up? - set_rule(world.get_entrance('Dark Lake Hylia Ledge Fairy', player), lambda state: state.has('Moon Pearl', player)) # bomb required + set_rule(world.get_entrance('Dark Lake Hylia Ledge Fairy', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player)) set_rule(world.get_entrance('Dark Lake Hylia Ledge Spike Cave', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Village of Outcasts Heavy Rock', player), lambda state: state.has('Moon Pearl', player) and can_lift_heavy_rocks(state, player)) - set_rule(world.get_entrance('Hype Cave', player), lambda state: state.has('Moon Pearl', player)) # bomb required - set_rule(world.get_entrance('Brewery', player), lambda state: state.has('Moon Pearl', player)) # bomb required + set_rule(world.get_entrance('Hype Cave', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player)) + set_rule(world.get_entrance('Brewery', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player)) set_rule(world.get_entrance('Thieves Town', player), lambda state: state.has('Moon Pearl', player)) # bunny cannot pull set_rule(world.get_entrance('Skull Woods First Section Hole (North)', player), lambda state: state.has('Moon Pearl', player)) # bunny cannot lift bush set_rule(world.get_entrance('Skull Woods Second Section Hole', player), lambda state: state.has('Moon Pearl', player)) # bunny cannot lift bush @@ -621,9 +717,9 @@ def inverted_rules(world, player): # overworld requirements set_rule(world.get_location('Maze Race', player), lambda state: state.has('Moon Pearl', player)) - set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: state.has('Moon Pearl', player)) - set_rule(world.get_entrance('Ice Rod Cave', player), lambda state: state.has('Moon Pearl', player)) - set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: state.has('Moon Pearl', player)) + set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player)) + set_rule(world.get_entrance('Ice Rod Cave', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player)) + set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player)) set_rule(world.get_entrance('Potion Shop Pier', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Light World Pier', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has('Pegasus Boots', player) and state.has('Moon Pearl', player)) @@ -669,7 +765,7 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Bush Covered Lawn Outer Bushes', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Bomb Hut Inner Bushes', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Bomb Hut Outer Bushes', player), lambda state: state.has('Moon Pearl', player)) - set_rule(world.get_entrance('Light World Bomb Hut', player), lambda state: state.has('Moon Pearl', player)) # need bomb + set_rule(world.get_entrance('Light World Bomb Hut', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player)) set_rule(world.get_entrance('North Fairy Cave Drop', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Lost Woods Hideout Drop', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_location('Potion Shop', player), lambda state: state.has('Mushroom', player) and (state.can_reach('Potion Shop Area', 'Region', player))) # new inverted region, need pearl for bushes or access to potion shop door/waterfall fairy @@ -715,6 +811,11 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Bumper Cave Exit (Top)', player), lambda state: state.has('Cape', player)) set_rule(world.get_entrance('Bumper Cave Exit (Bottom)', player), lambda state: state.has('Cape', player) or state.has('Hookshot', player)) + set_rule(world.get_entrance('Hype Cave', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_entrance('Brewery', player), lambda state: can_use_bombs(state, player)) + set_rule(world.get_entrance('Dark Lake Hylia Ledge Fairy', player), lambda state: can_use_bombs(state, player)) + + set_rule(world.get_entrance('Skull Woods Final Section', player), lambda state: state.has('Fire Rod', player)) set_rule(world.get_entrance('Misery Mire', player), lambda state: has_sword(state, player) and has_misery_mire_medallion(state, player)) # sword required to cast magic (!) @@ -900,20 +1001,25 @@ def add_conditional_lamps(world, player): def open_rules(world, player): + + set_rule(world.get_location('Hyrule Castle - Map Guard Key Drop', player), + lambda state: can_kill_most_things(state, player, 1)) + def basement_key_rule(state): if location_item_name(state, 'Sewers - Key Rat Key Drop', player) == ("Small Key (Hyrule Castle)", player): return state._lttp_has_key("Small Key (Hyrule Castle)", player, 2) else: return state._lttp_has_key("Small Key (Hyrule Castle)", player, 3) - set_rule(world.get_location('Hyrule Castle - Boomerang Guard Key Drop', player), basement_key_rule) + set_rule(world.get_location('Hyrule Castle - Boomerang Guard Key Drop', player), + lambda state: basement_key_rule(state) and can_kill_most_things(state, player, 2)) set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), basement_key_rule) set_rule(world.get_location('Sewers - Key Rat Key Drop', player), - lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 3)) + lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 3) and can_kill_most_things(state, player, 1)) set_rule(world.get_location('Hyrule Castle - Big Key Drop', player), - lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4)) + lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4) and can_kill_most_things(state, player, 1)) set_rule(world.get_location('Hyrule Castle - Zelda\'s Chest', player), lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4) and state.has('Big Key (Hyrule Castle)', player)) @@ -924,6 +1030,7 @@ def swordless_rules(world, player): set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 3) and state.has('Fire Rod', player)) # no curtain set_rule(world.get_location('Ice Palace - Jelly Key Drop', player), lambda state: state.has('Fire Rod', player) or state.has('Bombos', player)) + set_rule(world.get_location('Ice Palace - Compass Chest', player), lambda state: (state.has('Fire Rod', player) or state.has('Bombos', player)) and state._lttp_has_key('Small Key (Ice Palace)', player)) set_rule(world.get_entrance('Ice Palace (Second Section)', player), lambda state: (state.has('Fire Rod', player) or state.has('Bombos', player)) and state._lttp_has_key('Small Key (Ice Palace)', player)) set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has('Hammer', player)) # need to damage ganon to get tiles to drop @@ -954,7 +1061,7 @@ def standard_rules(world, player): set_rule(world.get_entrance('Links House S&Q', player), lambda state: state.can_reach('Sanctuary', 'Region', player)) set_rule(world.get_entrance('Sanctuary S&Q', player), lambda state: state.can_reach('Sanctuary', 'Region', player)) - if world.smallkey_shuffle[player] != smallkey_shuffle.option_universal: + if world.small_key_shuffle[player] != small_key_shuffle.option_universal: set_rule(world.get_location('Hyrule Castle - Boomerang Guard Key Drop', player), lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 1)) set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), @@ -1062,15 +1169,15 @@ def set_trock_key_rules(world, player): return 6 # If TR is only accessible from the middle, the big key must be further restricted to prevent softlock potential - if not can_reach_front and not world.smallkey_shuffle[player]: + if not can_reach_front and not world.small_key_shuffle[player]: # Must not go in the Big Key Chest - only 1 other chest available and 2+ keys required for all other chests forbid_item(world.get_location('Turtle Rock - Big Key Chest', player), 'Big Key (Turtle Rock)', player) if not can_reach_big_chest: # Must not go in the Chain Chomps chest - only 2 other chests available and 3+ keys required for all other chests forbid_item(world.get_location('Turtle Rock - Chain Chomps', player), 'Big Key (Turtle Rock)', player) forbid_item(world.get_location('Turtle Rock - Pokey 2 Key Drop', player), 'Big Key (Turtle Rock)', player) - if world.accessibility[player] == 'locations' and world.goal[player] != 'icerodhunt': - if world.bigkey_shuffle[player] and can_reach_big_chest: + if world.accessibility[player] == 'locations': + if world.big_key_shuffle[player] and can_reach_big_chest: # Must not go in the dungeon - all 3 available chests (Chomps, Big Chest, Crystaroller) must be keys to access laser bridge, and the big key is required first for location in ['Turtle Rock - Chain Chomps', 'Turtle Rock - Compass Chest', 'Turtle Rock - Pokey 1 Key Drop', 'Turtle Rock - Pokey 2 Key Drop', @@ -1515,8 +1622,10 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool): # regions for the exits of multi-entrance caves/drops that bunny cannot pass # Note spiral cave and two brothers house are passable in superbunny state for glitch logic with extra requirements. - bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', - 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)'] + bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', + 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', + 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', + 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)'] bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', @@ -1549,7 +1658,7 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool): def get_rule_to_add(region, location = None, connecting_entrance = None): # In OWG, a location can potentially be superbunny-mirror accessible or # bunny revival accessible. - if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic']: + if world.glitches_required[player] in ['minor_glitches', 'overworld_glitches', 'hybrid_major_glitches', 'no_logic']: if region.name == 'Swamp Palace (Entrance)': # Need to 0hp revive - not in logic return lambda state: state.has('Moon Pearl', player) if region.name == 'Tower of Hera (Bottom)': # Need to hit the crystal switch @@ -1589,7 +1698,7 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool): seen.add(new_region) if not is_link(new_region): # For glitch rulesets, establish superbunny and revival rules. - if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic'] and entrance.name not in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): + if world.glitches_required[player] in ['minor_glitches', 'overworld_glitches', 'hybrid_major_glitches', 'no_logic'] and entrance.name not in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions(): possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has('Magic Mirror', player) and has_sword(state, player)) elif (region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions() @@ -1626,7 +1735,7 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool): # Add requirements for all locations that are actually in the dark world, except those available to the bunny, including dungeon revival for entrance in world.get_entrances(player): if is_bunny(entrance.connected_region): - if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic'] : + if world.glitches_required[player] in ['minor_glitches', 'overworld_glitches', 'hybrid_major_glitches', 'no_logic'] : if entrance.connected_region.type == LTTPRegionType.Dungeon: if entrance.parent_region.type != LTTPRegionType.Dungeon and entrance.connected_region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): add_rule(entrance, get_rule_to_add(entrance.connected_region, None, entrance)) @@ -1634,7 +1743,7 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool): if entrance.connected_region.name == 'Turtle Rock (Entrance)': add_rule(world.get_entrance('Turtle Rock Entrance Gap', player), get_rule_to_add(entrance.connected_region, None, entrance)) for location in entrance.connected_region.locations: - if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic'] and entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances(): + if world.glitches_required[player] in ['minor_glitches', 'overworld_glitches', 'hybrid_major_glitches', 'no_logic'] and entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances(): continue if location.name in bunny_accessible_locations: continue diff --git a/worlds/alttp/Shops.py b/worlds/alttp/Shops.py index c0f2e223..64a385a1 100644 --- a/worlds/alttp/Shops.py +++ b/worlds/alttp/Shops.py @@ -5,11 +5,14 @@ import logging from Utils import int16_as_bytes +from worlds.generic.Rules import add_rule + +from BaseClasses import CollectionState from .SubClasses import ALttPLocation from .EntranceShuffle import door_addresses -from .Items import item_name_groups, item_table, ItemFactory, trap_replaceable, GetBeemizerItem -from .Options import smallkey_shuffle - +from .Items import item_name_groups +from .Options import small_key_shuffle, RandomizeShopInventories +from .StateHelpers import has_hearts, can_use_bombs, can_hold_arrows logger = logging.getLogger("Shops") @@ -36,9 +39,9 @@ class ShopPriceType(IntEnum): Item = 10 -class Shop(): +class Shop: slots: int = 3 # slot count is not dynamic in asm, however inventory can have None as empty slots - blacklist: Set[str] = set() # items that don't work, todo: actually check against this + blacklist: Set[str] = set() # items that don't work type = ShopType.Shop slot_names: Dict[int, str] = { 0: " Left", @@ -103,7 +106,7 @@ class Shop(): self.inventory = [None] * self.slots def add_inventory(self, slot: int, item: str, price: int, max: int = 0, - replacement: Optional[str] = None, replacement_price: int = 0, create_location: bool = False, + replacement: Optional[str] = None, replacement_price: int = 0, player: int = 0, price_type: int = ShopPriceType.Rupees, replacement_price_type: int = ShopPriceType.Rupees): self.inventory[slot] = { @@ -114,33 +117,23 @@ class Shop(): 'replacement': replacement, 'replacement_price': replacement_price, 'replacement_price_type': replacement_price_type, - 'create_location': create_location, 'player': player } def push_inventory(self, slot: int, item: str, price: int, max: int = 1, player: int = 0, price_type: int = ShopPriceType.Rupees): - if not self.inventory[slot]: - raise ValueError("Inventory can't be pushed back if it doesn't exist") - - if not self.can_push_inventory(slot): - logging.warning(f'Warning, there is already an item pushed into this slot.') self.inventory[slot] = { 'item': item, 'price': price, 'price_type': price_type, 'max': max, - 'replacement': self.inventory[slot]["item"], - 'replacement_price': self.inventory[slot]["price"], - 'replacement_price_type': self.inventory[slot]["price_type"], - 'create_location': self.inventory[slot]["create_location"], + 'replacement': self.inventory[slot]["item"] if self.inventory[slot] else None, + 'replacement_price': self.inventory[slot]["price"] if self.inventory[slot] else 0, + 'replacement_price_type': self.inventory[slot]["price_type"] if self.inventory[slot] else ShopPriceType.Rupees, 'player': player } - def can_push_inventory(self, slot: int): - return self.inventory[slot] and not self.inventory[slot]["replacement"] - class TakeAny(Shop): type = ShopType.TakeAny @@ -156,6 +149,10 @@ class UpgradeShop(Shop): # Potions break due to VRAM flags set in UpgradeShop. # Didn't check for more things breaking as not much else can be shuffled here currently blacklist = item_name_groups["Potions"] + slot_names: Dict[int, str] = { + 0: " Left", + 1: " Right" + } shop_class_mapping = {ShopType.UpgradeShop: UpgradeShop, @@ -163,191 +160,84 @@ shop_class_mapping = {ShopType.UpgradeShop: UpgradeShop, ShopType.TakeAny: TakeAny} -def FillDisabledShopSlots(world): - shop_slots: Set[ALttPLocation] = {location for shop_locations in (shop.region.locations for shop in world.shops) - for location in shop_locations - if location.shop_slot is not None and location.shop_slot_disabled} +def push_shop_inventories(multiworld): + shop_slots = [location for shop_locations in (shop.region.locations for shop in multiworld.shops if shop.type + != ShopType.TakeAny) for location in shop_locations if location.shop_slot is not None] + for location in shop_slots: - location.shop_slot_disabled = True - shop: Shop = location.parent_region.shop - location.item = ItemFactory(shop.inventory[location.shop_slot]['item'], location.player) - location.item_rule = lambda item: item.name == location.item.name and item.player == location.player - location.locked = True + item_name = location.item.name + # Retro Bow arrows will already have been pushed + if (not multiworld.retro_bow[location.player]) or ((item_name, location.item.player) + != ("Single Arrow", location.player)): + location.shop.push_inventory(location.shop_slot, item_name, location.shop_price, + 1, location.item.player if location.item.player != location.player else 0, + location.shop_price_type) + location.shop_price = location.shop.inventory[location.shop_slot]["price"] = min(location.shop_price, + get_price(multiworld, location.shop.inventory[location.shop_slot], location.player, + location.shop_price_type)[1]) -def ShopSlotFill(multiworld): - shop_slots: Set[ALttPLocation] = {location for shop_locations in - (shop.region.locations for shop in multiworld.shops if shop.type != ShopType.TakeAny) - for location in shop_locations if location.shop_slot is not None} - - removed = set() - for location in shop_slots: - shop: Shop = location.parent_region.shop - if not shop.can_push_inventory(location.shop_slot) or location.shop_slot_disabled: - location.shop_slot_disabled = True - removed.add(location) - - if removed: - shop_slots -= removed - - if shop_slots: - logger.info("Filling LttP Shop Slots") - del shop_slots - - from Fill import swap_location_item - # TODO: allow each game to register a blacklist to be used here? - blacklist_words = {"Rupee"} - blacklist_words = {item_name for item_name in item_table if any( - blacklist_word in item_name for blacklist_word in blacklist_words)} - blacklist_words.add("Bee") - - locations_per_sphere = [sorted(sphere, key=lambda location: (location.name, location.player)) - for sphere in multiworld.get_spheres()] - - # currently special care needs to be taken so that Shop.region.locations.item is identical to Shop.inventory - # Potentially create Locations as needed and make inventory the only source, to prevent divergence - cumu_weights = [] - shops_per_sphere = [] - candidates_per_sphere = [] - - # sort spheres into piles of valid candidates and shops - for sphere in locations_per_sphere: - current_shops_slots = [] - current_candidates = [] - shops_per_sphere.append(current_shops_slots) - candidates_per_sphere.append(current_candidates) - for location in sphere: - if isinstance(location, ALttPLocation) and location.shop_slot is not None: - if not location.shop_slot_disabled: - current_shops_slots.append(location) - elif not location.locked and location.item.name not in blacklist_words: - current_candidates.append(location) - if cumu_weights: - x = cumu_weights[-1] - else: - x = 0 - cumu_weights.append(len(current_candidates) + x) - - multiworld.random.shuffle(current_candidates) - - del locations_per_sphere - - for i, current_shop_slots in enumerate(shops_per_sphere): - if current_shop_slots: - # getting all candidates and shuffling them feels cpu expensive, there may be a better method - candidates = [(location, i) for i, candidates in enumerate(candidates_per_sphere[i:], start=i) - for location in candidates] - multiworld.random.shuffle(candidates) - for location in current_shop_slots: - shop: Shop = location.parent_region.shop - for index, (c, swapping_sphere_id) in enumerate(candidates): # chosen item locations - if c.item_rule(location.item) and location.item_rule(c.item): - swap_location_item(c, location, check_locked=False) - logger.debug(f"Swapping {c} into {location}:: {location.item}") - # remove candidate - candidates_per_sphere[swapping_sphere_id].remove(c) - candidates.pop(index) - break - - else: - # This *should* never happen. But let's fail safely just in case. - logger.warning("Ran out of ShopShuffle Item candidate locations.") - location.shop_slot_disabled = True - continue - - item_name = location.item.name - if location.item.game != "A Link to the Past": - if location.item.advancement: - price = multiworld.random.randrange(8, 56) - elif location.item.useful: - price = multiworld.random.randrange(4, 28) - else: - price = multiworld.random.randrange(2, 14) - elif any(x in item_name for x in - ['Compass', 'Map', 'Single Bomb', 'Single Arrow', 'Piece of Heart']): - price = multiworld.random.randrange(1, 7) - elif any(x in item_name for x in ['Arrow', 'Bomb', 'Clock']): - price = multiworld.random.randrange(2, 14) - elif any(x in item_name for x in ['Small Key', 'Heart']): - price = multiworld.random.randrange(4, 28) - else: - price = multiworld.random.randrange(8, 56) - - shop.push_inventory(location.shop_slot, item_name, - min(int(price * multiworld.shop_price_modifier[location.player] / 100) * 5, 9999), 1, - location.item.player if location.item.player != location.player else 0) - if 'P' in multiworld.shop_shuffle[location.player]: - price_to_funny_price(multiworld, shop.inventory[location.shop_slot], location.player) - - FillDisabledShopSlots(multiworld) - - -def create_shops(world, player: int): - option = world.shop_shuffle[player] +def create_shops(multiworld, player: int): player_shop_table = shop_table.copy() - if "w" in option: + if multiworld.include_witch_hut[player]: player_shop_table["Potion Shop"] = player_shop_table["Potion Shop"]._replace(locked=False) dynamic_shop_slots = total_dynamic_shop_slots + 3 else: dynamic_shop_slots = total_dynamic_shop_slots + if multiworld.shuffle_capacity_upgrades[player]: + player_shop_table["Capacity Upgrade"] = player_shop_table["Capacity Upgrade"]._replace(locked=False) - num_slots = min(dynamic_shop_slots, world.shop_item_slots[player]) + num_slots = min(dynamic_shop_slots, multiworld.shop_item_slots[player]) single_purchase_slots: List[bool] = [True] * num_slots + [False] * (dynamic_shop_slots - num_slots) - world.random.shuffle(single_purchase_slots) + multiworld.random.shuffle(single_purchase_slots) - if 'g' in option or 'f' in option: + if multiworld.randomize_shop_inventories[player]: default_shop_table = [i for l in [shop_generation_types[x] for x in ['arrows', 'bombs', 'potions', 'shields', 'bottle'] if - not world.retro_bow[player] or x != 'arrows'] for i in l] - new_basic_shop = world.random.sample(default_shop_table, k=3) - new_dark_shop = world.random.sample(default_shop_table, k=3) + not multiworld.retro_bow[player] or x != 'arrows'] for i in l] + new_basic_shop = multiworld.random.sample(default_shop_table, k=3) + new_dark_shop = multiworld.random.sample(default_shop_table, k=3) for name, shop in player_shop_table.items(): typ, shop_id, keeper, custom, locked, items, sram_offset = shop if not locked: - new_items = world.random.sample(default_shop_table, k=3) - if 'f' not in option: + new_items = multiworld.random.sample(default_shop_table, k=len(items)) + if multiworld.randomize_shop_inventories[player] == RandomizeShopInventories.option_randomize_by_shop_type: if items == _basic_shop_defaults: new_items = new_basic_shop elif items == _dark_world_shop_defaults: new_items = new_dark_shop - keeper = world.random.choice([0xA0, 0xC1, 0xFF]) + keeper = multiworld.random.choice([0xA0, 0xC1, 0xFF]) player_shop_table[name] = ShopData(typ, shop_id, keeper, custom, locked, new_items, sram_offset) - if world.mode[player] == "inverted": + if multiworld.mode[player] == "inverted": # make sure that blue potion is available in inverted, special case locked = None; lock when done. player_shop_table["Dark Lake Hylia Shop"] = \ player_shop_table["Dark Lake Hylia Shop"]._replace(items=_inverted_hylia_shop_defaults, locked=None) - chance_100 = int(world.retro_bow[player]) * 0.25 + int( - world.smallkey_shuffle[player] == smallkey_shuffle.option_universal) * 0.5 for region_name, (room_id, type, shopkeeper, custom, locked, inventory, sram_offset) in player_shop_table.items(): - region = world.get_region(region_name, player) + region = multiworld.get_region(region_name, player) shop: Shop = shop_class_mapping[type](region, room_id, shopkeeper, custom, locked, sram_offset) # special case: allow shop slots, but do not allow overwriting of base inventory behind them if locked is None: shop.locked = True region.shop = shop - world.shops.append(shop) + multiworld.shops.append(shop) for index, item in enumerate(inventory): shop.add_inventory(index, *item) - if not locked and num_slots: + if not locked and (num_slots or type == ShopType.UpgradeShop): slot_name = f"{region.name}{shop.slot_names[index]}" loc = ALttPLocation(player, slot_name, address=shop_table_by_location[slot_name], parent=region, hint_text="for sale") + loc.shop_price_type, loc.shop_price = get_price(multiworld, None, player) + loc.item_rule = lambda item, spot=loc: not any(i for i in price_blacklist[spot.shop_price_type] if i in item.name) + add_rule(loc, lambda state, spot=loc: shop_price_rules(state, player, spot)) + loc.shop = shop loc.shop_slot = index - loc.locked = True - if single_purchase_slots.pop(): - if world.goal[player] != 'icerodhunt': - if world.random.random() < chance_100: - additional_item = 'Rupees (100)' - else: - additional_item = 'Rupees (50)' - else: - additional_item = GetBeemizerItem(world, player, 'Nothing') - loc.item = ItemFactory(additional_item, player) - else: - loc.item = ItemFactory(GetBeemizerItem(world, player, 'Nothing'), player) + if ((not (multiworld.shuffle_capacity_upgrades[player] and type == ShopType.UpgradeShop)) + and not single_purchase_slots.pop()): loc.shop_slot_disabled = True - shop.region.locations.append(loc) + loc.locked = True + else: + shop.region.locations.append(loc) class ShopData(NamedTuple): @@ -387,9 +277,10 @@ total_dynamic_shop_slots = sum(3 for shopname, data in shop_table.items() if not SHOP_ID_START = 0x400000 shop_table_by_location_id = dict(enumerate( - (f"{name}{Shop.slot_names[num]}" for name, shop_data in - sorted(shop_table.items(), key=lambda item: item[1].sram_offset) - for num in range(3)), start=SHOP_ID_START)) + (f"{name}{UpgradeShop.slot_names[num]}" if shop_data.type == ShopType.UpgradeShop else + f"{name}{Shop.slot_names[num]}" for name, shop_data in sorted(shop_table.items(), + key=lambda item: item[1].sram_offset) + for num in range(2 if shop_data.type == ShopType.UpgradeShop else 3)), start=SHOP_ID_START)) shop_table_by_location_id[(SHOP_ID_START + total_shop_slots)] = "Old Man Sword Cave" shop_table_by_location_id[(SHOP_ID_START + total_shop_slots + 1)] = "Take-Any #1" @@ -409,114 +300,54 @@ shop_generation_types = { } -def set_up_shops(world, player: int): +def set_up_shops(multiworld, player: int): # TODO: move hard+ mode changes for shields here, utilizing the new shops - if world.retro_bow[player]: - rss = world.get_region('Red Shield Shop', player).shop + if multiworld.retro_bow[player]: + rss = multiworld.get_region('Red Shield Shop', player).shop replacement_items = [['Red Potion', 150], ['Green Potion', 75], ['Blue Potion', 200], ['Bombs (10)', 50], ['Blue Shield', 50], ['Small Heart', 10]] # Can't just replace the single arrow with 10 arrows as retro doesn't need them. - if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal: + if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal: replacement_items.append(['Small Key (Universal)', 100]) - replacement_item = world.random.choice(replacement_items) + replacement_item = multiworld.random.choice(replacement_items) rss.add_inventory(2, 'Single Arrow', 80, 1, replacement_item[0], replacement_item[1]) rss.locked = True - if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal or world.retro_bow[player]: - for shop in world.random.sample([s for s in world.shops if - s.custom and not s.locked and s.type == ShopType.Shop and s.region.player == player], - 5): + if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal or multiworld.retro_bow[player]: + for shop in multiworld.random.sample([s for s in multiworld.shops if + s.custom and not s.locked and s.type == ShopType.Shop + and s.region.player == player], 5): shop.locked = True slots = [0, 1, 2] - world.random.shuffle(slots) + multiworld.random.shuffle(slots) slots = iter(slots) - if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal: + if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal: shop.add_inventory(next(slots), 'Small Key (Universal)', 100) - if world.retro_bow[player]: + if multiworld.retro_bow[player]: shop.push_inventory(next(slots), 'Single Arrow', 80) - -def shuffle_shops(world, items, player: int): - option = world.shop_shuffle[player] - if 'u' in option: - progressive = world.progressive[player] - progressive = world.random.choice([True, False]) if progressive == 'grouped_random' else progressive == 'on' - progressive &= world.goal == 'icerodhunt' - new_items = ["Bomb Upgrade (+5)"] * 6 - new_items.append("Bomb Upgrade (+5)" if progressive else "Bomb Upgrade (+10)") - - if not world.retro_bow[player]: - new_items += ["Arrow Upgrade (+5)"] * 6 - new_items.append("Arrow Upgrade (+5)" if progressive else "Arrow Upgrade (+10)") - - world.random.shuffle(new_items) # Decide what gets tossed randomly if it can't insert everything. - - capacityshop: Optional[Shop] = None - for shop in world.shops: + if multiworld.shuffle_capacity_upgrades[player]: + for shop in multiworld.shops: if shop.type == ShopType.UpgradeShop and shop.region.player == player and \ shop.region.name == "Capacity Upgrade": shop.clear_inventory() - capacityshop = shop - if world.goal[player] != 'icerodhunt': - for i, item in enumerate(items): - if item.name in trap_replaceable: - items[i] = ItemFactory(new_items.pop(), player) - if not new_items: - break - else: - logging.warning( - f"Not all upgrades put into Player{player}' item pool. Putting remaining items in Capacity Upgrade shop instead.") - bombupgrades = sum(1 for item in new_items if 'Bomb Upgrade' in item) - arrowupgrades = sum(1 for item in new_items if 'Arrow Upgrade' in item) - slots = iter(range(2)) - if bombupgrades: - capacityshop.add_inventory(next(slots), 'Bomb Upgrade (+5)', 100, bombupgrades) - if arrowupgrades: - capacityshop.add_inventory(next(slots), 'Arrow Upgrade (+5)', 100, arrowupgrades) - else: - for item in new_items: - world.push_precollected(ItemFactory(item, player)) - - if any(setting in option for setting in 'ipP'): + if (multiworld.shuffle_shop_inventories[player] or multiworld.randomize_shop_prices[player] + or multiworld.randomize_cost_types[player]): shops = [] - upgrade_shops = [] total_inventory = [] - for shop in world.shops: + for shop in multiworld.shops: if shop.region.player == player: - if shop.type == ShopType.UpgradeShop: - upgrade_shops.append(shop) - elif shop.type == ShopType.Shop and not shop.locked: + if shop.type == ShopType.Shop and not shop.locked: shops.append(shop) total_inventory.extend(shop.inventory) - if 'p' in option: - def price_adjust(price: int) -> int: - # it is important that a base price of 0 always returns 0 as new price! - adjust = 2 if price < 100 else 5 - return int((price / adjust) * (0.5 + world.random.random() * 1.5)) * adjust + for item in total_inventory: + item["price_type"], item["price"] = get_price(multiworld, item, player) - def adjust_item(item): - if item: - item["price"] = price_adjust(item["price"]) - item['replacement_price'] = price_adjust(item["price"]) - - for item in total_inventory: - adjust_item(item) - for shop in upgrade_shops: - for item in shop.inventory: - adjust_item(item) - - if 'P' in option: - for item in total_inventory: - price_to_funny_price(world, item, player) - # Don't apply to upgrade shops - # Upgrade shop is only one place, and will generally be too easy to - # replenish hearts and bombs - - if 'i' in option: - world.random.shuffle(total_inventory) + if multiworld.shuffle_shop_inventories[player]: + multiworld.random.shuffle(total_inventory) i = 0 for shop in shops: @@ -539,16 +370,18 @@ price_blacklist = { } price_chart = { - ShopPriceType.Rupees: lambda p: p, - ShopPriceType.Hearts: lambda p: min(5, p // 5) * 8, # Each heart is 0x8 in memory, Max of 5 hearts (20 total??) - ShopPriceType.Magic: lambda p: min(15, p // 5) * 8, # Each pip is 0x8 in memory, Max of 15 pips (16 total...) - ShopPriceType.Bombs: lambda p: max(1, min(10, p // 5)), # 10 Bombs max - ShopPriceType.Arrows: lambda p: max(1, min(30, p // 5)), # 30 Arrows Max - ShopPriceType.HeartContainer: lambda p: 0x8, - ShopPriceType.BombUpgrade: lambda p: 0x1, - ShopPriceType.ArrowUpgrade: lambda p: 0x1, - ShopPriceType.Keys: lambda p: min(3, (p // 100) + 1), # Max of 3 keys for a price - ShopPriceType.Potion: lambda p: (p // 5) % 5, + ShopPriceType.Rupees: lambda p, d: p, + # Each heart is 0x8 in memory, Max of 19 hearts on easy/normal, 9 on hard, 7 on expert + ShopPriceType.Hearts: lambda p, d: max(8, min([19, 19, 9, 7][d], p // 14) * 8), + # Each pip is 0x8 in memory, Max of 15 pips (16 total) + ShopPriceType.Magic: lambda p, d: max(8, min(15, p // 18) * 8), + ShopPriceType.Bombs: lambda p, d: max(1, min(50, p // 5)), # 50 Bombs max + ShopPriceType.Arrows: lambda p, d: max(1, min(70, p // 4)), # 70 Arrows Max + ShopPriceType.HeartContainer: lambda p, d: 0x8, + ShopPriceType.BombUpgrade: lambda p, d: 0x1, + ShopPriceType.ArrowUpgrade: lambda p, d: 0x1, + ShopPriceType.Keys: lambda p, d: max(1, min(3, (p // 90) + 1)), # Max of 3 keys for a price + ShopPriceType.Potion: lambda p, d: (p // 5) % 5, } price_type_display_name = { @@ -557,6 +390,8 @@ price_type_display_name = { ShopPriceType.Bombs: "Bombs", ShopPriceType.Arrows: "Arrows", ShopPriceType.Keys: "Keys", + ShopPriceType.Item: "Item", + ShopPriceType.Magic: "Magic" } # price division @@ -565,57 +400,74 @@ price_rate_display = { ShopPriceType.Magic: 8, } -# prices with no? logic requirements -simple_price_types = [ - ShopPriceType.Rupees, - ShopPriceType.Hearts, - ShopPriceType.Bombs, - ShopPriceType.Arrows, - ShopPriceType.Keys -] + +def get_price_modifier(item): + if item.game == "A Link to the Past": + if any(x in item.name for x in + ['Compass', 'Map', 'Single Bomb', 'Single Arrow', 'Piece of Heart']): + return 0.125 + elif any(x in item.name for x in + ['Arrow', 'Bomb', 'Clock']) and item.name != "Bombos" and "(50)" not in item.name: + return 0.25 + elif any(x in item.name for x in ['Small Key', 'Heart']): + return 0.5 + else: + return 1 + if item.advancement: + return 1 + elif item.useful: + return 0.5 + else: + return 0.25 -def price_to_funny_price(world, item: dict, player: int): - """ - Converts a raw Rupee price into a special price type - """ +def get_price(multiworld, item, player: int, price_type=None): + """Converts a raw Rupee price into a special price type""" + + if price_type: + price_types = [price_type] + else: + price_types = [ShopPriceType.Rupees] # included as a chance to not change price + if multiworld.randomize_cost_types[player]: + price_types += [ + ShopPriceType.Hearts, + ShopPriceType.Bombs, + ShopPriceType.Magic, + ] + if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal: + if item and item["item"] == "Small Key (Universal)": + price_types = [ShopPriceType.Rupees, ShopPriceType.Magic] # no logical requirements for repeatable keys + else: + price_types.append(ShopPriceType.Keys) + if multiworld.retro_bow[player]: + if item and item["item"] == "Single Arrow": + price_types = [ShopPriceType.Rupees, ShopPriceType.Magic] # no logical requirements for arrows + else: + price_types.append(ShopPriceType.Arrows) + diff = multiworld.item_pool[player].value if item: - price_types = [ - ShopPriceType.Rupees, # included as a chance to not change price type - ShopPriceType.Hearts, - ShopPriceType.Bombs, - ] - # don't pay in universal keys to get access to universal keys - if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal \ - and not "Small Key (Universal)" == item['replacement']: - price_types.append(ShopPriceType.Keys) - if not world.retro_bow[player]: - price_types.append(ShopPriceType.Arrows) - world.random.shuffle(price_types) + # This is for a shop's regular inventory, the item is already determined, and we will decide the price here + price = item["price"] + if multiworld.randomize_shop_prices[player]: + adjust = 2 if price < 100 else 5 + price = int((price / adjust) * (0.5 + multiworld.random.random() * 1.5)) * adjust + multiworld.random.shuffle(price_types) for p_type in price_types: - # Ignore rupee prices - if p_type == ShopPriceType.Rupees: - return if any(x in item['item'] for x in price_blacklist[p_type]): continue - else: - item['price'] = min(price_chart[p_type](item['price']), 255) - item['price_type'] = p_type - break + return p_type, price_chart[p_type](price, diff) + else: + # This is an AP location and the price will be adjusted after an item is shuffled into it + p_type = multiworld.random.choice(price_types) + return p_type, price_chart[p_type](min(int(multiworld.random.randint(8, 56) + * multiworld.shop_price_modifier[player] / 100) * 5, 9999), diff) -def create_dynamic_shop_locations(world, player): - for shop in world.shops: - if shop.region.player == player: - for i, item in enumerate(shop.inventory): - if item is None: - continue - if item['create_location']: - slot_name = f"{shop.region.name}{shop.slot_names[i]}" - loc = ALttPLocation(player, slot_name, - address=shop_table_by_location[slot_name], parent=shop.region) - loc.place_locked_item(ItemFactory(item['item'], player)) - if shop.type == ShopType.TakeAny: - loc.shop_slot_disabled = True - shop.region.locations.append(loc) - loc.shop_slot = i +def shop_price_rules(state: CollectionState, player: int, location: ALttPLocation): + if location.shop_price_type == ShopPriceType.Hearts: + return has_hearts(state, player, (location.shop_price / 8) + 1) + elif location.shop_price_type == ShopPriceType.Bombs: + return can_use_bombs(state, player, location.shop_price) + elif location.shop_price_type == ShopPriceType.Arrows: + return can_hold_arrows(state, player, location.shop_price) + return True diff --git a/worlds/alttp/StateHelpers.py b/worlds/alttp/StateHelpers.py index 38ce00ef..4ed1b1ca 100644 --- a/worlds/alttp/StateHelpers.py +++ b/worlds/alttp/StateHelpers.py @@ -10,7 +10,7 @@ def is_not_bunny(state: CollectionState, region: LTTPRegion, player: int) -> boo def can_bomb_clip(state: CollectionState, region: LTTPRegion, player: int) -> bool: - return is_not_bunny(state, region, player) and state.has('Pegasus Boots', player) + return can_use_bombs(state, player) and is_not_bunny(state, region, player) and state.has('Pegasus Boots', player) def can_buy_unlimited(state: CollectionState, item: str, player: int) -> bool: @@ -83,13 +83,47 @@ def can_extend_magic(state: CollectionState, player: int, smallmagic: int = 16, return basemagic >= smallmagic +def can_hold_arrows(state: CollectionState, player: int, quantity: int): + arrows = 30 + ((state.count("Arrow Upgrade (+5)", player) * 5) + (state.count("Arrow Upgrade (+10)", player) * 10) + + (state.count("Bomb Upgrade (50)", player) * 50)) + # Arrow Upgrade (+5) beyond the 6th gives +10 + arrows += max(0, ((state.count("Arrow Upgrade (+5)", player) - 6) * 10)) + return min(70, arrows) >= quantity + + +def can_use_bombs(state: CollectionState, player: int, quantity: int = 1) -> bool: + bombs = 0 if state.multiworld.bombless_start[player] else 10 + bombs += ((state.count("Bomb Upgrade (+5)", player) * 5) + (state.count("Bomb Upgrade (+10)", player) * 10) + + (state.count("Bomb Upgrade (50)", player) * 50)) + # Bomb Upgrade (+5) beyond the 6th gives +10 + bombs += max(0, ((state.count("Bomb Upgrade (+5)", player) - 6) * 10)) + if (not state.multiworld.shuffle_capacity_upgrades[player]) and state.has("Capacity Upgrade Shop", player): + bombs += 40 + return bombs >= min(quantity, 50) + + +def can_bomb_or_bonk(state: CollectionState, player: int) -> bool: + return state.has("Pegasus Boots", player) or can_use_bombs(state, player) + + def can_kill_most_things(state: CollectionState, player: int, enemies: int = 5) -> bool: - return (has_melee_weapon(state, player) - or state.has('Cane of Somaria', player) - or (state.has('Cane of Byrna', player) and (enemies < 6 or can_extend_magic(state, player))) - or can_shoot_arrows(state, player) - or state.has('Fire Rod', player) - or (state.has('Bombs (10)', player) and enemies < 6)) + if state.multiworld.enemy_shuffle[player]: + # I don't fully understand Enemizer's logic for placing enemies in spots where they need to be killable, if any. + # Just go with maximal requirements for now. + return (has_melee_weapon(state, player) + and state.has('Cane of Somaria', player) + and state.has('Cane of Byrna', player) and can_extend_magic(state, player) + and can_shoot_arrows(state, player) + and state.has('Fire Rod', player) + and can_use_bombs(state, player, enemies * 4)) + else: + return (has_melee_weapon(state, player) + or state.has('Cane of Somaria', player) + or (state.has('Cane of Byrna', player) and (enemies < 6 or can_extend_magic(state, player))) + or can_shoot_arrows(state, player) + or state.has('Fire Rod', player) + or (state.multiworld.enemy_health[player] in ("easy", "default") + and can_use_bombs(state, player, enemies * 4))) def can_get_good_bee(state: CollectionState, player: int) -> bool: @@ -159,4 +193,4 @@ def can_get_glitched_speed_dw(state: CollectionState, player: int) -> bool: rules = [state.has('Pegasus Boots', player), any([state.has('Hookshot', player), has_sword(state, player)])] if state.multiworld.mode[player] != 'inverted': rules.append(state.has('Moon Pearl', player)) - return all(rules) \ No newline at end of file + return all(rules) diff --git a/worlds/alttp/SubClasses.py b/worlds/alttp/SubClasses.py index 22eeebe1..769dcc19 100644 --- a/worlds/alttp/SubClasses.py +++ b/worlds/alttp/SubClasses.py @@ -14,9 +14,12 @@ class ALttPLocation(Location): crystal: bool player_address: Optional[int] _hint_text: Optional[str] + shop: None shop_slot: Optional[int] = None """If given as integer, shop_slot is the shop's inventory index.""" shop_slot_disabled: bool = False + shop_price = 0 + shop_price_type = None parent_region: "LTTPRegion" def __init__(self, player: int, name: str, address: Optional[int] = None, crystal: bool = False, diff --git a/worlds/alttp/UnderworldGlitchRules.py b/worlds/alttp/UnderworldGlitchRules.py index a6aefc74..497d5de4 100644 --- a/worlds/alttp/UnderworldGlitchRules.py +++ b/worlds/alttp/UnderworldGlitchRules.py @@ -42,7 +42,7 @@ def dungeon_reentry_rules(world, player, clip: Entrance, dungeon_region: str, du fix_fake_worlds = world.fix_fake_world[player] dungeon_entrance = [r for r in world.get_region(dungeon_region, player).entrances if r.name != clip.name][0] - if not fix_dungeon_exits: # vanilla, simple, restricted, dungeonssimple; should never have fake worlds fix + if not fix_dungeon_exits: # vanilla, simple, restricted, dungeons_simple; should never have fake worlds fix # Dungeons are only shuffled among themselves. We need to check SW, MM, and AT because they can't be reentered trivially. if dungeon_entrance.name == 'Skull Woods Final Section': set_rule(clip, lambda state: False) # entrance doesn't exist until you fire rod it from the other side @@ -52,12 +52,12 @@ def dungeon_reentry_rules(world, player, clip: Entrance, dungeon_region: str, du add_rule(clip, lambda state: state.has('Cape', player) or has_beam_sword(state, player) or state.has('Beat Agahnim 1', player)) # kill/bypass barrier # Then we set a restriction on exiting the dungeon, so you can't leave unless you got in normally. add_rule(world.get_entrance(dungeon_exit, player), lambda state: dungeon_entrance.can_reach(state)) - elif not fix_fake_worlds: # full, dungeonsfull; fixed dungeon exits, but no fake worlds fix + elif not fix_fake_worlds: # full, dungeons_full; fixed dungeon exits, but no fake worlds fix # Entry requires the entrance's requirements plus a fake pearl, but you don't gain logical access to the surrounding region. add_rule(clip, lambda state: dungeon_entrance.access_rule(fake_pearl_state(state, player))) # exiting restriction add_rule(world.get_entrance(dungeon_exit, player), lambda state: dungeon_entrance.can_reach(state)) - # Otherwise, the shuffle type is crossed, dungeonscrossed, or insanity; all of these do not need additional rules on where we can go, + # Otherwise, the shuffle type is crossed, dungeons_crossed, or insanity; all of these do not need additional rules on where we can go, # since the clip links directly to the exterior region. @@ -93,7 +93,7 @@ def underworld_glitches_rules(world, player): # We need to be able to s+q to old man, then go to either Mire or Hera at either Hera or GT. # First we require a certain type of entrance shuffle, then build the rule from its pieces. if not world.swamp_patch_required[player]: - if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']: + if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']: rule_map = { 'Misery Mire (Entrance)': (lambda state: True), 'Tower of Hera (Bottom)': (lambda state: state.can_reach('Tower of Hera Big Key Door', 'Entrance', player)) diff --git a/worlds/alttp/__init__.py b/worlds/alttp/__init__.py index 3f380d00..e1216010 100644 --- a/worlds/alttp/__init__.py +++ b/worlds/alttp/__init__.py @@ -13,14 +13,14 @@ from .EntranceShuffle import link_entrances, link_inverted_entrances, plando_con from .InvertedRegions import create_inverted_regions, mark_dark_world_regions from .ItemPool import generate_itempool, difficulties from .Items import item_init_table, item_name_groups, item_table, GetBeemizerItem -from .Options import alttp_options, smallkey_shuffle +from .Options import alttp_options, small_key_shuffle from .Regions import lookup_name_to_id, create_regions, mark_light_world_regions, lookup_vanilla_location_to_entrance, \ is_main_entrance, key_drop_data from .Client import ALTTPSNIClient from .Rom import LocalRom, patch_rom, patch_race_rom, check_enemizer, patch_enemizer, apply_rom_settings, \ get_hash_string, get_base_rom_path, LttPDeltaPatch from .Rules import set_rules -from .Shops import create_shops, Shop, ShopSlotFill, ShopType, price_rate_display, price_type_display_name +from .Shops import create_shops, Shop, push_shop_inventories, ShopType, price_rate_display, price_type_display_name from .SubClasses import ALttPItem, LTTPRegionType from worlds.AutoWorld import World, WebWorld, LogicMixin from .StateHelpers import can_buy_unlimited @@ -213,7 +213,7 @@ class ALTTPWorld(World): item_name_to_id = {name: data.item_code for name, data in item_table.items() if type(data.item_code) == int} location_name_to_id = lookup_name_to_id - data_version = 8 + data_version = 9 required_client_version = (0, 4, 1) web = ALTTPWeb() @@ -290,33 +290,34 @@ class ALTTPWorld(World): self.pyramid_fairy_bottle_fill = self.random.choice(bottle_options) if multiworld.mode[player] == 'standard': - if multiworld.smallkey_shuffle[player]: - if (multiworld.smallkey_shuffle[player] not in - (smallkey_shuffle.option_universal, smallkey_shuffle.option_own_dungeons, - smallkey_shuffle.option_start_with)): + if multiworld.small_key_shuffle[player]: + if (multiworld.small_key_shuffle[player] not in + (small_key_shuffle.option_universal, small_key_shuffle.option_own_dungeons, + small_key_shuffle.option_start_with)): self.multiworld.local_early_items[self.player]["Small Key (Hyrule Castle)"] = 1 self.multiworld.local_items[self.player].value.add("Small Key (Hyrule Castle)") self.multiworld.non_local_items[self.player].value.discard("Small Key (Hyrule Castle)") - if multiworld.bigkey_shuffle[player]: + if multiworld.big_key_shuffle[player]: self.multiworld.local_items[self.player].value.add("Big Key (Hyrule Castle)") self.multiworld.non_local_items[self.player].value.discard("Big Key (Hyrule Castle)") # system for sharing ER layouts self.er_seed = str(multiworld.random.randint(0, 2 ** 64)) - if "-" in multiworld.shuffle[player]: - shuffle, seed = multiworld.shuffle[player].split("-", 1) - multiworld.shuffle[player] = shuffle + if multiworld.entrance_shuffle[player] != "vanilla" and multiworld.entrance_shuffle_seed[player] != "random": + shuffle = multiworld.entrance_shuffle[player].current_key if shuffle == "vanilla": self.er_seed = "vanilla" - elif seed.startswith("group-") or multiworld.is_race: + elif (not multiworld.entrance_shuffle_seed[player].value.isdigit()) or multiworld.is_race: self.er_seed = get_same_seed(multiworld, ( - shuffle, seed, multiworld.retro_caves[player], multiworld.mode[player], multiworld.logic[player])) + shuffle, multiworld.entrance_shuffle_seed[player].value, multiworld.retro_caves[player], multiworld.mode[player], + multiworld.glitches_required[player])) else: # not a race or group seed, use set seed as is. - self.er_seed = seed - elif multiworld.shuffle[player] == "vanilla": + self.er_seed = int(multiworld.entrance_shuffle_seed[player].value) + elif multiworld.entrance_shuffle[player] == "vanilla": self.er_seed = "vanilla" - for dungeon_item in ["smallkey_shuffle", "bigkey_shuffle", "compass_shuffle", "map_shuffle"]: + + for dungeon_item in ["small_key_shuffle", "big_key_shuffle", "compass_shuffle", "map_shuffle"]: option = getattr(multiworld, dungeon_item)[player] if option == "own_world": multiworld.local_items[player].value |= self.item_name_groups[option.item_name_group] @@ -329,10 +330,10 @@ class ALTTPWorld(World): if option == "original_dungeon": self.dungeon_specific_item_names |= self.item_name_groups[option.item_name_group] - multiworld.difficulty_requirements[player] = difficulties[multiworld.difficulty[player]] + multiworld.difficulty_requirements[player] = difficulties[multiworld.item_pool[player].current_key] # enforce pre-defined local items. - if multiworld.goal[player] in ["localtriforcehunt", "localganontriforcehunt"]: + if multiworld.goal[player] in ["local_triforce_hunt", "local_ganon_triforce_hunt"]: multiworld.local_items[player].value.add('Triforce Piece') # Not possible to place crystals outside boss prizes yet (might as well make it consistent with pendants too). @@ -345,9 +346,6 @@ class ALTTPWorld(World): player = self.player world = self.multiworld - world.triforce_pieces_available[player] = max(world.triforce_pieces_available[player], - world.triforce_pieces_required[player]) - if world.mode[player] != 'inverted': create_regions(world, player) else: @@ -355,8 +353,8 @@ class ALTTPWorld(World): create_shops(world, player) self.create_dungeons() - if world.logic[player] not in ["noglitches", "minorglitches"] and world.shuffle[player] in \ - {"vanilla", "dungeonssimple", "dungeonsfull", "simple", "restricted", "full"}: + if world.glitches_required[player] not in ["no_glitches", "minor_glitches"] and world.entrance_shuffle[player] in \ + {"vanilla", "dungeons_simple", "dungeons_full", "simple", "restricted", "full"}: world.fix_fake_world[player] = False # seeded entrance shuffle @@ -455,7 +453,7 @@ class ALTTPWorld(World): if state.has('Silver Bow', item.player): return elif state.has('Bow', item.player) and (self.multiworld.difficulty_requirements[item.player].progressive_bow_limit >= 2 - or self.multiworld.logic[item.player] == 'noglitches' + or self.multiworld.glitches_required[item.player] == 'no_glitches' or self.multiworld.swordless[item.player]): # modes where silver bow is always required for ganon return 'Silver Bow' elif self.multiworld.difficulty_requirements[item.player].progressive_bow_limit >= 1: @@ -499,9 +497,9 @@ class ALTTPWorld(World): break else: raise FillError('Unable to place dungeon prizes') - if world.mode[player] == 'standard' and world.smallkey_shuffle[player] \ - and world.smallkey_shuffle[player] != smallkey_shuffle.option_universal and \ - world.smallkey_shuffle[player] != smallkey_shuffle.option_own_dungeons: + if world.mode[player] == 'standard' and world.small_key_shuffle[player] \ + and world.small_key_shuffle[player] != small_key_shuffle.option_universal and \ + world.small_key_shuffle[player] != small_key_shuffle.option_own_dungeons: world.local_early_items[player]["Small Key (Hyrule Castle)"] = 1 @classmethod @@ -509,10 +507,9 @@ class ALTTPWorld(World): from .Dungeons import fill_dungeons_restrictive fill_dungeons_restrictive(world) - @classmethod def stage_post_fill(cls, world): - ShopSlotFill(world) + push_shop_inventories(world) @property def use_enemizer(self) -> bool: @@ -579,7 +576,7 @@ class ALTTPWorld(World): @classmethod def stage_extend_hint_information(cls, world, hint_data: typing.Dict[int, typing.Dict[int, str]]): er_hint_data = {player: {} for player in world.get_game_players("A Link to the Past") if - world.shuffle[player] != "vanilla" or world.retro_caves[player]} + world.entrance_shuffle[player] != "vanilla" or world.retro_caves[player]} for region in world.regions: if region.player in er_hint_data and region.locations: @@ -645,9 +642,9 @@ class ALTTPWorld(World): trash_counts = {} for player in world.get_game_players("A Link to the Past"): if not world.ganonstower_vanilla[player] or \ - world.logic[player] in {'owglitches', 'hybridglitches', "nologic"}: + world.glitches_required[player] in {'overworld_glitches', 'hybrid_major_glitches', "no_logic"}: pass - elif 'triforcehunt' in world.goal[player] and ('local' in world.goal[player] or world.players == 1): + elif 'triforce_hunt' in world.goal[player].current_key and ('local' in world.goal[player].current_key or world.players == 1): trash_counts[player] = world.random.randint(world.crystals_needed_for_gt[player] * 2, world.crystals_needed_for_gt[player] * 4) else: @@ -681,35 +678,6 @@ class ALTTPWorld(World): return variable return "Yes" if variable else "No" - spoiler_handle.write('Logic: %s\n' % self.multiworld.logic[self.player]) - spoiler_handle.write('Dark Room Logic: %s\n' % self.multiworld.dark_room_logic[self.player]) - spoiler_handle.write('Mode: %s\n' % self.multiworld.mode[self.player]) - spoiler_handle.write('Goal: %s\n' % self.multiworld.goal[self.player]) - if "triforce" in self.multiworld.goal[self.player]: # triforce hunt - spoiler_handle.write("Pieces available for Triforce: %s\n" % - self.multiworld.triforce_pieces_available[self.player]) - spoiler_handle.write("Pieces required for Triforce: %s\n" % - self.multiworld.triforce_pieces_required[self.player]) - spoiler_handle.write('Difficulty: %s\n' % self.multiworld.difficulty[self.player]) - spoiler_handle.write('Item Functionality: %s\n' % self.multiworld.item_functionality[self.player]) - spoiler_handle.write('Entrance Shuffle: %s\n' % self.multiworld.shuffle[self.player]) - if self.multiworld.shuffle[self.player] != "vanilla": - spoiler_handle.write('Entrance Shuffle Seed %s\n' % self.er_seed) - spoiler_handle.write('Shop inventory shuffle: %s\n' % - bool_to_text("i" in self.multiworld.shop_shuffle[self.player])) - spoiler_handle.write('Shop price shuffle: %s\n' % - bool_to_text("p" in self.multiworld.shop_shuffle[self.player])) - spoiler_handle.write('Shop upgrade shuffle: %s\n' % - bool_to_text("u" in self.multiworld.shop_shuffle[self.player])) - spoiler_handle.write('New Shop inventory: %s\n' % - bool_to_text("g" in self.multiworld.shop_shuffle[self.player] or - "f" in self.multiworld.shop_shuffle[self.player])) - spoiler_handle.write('Custom Potion Shop: %s\n' % - bool_to_text("w" in self.multiworld.shop_shuffle[self.player])) - spoiler_handle.write('Enemy health: %s\n' % self.multiworld.enemy_health[self.player]) - spoiler_handle.write('Enemy damage: %s\n' % self.multiworld.enemy_damage[self.player]) - spoiler_handle.write('Prize shuffle %s\n' % self.multiworld.shuffle_prizes[self.player]) - def write_spoiler(self, spoiler_handle: typing.TextIO) -> None: player_name = self.multiworld.get_player_name(self.player) spoiler_handle.write("\n\nMedallions:\n") @@ -783,7 +751,7 @@ class ALTTPWorld(World): if item["replacement"] is None: continue shop_data["item_{}".format(index)] +=\ - f", {item['replacement']} - {item['replacement_price']}" \ + f", {item['replacement']} - {item['replacement_price'] // price_rate_display.get(item['replacement_price_type'], 1)}" \ f" {price_type_display_name[item['replacement_price_type']]}" return shop_data @@ -796,10 +764,7 @@ class ALTTPWorld(World): item))) def get_filler_item_name(self) -> str: - if self.multiworld.goal[self.player] == "icerodhunt": - item = "Nothing" - else: - item = self.multiworld.random.choice(extras_list) + item = self.multiworld.random.choice(extras_list) return GetBeemizerItem(self.multiworld, self.player, item) def get_pre_fill_items(self): @@ -819,20 +784,20 @@ class ALTTPWorld(World): # for convenient auto-tracking of the generated settings and adjusting the tracker accordingly slot_options = ["crystals_needed_for_gt", "crystals_needed_for_ganon", "open_pyramid", - "bigkey_shuffle", "smallkey_shuffle", "compass_shuffle", "map_shuffle", + "big_key_shuffle", "small_key_shuffle", "compass_shuffle", "map_shuffle", "progressive", "swordless", "retro_bow", "retro_caves", "shop_item_slots", - "boss_shuffle", "pot_shuffle", "enemy_shuffle", "key_drop_shuffle"] + "boss_shuffle", "pot_shuffle", "enemy_shuffle", "key_drop_shuffle", "bombless_start", + "randomize_shop_inventories", "shuffle_shop_inventories", "shuffle_capacity_upgrades", + "entrance_shuffle", "dark_room_logic", "goal", "mode", + "triforce_pieces_mode", "triforce_pieces_percentage", "triforce_pieces_required", + "triforce_pieces_available", "triforce_pieces_extra", + ] slot_data = {option_name: getattr(self.multiworld, option_name)[self.player].value for option_name in slot_options} slot_data.update({ - 'mode': self.multiworld.mode[self.player], - 'goal': self.multiworld.goal[self.player], - 'dark_room_logic': self.multiworld.dark_room_logic[self.player], 'mm_medalion': self.multiworld.required_medallions[self.player][0], 'tr_medalion': self.multiworld.required_medallions[self.player][1], - 'shop_shuffle': self.multiworld.shop_shuffle[self.player], - 'entrance_shuffle': self.multiworld.shuffle[self.player], } ) return slot_data @@ -849,8 +814,8 @@ def get_same_seed(world, seed_def: tuple) -> str: class ALttPLogic(LogicMixin): def _lttp_has_key(self, item, player, count: int = 1): - if self.multiworld.logic[player] == 'nologic': + if self.multiworld.glitches_required[player] == 'no_logic': return True - if self.multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal: + if self.multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal: return can_buy_unlimited(self, 'Small Key (Universal)', player) return self.prog_items[player][item] >= count diff --git a/worlds/alttp/test/dungeons/TestAgahnimsTower.py b/worlds/alttp/test/dungeons/TestAgahnimsTower.py index 94e78548..c44a92be 100644 --- a/worlds/alttp/test/dungeons/TestAgahnimsTower.py +++ b/worlds/alttp/test/dungeons/TestAgahnimsTower.py @@ -7,25 +7,25 @@ class TestAgahnimsTower(TestDungeon): self.starting_regions = ['Agahnims Tower'] self.run_tests([ ["Castle Tower - Room 03", False, []], - ["Castle Tower - Room 03", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], + ["Castle Tower - Room 03", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], ["Castle Tower - Room 03", True, ['Progressive Sword']], ["Castle Tower - Dark Maze", False, []], ["Castle Tower - Dark Maze", False, [], ['Small Key (Agahnims Tower)']], ["Castle Tower - Dark Maze", False, [], ['Lamp']], - ["Castle Tower - Dark Maze", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], + ["Castle Tower - Dark Maze", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], ["Castle Tower - Dark Maze", True, ['Progressive Sword', 'Small Key (Agahnims Tower)', 'Lamp']], ["Castle Tower - Dark Archer Key Drop", False, []], ["Castle Tower - Dark Archer Key Drop", False, ['Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)']], ["Castle Tower - Dark Archer Key Drop", False, [], ['Lamp']], - ["Castle Tower - Dark Archer Key Drop", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], + ["Castle Tower - Dark Archer Key Drop", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], ["Castle Tower - Dark Archer Key Drop", True, ['Progressive Sword', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Lamp']], ["Castle Tower - Circle of Pots Key Drop", False, []], ["Castle Tower - Circle of Pots Key Drop", False, ['Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)']], ["Castle Tower - Circle of Pots Key Drop", False, [], ['Lamp']], - ["Castle Tower - Circle of Pots Key Drop", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], + ["Castle Tower - Circle of Pots Key Drop", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], ["Castle Tower - Circle of Pots Key Drop", True, ['Progressive Sword', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Lamp']], ["Agahnim 1", False, []], diff --git a/worlds/alttp/test/dungeons/TestDarkPalace.py b/worlds/alttp/test/dungeons/TestDarkPalace.py index e3974e77..3912fbd2 100644 --- a/worlds/alttp/test/dungeons/TestDarkPalace.py +++ b/worlds/alttp/test/dungeons/TestDarkPalace.py @@ -11,29 +11,37 @@ class TestDarkPalace(TestDungeon): ["Palace of Darkness - The Arena - Ledge", False, []], ["Palace of Darkness - The Arena - Ledge", False, [], ['Progressive Bow']], - ["Palace of Darkness - The Arena - Ledge", True, ['Progressive Bow']], + ["Palace of Darkness - The Arena - Ledge", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Palace of Darkness - The Arena - Ledge", True, ['Progressive Bow', 'Bomb Upgrade (+5)']], ["Palace of Darkness - Map Chest", False, []], ["Palace of Darkness - Map Chest", False, [], ['Progressive Bow']], - ["Palace of Darkness - Map Chest", True, ['Progressive Bow']], + ["Palace of Darkness - Map Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Palace of Darkness - Map Chest", True, ['Progressive Bow', 'Bomb Upgrade (+5)']], + ["Palace of Darkness - Map Chest", True, ['Progressive Bow', 'Pegasus Boots']], #Lower requirement for self-locking key #No lower requirement when bow/hammer is out of logic ["Palace of Darkness - Big Key Chest", False, []], ["Palace of Darkness - Big Key Chest", False, [key]*5, [key]], - ["Palace of Darkness - Big Key Chest", True, [key]*6], + ["Palace of Darkness - Big Key Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Palace of Darkness - Big Key Chest", True, [key]*6 + ['Bomb Upgrade (+5)']], ["Palace of Darkness - The Arena - Bridge", False, []], ["Palace of Darkness - The Arena - Bridge", False, [], [key, 'Progressive Bow']], ["Palace of Darkness - The Arena - Bridge", False, [], [key, 'Hammer']], + ["Palace of Darkness - The Arena - Bridge", False, [], [key, 'Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], ["Palace of Darkness - The Arena - Bridge", True, [key]], - ["Palace of Darkness - The Arena - Bridge", True, ['Progressive Bow', 'Hammer']], + ["Palace of Darkness - The Arena - Bridge", True, ['Progressive Bow', 'Hammer', 'Bomb Upgrade (+5)']], + ["Palace of Darkness - The Arena - Bridge", True, ['Progressive Bow', 'Hammer', 'Pegasus Boots']], ["Palace of Darkness - Stalfos Basement", False, []], ["Palace of Darkness - Stalfos Basement", False, [], [key, 'Progressive Bow']], ["Palace of Darkness - Stalfos Basement", False, [], [key, 'Hammer']], + ["Palace of Darkness - Stalfos Basement", False, [], [key, 'Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], ["Palace of Darkness - Stalfos Basement", True, [key]], - ["Palace of Darkness - Stalfos Basement", True, ['Progressive Bow', 'Hammer']], + ["Palace of Darkness - Stalfos Basement", True, ['Progressive Bow', 'Hammer', 'Bomb Upgrade (+5)']], + ["Palace of Darkness - Stalfos Basement", True, ['Progressive Bow', 'Hammer', 'Pegasus Boots']], ["Palace of Darkness - Compass Chest", False, []], ["Palace of Darkness - Compass Chest", False, [key]*3, [key]], @@ -67,8 +75,9 @@ class TestDarkPalace(TestDungeon): ["Palace of Darkness - Big Chest", False, []], ["Palace of Darkness - Big Chest", False, [], ['Lamp']], ["Palace of Darkness - Big Chest", False, [], ['Big Key (Palace of Darkness)']], + ["Palace of Darkness - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], ["Palace of Darkness - Big Chest", False, [key]*5, [key]], - ["Palace of Darkness - Big Chest", True, ['Lamp', 'Big Key (Palace of Darkness)'] + [key]*6], + ["Palace of Darkness - Big Chest", True, ['Bomb Upgrade (+5)', 'Lamp', 'Big Key (Palace of Darkness)'] + [key]*6], ["Palace of Darkness - Boss", False, []], ["Palace of Darkness - Boss", False, [], ['Lamp']], diff --git a/worlds/alttp/test/dungeons/TestDungeon.py b/worlds/alttp/test/dungeons/TestDungeon.py index 8ca2791d..1f8288ac 100644 --- a/worlds/alttp/test/dungeons/TestDungeon.py +++ b/worlds/alttp/test/dungeons/TestDungeon.py @@ -14,6 +14,8 @@ class TestDungeon(LTTPTestBase): self.starting_regions = [] # Where to start exploring self.remove_exits = [] # Block dungeon exits self.multiworld.difficulty_requirements[1] = difficulties['normal'] + self.multiworld.bombless_start[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = True create_regions(self.multiworld, 1) self.multiworld.worlds[1].create_dungeons() create_shops(self.multiworld, 1) diff --git a/worlds/alttp/test/dungeons/TestEasternPalace.py b/worlds/alttp/test/dungeons/TestEasternPalace.py index 35c1b992..c1a97834 100644 --- a/worlds/alttp/test/dungeons/TestEasternPalace.py +++ b/worlds/alttp/test/dungeons/TestEasternPalace.py @@ -18,8 +18,8 @@ class TestEasternPalace(TestDungeon): ["Eastern Palace - Big Key Chest", False, []], ["Eastern Palace - Big Key Chest", False, [], ['Lamp']], - ["Eastern Palace - Big Key Chest", True, ['Lamp', 'Small Key (Eastern Palace)', 'Small Key (Eastern Palace)']], - ["Eastern Palace - Big Key Chest", True, ['Lamp', 'Big Key (Eastern Palace)']], + ["Eastern Palace - Big Key Chest", True, ['Lamp', 'Small Key (Eastern Palace)', 'Small Key (Eastern Palace)', 'Progressive Sword']], + ["Eastern Palace - Big Key Chest", True, ['Lamp', 'Big Key (Eastern Palace)', 'Progressive Sword']], #@todo: Advanced? ["Eastern Palace - Boss", False, []], diff --git a/worlds/alttp/test/dungeons/TestGanonsTower.py b/worlds/alttp/test/dungeons/TestGanonsTower.py index d22dc92b..98bc6fa5 100644 --- a/worlds/alttp/test/dungeons/TestGanonsTower.py +++ b/worlds/alttp/test/dungeons/TestGanonsTower.py @@ -103,16 +103,16 @@ class TestGanonsTower(TestDungeon): ["Ganons Tower - Compass Room - Bottom Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Cane of Somaria']], ["Ganons Tower - Big Key Chest", False, []], - ["Ganons Tower - Big Key Chest", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']], - ["Ganons Tower - Big Key Chest", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']], + ["Ganons Tower - Big Key Chest", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']], + ["Ganons Tower - Big Key Chest", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']], ["Ganons Tower - Big Key Room - Left", False, []], - ["Ganons Tower - Big Key Room - Left", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']], - ["Ganons Tower - Big Key Room - Left", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']], + ["Ganons Tower - Big Key Room - Left", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']], + ["Ganons Tower - Big Key Room - Left", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']], ["Ganons Tower - Big Key Room - Right", False, []], - ["Ganons Tower - Big Key Room - Right", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']], - ["Ganons Tower - Big Key Room - Right", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']], + ["Ganons Tower - Big Key Room - Right", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']], + ["Ganons Tower - Big Key Room - Right", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']], ["Ganons Tower - Mini Helmasaur Room - Left", False, []], ["Ganons Tower - Mini Helmasaur Room - Left", False, [], ['Progressive Bow']], diff --git a/worlds/alttp/test/dungeons/TestIcePalace.py b/worlds/alttp/test/dungeons/TestIcePalace.py index edc9f1fb..7a15c5c0 100644 --- a/worlds/alttp/test/dungeons/TestIcePalace.py +++ b/worlds/alttp/test/dungeons/TestIcePalace.py @@ -11,8 +11,9 @@ class TestIcePalace(TestDungeon): ["Ice Palace - Big Key Chest", False, [], ['Progressive Glove']], ["Ice Palace - Big Key Chest", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Big Key Chest", False, [], ['Fire Rod', 'Progressive Sword']], - ["Ice Palace - Big Key Chest", True, ['Progressive Glove', 'Fire Rod', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']], - ["Ice Palace - Big Key Chest", True, ['Progressive Glove', 'Bombos', 'Progressive Sword', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']], + ["Ice Palace - Big Key Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Palace - Big Key Chest", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Fire Rod', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']], + ["Ice Palace - Big Key Chest", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Bombos', 'Progressive Sword', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']], #@todo: Change from item randomizer - Right side key door is only in logic if big key is in there #["Ice Palace - Big Key Chest", True, ['Progressive Glove', 'Cane of Byrna', 'Fire Rod', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']], #["Ice Palace - Big Key Chest", True, ['Progressive Glove', 'Cane of Byrna', 'Bombos', 'Progressive Sword', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']], @@ -30,8 +31,9 @@ class TestIcePalace(TestDungeon): ["Ice Palace - Map Chest", False, [], ['Progressive Glove']], ["Ice Palace - Map Chest", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Map Chest", False, [], ['Fire Rod', 'Progressive Sword']], - ["Ice Palace - Map Chest", True, ['Progressive Glove', 'Fire Rod', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']], - ["Ice Palace - Map Chest", True, ['Progressive Glove', 'Bombos', 'Progressive Sword', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']], + ["Ice Palace - Map Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Palace - Map Chest", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Fire Rod', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']], + ["Ice Palace - Map Chest", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Bombos', 'Progressive Sword', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']], #["Ice Palace - Map Chest", True, ['Progressive Glove', 'Cane of Byrna', 'Fire Rod', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']], #["Ice Palace - Map Chest", True, ['Progressive Glove', 'Cane of Byrna', 'Bombos', 'Progressive Sword', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']], #["Ice Palace - Map Chest", True, ['Progressive Glove', 'Cape', 'Fire Rod', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']], @@ -40,8 +42,9 @@ class TestIcePalace(TestDungeon): ["Ice Palace - Spike Room", False, []], ["Ice Palace - Spike Room", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Spike Room", False, [], ['Fire Rod', 'Progressive Sword']], - ["Ice Palace - Spike Room", True, ['Fire Rod', 'Hookshot', 'Small Key (Ice Palace)']], - ["Ice Palace - Spike Room", True, ['Bombos', 'Progressive Sword', 'Hookshot', 'Small Key (Ice Palace)']], + ["Ice Palace - Spike Room", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Palace - Spike Room", True, ['Bomb Upgrade (+5)', 'Fire Rod', 'Hookshot', 'Small Key (Ice Palace)']], + ["Ice Palace - Spike Room", True, ['Bomb Upgrade (+5)', 'Bombos', 'Progressive Sword', 'Hookshot', 'Small Key (Ice Palace)']], #["Ice Palace - Spike Room", True, ['Cape', 'Fire Rod', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']], #["Ice Palace - Spike Room", True, ['Cape', 'Bombos', 'Progressive Sword', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']], #["Ice Palace - Spike Room", True, ['Cane of Byrna', 'Fire Rod', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']], @@ -50,21 +53,24 @@ class TestIcePalace(TestDungeon): ["Ice Palace - Freezor Chest", False, []], ["Ice Palace - Freezor Chest", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Freezor Chest", False, [], ['Fire Rod', 'Progressive Sword']], - ["Ice Palace - Freezor Chest", True, ['Fire Rod']], - ["Ice Palace - Freezor Chest", True, ['Bombos', 'Progressive Sword']], + ["Ice Palace - Freezor Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Palace - Freezor Chest", True, ['Bomb Upgrade (+5)', 'Fire Rod']], + ["Ice Palace - Freezor Chest", True, ['Bomb Upgrade (+5)', 'Bombos', 'Progressive Sword']], ["Ice Palace - Iced T Room", False, []], ["Ice Palace - Iced T Room", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Iced T Room", False, [], ['Fire Rod', 'Progressive Sword']], - ["Ice Palace - Iced T Room", True, ['Fire Rod']], - ["Ice Palace - Iced T Room", True, ['Bombos', 'Progressive Sword']], + ["Ice Palace - Iced T Room", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Palace - Iced T Room", True, ['Bomb Upgrade (+5)', 'Fire Rod']], + ["Ice Palace - Iced T Room", True, ['Bomb Upgrade (+5)', 'Bombos', 'Progressive Sword']], ["Ice Palace - Big Chest", False, []], ["Ice Palace - Big Chest", False, [], ['Big Key (Ice Palace)']], ["Ice Palace - Big Chest", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Big Chest", False, [], ['Fire Rod', 'Progressive Sword']], - ["Ice Palace - Big Chest", True, ['Big Key (Ice Palace)', 'Fire Rod']], - ["Ice Palace - Big Chest", True, ['Big Key (Ice Palace)', 'Bombos', 'Progressive Sword']], + ["Ice Palace - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Palace - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Ice Palace)', 'Fire Rod']], + ["Ice Palace - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Ice Palace)', 'Bombos', 'Progressive Sword']], ["Ice Palace - Boss", False, []], ["Ice Palace - Boss", False, [], ['Hammer']], @@ -72,9 +78,10 @@ class TestIcePalace(TestDungeon): ["Ice Palace - Boss", False, [], ['Big Key (Ice Palace)']], ["Ice Palace - Boss", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Boss", False, [], ['Fire Rod', 'Progressive Sword']], + ["Ice Palace - Boss", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], # need hookshot now to reach the right side for the 6th key - ["Ice Palace - Boss", True, ['Progressive Glove', 'Big Key (Ice Palace)', 'Fire Rod', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Hookshot']], - ["Ice Palace - Boss", True, ['Progressive Glove', 'Big Key (Ice Palace)', 'Fire Rod', 'Hammer', 'Cane of Somaria', 'Small Key (Ice Palace)', 'Hookshot']], - ["Ice Palace - Boss", True, ['Progressive Glove', 'Big Key (Ice Palace)', 'Bombos', 'Progressive Sword', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Hookshot']], - ["Ice Palace - Boss", True, ['Progressive Glove', 'Big Key (Ice Palace)', 'Bombos', 'Progressive Sword', 'Hammer', 'Cane of Somaria', 'Small Key (Ice Palace)', 'Hookshot']], + ["Ice Palace - Boss", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Big Key (Ice Palace)', 'Fire Rod', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Hookshot']], + ["Ice Palace - Boss", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Big Key (Ice Palace)', 'Fire Rod', 'Hammer', 'Cane of Somaria', 'Small Key (Ice Palace)', 'Hookshot']], + ["Ice Palace - Boss", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Big Key (Ice Palace)', 'Bombos', 'Progressive Sword', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Hookshot']], + ["Ice Palace - Boss", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Big Key (Ice Palace)', 'Bombos', 'Progressive Sword', 'Hammer', 'Cane of Somaria', 'Small Key (Ice Palace)', 'Hookshot']], ]) \ No newline at end of file diff --git a/worlds/alttp/test/dungeons/TestMiseryMire.py b/worlds/alttp/test/dungeons/TestMiseryMire.py index ea5fb288..6cbf4292 100644 --- a/worlds/alttp/test/dungeons/TestMiseryMire.py +++ b/worlds/alttp/test/dungeons/TestMiseryMire.py @@ -78,7 +78,8 @@ class TestMiseryMire(TestDungeon): ["Misery Mire - Boss", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow']], ["Misery Mire - Boss", False, [], ['Big Key (Misery Mire)']], ["Misery Mire - Boss", False, [], ['Pegasus Boots', 'Hookshot']], - ["Misery Mire - Boss", True, ['Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Progressive Sword', 'Pegasus Boots']], - ["Misery Mire - Boss", True, ['Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Hammer', 'Pegasus Boots']], - ["Misery Mire - Boss", True, ['Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Progressive Bow', 'Pegasus Boots']], + ["Misery Mire - Boss", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Misery Mire - Boss", True, ['Bomb Upgrade (+5)', 'Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Progressive Sword', 'Pegasus Boots']], + ["Misery Mire - Boss", True, ['Bomb Upgrade (+5)', 'Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Hammer', 'Pegasus Boots']], + ["Misery Mire - Boss", True, ['Bomb Upgrade (+5)', 'Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Progressive Bow', 'Pegasus Boots']], ]) \ No newline at end of file diff --git a/worlds/alttp/test/dungeons/TestSkullWoods.py b/worlds/alttp/test/dungeons/TestSkullWoods.py index 7f97c4d2..55c8d2e2 100644 --- a/worlds/alttp/test/dungeons/TestSkullWoods.py +++ b/worlds/alttp/test/dungeons/TestSkullWoods.py @@ -8,7 +8,8 @@ class TestSkullWoods(TestDungeon): self.run_tests([ ["Skull Woods - Big Chest", False, []], ["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']], - ["Skull Woods - Big Chest", True, ['Big Key (Skull Woods)']], + ["Skull Woods - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Skull Woods - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Skull Woods)']], ["Skull Woods - Compass Chest", True, []], @@ -64,7 +65,8 @@ class TestSkullWoods(TestDungeon): self.run_tests([ ["Skull Woods - Big Chest", False, []], ["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']], - ["Skull Woods - Big Chest", True, ['Big Key (Skull Woods)']], + ["Skull Woods - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Skull Woods - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Skull Woods)']], ["Skull Woods - Compass Chest", False, []], ["Skull Woods - Compass Chest", False, ['Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)'], ['Small Key (Skull Woods)']], diff --git a/worlds/alttp/test/dungeons/TestSwampPalace.py b/worlds/alttp/test/dungeons/TestSwampPalace.py index 51440f6c..bddf4061 100644 --- a/worlds/alttp/test/dungeons/TestSwampPalace.py +++ b/worlds/alttp/test/dungeons/TestSwampPalace.py @@ -30,7 +30,8 @@ class TestSwampPalace(TestDungeon): ["Swamp Palace - Map Chest", False, [], ['Flippers']], ["Swamp Palace - Map Chest", False, [], ['Open Floodgate']], ["Swamp Palace - Map Chest", False, [], ['Small Key (Swamp Palace)']], - ["Swamp Palace - Map Chest", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers']], + ["Swamp Palace - Map Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Swamp Palace - Map Chest", True, ['Bomb Upgrade (+5)', 'Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers']], ["Swamp Palace - West Chest", False, []], ["Swamp Palace - West Chest", False, [], ['Flippers']], diff --git a/worlds/alttp/test/dungeons/TestThievesTown.py b/worlds/alttp/test/dungeons/TestThievesTown.py index 01f1570a..752b5305 100644 --- a/worlds/alttp/test/dungeons/TestThievesTown.py +++ b/worlds/alttp/test/dungeons/TestThievesTown.py @@ -41,8 +41,9 @@ class TestThievesTown(TestDungeon): ["Thieves' Town - Boss", False, []], ["Thieves' Town - Boss", False, [], ['Big Key (Thieves Town)']], ["Thieves' Town - Boss", False, [], ['Hammer', 'Progressive Sword', 'Cane of Somaria', 'Cane of Byrna']], - ["Thieves' Town - Boss", True, ['Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Hammer']], - ["Thieves' Town - Boss", True, ['Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Progressive Sword']], - ["Thieves' Town - Boss", True, ['Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Cane of Somaria']], - ["Thieves' Town - Boss", True, ['Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Cane of Byrna']], + ["Thieves' Town - Boss", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Thieves' Town - Boss", True, ['Bomb Upgrade (+5)', 'Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Hammer']], + ["Thieves' Town - Boss", True, ['Bomb Upgrade (+5)', 'Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Progressive Sword']], + ["Thieves' Town - Boss", True, ['Bomb Upgrade (+5)', 'Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Cane of Somaria']], + ["Thieves' Town - Boss", True, ['Bomb Upgrade (+5)', 'Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Cane of Byrna']], ]) \ No newline at end of file diff --git a/worlds/alttp/test/dungeons/TestTowerOfHera.py b/worlds/alttp/test/dungeons/TestTowerOfHera.py index 04685a66..3299e202 100644 --- a/worlds/alttp/test/dungeons/TestTowerOfHera.py +++ b/worlds/alttp/test/dungeons/TestTowerOfHera.py @@ -18,11 +18,11 @@ class TestTowerOfHera(TestDungeon): ["Tower of Hera - Compass Chest", False, []], ["Tower of Hera - Compass Chest", False, [], ['Big Key (Tower of Hera)']], - ["Tower of Hera - Compass Chest", True, ['Big Key (Tower of Hera)']], + ["Tower of Hera - Compass Chest", True, ['Big Key (Tower of Hera)', 'Progressive Sword']], ["Tower of Hera - Big Chest", False, []], ["Tower of Hera - Big Chest", False, [], ['Big Key (Tower of Hera)']], - ["Tower of Hera - Big Chest", True, ['Big Key (Tower of Hera)']], + ["Tower of Hera - Big Chest", True, ['Big Key (Tower of Hera)', 'Progressive Sword']], ["Tower of Hera - Boss", False, []], ["Tower of Hera - Boss", False, [], ['Big Key (Tower of Hera)']], diff --git a/worlds/alttp/test/inverted/TestInverted.py b/worlds/alttp/test/inverted/TestInverted.py index f5608ba0..f2c585e4 100644 --- a/worlds/alttp/test/inverted/TestInverted.py +++ b/worlds/alttp/test/inverted/TestInverted.py @@ -14,7 +14,9 @@ class TestInverted(TestBase, LTTPTestBase): def setUp(self): self.world_setup() self.multiworld.difficulty_requirements[1] = difficulties['normal'] - self.multiworld.mode[1] = "inverted" + self.multiworld.mode[1].value = 2 + self.multiworld.bombless_start[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = True create_inverted_regions(self.multiworld, 1) self.multiworld.worlds[1].create_dungeons() create_shops(self.multiworld, 1) diff --git a/worlds/alttp/test/inverted/TestInvertedBombRules.py b/worlds/alttp/test/inverted/TestInvertedBombRules.py index d9eacb5a..83a25812 100644 --- a/worlds/alttp/test/inverted/TestInvertedBombRules.py +++ b/worlds/alttp/test/inverted/TestInvertedBombRules.py @@ -11,8 +11,8 @@ class TestInvertedBombRules(LTTPTestBase): def setUp(self): self.world_setup() - self.multiworld.mode[1] = "inverted" self.multiworld.difficulty_requirements[1] = difficulties['normal'] + self.multiworld.mode[1].value = 2 create_inverted_regions(self.multiworld, 1) self.multiworld.worlds[1].create_dungeons() diff --git a/worlds/alttp/test/inverted/TestInvertedDarkWorld.py b/worlds/alttp/test/inverted/TestInvertedDarkWorld.py index 710ee07f..16b837ee 100644 --- a/worlds/alttp/test/inverted/TestInvertedDarkWorld.py +++ b/worlds/alttp/test/inverted/TestInvertedDarkWorld.py @@ -5,7 +5,8 @@ class TestInvertedDarkWorld(TestInverted): def testNorthWest(self): self.run_location_tests([ - ["Brewery", True, []], + ["Brewery", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Brewery", True, ['Bomb Upgrade (+5)']], ["C-Shaped House", True, []], @@ -77,15 +78,16 @@ class TestInvertedDarkWorld(TestInverted): def testSouth(self): self.run_location_tests([ - ["Hype Cave - Top", True, []], - - ["Hype Cave - Middle Right", True, []], - - ["Hype Cave - Middle Left", True, []], - - ["Hype Cave - Bottom", True, []], - - ["Hype Cave - Generous Guy", True, []], + ["Hype Cave - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Middle Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Middle Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)']], ["Stumpy", True, []], diff --git a/worlds/alttp/test/inverted/TestInvertedDeathMountain.py b/worlds/alttp/test/inverted/TestInvertedDeathMountain.py index aedec2a1..605a9dc3 100644 --- a/worlds/alttp/test/inverted/TestInvertedDeathMountain.py +++ b/worlds/alttp/test/inverted/TestInvertedDeathMountain.py @@ -40,10 +40,12 @@ class TestInvertedDeathMountain(TestInverted): ["Paradox Cave Lower - Far Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Far Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Lower - Far Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Cane of Somaria', 'Fire Rod']], + ["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Progressive Sword', 'Progressive Sword']], + ["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Fire Rod']], + ["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Progressive Bow']], ["Paradox Cave Lower - Left", False, []], ["Paradox Cave Lower - Left", False, [], ['Moon Pearl']], @@ -52,10 +54,12 @@ class TestInvertedDeathMountain(TestInverted): ["Paradox Cave Lower - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Lower - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Cane of Somaria', 'Fire Rod']], + ["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']], + ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']], + ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Progressive Sword', 'Progressive Sword']], + ["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Fire Rod']], + ["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Progressive Bow']], ["Paradox Cave Lower - Middle", False, []], ["Paradox Cave Lower - Middle", False, [], ['Moon Pearl']], @@ -64,10 +68,12 @@ class TestInvertedDeathMountain(TestInverted): ["Paradox Cave Lower - Middle", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Middle", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Lower - Middle", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Cane of Somaria', 'Fire Rod']], + ["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']], + ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']], + ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Progressive Sword', 'Progressive Sword']], + ["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Fire Rod']], + ["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Progressive Bow']], ["Paradox Cave Lower - Right", False, []], ["Paradox Cave Lower - Right", False, [], ['Moon Pearl']], @@ -76,10 +82,12 @@ class TestInvertedDeathMountain(TestInverted): ["Paradox Cave Lower - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Lower - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Cane of Somaria', 'Fire Rod']], + ["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']], + ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']], + ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Progressive Sword', 'Progressive Sword']], + ["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Fire Rod']], + ["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Progressive Bow']], ["Paradox Cave Lower - Far Right", False, []], ["Paradox Cave Lower - Far Right", False, [], ['Moon Pearl']], @@ -88,10 +96,12 @@ class TestInvertedDeathMountain(TestInverted): ["Paradox Cave Lower - Far Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Far Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Lower - Far Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Cane of Somaria', 'Fire Rod']], + ["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Progressive Sword', 'Progressive Sword']], + ["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Fire Rod']], + ["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Progressive Bow']], ["Paradox Cave Upper - Left", False, []], ["Paradox Cave Upper - Left", False, [], ['Moon Pearl']], @@ -100,10 +110,11 @@ class TestInvertedDeathMountain(TestInverted): ["Paradox Cave Upper - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Upper - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Upper - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["Paradox Cave Upper - Right", False, []], ["Paradox Cave Upper - Right", False, [], ['Moon Pearl']], @@ -112,20 +123,22 @@ class TestInvertedDeathMountain(TestInverted): ["Paradox Cave Upper - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Upper - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Upper - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["Mimic Cave", False, []], ["Mimic Cave", False, [], ['Moon Pearl']], ["Mimic Cave", False, [], ['Hammer']], ["Mimic Cave", False, [], ['Progressive Glove', 'Flute']], ["Mimic Cave", False, [], ['Lamp', 'Flute']], - ["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot']], - ["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']], - ["Mimic Cave", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']], - ["Mimic Cave", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']], + ["Mimic Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Bow', 'Cane of Somaria', 'Progressive Sword']], + ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Flute', 'Moon Pearl', 'Hammer', 'Hookshot']], + ["Mimic Cave", True, ['Progressive Bow', 'Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']], + ["Mimic Cave", True, ['Cane of Somaria', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']], + ["Mimic Cave", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']], ["Ether Tablet", False, []], ["Ether Tablet", False, [], ['Moon Pearl']], diff --git a/worlds/alttp/test/inverted/TestInvertedLightWorld.py b/worlds/alttp/test/inverted/TestInvertedLightWorld.py index 9d4b9099..77af0931 100644 --- a/worlds/alttp/test/inverted/TestInvertedLightWorld.py +++ b/worlds/alttp/test/inverted/TestInvertedLightWorld.py @@ -44,15 +44,17 @@ class TestInvertedLightWorld(TestInverted): ["Chicken House", False, []], ["Chicken House", False, [], ['Moon Pearl']], - ["Chicken House", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Chicken House", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Chicken House", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Chicken House", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Chicken House", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Chicken House", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Chicken House", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Kakariko Well - Top", False, []], ["Kakariko Well - Top", False, [], ['Moon Pearl']], - ["Kakariko Well - Top", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Kakariko Well - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Kakariko Well - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Kakariko Well - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Kakariko Well - Left", False, []], ["Kakariko Well - Left", False, [], ['Moon Pearl']], @@ -80,9 +82,10 @@ class TestInvertedLightWorld(TestInverted): ["Blind's Hideout - Top", False, []], ["Blind's Hideout - Top", False, [], ['Moon Pearl']], - ["Blind's Hideout - Top", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Blind's Hideout - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Blind's Hideout - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Blind's Hideout - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Blind's Hideout - Left", False, []], ["Blind's Hideout - Left", False, [], ['Moon Pearl']], @@ -161,9 +164,10 @@ class TestInvertedLightWorld(TestInverted): ["Maze Race", False, []], ["Maze Race", False, [], ['Moon Pearl']], - ["Maze Race", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Maze Race", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Maze Race", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Maze Race", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Maze Race", True, ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']], + ["Maze Race", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Maze Race", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ]) def testSouthLightWorld(self): @@ -184,9 +188,10 @@ class TestInvertedLightWorld(TestInverted): ["Aginah's Cave", False, []], ["Aginah's Cave", False, [], ['Moon Pearl']], - ["Aginah's Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Aginah's Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Aginah's Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Aginah's Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Aginah's Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Aginah's Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Aginah's Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Bombos Tablet", False, []], ["Bombos Tablet", False, ['Progressive Sword'], ['Progressive Sword']], @@ -212,39 +217,45 @@ class TestInvertedLightWorld(TestInverted): ["Mini Moldorm Cave - Far Left", False, []], ["Mini Moldorm Cave - Far Left", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Mini Moldorm Cave - Far Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Sword']], + ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Progressive Sword']], ["Mini Moldorm Cave - Left", False, []], ["Mini Moldorm Cave - Left", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Mini Moldorm Cave - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Sword']], + ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Progressive Sword']], ["Mini Moldorm Cave - Generous Guy", False, []], ["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Mini Moldorm Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Sword']], + ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Progressive Sword']], ["Mini Moldorm Cave - Right", False, []], ["Mini Moldorm Cave - Right", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Mini Moldorm Cave - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Sword']], + ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Progressive Sword']], ["Mini Moldorm Cave - Far Right", False, []], ["Mini Moldorm Cave - Far Right", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Mini Moldorm Cave - Far Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Sword']], + ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Progressive Sword']], ["Ice Rod Cave", False, []], ["Ice Rod Cave", False, [], ['Moon Pearl']], - ["Ice Rod Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Ice Rod Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Ice Rod Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Rod Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Ice Rod Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Ice Rod Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ]) def testZoraArea(self): @@ -302,21 +313,24 @@ class TestInvertedLightWorld(TestInverted): ["Sahasrahla's Hut - Left", False, []], ["Sahasrahla's Hut - Left", False, [], ['Moon Pearl']], - ["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Sahasrahla's Hut - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Sahasrahla's Hut - Middle", False, []], ["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl']], - ["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Sahasrahla's Hut - Middle", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Middle", True, ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']], + ["Sahasrahla's Hut - Middle", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Sahasrahla's Hut - Middle", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Sahasrahla's Hut - Right", False, []], ["Sahasrahla's Hut - Right", False, [], ['Moon Pearl']], - ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Sahasrahla's Hut - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Right", True, ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']], + ["Sahasrahla's Hut - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Sahasrahla's Hut - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Sahasrahla", False, []], ["Sahasrahla", False, [], ['Green Pendant']], @@ -346,9 +360,10 @@ class TestInvertedLightWorld(TestInverted): ["Graveyard Cave", False, []], ["Graveyard Cave", False, [], ['Moon Pearl']], - ["Graveyard Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Graveyard Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Graveyard Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], + ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], ["Potion Shop", False, []], ["Potion Shop", False, [], ['Mushroom']], diff --git a/worlds/alttp/test/inverted/TestInvertedTurtleRock.py b/worlds/alttp/test/inverted/TestInvertedTurtleRock.py index fe8979c1..f3698c90 100644 --- a/worlds/alttp/test/inverted/TestInvertedTurtleRock.py +++ b/worlds/alttp/test/inverted/TestInvertedTurtleRock.py @@ -21,10 +21,10 @@ class TestInvertedTurtleRock(TestInverted): ["Turtle Rock - Chain Chomps", False, ['Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']], ["Turtle Rock - Chain Chomps", True, ['Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], ["Turtle Rock - Chain Chomps", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Chain Chomps", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Turtle Rock - Chain Chomps", True, ['Bomb Upgrade (+5)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], ["Turtle Rock - Chain Chomps", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']], ["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot']], - ["Turtle Rock - Chain Chomps", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']], + ["Turtle Rock - Chain Chomps", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Fire Rod']], ["Turtle Rock - Roller Room - Left", False, []], ["Turtle Rock - Roller Room - Left", False, [], ['Cane of Somaria']], @@ -54,8 +54,8 @@ class TestInvertedTurtleRock(TestInverted): ["Turtle Rock - Big Chest", False, [], ['Big Key (Turtle Rock)']], ["Turtle Rock - Big Chest", False, [], ['Magic Mirror', 'Cane of Somaria']], ["Turtle Rock - Big Chest", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Turtle Rock)', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], ["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria']], ["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Hookshot']], ["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']], @@ -68,10 +68,10 @@ class TestInvertedTurtleRock(TestInverted): ["Turtle Rock - Big Key Chest", True, ['Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], ["Turtle Rock - Big Key Chest", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], # Mirror in from ledge, use left side entrance, have enough keys to get to the chest - ["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Big Key Chest", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Big Key Chest", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Key Chest", True, ['Progressive Sword', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Key Chest", True, ['Progressive Sword', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Key Chest", True, ['Progressive Sword', 'Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Key Chest", True, ['Progressive Sword', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], ["Turtle Rock - Crystaroller Room", False, []], ["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']], @@ -102,8 +102,11 @@ class TestInvertedTurtleRock(TestInverted): ["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Magic Upgrade (1/2)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)','Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']], ["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']], ["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Flute', 'Magic Mirror', 'Moon Pearl', 'Hookshot', 'Hammer', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']] + ]) + + def testEyeBridge(self): for location in ["Turtle Rock - Eye Bridge - Top Right", "Turtle Rock - Eye Bridge - Top Left", "Turtle Rock - Eye Bridge - Bottom Right", "Turtle Rock - Eye Bridge - Bottom Left"]: diff --git a/worlds/alttp/test/inverted_minor_glitches/TestInvertedDarkWorld.py b/worlds/alttp/test/inverted_minor_glitches/TestInvertedDarkWorld.py index 69f56448..dd4a74b6 100644 --- a/worlds/alttp/test/inverted_minor_glitches/TestInvertedDarkWorld.py +++ b/worlds/alttp/test/inverted_minor_glitches/TestInvertedDarkWorld.py @@ -5,7 +5,8 @@ class TestInvertedDarkWorld(TestInvertedMinor): def testNorthWest(self): self.run_location_tests([ - ["Brewery", True, []], + ["Brewery", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Brewery", True, ['Bomb Upgrade (+5)']], ["C-Shaped House", True, []], @@ -67,15 +68,16 @@ class TestInvertedDarkWorld(TestInvertedMinor): def testSouth(self): self.run_location_tests([ - ["Hype Cave - Top", True, []], - - ["Hype Cave - Middle Right", True, []], - - ["Hype Cave - Middle Left", True, []], - - ["Hype Cave - Bottom", True, []], - - ["Hype Cave - Generous Guy", True, []], + ["Hype Cave - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Middle Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Middle Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)']], ["Stumpy", True, []], diff --git a/worlds/alttp/test/inverted_minor_glitches/TestInvertedDeathMountain.py b/worlds/alttp/test/inverted_minor_glitches/TestInvertedDeathMountain.py index c68a8e5f..c189d107 100644 --- a/worlds/alttp/test/inverted_minor_glitches/TestInvertedDeathMountain.py +++ b/worlds/alttp/test/inverted_minor_glitches/TestInvertedDeathMountain.py @@ -40,10 +40,11 @@ class TestInvertedDeathMountain(TestInvertedMinor): ["Paradox Cave Lower - Far Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Far Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Lower - Far Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod']], + ["Paradox Cave Lower - Far Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Bow', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], + ["Paradox Cave Lower - Far Left", True, ['Cane of Somaria', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["Paradox Cave Lower - Left", False, []], ["Paradox Cave Lower - Left", False, [], ['Moon Pearl']], @@ -52,10 +53,11 @@ class TestInvertedDeathMountain(TestInvertedMinor): ["Paradox Cave Lower - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Lower - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod']], + ["Paradox Cave Lower - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Lower - Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Lower - Left", True, ['Progressive Bow', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], + ["Paradox Cave Lower - Left", True, ['Cane of Somaria', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["Paradox Cave Lower - Middle", False, []], ["Paradox Cave Lower - Middle", False, [], ['Moon Pearl']], @@ -64,10 +66,11 @@ class TestInvertedDeathMountain(TestInvertedMinor): ["Paradox Cave Lower - Middle", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Middle", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Lower - Middle", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod']], + ["Paradox Cave Lower - Middle", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Lower - Middle", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Lower - Middle", True, ['Progressive Bow', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], + ["Paradox Cave Lower - Middle", True, ['Cane of Somaria', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["Paradox Cave Lower - Right", False, []], ["Paradox Cave Lower - Right", False, [], ['Moon Pearl']], @@ -76,10 +79,11 @@ class TestInvertedDeathMountain(TestInvertedMinor): ["Paradox Cave Lower - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Lower - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod']], + ["Paradox Cave Lower - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Lower - Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Lower - Right", True, ['Progressive Bow', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], + ["Paradox Cave Lower - Right", True, ['Cane of Somaria', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["Paradox Cave Lower - Far Right", False, []], ["Paradox Cave Lower - Far Right", False, [], ['Moon Pearl']], @@ -88,10 +92,11 @@ class TestInvertedDeathMountain(TestInvertedMinor): ["Paradox Cave Lower - Far Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Far Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Lower - Far Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod']], + ["Paradox Cave Lower - Far Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Bow', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], + ["Paradox Cave Lower - Far Right", True, ['Cane of Somaria', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["Paradox Cave Upper - Left", False, []], ["Paradox Cave Upper - Left", False, [], ['Moon Pearl']], @@ -100,10 +105,11 @@ class TestInvertedDeathMountain(TestInvertedMinor): ["Paradox Cave Upper - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Upper - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Upper - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["Paradox Cave Upper - Right", False, []], ["Paradox Cave Upper - Right", False, [], ['Moon Pearl']], @@ -112,20 +118,21 @@ class TestInvertedDeathMountain(TestInvertedMinor): ["Paradox Cave Upper - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']], ["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']], - ["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], - ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], - ["Paradox Cave Upper - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Paradox Cave Upper - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["Mimic Cave", False, []], ["Mimic Cave", False, [], ['Moon Pearl']], ["Mimic Cave", False, [], ['Hammer']], ["Mimic Cave", False, [], ['Progressive Glove', 'Flute']], ["Mimic Cave", False, [], ['Lamp', 'Flute']], - ["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot']], - ["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']], - ["Mimic Cave", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']], - ["Mimic Cave", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']], + ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Flute', 'Moon Pearl', 'Hammer', 'Hookshot']], + ["Mimic Cave", True, ['Progressive Sword', 'Progressive Sword', 'Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']], + ["Mimic Cave", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']], + ["Mimic Cave", True, ['Cane of Somaria', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']], ["Ether Tablet", False, []], ["Ether Tablet", False, [], ['Moon Pearl']], diff --git a/worlds/alttp/test/inverted_minor_glitches/TestInvertedLightWorld.py b/worlds/alttp/test/inverted_minor_glitches/TestInvertedLightWorld.py index 376e7b4b..086c1c92 100644 --- a/worlds/alttp/test/inverted_minor_glitches/TestInvertedLightWorld.py +++ b/worlds/alttp/test/inverted_minor_glitches/TestInvertedLightWorld.py @@ -43,16 +43,18 @@ class TestInvertedLightWorld(TestInvertedMinor): ["Chicken House", False, []], ["Chicken House", False, [], ['Moon Pearl']], - ["Chicken House", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Chicken House", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Chicken House", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Chicken House", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']], + ["Chicken House", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Chicken House", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Chicken House", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], # top can't be bombed as super bunny and needs Moon Pearl ["Kakariko Well - Top", False, []], ["Kakariko Well - Top", False, [], ['Moon Pearl']], - ["Kakariko Well - Top", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Kakariko Well - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Kakariko Well - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Kakariko Well - Top", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']], + ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Kakariko Well - Left", False, []], ["Kakariko Well - Left", True, ['Beat Agahnim 1']], @@ -76,9 +78,10 @@ class TestInvertedLightWorld(TestInvertedMinor): ["Blind's Hideout - Top", False, []], ["Blind's Hideout - Top", False, [], ['Moon Pearl', 'Magic Mirror']], - ["Blind's Hideout - Top", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Blind's Hideout - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Blind's Hideout - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Blind's Hideout - Top", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']], + ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Blind's Hideout - Left", False, []], ["Blind's Hideout - Left", False, [], ['Moon Pearl', 'Magic Mirror']], @@ -157,9 +160,10 @@ class TestInvertedLightWorld(TestInvertedMinor): ["Maze Race", False, []], ["Maze Race", False, [], ['Moon Pearl']], - ["Maze Race", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Maze Race", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Maze Race", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Maze Race", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)', 'Pegasus Boots']], + ["Maze Race", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Maze Race", True, ['Pegasus Boots', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Maze Race", True, ['Pegasus Boots', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ]) def testSouthLightWorld(self): @@ -179,9 +183,10 @@ class TestInvertedLightWorld(TestInvertedMinor): ["Aginah's Cave", False, []], ["Aginah's Cave", False, [], ['Moon Pearl']], - ["Aginah's Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Aginah's Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Aginah's Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Aginah's Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Aginah's Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Aginah's Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Aginah's Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Bombos Tablet", False, []], ["Bombos Tablet", False, ['Progressive Sword'], ['Progressive Sword']], @@ -209,39 +214,45 @@ class TestInvertedLightWorld(TestInvertedMinor): ["Mini Moldorm Cave - Far Left", False, []], ["Mini Moldorm Cave - Far Left", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Mini Moldorm Cave - Far Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Beat Agahnim 1']], + ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Mini Moldorm Cave - Left", False, []], ["Mini Moldorm Cave - Left", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Mini Moldorm Cave - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Beat Agahnim 1']], + ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Mini Moldorm Cave - Generous Guy", False, []], ["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Mini Moldorm Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Beat Agahnim 1']], + ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Mini Moldorm Cave - Right", False, []], ["Mini Moldorm Cave - Right", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Mini Moldorm Cave - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Beat Agahnim 1']], + ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Mini Moldorm Cave - Far Right", False, []], ["Mini Moldorm Cave - Far Right", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Mini Moldorm Cave - Far Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Beat Agahnim 1']], + ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Ice Rod Cave", False, []], ["Ice Rod Cave", False, [], ['Moon Pearl']], - ["Ice Rod Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Ice Rod Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Ice Rod Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Rod Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Ice Rod Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Ice Rod Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ]) def testZoraArea(self): @@ -297,25 +308,28 @@ class TestInvertedLightWorld(TestInvertedMinor): ["Sahasrahla's Hut - Left", False, []], ["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Magic Mirror']], - ["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Sahasrahla's Hut - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Sahasrahla's Hut - Left", True, ['Pegasus Boots', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Sahasrahla's Hut - Left", True, ['Pegasus Boots', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], # super bunny bonk ["Sahasrahla's Hut - Left", True, ['Magic Mirror', 'Beat Agahnim 1', 'Pegasus Boots']], ["Sahasrahla's Hut - Middle", False, []], ["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Magic Mirror']], - ["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Sahasrahla's Hut - Middle", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Middle", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Sahasrahla's Hut - Middle", True, ['Pegasus Boots', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Sahasrahla's Hut - Middle", True, ['Pegasus Boots', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], # super bunny bonk ["Sahasrahla's Hut - Middle", True, ['Magic Mirror', 'Beat Agahnim 1', 'Pegasus Boots']], ["Sahasrahla's Hut - Right", False, []], ["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Magic Mirror']], - ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], - ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Sahasrahla's Hut - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], + ["Sahasrahla's Hut - Right", True, ['Pegasus Boots', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Sahasrahla's Hut - Right", True, ['Pegasus Boots', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], # super bunny bonk ["Sahasrahla's Hut - Right", True, ['Magic Mirror', 'Beat Agahnim 1', 'Pegasus Boots']], @@ -347,9 +361,10 @@ class TestInvertedLightWorld(TestInvertedMinor): ["Graveyard Cave", False, []], ["Graveyard Cave", False, [], ['Moon Pearl']], - ["Graveyard Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Graveyard Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Graveyard Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], + ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], ["Potion Shop", False, []], ["Potion Shop", False, [], ['Mushroom']], diff --git a/worlds/alttp/test/inverted_minor_glitches/TestInvertedMinor.py b/worlds/alttp/test/inverted_minor_glitches/TestInvertedMinor.py index 33e58229..0219332e 100644 --- a/worlds/alttp/test/inverted_minor_glitches/TestInvertedMinor.py +++ b/worlds/alttp/test/inverted_minor_glitches/TestInvertedMinor.py @@ -13,8 +13,10 @@ from worlds.alttp.test import LTTPTestBase class TestInvertedMinor(TestBase, LTTPTestBase): def setUp(self): self.world_setup() - self.multiworld.mode[1] = "inverted" - self.multiworld.logic[1] = "minorglitches" + self.multiworld.mode[1].value = 2 + self.multiworld.glitches_required[1] = "minor_glitches" + self.multiworld.bombless_start[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = True self.multiworld.difficulty_requirements[1] = difficulties['normal'] create_inverted_regions(self.multiworld, 1) self.multiworld.worlds[1].create_dungeons() diff --git a/worlds/alttp/test/inverted_minor_glitches/TestInvertedTurtleRock.py b/worlds/alttp/test/inverted_minor_glitches/TestInvertedTurtleRock.py index d7b5c9f7..3c75a2c3 100644 --- a/worlds/alttp/test/inverted_minor_glitches/TestInvertedTurtleRock.py +++ b/worlds/alttp/test/inverted_minor_glitches/TestInvertedTurtleRock.py @@ -22,10 +22,10 @@ class TestInvertedTurtleRock(TestInvertedMinor): ["Turtle Rock - Chain Chomps", False, ['Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']], ["Turtle Rock - Chain Chomps", True, ['Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], ["Turtle Rock - Chain Chomps", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Chain Chomps", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Turtle Rock - Chain Chomps", True, ['Bomb Upgrade (+5)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], ["Turtle Rock - Chain Chomps", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']], ["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot']], - ["Turtle Rock - Chain Chomps", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']], + ["Turtle Rock - Chain Chomps", True, ['Fire Rod', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']], ["Turtle Rock - Roller Room - Left", False, []], ["Turtle Rock - Roller Room - Left", False, [], ['Cane of Somaria']], @@ -55,8 +55,8 @@ class TestInvertedTurtleRock(TestInvertedMinor): ["Turtle Rock - Big Chest", False, [], ['Big Key (Turtle Rock)']], ["Turtle Rock - Big Chest", False, [], ['Magic Mirror', 'Cane of Somaria']], ["Turtle Rock - Big Chest", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Turtle Rock)', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], ["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria']], ["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Hookshot']], ["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']], @@ -69,10 +69,10 @@ class TestInvertedTurtleRock(TestInvertedMinor): ["Turtle Rock - Big Key Chest", True, ['Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], ["Turtle Rock - Big Key Chest", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], # Mirror in from ledge, use left side entrance, have enough keys to get to the chest - ["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Big Key Chest", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], - ["Turtle Rock - Big Key Chest", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Key Chest", True, ['Progressive Sword', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Key Chest", True, ['Progressive Sword', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Key Chest", True, ['Progressive Sword', 'Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Turtle Rock - Big Key Chest", True, ['Progressive Sword', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], ["Turtle Rock - Crystaroller Room", False, []], ["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']], @@ -98,7 +98,7 @@ class TestInvertedTurtleRock(TestInvertedMinor): ["Turtle Rock - Boss", False, [], ['Big Key (Turtle Rock)']], ["Turtle Rock - Boss", False, [], ['Magic Mirror', 'Lamp']], ["Turtle Rock - Boss", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']], - ["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Flute', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Bottle', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']], + ["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Flute', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Bottle', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']], ["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Bottle', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']], ["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Magic Upgrade (1/2)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)','Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']], ["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']], diff --git a/worlds/alttp/test/inverted_owg/TestDarkWorld.py b/worlds/alttp/test/inverted_owg/TestDarkWorld.py index e7e720d2..8fb234f0 100644 --- a/worlds/alttp/test/inverted_owg/TestDarkWorld.py +++ b/worlds/alttp/test/inverted_owg/TestDarkWorld.py @@ -5,15 +5,16 @@ class TestDarkWorld(TestInvertedOWG): def testSouthDarkWorld(self): self.run_location_tests([ - ["Hype Cave - Top", True, []], - - ["Hype Cave - Middle Right", True, []], - - ["Hype Cave - Middle Left", True, []], - - ["Hype Cave - Bottom", True, []], - - ["Hype Cave - Generous Guy", True, []], + ["Hype Cave - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)']], ["Stumpy", True, []], @@ -22,7 +23,8 @@ class TestDarkWorld(TestInvertedOWG): def testWestDarkWorld(self): self.run_location_tests([ - ["Brewery", True, []], + ["Brewery", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Brewery", True, ['Bomb Upgrade (+5)']], ["C-Shaped House", True, []], diff --git a/worlds/alttp/test/inverted_owg/TestDeathMountain.py b/worlds/alttp/test/inverted_owg/TestDeathMountain.py index 79796a7a..b509643d 100644 --- a/worlds/alttp/test/inverted_owg/TestDeathMountain.py +++ b/worlds/alttp/test/inverted_owg/TestDeathMountain.py @@ -24,36 +24,38 @@ class TestDeathMountain(TestInvertedOWG): ["Paradox Cave Lower - Far Left", False, []], ["Paradox Cave Lower - Far Left", False, [], ['Moon Pearl']], - ["Paradox Cave Lower - Far Left", True, ['Moon Pearl', 'Pegasus Boots']], + ["Paradox Cave Lower - Far Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Paradox Cave Lower - Left", False, []], ["Paradox Cave Lower - Left", False, [], ['Moon Pearl']], - ["Paradox Cave Lower - Left", True, ['Moon Pearl', 'Pegasus Boots']], + ["Paradox Cave Lower - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Paradox Cave Lower - Middle", False, []], ["Paradox Cave Lower - Middle", False, [], ['Moon Pearl']], - ["Paradox Cave Lower - Middle", True, ['Moon Pearl', 'Pegasus Boots']], + ["Paradox Cave Lower - Middle", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Paradox Cave Lower - Right", False, []], ["Paradox Cave Lower - Right", False, [], ['Moon Pearl']], - ["Paradox Cave Lower - Right", True, ['Moon Pearl', 'Pegasus Boots']], + ["Paradox Cave Lower - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Paradox Cave Lower - Far Right", False, []], ["Paradox Cave Lower - Far Right", False, [], ['Moon Pearl']], - ["Paradox Cave Lower - Far Right", True, ['Moon Pearl', 'Pegasus Boots']], + ["Paradox Cave Lower - Far Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Paradox Cave Upper - Left", False, []], ["Paradox Cave Upper - Left", False, [], ['Moon Pearl']], - ["Paradox Cave Upper - Left", True, ['Moon Pearl', 'Pegasus Boots']], + ["Paradox Cave Upper - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Paradox Cave Upper - Right", False, []], ["Paradox Cave Upper - Right", False, [], ['Moon Pearl']], - ["Paradox Cave Upper - Right", True, ['Moon Pearl', 'Pegasus Boots']], + ["Paradox Cave Upper - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Mimic Cave", False, []], ["Mimic Cave", False, [], ['Moon Pearl']], ["Mimic Cave", False, [], ['Hammer']], - ["Mimic Cave", True, ['Moon Pearl', 'Hammer', 'Pegasus Boots']], + ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Hammer', 'Pegasus Boots']], ["Ether Tablet", False, []], ["Ether Tablet", False, ['Progressive Sword'], ['Progressive Sword']], diff --git a/worlds/alttp/test/inverted_owg/TestDungeons.py b/worlds/alttp/test/inverted_owg/TestDungeons.py index f5d07544..0d844589 100644 --- a/worlds/alttp/test/inverted_owg/TestDungeons.py +++ b/worlds/alttp/test/inverted_owg/TestDungeons.py @@ -13,16 +13,16 @@ class TestDungeons(TestInvertedOWG): ["Sanctuary", False, []], ["Sanctuary", False, ['Beat Agahnim 1']], ["Sanctuary", True, ['Magic Mirror', 'Beat Agahnim 1']], - ["Sanctuary", True, ['Lamp', 'Beat Agahnim 1', 'Small Key (Hyrule Castle)']], + ["Sanctuary", True, ['Progressive Sword', 'Lamp', 'Beat Agahnim 1', 'Small Key (Hyrule Castle)']], ["Sanctuary", True, ['Moon Pearl', 'Pegasus Boots']], ["Sanctuary", True, ['Magic Mirror', 'Pegasus Boots']], ["Sewers - Secret Room - Left", False, []], ["Sewers - Secret Room - Left", True, ['Moon Pearl', 'Progressive Glove', 'Pegasus Boots']], - ["Sewers - Secret Room - Left", True, ['Moon Pearl', 'Pegasus Boots', 'Lamp', 'Small Key (Hyrule Castle)']], - ["Sewers - Secret Room - Left", True, - ['Magic Mirror', 'Pegasus Boots', 'Lamp', 'Small Key (Hyrule Castle)']], - ["Sewers - Secret Room - Left", True, ['Beat Agahnim 1', 'Lamp', 'Small Key (Hyrule Castle)']], + ["Sewers - Secret Room - Left", True, ['Progressive Sword', 'Moon Pearl', 'Pegasus Boots', 'Lamp', 'Small Key (Hyrule Castle)']], + ["Sewers - Secret Room - Left", True, ['Progressive Sword', 'Magic Mirror', 'Pegasus Boots', 'Lamp', 'Small Key (Hyrule Castle)']], + ["Sewers - Secret Room - Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Beat Agahnim 1', 'Lamp', 'Small Key (Hyrule Castle)']], + ["Sewers - Secret Room - Left", True, ['Bomb Upgrade (+10)', 'Beat Agahnim 1', 'Lamp', 'Small Key (Hyrule Castle)']], ["Eastern Palace - Compass Chest", False, []], ["Eastern Palace - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots']], @@ -45,7 +45,7 @@ class TestDungeons(TestInvertedOWG): ["Tower of Hera - Basement Cage", True, ['Pegasus Boots', 'Moon Pearl']], ["Castle Tower - Room 03", False, []], - ["Castle Tower - Room 03", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], + ["Castle Tower - Room 03", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], ["Castle Tower - Room 03", True, ['Pegasus Boots', 'Progressive Sword']], ["Castle Tower - Room 03", True, ['Pegasus Boots', 'Progressive Bow']], @@ -62,7 +62,8 @@ class TestDungeons(TestInvertedOWG): ["Skull Woods - Big Chest", False, []], ["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']], - ["Skull Woods - Big Chest", True, ['Big Key (Skull Woods)']], + ["Skull Woods - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Skull Woods - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Skull Woods)']], ["Skull Woods - Big Key Chest", True, []], @@ -89,7 +90,16 @@ class TestDungeons(TestInvertedOWG): ["Turtle Rock - Compass Chest", True, ['Pegasus Boots', 'Quake', 'Progressive Sword', 'Cane of Somaria']], ["Turtle Rock - Chain Chomps", False, []], - ["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl']], + ["Turtle Rock - Chain Chomps", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Hookshot', 'Progressive Sword', 'Progressive Bow', 'Blue Boomerang', 'Red Boomerang', 'Cane of Somaria', 'Fire Rod', 'Ice Rod']], + ["Turtle Rock - Chain Chomps", True, ['Bomb Upgrade (+5)', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']], + ["Turtle Rock - Chain Chomps", True, ['Hookshot', 'Pegasus Boots']], + ["Turtle Rock - Chain Chomps", True, ['Progressive Bow', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']], + ["Turtle Rock - Chain Chomps", True, ['Blue Boomerang', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']], + ["Turtle Rock - Chain Chomps", True, ['Red Boomerang', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']], + ["Turtle Rock - Chain Chomps", True, ['Cane of Somaria', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']], + ["Turtle Rock - Chain Chomps", True, ['Fire Rod', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']], + ["Turtle Rock - Chain Chomps", True, ['Ice Rod', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']], + ["Turtle Rock - Chain Chomps", True, ['Progressive Sword', 'Progressive Sword', 'Pegasus Boots']], ["Turtle Rock - Crystaroller Room", False, []], ["Turtle Rock - Crystaroller Room", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl', 'Big Key (Turtle Rock)']], diff --git a/worlds/alttp/test/inverted_owg/TestInvertedOWG.py b/worlds/alttp/test/inverted_owg/TestInvertedOWG.py index a4e84fce..849f0609 100644 --- a/worlds/alttp/test/inverted_owg/TestInvertedOWG.py +++ b/worlds/alttp/test/inverted_owg/TestInvertedOWG.py @@ -13,8 +13,10 @@ from worlds.alttp.test import LTTPTestBase class TestInvertedOWG(TestBase, LTTPTestBase): def setUp(self): self.world_setup() - self.multiworld.logic[1] = "owglitches" - self.multiworld.mode[1] = "inverted" + self.multiworld.glitches_required[1] = "overworld_glitches" + self.multiworld.mode[1].value = 2 + self.multiworld.bombless_start[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = True self.multiworld.difficulty_requirements[1] = difficulties['normal'] create_inverted_regions(self.multiworld, 1) self.multiworld.worlds[1].create_dungeons() diff --git a/worlds/alttp/test/inverted_owg/TestLightWorld.py b/worlds/alttp/test/inverted_owg/TestLightWorld.py index de92b4ef..bd18259b 100644 --- a/worlds/alttp/test/inverted_owg/TestLightWorld.py +++ b/worlds/alttp/test/inverted_owg/TestLightWorld.py @@ -40,40 +40,46 @@ class TestLightWorld(TestInvertedOWG): ["Chicken House", False, []], ["Chicken House", False, [], ['Moon Pearl']], - ["Chicken House", True, ['Moon Pearl', 'Pegasus Boots']], + ["Chicken House", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Chicken House", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Aginah's Cave", False, []], ["Aginah's Cave", False, [], ['Moon Pearl']], - ["Aginah's Cave", True, ['Moon Pearl', 'Pegasus Boots']], + ["Aginah's Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Aginah's Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Sahasrahla's Hut - Left", False, []], ["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Magic Mirror']], ["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Pegasus Boots']], + ["Sahasrahla's Hut - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], ["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Pegasus Boots']], ["Sahasrahla's Hut - Left", True, ['Magic Mirror', 'Pegasus Boots']], ##todo: Damage boost superbunny not in logic #["Sahasrahla's Hut - Left", True, ['Beat Agahnim 1', 'Pegasus Boots']], - ["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], + ["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], ["Sahasrahla's Hut - Middle", False, []], ["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Magic Mirror']], ["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Pegasus Boots']], + ["Sahasrahla's Hut - Middle", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], ["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Pegasus Boots']], ["Sahasrahla's Hut - Middle", True, ['Magic Mirror', 'Pegasus Boots']], #["Sahasrahla's Hut - Middle", True, ['Beat Agahnim 1', 'Pegasus Boots']], - ["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Beat Agahnim 1']], + ["Sahasrahla's Hut - Middle", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], ["Sahasrahla's Hut - Right", False, []], ["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Magic Mirror']], ["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Pegasus Boots']], + ["Sahasrahla's Hut - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Pegasus Boots']], ["Sahasrahla's Hut - Right", True, ['Magic Mirror', 'Pegasus Boots']], #["Sahasrahla's Hut - Right", True, ['Beat Agahnim 1', 'Pegasus Boots']], - ["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], + ["Sahasrahla's Hut - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']], ["Kakariko Well - Top", False, []], ["Kakariko Well - Top", False, [], ['Moon Pearl']], - ["Kakariko Well - Top", True, ['Moon Pearl', 'Pegasus Boots']], + ["Kakariko Well - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Kakariko Well - Left", False, []], ["Kakariko Well - Left", True, ['Moon Pearl', 'Pegasus Boots']], @@ -101,7 +107,8 @@ class TestLightWorld(TestInvertedOWG): ["Blind's Hideout - Top", False, []], ["Blind's Hideout - Top", False, [], ['Moon Pearl']], - ["Blind's Hideout - Top", True, ['Moon Pearl', 'Pegasus Boots']], + ["Blind's Hideout - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Blind's Hideout - Left", False, []], ["Blind's Hideout - Left", False, [], ['Moon Pearl', 'Magic Mirror']], @@ -134,27 +141,33 @@ class TestLightWorld(TestInvertedOWG): ["Mini Moldorm Cave - Far Left", False, []], ["Mini Moldorm Cave - Far Left", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Pegasus Boots']], + ["Mini Moldorm Cave - Far Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Pegasus Boots']], ["Mini Moldorm Cave - Left", False, []], ["Mini Moldorm Cave - Left", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Pegasus Boots']], + ["Mini Moldorm Cave - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Pegasus Boots']], ["Mini Moldorm Cave - Right", False, []], ["Mini Moldorm Cave - Right", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Pegasus Boots']], + ["Mini Moldorm Cave - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Pegasus Boots']], ["Mini Moldorm Cave - Far Right", False, []], ["Mini Moldorm Cave - Far Right", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Pegasus Boots']], + ["Mini Moldorm Cave - Far Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Pegasus Boots']], ["Mini Moldorm Cave - Generous Guy", False, []], ["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']], - ["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Pegasus Boots']], + ["Mini Moldorm Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Pegasus Boots']], ["Ice Rod Cave", False, []], ["Ice Rod Cave", False, [], ['Moon Pearl']], - ["Ice Rod Cave", True, ['Moon Pearl', 'Pegasus Boots']], + ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Rod Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], #I don't think so #["Ice Rod Cave", True, ['Magic Mirror', 'Pegasus Boots', 'BigRedBomb']], #["Ice Rod Cave", True, ['Magic Mirror', 'Beat Agahnim 1', 'BigRedBomb']], @@ -236,7 +249,8 @@ class TestLightWorld(TestInvertedOWG): ["Graveyard Cave", False, []], ["Graveyard Cave", False, [], ['Moon Pearl']], - ["Graveyard Cave", True, ['Moon Pearl', 'Pegasus Boots']], + ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], ["Checkerboard Cave", False, []], ["Checkerboard Cave", False, [], ['Progressive Glove']], diff --git a/worlds/alttp/test/minor_glitches/TestDarkWorld.py b/worlds/alttp/test/minor_glitches/TestDarkWorld.py index 3a6f9725..9b0e43ea 100644 --- a/worlds/alttp/test/minor_glitches/TestDarkWorld.py +++ b/worlds/alttp/test/minor_glitches/TestDarkWorld.py @@ -7,43 +7,48 @@ class TestDarkWorld(TestMinor): self.run_location_tests([ ["Hype Cave - Top", False, []], ["Hype Cave - Top", False, [], ['Moon Pearl']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Middle Right", False, []], ["Hype Cave - Middle Right", False, [], ['Moon Pearl']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Middle Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Middle Left", False, []], ["Hype Cave - Middle Left", False, [], ['Moon Pearl']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Middle Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Bottom", False, []], ["Hype Cave - Bottom", False, [], ['Moon Pearl']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Generous Guy", False, []], ["Hype Cave - Generous Guy", False, [], ['Moon Pearl']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Stumpy", False, []], ["Stumpy", False, [], ['Moon Pearl']], @@ -66,10 +71,11 @@ class TestDarkWorld(TestMinor): self.run_location_tests([ ["Brewery", False, []], ["Brewery", False, [], ['Moon Pearl']], - ["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Brewery", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["C-Shaped House", False, []], ["C-Shaped House", False, [], ['Moon Pearl']], diff --git a/worlds/alttp/test/minor_glitches/TestDeathMountain.py b/worlds/alttp/test/minor_glitches/TestDeathMountain.py index 2603aaeb..4446ee7e 100644 --- a/worlds/alttp/test/minor_glitches/TestDeathMountain.py +++ b/worlds/alttp/test/minor_glitches/TestDeathMountain.py @@ -48,7 +48,8 @@ class TestDeathMountain(TestMinor): ["Mimic Cave", False, [], ['Moon Pearl']], ["Mimic Cave", False, [], ['Cane of Somaria']], ["Mimic Cave", False, ['Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']], - ["Mimic Cave", True, ['Quake', 'Progressive Sword', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Moon Pearl', 'Cane of Somaria', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Mimic Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Quake', 'Progressive Sword', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Moon Pearl', 'Cane of Somaria', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], ["Spiral Cave", False, []], ["Spiral Cave", False, [], ['Progressive Glove', 'Flute']], @@ -73,10 +74,11 @@ class TestDeathMountain(TestMinor): ["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Far Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Far Left", False, ['Flute', 'Hammer']], - ["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Lower - Far Left", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Far Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']], + ["Paradox Cave Lower - Far Left", True, ['Cane of Somaria', 'Flute', 'Hookshot']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Far Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Left", False, []], ["Paradox Cave Lower - Left", False, [], ['Progressive Glove', 'Flute']], @@ -87,10 +89,11 @@ class TestDeathMountain(TestMinor): ["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Left", False, ['Flute', 'Hammer']], - ["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']], + ["Paradox Cave Lower - Left", True, ['Cane of Somaria', 'Flute', 'Hookshot']], + ["Paradox Cave Lower - Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Left", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Middle", False, []], ["Paradox Cave Lower - Middle", False, [], ['Progressive Glove', 'Flute']], @@ -101,10 +104,11 @@ class TestDeathMountain(TestMinor): ["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Middle", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Middle", False, ['Flute', 'Hammer']], - ["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Middle", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']], + ["Paradox Cave Lower - Middle", True, ['Cane of Somaria', 'Flute', 'Hookshot']], + ["Paradox Cave Lower - Middle", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Middle", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Middle", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Right", False, []], ["Paradox Cave Lower - Right", False, [], ['Progressive Glove', 'Flute']], @@ -115,10 +119,11 @@ class TestDeathMountain(TestMinor): ["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Right", False, ['Flute', 'Hammer']], - ["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']], + ["Paradox Cave Lower - Right", True, ['Cane of Somaria', 'Flute', 'Hookshot']], + ["Paradox Cave Lower - Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Right", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Far Right", False, []], ["Paradox Cave Lower - Far Right", False, [], ['Progressive Glove', 'Flute']], @@ -129,10 +134,11 @@ class TestDeathMountain(TestMinor): ["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Far Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Far Right", False, ['Flute', 'Hammer']], - ["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Lower - Far Right", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Far Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']], + ["Paradox Cave Lower - Far Right", True, ['Cane of Somaria', 'Flute', 'Hookshot']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Far Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']], ["Paradox Cave Upper - Left", False, []], ["Paradox Cave Upper - Left", False, [], ['Progressive Glove', 'Flute']], @@ -143,10 +149,11 @@ class TestDeathMountain(TestMinor): ["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Upper - Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Upper - Left", False, ['Flute', 'Hammer']], - ["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot']], - ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Upper - Left", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Upper - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']], ["Paradox Cave Upper - Right", False, []], ["Paradox Cave Upper - Right", False, [], ['Progressive Glove', 'Flute']], @@ -157,10 +164,11 @@ class TestDeathMountain(TestMinor): ["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Upper - Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Upper - Right", False, ['Flute', 'Hammer']], - ["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot']], - ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Upper - Right", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Upper - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']], ]) def testWestDarkWorldDeathMountain(self): diff --git a/worlds/alttp/test/minor_glitches/TestLightWorld.py b/worlds/alttp/test/minor_glitches/TestLightWorld.py index bdfdc234..017f2d64 100644 --- a/worlds/alttp/test/minor_glitches/TestLightWorld.py +++ b/worlds/alttp/test/minor_glitches/TestLightWorld.py @@ -29,17 +29,21 @@ class TestLightWorld(TestMinor): ["Kakariko Tavern", True, []], - ["Chicken House", True, []], + ["Chicken House", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Chicken House", True, ['Bomb Upgrade (+5)']], - ["Aginah's Cave", True, []], + ["Aginah's Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Aginah's Cave", True, ['Bomb Upgrade (+5)']], - ["Sahasrahla's Hut - Left", True, []], + ["Sahasrahla's Hut - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)']], + ["Sahasrahla's Hut - Middle", True, ['Pegasus Boots']], + ["Sahasrahla's Hut - Middle", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Right", True, ['Bomb Upgrade (+5)']], + ["Sahasrahla's Hut - Right", True, ['Pegasus Boots']], - ["Sahasrahla's Hut - Middle", True, []], - - ["Sahasrahla's Hut - Right", True, []], - - ["Kakariko Well - Top", True, []], + ["Kakariko Well - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)']], ["Kakariko Well - Left", True, []], @@ -49,7 +53,8 @@ class TestLightWorld(TestMinor): ["Kakariko Well - Bottom", True, []], - ["Blind's Hideout - Top", True, []], + ["Blind's Hideout - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)']], ["Blind's Hideout - Left", True, []], @@ -63,15 +68,19 @@ class TestLightWorld(TestMinor): ["Bonk Rock Cave", False, [], ['Pegasus Boots']], ["Bonk Rock Cave", True, ['Pegasus Boots']], - ["Mini Moldorm Cave - Far Left", True, []], + ["Mini Moldorm Cave - Far Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Far Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], - ["Mini Moldorm Cave - Left", True, []], - - ["Mini Moldorm Cave - Right", True, []], - - ["Mini Moldorm Cave - Far Right", True, []], - - ["Ice Rod Cave", True, []], + ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Rod Cave", True, ['Bomb Upgrade (+5)']], ["Bottle Merchant", True, []], @@ -131,11 +140,12 @@ class TestLightWorld(TestMinor): ["Graveyard Cave", False, []], ["Graveyard Cave", False, [], ['Magic Mirror']], ["Graveyard Cave", False, [], ['Moon Pearl']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Checkerboard Cave", False, []], ["Checkerboard Cave", False, [], ['Progressive Glove']], @@ -143,8 +153,6 @@ class TestLightWorld(TestMinor): ["Checkerboard Cave", False, [], ['Magic Mirror']], ["Checkerboard Cave", True, ['Flute', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], - ["Mini Moldorm Cave - Generous Guy", True, []], - ["Library", False, []], ["Library", False, [], ['Pegasus Boots']], ["Library", True, ['Pegasus Boots']], @@ -155,7 +163,10 @@ class TestLightWorld(TestMinor): ["Potion Shop", False, [], ['Mushroom']], ["Potion Shop", True, ['Mushroom']], - ["Maze Race", True, []], + ["Maze Race", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Magic Mirror', 'Pegasus Boots']], + ["Maze Race", True, ['Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Maze Race", True, ['Bomb Upgrade (+5)']], + ["Maze Race", True, ['Pegasus Boots']], ["Desert Ledge", False, []], ["Desert Ledge", False, [], ['Book of Mudora', 'Flute']], diff --git a/worlds/alttp/test/minor_glitches/TestMinor.py b/worlds/alttp/test/minor_glitches/TestMinor.py index d5cfd309..c7de74d3 100644 --- a/worlds/alttp/test/minor_glitches/TestMinor.py +++ b/worlds/alttp/test/minor_glitches/TestMinor.py @@ -10,7 +10,9 @@ from worlds.alttp.test import LTTPTestBase class TestMinor(TestBase, LTTPTestBase): def setUp(self): self.world_setup() - self.multiworld.logic[1] = "minorglitches" + self.multiworld.glitches_required[1] = "minor_glitches" + self.multiworld.bombless_start[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = True self.multiworld.difficulty_requirements[1] = difficulties['normal'] self.multiworld.worlds[1].er_seed = 0 self.multiworld.worlds[1].create_regions() diff --git a/worlds/alttp/test/owg/TestDarkWorld.py b/worlds/alttp/test/owg/TestDarkWorld.py index 93324656..c671f648 100644 --- a/worlds/alttp/test/owg/TestDarkWorld.py +++ b/worlds/alttp/test/owg/TestDarkWorld.py @@ -7,48 +7,53 @@ class TestDarkWorld(TestVanillaOWG): self.run_location_tests([ ["Hype Cave - Top", False, []], ["Hype Cave - Top", False, [], ['Moon Pearl']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Pegasus Boots']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Middle Right", False, []], ["Hype Cave - Middle Right", False, [], ['Moon Pearl']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Pegasus Boots']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Middle Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Middle Left", False, []], ["Hype Cave - Middle Left", False, [], ['Moon Pearl']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Pegasus Boots']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Middle Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Bottom", False, []], ["Hype Cave - Bottom", False, [], ['Moon Pearl']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Pegasus Boots']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Generous Guy", False, []], ["Hype Cave - Generous Guy", False, [], ['Moon Pearl']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Pegasus Boots']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Stumpy", False, []], ["Stumpy", False, [], ['Moon Pearl']], @@ -129,13 +134,14 @@ class TestDarkWorld(TestVanillaOWG): self.run_location_tests([ ["Brewery", False, []], ["Brewery", False, [], ['Moon Pearl']], + ["Brewery", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], ["Brewery", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot', 'Progressive Glove']], - ["Brewery", True, ['Moon Pearl', 'Pegasus Boots']], - ["Brewery", True, ['Moon Pearl', 'Flute', 'Magic Mirror']], - ["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Flute', 'Magic Mirror']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["C-Shaped House", False, []], ["C-Shaped House", False, [], ['Moon Pearl', 'Magic Mirror']], diff --git a/worlds/alttp/test/owg/TestDeathMountain.py b/worlds/alttp/test/owg/TestDeathMountain.py index 41031c65..0933b288 100644 --- a/worlds/alttp/test/owg/TestDeathMountain.py +++ b/worlds/alttp/test/owg/TestDeathMountain.py @@ -48,9 +48,10 @@ class TestDeathMountain(TestVanillaOWG): ["Mimic Cave", False, [], ['Hammer']], ["Mimic Cave", False, [], ['Pegasus Boots', 'Flute', 'Lamp']], ["Mimic Cave", False, [], ['Pegasus Boots', 'Flute', 'Progressive Glove']], - ["Mimic Cave", True, ['Magic Mirror', 'Hammer', 'Pegasus Boots']], - ["Mimic Cave", True, ['Magic Mirror', 'Hammer', 'Progressive Glove', 'Lamp']], - ["Mimic Cave", True, ['Magic Mirror', 'Hammer', 'Flute']], + ["Mimic Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Hookshot', 'Hammer']], + ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Magic Mirror', 'Hammer', 'Pegasus Boots']], + ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Magic Mirror', 'Hammer', 'Progressive Glove', 'Lamp']], + ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Magic Mirror', 'Hammer', 'Flute']], ["Spiral Cave", False, []], ["Spiral Cave", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], @@ -64,65 +65,72 @@ class TestDeathMountain(TestVanillaOWG): ["Paradox Cave Lower - Far Left", False, []], ["Paradox Cave Lower - Far Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Lower - Far Left", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], - ["Paradox Cave Lower - Far Left", True, ['Pegasus Boots']], - ["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], - ["Paradox Cave Lower - Far Left", True, ['Flute', 'Magic Mirror']], + ["Paradox Cave Lower - Far Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']], + ["Paradox Cave Lower - Far Left", True, ['Fire Rod', 'Pegasus Boots']], + ["Paradox Cave Lower - Far Left", True, ['Cane of Somaria', 'Flute', 'Hookshot']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Far Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror']], ["Paradox Cave Lower - Left", False, []], ["Paradox Cave Lower - Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Lower - Left", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], - ["Paradox Cave Lower - Left", True, ['Pegasus Boots']], - ["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], - ["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror']], + ["Paradox Cave Lower - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']], + ["Paradox Cave Lower - Left", True, ['Fire Rod', 'Pegasus Boots']], + ["Paradox Cave Lower - Left", True, ['Cane of Somaria', 'Flute', 'Hookshot']], + ["Paradox Cave Lower - Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Left", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror']], ["Paradox Cave Lower - Middle", False, []], ["Paradox Cave Lower - Middle", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Lower - Middle", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], - ["Paradox Cave Lower - Middle", True, ['Pegasus Boots']], - ["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], - ["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror']], + ["Paradox Cave Lower - Middle", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']], + ["Paradox Cave Lower - Middle", True, ['Fire Rod', 'Pegasus Boots']], + ["Paradox Cave Lower - Middle", True, ['Cane of Somaria', 'Flute', 'Hookshot']], + ["Paradox Cave Lower - Middle", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Middle", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Middle", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror']], ["Paradox Cave Lower - Right", False, []], ["Paradox Cave Lower - Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Lower - Right", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], - ["Paradox Cave Lower - Right", True, ['Pegasus Boots']], - ["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], - ["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror']], + ["Paradox Cave Lower - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']], + ["Paradox Cave Lower - Right", True, ['Fire Rod', 'Pegasus Boots']], + ["Paradox Cave Lower - Right", True, ['Cane of Somaria', 'Flute', 'Hookshot']], + ["Paradox Cave Lower - Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Right", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror']], ["Paradox Cave Lower - Far Right", False, []], ["Paradox Cave Lower - Far Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Lower - Far Right", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], - ["Paradox Cave Lower - Far Right", True, ['Pegasus Boots']], - ["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], - ["Paradox Cave Lower - Far Right", True, ['Flute', 'Magic Mirror']], + ["Paradox Cave Lower - Far Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']], + ["Paradox Cave Lower - Far Right", True, ['Fire Rod', 'Pegasus Boots']], + ["Paradox Cave Lower - Far Right", True, ['Cane of Somaria', 'Flute', 'Hookshot']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Lower - Far Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror']], ["Paradox Cave Upper - Left", False, []], ["Paradox Cave Upper - Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Upper - Left", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], - ["Paradox Cave Upper - Left", True, ['Pegasus Boots']], - ["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot']], - ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], - ["Paradox Cave Upper - Left", True, ['Flute', 'Magic Mirror']], + ["Paradox Cave Upper - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Pegasus Boots']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror']], ["Paradox Cave Upper - Right", False, []], ["Paradox Cave Upper - Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Upper - Right", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], - ["Paradox Cave Upper - Right", True, ['Pegasus Boots']], - ["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot']], - ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], - ["Paradox Cave Upper - Right", True, ['Flute', 'Magic Mirror']], + ["Paradox Cave Upper - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Pegasus Boots']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Magic Mirror']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror']], ]) def testWestDarkWorldDeathMountain(self): diff --git a/worlds/alttp/test/owg/TestDungeons.py b/worlds/alttp/test/owg/TestDungeons.py index 4f878969..f4688b7a 100644 --- a/worlds/alttp/test/owg/TestDungeons.py +++ b/worlds/alttp/test/owg/TestDungeons.py @@ -6,13 +6,14 @@ class TestDungeons(TestVanillaOWG): def testFirstDungeonChests(self): self.run_location_tests([ ["Hyrule Castle - Map Chest", True, []], - ["Hyrule Castle - Map Guard Key Drop", True, []], + ["Hyrule Castle - Map Guard Key Drop", False, []], + ["Hyrule Castle - Map Guard Key Drop", True, ['Progressive Sword']], ["Sanctuary", True, []], ["Sewers - Secret Room - Left", False, []], - ["Sewers - Secret Room - Left", True, ['Progressive Glove']], - ["Sewers - Secret Room - Left", True, ['Lamp', 'Small Key (Hyrule Castle)']], + ["Sewers - Secret Room - Left", True, ['Pegasus Boots', 'Progressive Glove']], + ["Sewers - Secret Room - Left", True, ['Progressive Sword', 'Bomb Upgrade (+5)', 'Lamp', 'Small Key (Hyrule Castle)']], ["Eastern Palace - Compass Chest", True, []], @@ -41,10 +42,9 @@ class TestDungeons(TestVanillaOWG): ["Castle Tower - Room 03", False, []], ["Castle Tower - Room 03", False, ['Progressive Sword'], ['Progressive Sword', 'Cape', 'Beat Agahnim 1']], - ["Castle Tower - Room 03", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']], ["Castle Tower - Room 03", True, ['Progressive Sword', 'Progressive Sword']], - ["Castle Tower - Room 03", True, ['Cape', 'Progressive Bow']], - ["Castle Tower - Room 03", True, ['Beat Agahnim 1', 'Fire Rod']], + ["Castle Tower - Room 03", True, ['Progressive Sword', 'Cape']], + ["Castle Tower - Room 03", True, ['Progressive Sword', 'Beat Agahnim 1']], ["Palace of Darkness - Shooter Room", False, []], ["Palace of Darkness - Shooter Room", False, [], ['Moon Pearl']], @@ -69,9 +69,10 @@ class TestDungeons(TestVanillaOWG): ["Skull Woods - Big Chest", False, []], ["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']], + ["Skull Woods - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], #todo: Bomb Jump in logic? #["Skull Woods - Big Chest", True, ['Magic Mirror', 'Pegasus Boots', 'Big Key (Skull Woods)']], - ["Skull Woods - Big Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Big Key (Skull Woods)']], + ["Skull Woods - Big Chest", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots', 'Big Key (Skull Woods)']], ["Skull Woods - Big Key Chest", False, []], ["Skull Woods - Big Key Chest", True, ['Magic Mirror', 'Pegasus Boots']], @@ -111,8 +112,8 @@ class TestDungeons(TestVanillaOWG): ["Turtle Rock - Chain Chomps", False, []], #todo: does clip require sword? #["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Pegasus Boots']], - ["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Pegasus Boots', 'Progressive Sword']], - ["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror']], + ["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Pegasus Boots', 'Progressive Sword', 'Progressive Sword']], + ["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror', 'Progressive Bow']], ["Turtle Rock - Crystaroller Room", False, []], ["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)']], diff --git a/worlds/alttp/test/owg/TestLightWorld.py b/worlds/alttp/test/owg/TestLightWorld.py index f3f1ba0c..84342a33 100644 --- a/worlds/alttp/test/owg/TestLightWorld.py +++ b/worlds/alttp/test/owg/TestLightWorld.py @@ -25,17 +25,21 @@ class TestLightWorld(TestVanillaOWG): ["Kakariko Tavern", True, []], - ["Chicken House", True, []], + ["Chicken House", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Chicken House", True, ['Bomb Upgrade (+5)']], - ["Aginah's Cave", True, []], + ["Aginah's Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Aginah's Cave", True, ['Bomb Upgrade (+5)']], - ["Sahasrahla's Hut - Left", True, []], + ["Sahasrahla's Hut - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)']], + ["Sahasrahla's Hut - Middle", True, ['Pegasus Boots']], + ["Sahasrahla's Hut - Middle", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Right", True, ['Bomb Upgrade (+5)']], + ["Sahasrahla's Hut - Right", True, ['Pegasus Boots']], - ["Sahasrahla's Hut - Middle", True, []], - - ["Sahasrahla's Hut - Right", True, []], - - ["Kakariko Well - Top", True, []], + ["Kakariko Well - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)']], ["Kakariko Well - Left", True, []], @@ -45,7 +49,8 @@ class TestLightWorld(TestVanillaOWG): ["Kakariko Well - Bottom", True, []], - ["Blind's Hideout - Top", True, []], + ["Blind's Hideout - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)']], ["Blind's Hideout - Left", True, []], @@ -59,15 +64,19 @@ class TestLightWorld(TestVanillaOWG): ["Bonk Rock Cave", False, [], ['Pegasus Boots']], ["Bonk Rock Cave", True, ['Pegasus Boots']], - ["Mini Moldorm Cave - Far Left", True, []], + ["Mini Moldorm Cave - Far Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Far Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], - ["Mini Moldorm Cave - Left", True, []], - - ["Mini Moldorm Cave - Right", True, []], - - ["Mini Moldorm Cave - Far Right", True, []], - - ["Ice Rod Cave", True, []], + ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Rod Cave", True, ['Bomb Upgrade (+5)']], ["Bottle Merchant", True, []], @@ -126,12 +135,13 @@ class TestLightWorld(TestVanillaOWG): ["Graveyard Cave", False, []], ["Graveyard Cave", False, [], ['Pegasus Boots', 'Magic Mirror']], ["Graveyard Cave", False, [], ['Pegasus Boots', 'Moon Pearl']], - ["Graveyard Cave", True, ['Pegasus Boots']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Pegasus Boots']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Checkerboard Cave", False, []], ["Checkerboard Cave", False, [], ['Progressive Glove']], @@ -140,8 +150,6 @@ class TestLightWorld(TestVanillaOWG): ["Checkerboard Cave", True, ['Pegasus Boots', 'Progressive Glove']], ["Checkerboard Cave", True, ['Flute', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], - ["Mini Moldorm Cave - Generous Guy", True, []], - ["Library", False, []], ["Library", False, [], ['Pegasus Boots']], ["Library", True, ['Pegasus Boots']], @@ -152,7 +160,10 @@ class TestLightWorld(TestVanillaOWG): ["Potion Shop", False, [], ['Mushroom']], ["Potion Shop", True, ['Mushroom']], - ["Maze Race", True, []], + ["Maze Race", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Magic Mirror', 'Pegasus Boots']], + ["Maze Race", True, ['Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Maze Race", True, ['Bomb Upgrade (+5)']], + ["Maze Race", True, ['Pegasus Boots']], ["Desert Ledge", False, []], ["Desert Ledge", False, [], ['Pegasus Boots', 'Book of Mudora', 'Flute']], diff --git a/worlds/alttp/test/owg/TestVanillaOWG.py b/worlds/alttp/test/owg/TestVanillaOWG.py index 37b0b6cc..1f8f2707 100644 --- a/worlds/alttp/test/owg/TestVanillaOWG.py +++ b/worlds/alttp/test/owg/TestVanillaOWG.py @@ -11,7 +11,9 @@ class TestVanillaOWG(TestBase, LTTPTestBase): def setUp(self): self.world_setup() self.multiworld.difficulty_requirements[1] = difficulties['normal'] - self.multiworld.logic[1] = "owglitches" + self.multiworld.glitches_required[1] = "overworld_glitches" + self.multiworld.bombless_start[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = True self.multiworld.worlds[1].er_seed = 0 self.multiworld.worlds[1].create_regions() self.multiworld.worlds[1].create_items() diff --git a/worlds/alttp/test/vanilla/TestDarkWorld.py b/worlds/alttp/test/vanilla/TestDarkWorld.py index ecb3e558..8ff09c52 100644 --- a/worlds/alttp/test/vanilla/TestDarkWorld.py +++ b/worlds/alttp/test/vanilla/TestDarkWorld.py @@ -7,43 +7,48 @@ class TestDarkWorld(TestVanilla): self.run_location_tests([ ["Hype Cave - Top", False, []], ["Hype Cave - Top", False, [], ['Moon Pearl']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Middle Right", False, []], ["Hype Cave - Middle Right", False, [], ['Moon Pearl']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Middle Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Middle Left", False, []], ["Hype Cave - Middle Left", False, [], ['Moon Pearl']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Middle Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Bottom", False, []], ["Hype Cave - Bottom", False, [], ['Moon Pearl']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Hype Cave - Generous Guy", False, []], ["Hype Cave - Generous Guy", False, [], ['Moon Pearl']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Stumpy", False, []], ["Stumpy", False, [], ['Moon Pearl']], @@ -66,10 +71,11 @@ class TestDarkWorld(TestVanilla): self.run_location_tests([ ["Brewery", False, []], ["Brewery", False, [], ['Moon Pearl']], - ["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], - ["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], - ["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Brewery", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["C-Shaped House", False, []], ["C-Shaped House", False, [], ['Moon Pearl']], diff --git a/worlds/alttp/test/vanilla/TestDeathMountain.py b/worlds/alttp/test/vanilla/TestDeathMountain.py index ecb3831f..d77f1a8d 100644 --- a/worlds/alttp/test/vanilla/TestDeathMountain.py +++ b/worlds/alttp/test/vanilla/TestDeathMountain.py @@ -48,7 +48,8 @@ class TestDeathMountain(TestVanilla): ["Mimic Cave", False, [], ['Moon Pearl']], ["Mimic Cave", False, [], ['Cane of Somaria']], ["Mimic Cave", False, ['Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']], - ["Mimic Cave", True, ['Quake', 'Progressive Sword', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Moon Pearl', 'Cane of Somaria', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], + ["Mimic Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Quake', 'Progressive Sword', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Moon Pearl', 'Cane of Somaria', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']], ["Spiral Cave", False, []], ["Spiral Cave", False, [], ['Progressive Glove', 'Flute']], @@ -73,10 +74,10 @@ class TestDeathMountain(TestVanilla): ["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Far Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Far Left", False, ['Flute', 'Hammer']], - ["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Lower - Far Left", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Cane of Somaria']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']], + ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']], + ["Paradox Cave Lower - Far Left", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']], ["Paradox Cave Lower - Left", False, []], ["Paradox Cave Lower - Left", False, [], ['Progressive Glove', 'Flute']], @@ -87,10 +88,10 @@ class TestDeathMountain(TestVanilla): ["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Left", False, ['Flute', 'Hammer']], - ["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Cane of Somaria']], + ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']], + ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']], + ["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']], ["Paradox Cave Lower - Middle", False, []], ["Paradox Cave Lower - Middle", False, [], ['Progressive Glove', 'Flute']], @@ -101,10 +102,10 @@ class TestDeathMountain(TestVanilla): ["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Middle", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Middle", False, ['Flute', 'Hammer']], - ["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Cane of Somaria']], + ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']], + ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']], + ["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']], ["Paradox Cave Lower - Right", False, []], ["Paradox Cave Lower - Right", False, [], ['Progressive Glove', 'Flute']], @@ -115,10 +116,10 @@ class TestDeathMountain(TestVanilla): ["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Right", False, ['Flute', 'Hammer']], - ["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Cane of Somaria']], + ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']], + ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']], + ["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']], ["Paradox Cave Lower - Far Right", False, []], ["Paradox Cave Lower - Far Right", False, [], ['Progressive Glove', 'Flute']], @@ -129,10 +130,10 @@ class TestDeathMountain(TestVanilla): ["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Lower - Far Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Far Right", False, ['Flute', 'Hammer']], - ["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot']], - ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Lower - Far Right", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Cane of Somaria']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']], + ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']], + ["Paradox Cave Lower - Far Right", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']], ["Paradox Cave Upper - Left", False, []], ["Paradox Cave Upper - Left", False, [], ['Progressive Glove', 'Flute']], @@ -143,10 +144,11 @@ class TestDeathMountain(TestVanilla): ["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Upper - Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Upper - Left", False, ['Flute', 'Hammer']], - ["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot']], - ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Upper - Left", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Upper - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']], ["Paradox Cave Upper - Right", False, []], ["Paradox Cave Upper - Right", False, [], ['Progressive Glove', 'Flute']], @@ -157,10 +159,11 @@ class TestDeathMountain(TestVanilla): ["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot']], ["Paradox Cave Upper - Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Upper - Right", False, ['Flute', 'Hammer']], - ["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot']], - ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], - ["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], - ["Paradox Cave Upper - Right", True, ['Flute', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Upper - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], + ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']], ]) def testWestDarkWorldDeathMountain(self): diff --git a/worlds/alttp/test/vanilla/TestLightWorld.py b/worlds/alttp/test/vanilla/TestLightWorld.py index 977e8072..6d9284ab 100644 --- a/worlds/alttp/test/vanilla/TestLightWorld.py +++ b/worlds/alttp/test/vanilla/TestLightWorld.py @@ -29,17 +29,21 @@ class TestLightWorld(TestVanilla): ["Kakariko Tavern", True, []], - ["Chicken House", True, []], + ["Chicken House", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Chicken House", True, ['Bomb Upgrade (+5)']], - ["Aginah's Cave", True, []], + ["Aginah's Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Aginah's Cave", True, ['Bomb Upgrade (+5)']], - ["Sahasrahla's Hut - Left", True, []], + ["Sahasrahla's Hut - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)']], + ["Sahasrahla's Hut - Middle", True, ['Pegasus Boots']], + ["Sahasrahla's Hut - Middle", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']], + ["Sahasrahla's Hut - Right", True, ['Bomb Upgrade (+5)']], + ["Sahasrahla's Hut - Right", True, ['Pegasus Boots']], - ["Sahasrahla's Hut - Middle", True, []], - - ["Sahasrahla's Hut - Right", True, []], - - ["Kakariko Well - Top", True, []], + ["Kakariko Well - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)']], ["Kakariko Well - Left", True, []], @@ -49,7 +53,8 @@ class TestLightWorld(TestVanilla): ["Kakariko Well - Bottom", True, []], - ["Blind's Hideout - Top", True, []], + ["Blind's Hideout - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)']], ["Blind's Hideout - Left", True, []], @@ -63,15 +68,19 @@ class TestLightWorld(TestVanilla): ["Bonk Rock Cave", False, [], ['Pegasus Boots']], ["Bonk Rock Cave", True, ['Pegasus Boots']], - ["Mini Moldorm Cave - Far Left", True, []], + ["Mini Moldorm Cave - Far Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Far Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], + ["Mini Moldorm Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Progressive Sword']], - ["Mini Moldorm Cave - Left", True, []], - - ["Mini Moldorm Cave - Right", True, []], - - ["Mini Moldorm Cave - Far Right", True, []], - - ["Ice Rod Cave", True, []], + ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Ice Rod Cave", True, ['Bomb Upgrade (+5)']], ["Bottle Merchant", True, []], @@ -136,11 +145,12 @@ class TestLightWorld(TestVanilla): ["Graveyard Cave", False, []], ["Graveyard Cave", False, [], ['Magic Mirror']], ["Graveyard Cave", False, [], ['Moon Pearl']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], - ["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], + ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], + ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Checkerboard Cave", False, []], ["Checkerboard Cave", False, [], ['Progressive Glove']], @@ -148,7 +158,6 @@ class TestLightWorld(TestVanilla): ["Checkerboard Cave", False, [], ['Magic Mirror']], ["Checkerboard Cave", True, ['Flute', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], - ["Mini Moldorm Cave - Generous Guy", True, []], ["Library", False, []], ["Library", False, [], ['Pegasus Boots']], @@ -160,7 +169,10 @@ class TestLightWorld(TestVanilla): ["Potion Shop", False, [], ['Mushroom']], ["Potion Shop", True, ['Mushroom']], - ["Maze Race", True, []], + ["Maze Race", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Magic Mirror', 'Pegasus Boots']], + ["Maze Race", True, ['Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], + ["Maze Race", True, ['Bomb Upgrade (+5)']], + ["Maze Race", True, ['Pegasus Boots']], ["Desert Ledge", False, []], ["Desert Ledge", False, [], ['Book of Mudora', 'Flute']], diff --git a/worlds/alttp/test/vanilla/TestVanilla.py b/worlds/alttp/test/vanilla/TestVanilla.py index 3c983e98..3f4fbad8 100644 --- a/worlds/alttp/test/vanilla/TestVanilla.py +++ b/worlds/alttp/test/vanilla/TestVanilla.py @@ -9,8 +9,10 @@ from worlds.alttp.test import LTTPTestBase class TestVanilla(TestBase, LTTPTestBase): def setUp(self): self.world_setup() - self.multiworld.logic[1] = "noglitches" + self.multiworld.glitches_required[1] = "no_glitches" self.multiworld.difficulty_requirements[1] = difficulties['normal'] + self.multiworld.bombless_start[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = True self.multiworld.worlds[1].er_seed = 0 self.multiworld.worlds[1].create_regions() self.multiworld.worlds[1].create_items()