LttP: Bombless Start and Options/Shops overhaul (#2357)

## What is this fixing or adding?
Adds Bombless Start option, along with proper bomb logic. This involves updating `can_kill_most_things` to include checking how many bombs can be held. Many places where the ability to kill enemies was assumed, now have logic. This fixes some possible existing logic issues, for example: Mini Moldorm cave checks currently are always in logic despite the fact that on expert enemy health it would require 12 bombs to kill each mini moldorm.

Overhauls options, pulling them out of core and in particular making large changes to how the shop options work.


Co-authored-by: espeon65536 <81029175+espeon65536@users.noreply.github.com>
Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com>
Co-authored-by: Bondo <38083232+BadmoonzZ@users.noreply.github.com>
Co-authored-by: espeon65536 <espeon65536@gmail.com>
Co-authored-by: Fabian Dill <Berserker66@users.noreply.github.com>
This commit is contained in:
Alchav 2024-02-19 19:07:49 -05:00 committed by GitHub
parent 933e5bacff
commit 7a86285807
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
60 changed files with 1926 additions and 2026 deletions

View File

@ -159,11 +159,11 @@ class MultiWorld():
self.fix_trock_doors = self.AttributeProxy( self.fix_trock_doors = self.AttributeProxy(
lambda player: self.shuffle[player] != 'vanilla' or self.mode[player] == 'inverted') lambda player: self.shuffle[player] != 'vanilla' or self.mode[player] == 'inverted')
self.fix_skullwoods_exit = self.AttributeProxy( 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( 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( 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): for player in range(1, players + 1):
def set_player_attr(attr, val): def set_player_attr(attr, val):

View File

@ -315,20 +315,6 @@ def prefer_int(input_data: str) -> Union[str, int]:
return input_data 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: def roll_percentage(percentage: Union[int, float]) -> bool:
"""Roll a percentage chance. """Roll a percentage chance.
percentage is expected to be in range [0, 100]""" 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: if options[option_key].supports_weighting:
return get_choice(option_key, category_dict) return get_choice(option_key, category_dict)
return category_dict[option_key] 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}.") 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): 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 = {} ret.plando_texts = {}
if PlandoOptions.texts in plando_options: if PlandoOptions.texts in plando_options:

Binary file not shown.

View File

@ -396,8 +396,6 @@ class BuildExeCommand(cx_Freeze.command.build_exe.BuildEXE):
folders_to_remove.append(file_name) folders_to_remove.append(file_name)
shutil.rmtree(world_directory) shutil.rmtree(world_directory)
shutil.copyfile("meta.yaml", self.buildfolder / "Players" / "Templates" / "meta.yaml") 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: try:
from maseya import z3pr from maseya import z3pr
except ImportError: except ImportError:

View File

@ -6,7 +6,7 @@ from typing import Optional, Union, List, Tuple, Callable, Dict, TYPE_CHECKING
from Fill import FillError from Fill import FillError
from .Options import LTTPBosses as Bosses from .Options import LTTPBosses as Bosses
from .StateHelpers import can_shoot_arrows, can_extend_magic, can_get_good_bee, has_sword, has_beam_sword, \ 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: if TYPE_CHECKING:
from . import ALTTPWorld from . import ALTTPWorld
@ -62,7 +62,8 @@ def MoldormDefeatRule(state, player: int) -> bool:
def HelmasaurKingDefeatRule(state, player: int) -> bool: def HelmasaurKingDefeatRule(state, player: int) -> bool:
# TODO: technically possible with the hammer # 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: def ArrghusDefeatRule(state, player: int) -> bool:
@ -143,7 +144,7 @@ def GanonDefeatRule(state, player: int) -> bool:
can_hurt = has_beam_sword(state, player) can_hurt = has_beam_sword(state, player)
common = can_hurt and has_fire_source(state, player) common = can_hurt and has_fire_source(state, player)
# silverless ganon may be needed in anything higher than no glitches # 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 # need to light torch a sufficient amount of times
return common and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or ( 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 state.has('Silver Bow', player) and can_shoot_arrows(state, player)) or

View File

@ -9,7 +9,7 @@ from Fill import fill_restrictive
from .Bosses import BossFactory, Boss from .Bosses import BossFactory, Boss
from .Items import ItemFactory from .Items import ItemFactory
from .Regions import lookup_boss_drops, key_drop_data from .Regions import lookup_boss_drops, key_drop_data
from .Options import smallkey_shuffle from .Options import small_key_shuffle
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from .SubClasses import ALttPLocation, ALttPItem 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): def make_dungeon(name, default_boss, dungeon_regions, big_key, small_keys, dungeon_items):
dungeon = Dungeon(name, dungeon_regions, big_key, 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) dungeon_items, player)
for item in dungeon.all_items: for item in dungeon.all_items:
item.dungeon = dungeon item.dungeon = dungeon

View File

@ -23,7 +23,7 @@ def parse_arguments(argv, no_defaults=False):
multiargs, _ = parser.parse_known_args(argv) multiargs, _ = parser.parse_known_args(argv)
parser = argparse.ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) 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='''\ help='''\
Select Enforcement of Item Requirements. (default: %(default)s) Select Enforcement of Item Requirements. (default: %(default)s)
No Glitches: No Glitches:
@ -49,7 +49,7 @@ def parse_arguments(argv, no_defaults=False):
instead of a bunny. instead of a bunny.
''') ''')
parser.add_argument('--goal', default=defval('ganon'), const='ganon', nargs='?', 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='''\ help='''\
Select completion goal. (default: %(default)s) Select completion goal. (default: %(default)s)
Ganon: Collect all crystals, beat Agahnim 2 then Ganon: Collect all crystals, beat Agahnim 2 then
@ -92,7 +92,7 @@ def parse_arguments(argv, no_defaults=False):
Hard: Reduced functionality. Hard: Reduced functionality.
Expert: Greatly 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='''\ help='''\
Select game timer setting. Affects available itempool. (default: %(default)s) Select game timer setting. Affects available itempool. (default: %(default)s)
None: No timer. None: No timer.
@ -151,7 +151,7 @@ def parse_arguments(argv, no_defaults=False):
slightly biased to placing progression items with slightly biased to placing progression items with
less restrictions. 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='''\ help='''\
Select Entrance Shuffling Algorithm. (default: %(default)s) Select Entrance Shuffling Algorithm. (default: %(default)s)
Full: Mix cave and dungeon entrances freely while limiting 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='''\ parser.add_argument('--open_pyramid', default=defval('auto'), help='''\
Pre-opens the pyramid hole, this removes the Agahnim 2 requirement for it. 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. 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 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. goal - Opens pyramid hole if the goal specifies a fast ganon.
yes - Always opens the pyramid hole. yes - Always opens the pyramid hole.
no - Never opens the pyramid hole. no - Never opens the pyramid hole.

View File

@ -21,17 +21,17 @@ def link_entrances(world, player):
connect_simple(world, exitname, regionname, player) connect_simple(world, exitname, regionname, player)
# if we do not shuffle, set default connections # 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: for exitname, regionname in default_connections:
connect_simple(world, exitname, regionname, player) connect_simple(world, exitname, regionname, player)
for exitname, regionname in default_dungeon_connections: for exitname, regionname in default_dungeon_connections:
connect_simple(world, exitname, regionname, player) connect_simple(world, exitname, regionname, player)
elif world.shuffle[player] == 'dungeonssimple': elif world.entrance_shuffle[player] == 'dungeons_simple':
for exitname, regionname in default_connections: for exitname, regionname in default_connections:
connect_simple(world, exitname, regionname, player) connect_simple(world, exitname, regionname, player)
simple_shuffle_dungeons(world, player) simple_shuffle_dungeons(world, player)
elif world.shuffle[player] == 'dungeonsfull': elif world.entrance_shuffle[player] == 'dungeons_full':
for exitname, regionname in default_connections: for exitname, regionname in default_connections:
connect_simple(world, exitname, regionname, player) 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, 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_mandatory_exits(world, dw_entrances, dungeon_exits, list(DW_Dungeon_Entrances_Must_Exit), player)
connect_caves(world, lw_entrances, dw_entrances, dungeon_exits, 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) crossed_shuffle_dungeons(world, player)
elif world.shuffle[player] == 'simple': elif world.entrance_shuffle[player] == 'simple':
simple_shuffle_dungeons(world, player) simple_shuffle_dungeons(world, player)
old_man_entrances = list(Old_Man_Entrances) old_man_entrances = list(Old_Man_Entrances)
@ -136,7 +136,7 @@ def link_entrances(world, player):
# place remaining doors # place remaining doors
connect_doors(world, single_doors, door_targets, player) connect_doors(world, single_doors, door_targets, player)
elif world.shuffle[player] == 'restricted': elif world.entrance_shuffle[player] == 'restricted':
simple_shuffle_dungeons(world, player) simple_shuffle_dungeons(world, player)
lw_entrances = list(LW_Entrances + LW_Single_Cave_Doors + Old_Man_Entrances) lw_entrances = list(LW_Entrances + LW_Single_Cave_Doors + Old_Man_Entrances)
@ -207,62 +207,8 @@ def link_entrances(world, player):
# place remaining doors # place remaining doors
connect_doors(world, doors, door_targets, player) connect_doors(world, doors, door_targets, player)
elif world.shuffle[player] == 'restricted_legacy':
simple_shuffle_dungeons(world, player)
lw_entrances = list(LW_Entrances) elif world.entrance_shuffle[player] == 'full':
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':
skull_woods_shuffle(world, player) skull_woods_shuffle(world, player)
lw_entrances = list(LW_Entrances + LW_Dungeon_Entrances + LW_Single_Cave_Doors + Old_Man_Entrances) 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 # place remaining doors
connect_doors(world, doors, door_targets, player) connect_doors(world, doors, door_targets, player)
elif world.shuffle[player] == 'crossed': elif world.entrance_shuffle[player] == 'crossed':
skull_woods_shuffle(world, player) 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) 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 # place remaining doors
connect_doors(world, entrances, door_targets, player) 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) elif world.entrance_shuffle[player] == 'insanity':
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':
# beware ye who enter here # 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 = 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 # place remaining doors
connect_doors(world, doors, door_targets, player) 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: else:
raise NotImplementedError( 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) overworld_glitch_connections(world, player)
# mandatory hybrid major glitches connections # 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) underworld_glitch_connections(world, player)
# check for swamp palace fix # check for swamp palace fix
@ -1106,17 +581,17 @@ def link_inverted_entrances(world, player):
connect_simple(world, exitname, regionname, player) connect_simple(world, exitname, regionname, player)
# if we do not shuffle, set default connections # 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: for exitname, regionname in inverted_default_connections:
connect_simple(world, exitname, regionname, player) connect_simple(world, exitname, regionname, player)
for exitname, regionname in inverted_default_dungeon_connections: for exitname, regionname in inverted_default_dungeon_connections:
connect_simple(world, exitname, regionname, player) 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: for exitname, regionname in inverted_default_connections:
connect_simple(world, exitname, regionname, player) connect_simple(world, exitname, regionname, player)
simple_shuffle_dungeons(world, 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: for exitname, regionname in inverted_default_connections:
connect_simple(world, exitname, regionname, player) 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_mandatory_exits(world, lw_entrances, dungeon_exits, lw_dungeon_entrances_must_exit, player)
connect_caves(world, lw_entrances, dw_entrances, dungeon_exits, 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) inverted_crossed_shuffle_dungeons(world, player)
elif world.shuffle[player] == 'simple': elif world.entrance_shuffle[player] == 'simple':
simple_shuffle_dungeons(world, player) simple_shuffle_dungeons(world, player)
old_man_entrances = list(Inverted_Old_Man_Entrances) old_man_entrances = list(Inverted_Old_Man_Entrances)
@ -1270,7 +745,7 @@ def link_inverted_entrances(world, player):
# place remaining doors # place remaining doors
connect_doors(world, single_doors, door_targets, player) connect_doors(world, single_doors, door_targets, player)
elif world.shuffle[player] == 'restricted': elif world.entrance_shuffle[player] == 'restricted':
simple_shuffle_dungeons(world, player) simple_shuffle_dungeons(world, player)
lw_entrances = list(Inverted_LW_Entrances + Inverted_LW_Single_Cave_Doors) 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 doors = lw_entrances + dw_entrances
# place remaining doors # place remaining doors
connect_doors(world, doors, door_targets, player) connect_doors(world, doors, door_targets, player)
elif world.shuffle[player] == 'full': elif world.entrance_shuffle[player] == 'full':
skull_woods_shuffle(world, player) skull_woods_shuffle(world, player)
lw_entrances = list(Inverted_LW_Entrances + Inverted_LW_Dungeon_Entrances + Inverted_LW_Single_Cave_Doors) 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 # place remaining doors
connect_doors(world, doors, door_targets, player) connect_doors(world, doors, door_targets, player)
elif world.shuffle[player] == 'crossed': elif world.entrance_shuffle[player] == 'crossed':
skull_woods_shuffle(world, player) 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) 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 # place remaining doors
connect_doors(world, entrances, door_targets, player) connect_doors(world, entrances, door_targets, player)
elif world.shuffle[player] == 'insanity': elif world.entrance_shuffle[player] == 'insanity':
# beware ye who enter here # 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)'] 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: else:
raise NotImplementedError('Shuffling not supported yet') 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) overworld_glitch_connections(world, player)
# mandatory hybrid major glitches connections # 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) underworld_glitch_connections(world, player)
# patch swamp drain # patch swamp drain
@ -1880,14 +1355,14 @@ def scramble_holes(world, player):
hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance')) hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance'))
# do not shuffle sanctuary into pyramid hole unless shuffle is crossed # 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')) hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
if world.shuffle_ganon: if world.shuffle_ganon:
world.random.shuffle(hole_targets) world.random.shuffle(hole_targets)
exit, target = hole_targets.pop() exit, target = hole_targets.pop()
connect_two_way(world, 'Pyramid Entrance', exit, player) connect_two_way(world, 'Pyramid Entrance', exit, player)
connect_entrance(world, 'Pyramid Hole', target, 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')) hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
world.random.shuffle(hole_targets) 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')) hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance'))
# do not shuffle sanctuary into pyramid hole unless shuffle is crossed # 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')) hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
if world.shuffle_ganon: if world.shuffle_ganon:
world.random.shuffle(hole_targets) world.random.shuffle(hole_targets)
exit, target = hole_targets.pop() exit, target = hole_targets.pop()
connect_two_way(world, 'Inverted Pyramid Entrance', exit, player) connect_two_way(world, 'Inverted Pyramid Entrance', exit, player)
connect_entrance(world, 'Inverted Pyramid Hole', target, 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')) hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
world.random.shuffle(hole_targets) 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_connections = Must_Exit_Invalid_Connections.copy()
invalid_cave_connections = defaultdict(set) 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 from worlds.alttp import OverworldGlitchRules
for entrance in OverworldGlitchRules.get_non_mandatory_exits(world.mode[player] == 'inverted'): for entrance in OverworldGlitchRules.get_non_mandatory_exits(world.mode[player] == 'inverted'):
invalid_connections[entrance] = set() invalid_connections[entrance] = set()
@ -3038,6 +2513,7 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
('Sanctuary Push Door', 'Sanctuary'), ('Sanctuary Push Door', 'Sanctuary'),
('Sewer Drop', 'Sewers'), ('Sewer Drop', 'Sewers'),
('Sewers Back Door', 'Sewers (Dark)'), ('Sewers Back Door', 'Sewers (Dark)'),
('Sewers Secret Room', 'Sewers Secret Room'),
('Agahnim 1', 'Agahnim 1'), ('Agahnim 1', 'Agahnim 1'),
('Flute Spot 1', 'Death Mountain'), ('Flute Spot 1', 'Death Mountain'),
('Death Mountain Entrance Rock', 'Death Mountain Entrance'), ('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 Access', 'Spiral Cave Ledge'),
('Spiral Cave Ledge Drop', 'East Death Mountain (Bottom)'), ('Spiral Cave Ledge Drop', 'East Death Mountain (Bottom)'),
('Spiral Cave (top to bottom)', 'Spiral Cave (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)'), ('East Death Mountain (Top)', 'East Death Mountain (Top)'),
('Death Mountain (Top)', 'Death Mountain (Top)'), ('Death Mountain (Top)', 'Death Mountain (Top)'),
('Death Mountain Drop', 'Death Mountain'), ('Death Mountain Drop', 'Death Mountain'),
@ -3227,6 +2705,7 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
('Sanctuary Push Door', 'Sanctuary'), ('Sanctuary Push Door', 'Sanctuary'),
('Sewer Drop', 'Sewers'), ('Sewer Drop', 'Sewers'),
('Sewers Back Door', 'Sewers (Dark)'), ('Sewers Back Door', 'Sewers (Dark)'),
('Sewers Secret Room', 'Sewers Secret Room'),
('Agahnim 1', 'Agahnim 1'), ('Agahnim 1', 'Agahnim 1'),
('Death Mountain Entrance Rock', 'Death Mountain Entrance'), ('Death Mountain Entrance Rock', 'Death Mountain Entrance'),
('Death Mountain Entrance Drop', 'Light World'), ('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 Access', 'Spiral Cave Ledge'),
('Spiral Cave Ledge Drop', 'East Death Mountain (Bottom)'), ('Spiral Cave Ledge Drop', 'East Death Mountain (Bottom)'),
('Spiral Cave (top to bottom)', 'Spiral Cave (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)'), ('East Death Mountain (Top)', 'East Death Mountain (Top)'),
('Death Mountain (Top)', 'Death Mountain (Top)'), ('Death Mountain (Top)', 'Death Mountain (Top)'),
('Death Mountain Drop', 'Death Mountain'), ('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)'), ('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'),
('Hookshot Cave Exit (South)', 'Dark Death Mountain (Top)'), ('Hookshot Cave Exit (South)', 'Dark Death Mountain (Top)'),
('Hookshot Cave Exit (North)', 'Death Mountain Floating Island (Dark World)'), ('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'), ('Mimic Cave', 'Mimic Cave'),
('Pyramid Hole', 'Pyramid'), ('Pyramid Hole', 'Pyramid'),
@ -3703,7 +3184,7 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
('Superbunny Cave (Bottom)', 'Superbunny Cave (Bottom)'), ('Superbunny Cave (Bottom)', 'Superbunny Cave (Bottom)'),
('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'), ('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'),
('Hookshot Cave Exit (North)', 'Death Mountain Floating Island (Dark World)'), ('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'), ('Mimic Cave', 'Mimic Cave'),
('Inverted Pyramid Hole', 'Pyramid'), ('Inverted Pyramid Hole', 'Pyramid'),
('Inverted Links House', 'Inverted Links House'), ('Inverted Links House', 'Inverted Links House'),

View File

@ -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, 'Kakariko Gamble Game', 'a game of chance'),
create_cave_region(world, player, 'Potion Shop', 'the potion shop', ['Potion Shop']), create_cave_region(world, player, 'Potion Shop', 'the potion shop', ['Potion Shop']),
create_lw_region(world, player, 'Lake Hylia Island', ['Lake Hylia Island']), 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, create_cave_region(world, player, 'Two Brothers House', 'a connector', None,
['Two Brothers House Exit (East)', 'Two Brothers House Exit (West)']), ['Two Brothers House Exit (East)', 'Two Brothers House Exit (West)']),
create_lw_region(world, player, 'Maze Race Ledge', ['Maze Race'], create_lw_region(world, player, 'Maze Race Ledge', ['Maze Race'],
@ -176,8 +176,9 @@ def create_inverted_regions(world, player):
'Throne Room']), '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, '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 (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', create_dungeon_region(world, player, 'Sewers', 'a drop\'s exit', None, ['Sanctuary Push Door', 'Sewers Back Door', 'Sewers Secret Room']),
'Sewers - Secret Room - Right'], ['Sanctuary Push Door', 'Sewers Back Door']), 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, '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, '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), 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', create_cave_region(world, player, 'Hookshot Cave', 'a connector',
['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right',
'Hookshot Cave - Bottom Left'], '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, create_dw_region(world, player, 'Death Mountain Floating Island (Dark World)', None,
['Floating Island Drop', 'Hookshot Cave Back Entrance']), ['Floating Island Drop', 'Hookshot Cave Back Entrance']),
create_cave_region(world, player, 'Mimic Cave', 'Mimic Cave', ['Mimic Cave']), 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 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 (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, '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 (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 - Compass Chest'], ['Ice Palace (Main)']), 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', create_dungeon_region(world, player, 'Ice Palace (Main)', 'Ice Palace', ['Ice Palace - Freezor Chest',
'Ice Palace - Many Pots Pot Key', 'Ice Palace - Many Pots Pot Key',
'Ice Palace - Big Chest', 'Ice Palace - Iced T Room'], ['Ice Palace (East)', 'Ice Palace (Kholdstare)']), 'Ice Palace - Big Chest', 'Ice Palace - Iced T Room'], ['Ice Palace (East)', 'Ice Palace (Kholdstare)']),

View File

@ -5,12 +5,12 @@ from BaseClasses import ItemClassification
from Fill import FillError from Fill import FillError
from .SubClasses import ALttPLocation, LTTPRegion, LTTPRegionType 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 .Bosses import place_bosses
from .Dungeons import get_dungeon_item_pool_player from .Dungeons import get_dungeon_item_pool_player
from .EntranceShuffle import connect_entrance from .EntranceShuffle import connect_entrance
from .Items import ItemFactory, GetBeemizerItem from .Items import ItemFactory, GetBeemizerItem, trap_replaceable, item_name_groups
from .Options import smallkey_shuffle, compass_shuffle, bigkey_shuffle, map_shuffle, LTTPBosses from .Options import small_key_shuffle, compass_shuffle, big_key_shuffle, map_shuffle, TriforcePiecesMode
from .StateHelpers import has_triforce_pieces, has_melee_weapon from .StateHelpers import has_triforce_pieces, has_melee_weapon
from .Regions import key_drop_data from .Regions import key_drop_data
@ -189,104 +189,62 @@ difficulties = {
), ),
} }
ice_rod_hunt_difficulties = dict()
for diff in {'easy', 'normal', 'hard', 'expert'}: items_reduction_table = (
ice_rod_hunt_difficulties[diff] = Difficulty( ("Piece of Heart", "Boss Heart Container", 4, 1),
baseitems=['Nothing'] * 41, # the order of the upgrades is important
bottles=['Nothing'] * 4, ("Arrow Upgrade (+5)", "Arrow Upgrade (+10)", 8, 4),
bottle_count=difficulties[diff].bottle_count, ("Arrow Upgrade (+5)", "Arrow Upgrade (+10)", 7, 4),
same_bottle=difficulties[diff].same_bottle, ("Arrow Upgrade (+5)", "Arrow Upgrade (+10)", 6, 3),
progressiveshield=['Nothing'] * 3, ("Arrow Upgrade (+10)", "Arrow Upgrade (70)", 4, 1),
basicshield=['Nothing'] * 3, ("Bomb Upgrade (+5)", "Bomb Upgrade (+10)", 8, 4),
progressivearmor=['Nothing'] * 2, ("Bomb Upgrade (+5)", "Bomb Upgrade (+10)", 7, 4),
basicarmor=['Nothing'] * 2, ("Bomb Upgrade (+5)", "Bomb Upgrade (+10)", 6, 3),
swordless=['Nothing'] * 4, ("Bomb Upgrade (+10)", "Bomb Upgrade (50)", 5, 1),
progressivemagic=['Nothing'] * 2, ("Bomb Upgrade (+10)", "Bomb Upgrade (50)", 4, 1),
basicmagic=['Nothing'] * 2, ("Progressive Sword", 4),
progressivesword=['Nothing'] * 4, ("Fighter Sword", 1),
basicsword=['Nothing'] * 4, ("Master Sword", 1),
progressivebow=['Nothing'] * 2, ("Tempered Sword", 1),
basicbow=['Nothing'] * 2, ("Golden Sword", 1),
timedohko=difficulties[diff].timedohko, ("Progressive Shield", 3),
timedother=difficulties[diff].timedother, ("Blue Shield", 1),
progressiveglove=['Nothing'] * 2, ("Red Shield", 1),
basicglove=['Nothing'] * 2, ("Mirror Shield", 1),
alwaysitems=['Ice Rod'] + ['Nothing'] * 19, ("Progressive Mail", 2),
legacyinsanity=['Nothing'] * 2, ("Blue Mail", 1),
universal_keys=['Nothing'] * 29, ("Red Mail", 1),
extras=[['Nothing'] * 15, ['Nothing'] * 15, ['Nothing'] * 10, ['Nothing'] * 5, ['Nothing'] * 25], ("Progressive Bow", 2),
progressive_sword_limit=difficulties[diff].progressive_sword_limit, ("Bow", 1),
progressive_shield_limit=difficulties[diff].progressive_shield_limit, ("Silver Bow", 1),
progressive_armor_limit=difficulties[diff].progressive_armor_limit, ("Lamp", 1),
progressive_bow_limit=difficulties[diff].progressive_bow_limit, ("Bottles",)
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,
)
def generate_itempool(world): def generate_itempool(world):
player = world.player player = world.player
multiworld = world.multiworld multiworld = world.multiworld
if multiworld.difficulty[player] not in difficulties: if multiworld.item_pool[player].current_key not in difficulties:
raise NotImplementedError(f"Diffulty {multiworld.difficulty[player]}") raise NotImplementedError(f"Diffulty {multiworld.item_pool[player]}")
if multiworld.goal[player] not in {'ganon', 'pedestal', 'bosses', 'triforcehunt', 'localtriforcehunt', 'icerodhunt', if multiworld.goal[player] not in ('ganon', 'pedestal', 'bosses', 'triforce_hunt', 'local_triforce_hunt',
'ganontriforcehunt', 'localganontriforcehunt', 'crystals', 'ganonpedestal'}: 'ganon_triforce_hunt', 'local_ganon_triforce_hunt', 'crystals',
'ganon_pedestal'):
raise NotImplementedError(f"Goal {multiworld.goal[player]} for player {player}") 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}") 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}") 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 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) multiworld.push_item(multiworld.get_location('Ganon', player), ItemFactory('Nothing', player), False)
else: else:
multiworld.push_item(multiworld.get_location('Ganon', player), ItemFactory('Triforce', player), False) multiworld.push_item(multiworld.get_location('Ganon', player), ItemFactory('Triforce', player), False)
if multiworld.goal[player] == 'icerodhunt': if multiworld.goal[player] in ['triforce_hunt', 'local_triforce_hunt']:
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']:
region = multiworld.get_region('Light World', player) region = multiworld.get_region('Light World', player)
loc = ALttPLocation(player, "Murahdahla", parent=region) loc = ALttPLocation(player, "Murahdahla", parent=region)
@ -308,7 +266,8 @@ def generate_itempool(world):
('Missing Smith', 'Return Smith'), ('Missing Smith', 'Return Smith'),
('Floodgate', 'Open Floodgate'), ('Floodgate', 'Open Floodgate'),
('Agahnim 1', 'Beat Agahnim 1'), ('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: for location_name, event_name in event_pairs:
location = multiworld.get_location(location_name, player) location = multiworld.get_location(location_name, player)
@ -340,17 +299,31 @@ def generate_itempool(world):
if not found_sword: if not found_sword:
found_sword = True found_sword = True
possible_weapons.append(item) 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 found_bow = True
possible_weapons.append(item) 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: if item not in possible_weapons:
possible_weapons.append(item) 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) starting_weapon = multiworld.random.choice(possible_weapons)
placed_items["Link's Uncle"] = starting_weapon placed_items["Link's Uncle"] = starting_weapon
pool.remove(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']: if (placed_items["Link's Uncle"] in ['Bow', 'Progressive Bow', 'Bombs (10)', 'Bomb Upgrade (+10)',
multiworld.escape_assist[player].append('bombs') '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(): for (location, item) in placed_items.items():
multiworld.get_location(location, player).place_locked_item(ItemFactory(item, player)) 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: for key_loc in key_drop_data:
key_data = key_drop_data[key_loc] key_data = key_drop_data[key_loc]
drop_item = ItemFactory(key_data[3], player) 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: if drop_item in dungeon_items:
dungeon_items.remove(drop_item) dungeon_items.remove(drop_item)
else: else:
@ -391,88 +364,151 @@ def generate_itempool(world):
world.dungeons[dungeon].small_keys.remove(drop_item) 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: elif world.dungeons[dungeon].big_key is not None and world.dungeons[dungeon].big_key == drop_item:
world.dungeons[dungeon].big_key = None 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 = multiworld.get_location(key_loc, player)
loc.place_locked_item(drop_item) loc.place_locked_item(drop_item)
loc.address = None loc.address = None
elif multiworld.goal[player] == 'icerodhunt': elif "Small" in key_data[3] and multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal:
# 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:
# key drop shuffle and universal keys are on. Add universal keys in place of key drop keys. # 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 dungeon_item_replacements = sum(difficulties[multiworld.difficulty[player]].extras, []) * 2
multiworld.random.shuffle(dungeon_item_replacements) multiworld.random.shuffle(dungeon_item_replacements)
if multiworld.goal[player] == 'icerodhunt':
for item in dungeon_items: for x in range(len(dungeon_items)-1, -1, -1):
multiworld.itempool.append(ItemFactory(GetBeemizerItem(multiworld, player, 'Nothing'), player)) 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) multiworld.push_precollected(item)
else: multiworld.itempool.append(ItemFactory(dungeon_item_replacements.pop(), player))
for x in range(len(dungeon_items)-1, -1, -1): multiworld.itempool.extend([item for item in dungeon_items])
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
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) set_up_shops(multiworld, player)
if multiworld.shop_shuffle[player]: if multiworld.retro_bow[player]:
shuffle_shops(multiworld, nonprogressionitems, 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]: if multiworld.retro_caves[player]:
set_up_take_anys(multiworld, player) # depends on world.itempool to be set 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 = { take_any_locations = {
@ -516,9 +552,14 @@ def set_up_take_anys(world, player):
sword = world.random.choice(swords) sword = world.random.choice(swords)
world.itempool.remove(sword) world.itempool.remove(sword)
world.itempool.append(ItemFactory('Rupees (20)', player)) 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: 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): for num in range(4):
take_any = LTTPRegion("Take-Any #{}".format(num+1), LTTPRegionType.Cave, 'a cave of choice', player, world) 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) take_any.shop = TakeAny(take_any, room_id, 0xE3, True, True, total_shop_slots + num + 1)
world.shops.append(take_any.shop) world.shops.append(take_any.shop)
take_any.shop.add_inventory(0, 'Blue Potion', 0, 0) 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): def get_pool_core(world, player: int):
shuffle = world.shuffle[player] shuffle = world.entrance_shuffle[player].current_key
difficulty = world.difficulty[player] difficulty = world.item_pool[player].current_key
timer = world.timer[player] timer = world.timer[player].current_key
goal = world.goal[player] goal = world.goal[player].current_key
mode = world.mode[player] mode = world.mode[player].current_key
swordless = world.swordless[player] swordless = world.swordless[player]
retro_bow = world.retro_bow[player] retro_bow = world.retro_bow[player]
logic = world.logic[player] logic = world.glitches_required[player]
pool = [] pool = []
placed_items = {} placed_items = {}
@ -552,7 +597,7 @@ def get_pool_core(world, player: int):
treasure_hunt_count = None treasure_hunt_count = None
treasure_hunt_icon = None treasure_hunt_icon = None
diff = ice_rod_hunt_difficulties[difficulty] if goal == 'icerodhunt' else difficulties[difficulty] diff = difficulties[difficulty]
pool.extend(diff.alwaysitems) pool.extend(diff.alwaysitems)
def place_item(loc, item): def place_item(loc, item):
@ -560,7 +605,7 @@ def get_pool_core(world, player: int):
placed_items[loc] = item placed_items[loc] = item
# provide boots to major glitch dependent seeds # 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') precollected_items.append('Pegasus Boots')
pool.remove('Pegasus Boots') pool.remove('Pegasus Boots')
pool.append('Rupees (20)') pool.append('Rupees (20)')
@ -611,7 +656,7 @@ def get_pool_core(world, player: int):
if want_progressives(world.random): if want_progressives(world.random):
pool.extend(diff.progressivebow) pool.extend(diff.progressivebow)
world.worlds[player].has_progressive_bows = True 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'] swordless_bows = ['Bow', 'Silver Bow']
if difficulty == "easy": if difficulty == "easy":
swordless_bows *= 2 swordless_bows *= 2
@ -627,21 +672,32 @@ def get_pool_core(world, player: int):
extraitems = total_items_to_place - len(pool) - len(placed_items) 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) pool.extend(diff.timedother)
extraitems -= len(diff.timedother) extraitems -= len(diff.timedother)
clock_mode = 'stopwatch' if timer == 'timed' else 'countdown' clock_mode = 'stopwatch' if timer == 'timed' else 'countdown'
elif timer == 'timed-ohko': elif timer == 'timed_ohko':
pool.extend(diff.timedohko) pool.extend(diff.timedohko)
extraitems -= len(diff.timedohko) extraitems -= len(diff.timedohko)
clock_mode = 'countdown-ohko' clock_mode = 'countdown-ohko'
additional_pieces_to_place = 0 additional_pieces_to_place = 0
if 'triforcehunt' in goal: if 'triforce_hunt' 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 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) pool.extend(["Triforce Piece"] * pieces_in_core)
extraitems -= 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' treasure_hunt_icon = 'Triforce Piece'
for extra in diff.extras: for extra in diff.extras:
@ -659,12 +715,12 @@ def get_pool_core(world, player: int):
pool.remove("Rupees (20)") pool.remove("Rupees (20)")
if retro_bow: 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] 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) pool.extend(diff.universal_keys)
if mode == 'standard': 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_locations = ['Secret Passage', 'Hyrule Castle - Map Guard Key Drop']
key_location = world.random.choice(key_locations) key_location = world.random.choice(key_locations)
key_locations.remove(key_location) key_locations.remove(key_location)
@ -688,8 +744,8 @@ def get_pool_core(world, player: int):
def make_custom_item_pool(world, player): def make_custom_item_pool(world, player):
shuffle = world.shuffle[player] shuffle = world.entrance_shuffle[player]
difficulty = world.difficulty[player] difficulty = world.item_pool[player]
timer = world.timer[player] timer = world.timer[player]
goal = world.goal[player] goal = world.goal[player]
mode = world.mode[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_count = world.triforce_pieces_required[player]
treasure_hunt_icon = 'Triforce Piece' treasure_hunt_icon = 'Triforce Piece'
if timer in ['display', 'timed', 'timed-countdown']: if timer in ['display', 'timed', 'timed_countdown']:
clock_mode = 'countdown' if timer == 'timed-countdown' else 'stopwatch' clock_mode = 'countdown' if timer == 'timed_countdown' else 'stopwatch'
elif timer == 'timed-ohko': elif timer == 'timed_ohko':
clock_mode = 'countdown-ohko' clock_mode = 'countdown-ohko'
elif timer == 'ohko': elif timer == 'ohko':
clock_mode = 'ohko' clock_mode = 'ohko'
@ -810,7 +866,7 @@ def make_custom_item_pool(world, player):
itemtotal = itemtotal + 1 itemtotal = itemtotal + 1
if mode == 'standard': 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( key_location = world.random.choice(
['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest', ['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest',
'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross']) '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(['Magic Mirror'] * customitemarray[22])
pool.extend(['Moon Pearl'] * customitemarray[28]) 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 itemtotal = itemtotal - 28 # Corrects for small keys not being in item pool in universal Mode
if world.key_drop_shuffle[player]: if world.key_drop_shuffle[player]:
itemtotal = itemtotal - (len(key_drop_data) - 1) itemtotal = itemtotal - (len(key_drop_data) - 1)

View File

@ -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"), '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'), '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'), '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 (+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.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 (+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'), '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 (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'), '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 (+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.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 (+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'), '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'), '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'), '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), '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), '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), '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()} 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_table[name].classification in {IC.progression, IC.progression_skip_balancing}}
item_name_groups['Progression Items'] = progression_items item_name_groups['Progression Items'] = progression_items
item_name_groups['Non Progression Items'] = everything - 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'} trap_replaceable = item_name_groups['Rupees'] | {'Arrows (10)', 'Single Bomb', 'Bombs (3)', 'Bombs (10)', 'Nothing'}

View File

@ -1,10 +1,18 @@
import typing import typing
from BaseClasses import MultiWorld 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_no_glitches = 0
option_minor_glitches = 1 option_minor_glitches = 1
option_overworld_glitches = 2 option_overworld_glitches = 2
@ -12,20 +20,122 @@ class Logic(Choice):
option_no_logic = 4 option_no_logic = 4
alias_owg = 2 alias_owg = 2
alias_hmg = 3 alias_hmg = 3
alias_none = 0
class Objective(Choice): class DarkRoomLogic(Choice):
option_crystals = 0 """Logic for unlit dark rooms. Lamp: require the Lamp for these rooms to be considered accessible.
# option_pendants = 1 Torches: in addition to lamp, allow the fire rod and presence of easily accessible torches for access.
option_triforce_pieces = 2 None: all dark rooms are always considered doable, meaning this may force completion of rooms in complete darkness."""
option_pedestal = 3 display_name = "Dark Room Logic"
option_bingo = 4 option_lamp = 0
option_torches = 1
option_none = 2
default = 0
class Goal(Choice): class Goal(Choice):
option_kill_ganon = 0 """Ganon: Climb GT, defeat Agahnim 2, and then kill Ganon
option_kill_ganon_and_gt_agahnim = 1 Crystals: Only killing Ganon is required. However, items may still be placed in GT
option_hand_in = 2 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): class OpenPyramid(Choice):
@ -44,10 +154,10 @@ class OpenPyramid(Choice):
def to_bool(self, world: MultiWorld, player: int) -> bool: def to_bool(self, world: MultiWorld, player: int) -> bool:
if self.value == self.option_goal: 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: elif self.value == self.option_auto:
return world.goal[player] in {'crystals', 'ganontriforcehunt', 'localganontriforcehunt', 'ganonpedestal'} \ return world.goal[player] in {'crystals', 'ganon_triforce_hunt', 'local_ganon_triforce_hunt', 'ganon_pedestal'} \
and (world.shuffle[player] in {'vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed'} or not and (world.entrance_shuffle[player] in {'vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed'} or not
world.shuffle_ganon) world.shuffle_ganon)
elif self.value == self.option_open: elif self.value == self.option_open:
return True return True
@ -76,13 +186,13 @@ class DungeonItem(Choice):
return self.value in {1, 2, 3, 4} return self.value in {1, 2, 3, 4}
class bigkey_shuffle(DungeonItem): class big_key_shuffle(DungeonItem):
"""Big Key Placement""" """Big Key Placement"""
item_name_group = "Big Keys" item_name_group = "Big Keys"
display_name = "Big Key Shuffle" display_name = "Big Key Shuffle"
class smallkey_shuffle(DungeonItem): class small_key_shuffle(DungeonItem):
"""Small Key Placement""" """Small Key Placement"""
option_universal = 5 option_universal = 5
item_name_group = "Small Keys" item_name_group = "Small Keys"
@ -107,6 +217,149 @@ class key_drop_shuffle(Toggle):
display_name = "Key Drop Shuffle" 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): class Crystals(Range):
range_start = 0 range_start = 0
range_end = 7 range_end = 7
@ -137,18 +390,52 @@ class ShopItemSlots(Range):
range_end = 30 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): class ShopPriceModifier(Range):
"""Percentage modifier for shuffled item prices in shops""" """Percentage modifier for shuffled item prices in shops"""
display_name = "Shop Price Cost Percent" display_name = "Shop Price Modifier"
range_start = 0 range_start = 0
default = 100 default = 100
range_end = 400 range_end = 400
class WorldState(Choice): class IncludeWitchHut(Toggle):
option_standard = 1 """Consider witch's hut like any other shop and shuffle/randomize it too"""
option_open = 0 display_name = "Include Witch's Hut"
option_inverted = 2
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): class LTTPBosses(PlandoBosses):
@ -236,6 +523,11 @@ class Swordless(Toggle):
display_name = "Swordless" 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 # 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 # Defer to Progressive Option (default), Progressive, Non-Progressive, Bow + Silvers, Retro
class RetroBow(Toggle): class RetroBow(Toggle):
@ -433,29 +725,66 @@ class AllowCollect(Toggle):
alttp_options: typing.Dict[str, type(Option)] = { 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_gt": CrystalsTower,
"crystals_needed_for_ganon": CrystalsGanon, "crystals_needed_for_ganon": CrystalsGanon,
"open_pyramid": OpenPyramid, "triforce_pieces_mode": TriforcePiecesMode,
"bigkey_shuffle": bigkey_shuffle, "triforce_pieces_percentage": TriforcePiecesPercentage,
"smallkey_shuffle": smallkey_shuffle, "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, "key_drop_shuffle": key_drop_shuffle,
"compass_shuffle": compass_shuffle, "compass_shuffle": compass_shuffle,
"map_shuffle": map_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, "progressive": Progressive,
"swordless": Swordless, "swordless": Swordless,
"dungeon_counters": DungeonCounters,
"retro_bow": RetroBow, "retro_bow": RetroBow,
"retro_caves": RetroCaves, "retro_caves": RetroCaves,
"hints": Hints, "hints": Hints,
"scams": Scams, "scams": Scams,
"restrict_dungeon_item_on_boss": RestrictBossItem,
"boss_shuffle": LTTPBosses, "boss_shuffle": LTTPBosses,
"pot_shuffle": PotShuffle, "pot_shuffle": PotShuffle,
"enemy_shuffle": EnemyShuffle, "enemy_shuffle": EnemyShuffle,
"killable_thieves": KillableThieves, "killable_thieves": KillableThieves,
"bush_shuffle": BushShuffle, "bush_shuffle": BushShuffle,
"shop_item_slots": ShopItemSlots, "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, "shop_price_modifier": ShopPriceModifier,
"shuffle_capacity_upgrades": ShuffleCapacityUpgrades,
"bombless_start": BomblessStart,
"shuffle_prizes": ShufflePrizes,
"tile_shuffle": TileShuffle, "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, "ow_palettes": OWPalette,
"uw_palettes": UWPalette, "uw_palettes": UWPalette,
"hud_palettes": HUDPalette, "hud_palettes": HUDPalette,
@ -469,10 +798,4 @@ alttp_options: typing.Dict[str, type(Option)] = {
"music": Music, "music": Music,
"reduceflashing": ReduceFlashing, "reduceflashing": ReduceFlashing,
"triforcehud": TriforceHud, "triforcehud": TriforceHud,
"glitch_boots": GlitchBoots,
"beemizer_total_chance": BeemizerTotalChance,
"beemizer_trap_chance": BeemizerTrapChance,
"death_link": DeathLink,
"allow_collect": AllowCollect,
"start_inventory_from_pool": StartInventoryPool,
} }

View File

@ -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, 'Kakariko Gamble Game', 'a game of chance'),
create_cave_region(world, player, 'Potion Shop', 'the potion shop', ['Potion Shop']), create_cave_region(world, player, 'Potion Shop', 'the potion shop', ['Potion Shop']),
create_lw_region(world, player, 'Lake Hylia Island', ['Lake Hylia Island']), 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_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_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'), 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']), ['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, '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 (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', create_dungeon_region(world, player, 'Sewers', 'a drop\'s exit', None, ['Sanctuary Push Door', 'Sewers Back Door', 'Sewers Secret Room']),
'Sewers - Secret Room - Right'], ['Sanctuary Push Door', 'Sewers Back Door']), 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, '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, '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), 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', create_cave_region(world, player, 'Hookshot Cave', 'a connector',
['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right',
'Hookshot Cave - Bottom Left'], '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, create_dw_region(world, player, 'Death Mountain Floating Island (Dark World)', None,
['Floating Island Drop', 'Hookshot Cave Back Entrance', 'Floating Island Mirror Spot']), ['Floating Island Drop', 'Hookshot Cave Back Entrance', 'Floating Island Mirror Spot']),
create_lw_region(world, player, 'Death Mountain Floating Island (Light World)', ['Floating Island']), 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 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 (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, '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 (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 - Compass Chest'], ['Ice Palace (Main)']), 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', create_dungeon_region(world, player, 'Ice Palace (Main)', 'Ice Palace', ['Ice Palace - Freezor Chest',
'Ice Palace - Many Pots Pot Key', 'Ice Palace - Many Pots Pot Key',
'Ice Palace - Big Chest', 'Ice Palace - Iced T Room'], ['Ice Palace (East)', 'Ice Palace (Kholdstare)']), '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), 'Missing Smith': (None, None, False, None),
'Dark Blacksmith Ruins': (None, None, False, None), 'Dark Blacksmith Ruins': (None, None, False, None),
'Flute Activation Spot': (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'), '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'), 'Desert Palace - Prize': ([0x1209E, 0x53F1C, 0x53F1D, 0x180053, 0x180078, 0xC6FF], None, True, 'Desert Palace'),
'Tower of Hera - Prize': ( 'Tower of Hera - Prize': (

View File

@ -4,7 +4,7 @@ import Utils
import worlds.Files import worlds.Files
LTTPJPN10HASH: str = "03a63945398191337e896e5771f77173" LTTPJPN10HASH: str = "03a63945398191337e896e5771f77173"
RANDOMIZERBASEHASH: str = "9952c2a3ec1b421e408df0d20c8f0c7f" RANDOMIZERBASEHASH: str = "35d010bc148e0ea0ee68e81e330223f1"
ROM_PLAYER_LIMIT: int = 255 ROM_PLAYER_LIMIT: int = 255
import io 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 SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
from .Items import ItemFactory, item_table, item_name_groups, progression_items from .Items import ItemFactory, item_table, item_name_groups, progression_items
from .EntranceShuffle import door_addresses from .EntranceShuffle import door_addresses
from .Options import smallkey_shuffle from .Options import small_key_shuffle
try: try:
from maseya import z3pr from maseya import z3pr
@ -294,7 +294,7 @@ def patch_enemizer(world, rom: LocalRom, enemizercli, output_directory):
'RandomizeBushEnemyChance': multiworld.bush_shuffle[player].value, 'RandomizeBushEnemyChance': multiworld.bush_shuffle[player].value,
'RandomizeEnemyHealthRange': multiworld.enemy_health[player] != 'default', 'RandomizeEnemyHealthRange': multiworld.enemy_health[player] != 'default',
'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[ 'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[
multiworld.enemy_health[player]], multiworld.enemy_health[player].current_key],
'OHKO': False, 'OHKO': False,
'RandomizeEnemyDamage': multiworld.enemy_damage[player] != 'default', 'RandomizeEnemyDamage': multiworld.enemy_damage[player] != 'default',
'AllowEnemyZeroDamage': True, '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 # Thanks to Zarby89 for originally finding these values
# todo fix screen scrolling # 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', exit.name in {'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit',
'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit',
'Palace of Darkness Exit', 'Swamp Palace Exit', 'Ganons Tower Exit', 'Palace of Darkness Exit', 'Swamp Palace Exit', 'Ganons Tower Exit',
'Desert Palace Exit (North)', 'Agahnims Tower Exit', 'Spiral Cave Exit (Top)', 'Desert Palace Exit (North)', 'Agahnims Tower Exit', 'Spiral Cave Exit (Top)',
'Superbunny Cave Exit (Bottom)', 'Turtle Rock Ledge Exit (East)'} and \ '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'}): 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. # 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 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. if world.retro_caves[player]: # Old man cave and Take any caves will count towards collection rate.
credits_total += 5 credits_total += 5
if world.shop_item_slots[player]: # Potion shop only counts towards collection rate if included in the shuffle. 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 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 # Set stun items
rom.write_byte(0x180180, 0x03) # All standard items rom.write_byte(0x180180, 0x03) # All standard items
# Set overflow items for progressive equipment # 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 overflow_replacement = GREEN_CLOCK
else: else:
overflow_replacement = GREEN_TWENTY_RUPEES 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]) difficulty.progressive_bow_limit, item_table[difficulty.basicbow[-1]].item_code])
if difficulty.progressive_bow_limit < 2 and ( 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_bytes(0x180098, [2, item_table["Silver Bow"].item_code])
rom.write_byte(0x180181, 0x01) # Make silver arrows work only on ganon rom.write_byte(0x180181, 0x01) # Make silver arrows work only on ganon
rom.write_byte(0x180182, 0x00) # Don't auto equip silvers on pickup 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[0xE1] = 0xDA # 5 Arrows -> Blue Rupee
prize_replacements[0xE2] = 0xDB # 10 Arrows -> Red 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 # shuffle prize packs
prizes = [0xD8, 0xD8, 0xD8, 0xD8, 0xD9, 0xD8, 0xD8, 0xD9, 0xDA, 0xD9, 0xDA, 0xDB, 0xDA, 0xD9, 0xDA, 0xDA, 0xE0, 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, 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)) byte = int(rom.read_byte(address))
rom.write_byte(address, prize_replacements.get(byte, byte)) 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 # set bonk prizes
bonk_prizes = [0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xAC, 0xE3, 0xE3, 0xDA, 0xE3, 0xDA, 0xD8, 0xAC, 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, 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 rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
gametype = 0x04 # item gametype = 0x04 # item
if world.shuffle[player] != 'vanilla': if world.entrance_shuffle[player] != 'vanilla':
gametype |= 0x02 # entrance gametype |= 0x02 # entrance
if enemized: if enemized:
gametype |= 0x01 # enemizer gametype |= 0x01 # enemizer
@ -1312,7 +1314,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
equip[0x36C] = 0x18 equip[0x36C] = 0x18
equip[0x36D] = 0x18 equip[0x36D] = 0x18
equip[0x379] = 0x68 equip[0x379] = 0x68
starting_max_bombs = 10 starting_max_bombs = 0 if world.bombless_start[player] else 10
starting_max_arrows = 30 starting_max_arrows = 30
startingstate = CollectionState(world) 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} '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 = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)': 50, 'Rupees (100)': 100,
'Rupees (300)': 300} 'Rupees (300)': 300}
bomb_caps = {'Bomb Upgrade (+5)': 5, 'Bomb 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_caps = {'Arrow Upgrade (+5)': 5, 'Arrow Upgrade (+10)': 10, 'Arrow Upgrade (70)': 70}
bombs = {'Single Bomb': 1, 'Bombs (3)': 3, 'Bombs (10)': 10} bombs = {'Single Bomb': 1, 'Bombs (3)': 3, 'Bombs (10)': 10}
arrows = {'Single Arrow': 1, 'Arrows (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[ 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)) 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)) 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, rom.write_bytes(0x180080,
[5, 10, 5, 10]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10) [5, 10, 5, 10]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10)
else: 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) | (0x02 if 'bombs' in world.escape_assist[player] else 0x00) |
(0x04 if 'magic' in world.escape_assist[player] else 0x00))) # Escape assist (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 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 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) rom.write_byte(0x18003E, 0x06)
elif world.goal[player] in ['bosses']: elif world.goal[player] in ['bosses']:
rom.write_byte(0x18003E, 0x02) # make ganon invincible until all bosses are beat 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 # c - enabled for inside compasses
# s - enabled for inside small keys # s - enabled for inside small keys
# block HC upstairs doors in rain state in standard mode # 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) | (0x02 if world.compass_shuffle[player] else 0x00)
| (0x04 if world.map_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 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 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 # b - Big Key
# a - Small Key # a - Small Key
# #
rom.write_byte(0x180045, ((0x00 if (world.smallkey_shuffle[player] == smallkey_shuffle.option_original_dungeon or rom.write_byte(0x180045, ((0x00 if (world.small_key_shuffle[player] == small_key_shuffle.option_original_dungeon or
world.smallkey_shuffle[player] == smallkey_shuffle.option_universal) else 0x01) world.small_key_shuffle[player] == small_key_shuffle.option_universal) else 0x01)
| (0x02 if world.bigkey_shuffle[player] else 0x00) | (0x02 if world.big_key_shuffle[player] else 0x00)
| (0x04 if world.map_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 | (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[ rom.write_int16(0x18017C, get_reveal_bytes('Crystal 5') | get_reveal_bytes('Crystal 6') if world.map_shuffle[
player] else 0x0000) # Bomb Shop Reveal player] else 0x0000) # Bomb Shop Reveal
rom.write_byte(0x180172, 0x01 if world.smallkey_shuffle[ rom.write_byte(0x180172, 0x01 if world.small_key_shuffle[
player] == smallkey_shuffle.option_universal else 0x00) # universal keys 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(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(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 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(0x180020, digging_game_rng)
rom.write_byte(0xEFD95, 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(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(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.logic[ rom.write_byte(0x186383, 0x01 if world.glitch_triforce or world.glitches_required[
player] == 'nologic' else 0x00) # disable glitching to Triforce from Ganons Room 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 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 # remove shield from uncle
@ -1660,8 +1662,8 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
0x4F]) 0x4F])
# allow smith into multi-entrance caves in appropriate shuffles # allow smith into multi-entrance caves in appropriate shuffles
if world.shuffle[player] in ['restricted', 'full', 'crossed', 'insanity', 'madness'] or ( if world.entrance_shuffle[player] in ['restricted', 'full', 'crossed', 'insanity'] or (
world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'): world.entrance_shuffle[player] == 'simple' and world.mode[player] == 'inverted'):
rom.write_byte(0x18004C, 0x01) rom.write_byte(0x18004C, 0x01)
# set correct flag for hera basement item # set correct flag for hera basement item
@ -1758,8 +1760,8 @@ def write_custom_shops(rom, world, player):
if item is None: if item is None:
break break
if world.shop_item_slots[player] or shop.type == ShopType.TakeAny: 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 \ count_shop = (shop.region.name != 'Potion Shop' or world.include_witch_hut[player]) and \
shop.region.name != 'Capacity Upgrade' (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) rom.write_byte(0x186560 + shop.sram_offset + slot, 1 if count_shop else 0)
if item['item'] == 'Single Arrow' and item['player'] == 0: if item['item'] == 'Single Arrow' and item['player'] == 0:
arrow_mask |= 1 << index arrow_mask |= 1 << index
@ -2201,7 +2203,7 @@ def write_strings(rom, world, player):
tt.removeUnwantedText() tt.removeUnwantedText()
# Let's keep this guy's text accurate to the shuffle setting. # 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_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.' 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'}) entrances_to_hint.update({'Inverted Ganons Tower': 'The sealed castle door'})
else: else:
entrances_to_hint.update({'Ganons Tower': 'Ganon\'s Tower'}) 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: for entrance in all_entrances:
if entrance.name in entrances_to_hint: if entrance.name in entrances_to_hint:
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text( this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(
@ -2265,9 +2267,9 @@ def write_strings(rom, world, player):
break break
# Now we write inconvenient locations for most shuffles and finish taking care of the less chaotic ones. # Now we write inconvenient locations for most shuffles and finish taking care of the less chaotic ones.
entrances_to_hint.update(InconvenientOtherEntrances) 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 hint_count = 0
elif world.shuffle[player] in ['simple', 'restricted', 'restricted_legacy']: elif world.entrance_shuffle[player] in ['simple', 'restricted']:
hint_count = 2 hint_count = 2
else: else:
hint_count = 4 hint_count = 4
@ -2284,14 +2286,14 @@ def write_strings(rom, world, player):
# Next we handle hints for randomly selected other entrances, # Next we handle hints for randomly selected other entrances,
# curating the selection intelligently based on shuffle. # 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(ConnectorEntrances)
entrances_to_hint.update(DungeonEntrances) entrances_to_hint.update(DungeonEntrances)
if world.mode[player] == 'inverted': if world.mode[player] == 'inverted':
entrances_to_hint.update({'Inverted Agahnims Tower': 'The dark mountain tower'}) entrances_to_hint.update({'Inverted Agahnims Tower': 'The dark mountain tower'})
else: else:
entrances_to_hint.update({'Agahnims Tower': 'The sealed castle door'}) 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(ConnectorEntrances)
entrances_to_hint.update(OtherEntrances) entrances_to_hint.update(OtherEntrances)
if world.mode[player] == 'inverted': if world.mode[player] == 'inverted':
@ -2301,15 +2303,15 @@ def write_strings(rom, world, player):
else: else:
entrances_to_hint.update({'Dark Sanctuary Hint': 'The dark sanctuary cave'}) entrances_to_hint.update({'Dark Sanctuary Hint': 'The dark sanctuary cave'})
entrances_to_hint.update({'Big Bomb Shop': 'The old bomb shop'}) 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) entrances_to_hint.update(InsanityEntrances)
if world.shuffle_ganon: if world.shuffle_ganon:
if world.mode[player] == 'inverted': if world.mode[player] == 'inverted':
entrances_to_hint.update({'Inverted Pyramid Entrance': 'The extra castle passage'}) entrances_to_hint.update({'Inverted Pyramid Entrance': 'The extra castle passage'})
else: else:
entrances_to_hint.update({'Pyramid Ledge': 'The pyramid ledge'}) entrances_to_hint.update({'Pyramid Ledge': 'The pyramid ledge'})
hint_count = 4 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', hint_count = 4 if world.entrance_shuffle[player] not in ['vanilla', 'dungeons_simple', 'dungeons_full',
'dungeonscrossed'] else 0 'dungeons_crossed'] else 0
for entrance in all_entrances: for entrance in all_entrances:
if entrance.name in entrances_to_hint: if entrance.name in entrances_to_hint:
if hint_count: 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. # 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() 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) locations_to_hint.extend(InconvenientVanillaLocations)
local_random.shuffle(locations_to_hint) local_random.shuffle(locations_to_hint)
hint_count = 3 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', hint_count = 3 if world.entrance_shuffle[player] not in ['vanilla', 'dungeons_simple', 'dungeons_full',
'dungeonscrossed'] else 5 'dungeons_crossed'] else 5
for location in locations_to_hint[:hint_count]: for location in locations_to_hint[:hint_count]:
if location == 'Swamp Left': if location == 'Swamp Left':
if local_random.randint(0, 1): 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. # Lastly we write hints to show where certain interesting items are.
items_to_hint = RelevantItems.copy() 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"] 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"] items_to_hint |= item_name_groups["Big Keys"]
if world.hints[player] == "full": if world.hints[player] == "full":
hint_count = len(hint_locations) # fill all remaining hint locations with Item hints. hint_count = len(hint_locations) # fill all remaining hint locations with Item hints.
else: else:
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', hint_count = 5 if world.entrance_shuffle[player] not in ['vanilla', 'dungeons_simple', 'dungeons_full',
'dungeonscrossed'] else 8 'dungeons_crossed'] else 8
hint_count = min(hint_count, len(items_to_hint), len(hint_locations)) hint_count = min(hint_count, len(items_to_hint), len(hint_locations))
if hint_count: if hint_count:
locations = world.find_items_in_locations(items_to_hint, player, True) 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'] = '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 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 ( 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) prog_bow_locs = world.find_item_locations('Progressive Bow', player, True)
world.per_slot_randoms[player].shuffle(prog_bow_locs) world.per_slot_randoms[player].shuffle(prog_bow_locs)
found_bow = False found_bow = False
@ -2448,7 +2450,7 @@ def write_strings(rom, world, player):
if world.goal[player] == 'bosses': if world.goal[player] == 'bosses':
tt['sign_ganon'] = 'You need to kill all bosses, Ganon last.' 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.' tt['sign_ganon'] = 'You need to pull the pedestal to defeat Ganon.'
elif world.goal[player] == "ganon": elif world.goal[player] == "ganon":
if world.crystals_needed_for_ganon[player] == 1: if world.crystals_needed_for_ganon[player] == 1:
@ -2456,14 +2458,6 @@ def write_strings(rom, world, player):
else: else:
tt['sign_ganon'] = f'You need {world.crystals_needed_for_ganon[player]} crystals to beat Ganon and ' \ tt['sign_ganon'] = f'You need {world.crystals_needed_for_ganon[player]} crystals to beat Ganon and ' \
f'have beaten Agahnim atop Ganons Tower' 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: else:
if world.crystals_needed_for_ganon[player] == 1: if world.crystals_needed_for_ganon[player] == 1:
tt['sign_ganon'] = 'You need a crystal to beat Ganon.' 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['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)] 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_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.' 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!' tt['sign_ganon'] = 'Go find the Triforce pieces with your friends... Ganon is invincible!'
else: else:
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!' 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_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!' tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
if world.treasure_hunt_count[player] > 1: 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.' % \ 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]) (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.' % \ 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]) (world.treasure_hunt_count[player], world.triforce_pieces_available[player])
else: 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.' % \ 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]) (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.' % \ 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]) (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 rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph proof
# the following bytes should only be written in vanilla # the following bytes should only be written in vanilla
# or they'll overwrite the randomizer's shuffles # 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 + 0x23, 0x37) # switch AT and GT
rom.write_byte(0xDBB73 + 0x36, 0x24) rom.write_byte(0xDBB73 + 0x36, 0x24)
rom.write_int16(0x15AEE + 2 * 0x38, 0x00E0) rom.write_int16(0x15AEE + 2 * 0x38, 0x00E0)
rom.write_int16(0x15AEE + 2 * 0x25, 0x000C) 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(0x15B8C, 0x6C)
rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house
rom.write_byte(0xDBB73 + 0x52, 0x01) 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_int16(snes_to_pc(0x02D9A6), 0x005A)
rom.write_byte(snes_to_pc(0x02D9B3), 0x12) rom.write_byte(snes_to_pc(0x02D9B3), 0x12)
# keep the old man spawn point at old man house unless shuffle is vanilla # 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_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01])
rom.write_int16(snes_to_pc(0x02D8DE), 0x00F1) rom.write_int16(snes_to_pc(0x02D8DE), 0x00F1)
rom.write_bytes(snes_to_pc(0x02D910), [0x1F, 0x1E, 0x1F, 0x1F, 0x03, 0x02, 0x03, 0x03]) 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_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(0x308300), 0x0140) # new pyramid hole entrance
rom.write_int16(snes_to_pc(0x308320), 0x001B) 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_byte(snes_to_pc(0x308340), 0x7B)
rom.write_int16(snes_to_pc(0x1af504), 0x148B) rom.write_int16(snes_to_pc(0x1af504), 0x148B)
rom.write_int16(snes_to_pc(0x1af50c), 0x149B) 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_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82])
rom.write_int16(0xDB96F + 2 * 0x35, 0x001B) # move pyramid exit door rom.write_int16(0xDB96F + 2 * 0x35, 0x001B) # move pyramid exit door
rom.write_int16(0xDBA71 + 2 * 0x35, 0x06A4) 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(0xDBB73 + 0x35, 0x36)
rom.write_byte(snes_to_pc(0x09D436), 0xF3) # remove castle gate warp 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_int16(0x15AEE + 2 * 0x37, 0x0010) # pyramid exit to new hc area
rom.write_byte(0x15B8C + 0x37, 0x1B) rom.write_byte(0x15B8C + 0x37, 0x1B)
rom.write_int16(0x15BDB + 2 * 0x37, 0x0418) rom.write_int16(0x15BDB + 2 * 0x37, 0x0418)

View File

@ -9,25 +9,25 @@ from worlds.generic.Rules import (add_item_rule, add_rule, forbid_item,
from . import OverworldGlitchRules from . import OverworldGlitchRules
from .Bosses import GanonDefeatRule from .Bosses import GanonDefeatRule
from .Items import ItemFactory, item_name_groups, item_table, progression_items 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 .OverworldGlitchRules import no_logic_rules, overworld_glitches_rules
from .Regions import LTTPRegionType, location_table from .Regions import LTTPRegionType, location_table
from .StateHelpers import (can_extend_magic, can_kill_most_things, from .StateHelpers import (can_extend_magic, can_kill_most_things,
can_lift_heavy_rocks, can_lift_rocks, can_lift_heavy_rocks, can_lift_rocks,
can_melt_things, can_retrieve_tablet, can_melt_things, can_retrieve_tablet,
can_shoot_arrows, has_beam_sword, has_crystals, 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_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 from .UnderworldGlitchRules import underworld_glitches_rules
def set_rules(world): def set_rules(world):
player = world.player player = world.player
world = world.multiworld 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 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( logging.info(
'WARNING! Seeds generated under this logic often require major glitches and may be impossible!') 'WARNING! Seeds generated under this logic often require major glitches and may be impossible!')
@ -45,8 +45,8 @@ def set_rules(world):
else: else:
world.completion_condition[player] = lambda state: state.has('Triforce', player) world.completion_condition[player] = lambda state: state.has('Triforce', player)
global_rules(world, player)
dungeon_boss_rules(world, player) dungeon_boss_rules(world, player)
global_rules(world, player)
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
default_rules(world, player) default_rules(world, player)
@ -61,24 +61,24 @@ def set_rules(world):
else: else:
raise NotImplementedError(f'World state {world.mode[player]} is not implemented yet') 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) 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 # Initially setting no_glitches_rules to set the baseline rules for some
# entrances. The overworld_glitches_rules set is primarily additive. # entrances. The overworld_glitches_rules set is primarily additive.
no_glitches_rules(world, player) no_glitches_rules(world, player)
fake_flipper_rules(world, player) fake_flipper_rules(world, player)
overworld_glitches_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) no_glitches_rules(world, player)
fake_flipper_rules(world, player) fake_flipper_rules(world, player)
overworld_glitches_rules(world, player) overworld_glitches_rules(world, player)
underworld_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) no_glitches_rules(world, player)
fake_flipper_rules(world, player) fake_flipper_rules(world, player)
else: 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': if world.goal[player] == 'bosses':
# require all bosses to beat ganon # require all bosses to beat ganon
@ -89,7 +89,7 @@ def set_rules(world):
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
set_big_bomb_rules(world, player) 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) 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') 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: else:
@ -97,18 +97,18 @@ def set_rules(world):
# if swamp and dam have not been moved we require mirror for swamp palace # 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. # 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)) 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 # 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) 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_rule(ganons_tower, lambda state: False)
set_trock_key_rules(world, player) set_trock_key_rules(world, player)
set_rule(ganons_tower, lambda state: has_crystals(state, state.multiworld.crystals_needed_for_gt[player], 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') 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') 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)) add_rule(location, lambda state: location.parent_region.dungeon.boss.can_defeat(state))
def set_always_allow(spot, rule): def set_always_allow(spot, rule):
spot.always_allow = rule spot.always_allow = rule
@ -184,6 +185,7 @@ def dungeon_boss_rules(world, player):
for location in boss_locations: for location in boss_locations:
set_defeat_dungeon_boss_rule(world.get_location(location, player)) set_defeat_dungeon_boss_rule(world.get_location(location, player))
def global_rules(world, player): def global_rules(world, player):
# ganon can only carry triforce # ganon can only carry triforce
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player) 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('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('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('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('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('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('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('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: set_rule(world.get_location('Spike Cave', player), lambda state:
state.has('Hammer', player) and can_lift_rocks(state, player) and 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), set_rule(world.get_entrance('Sewers Door', player),
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4) or ( 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 player] == 'standard')) # standard universal small keys cannot access the shop
set_rule(world.get_entrance('Sewers Back Door', player), set_rule(world.get_entrance('Sewers Back Door', 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))
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), 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)) 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), 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)) player))
set_rule(world.get_location('Castle Tower - Dark Archer Key Drop', 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)) player, 2))
set_rule(world.get_location('Castle Tower - Circle of Pots Key Drop', player), 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)) player, 3))
set_always_allow(world.get_location('Eastern Palace - Big Key Chest', player), 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) lambda state, item: item.name == 'Big Key (Eastern Palace)' and item.player == player)
set_rule(world.get_location('Eastern Palace - Big Key Chest', 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 lambda state: can_kill_most_things(state, player, 5) and (state._lttp_has_key('Small Key (Eastern Palace)',
((location_item_name(state, 'Eastern Palace - Big Key Chest', player) == ('Big Key (Eastern Palace)', player) player, 2) or ((location_item_name(state, 'Eastern Palace - Big Key Chest', player)
and state.has('Small Key (Eastern Palace)', 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), 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), set_rule(world.get_location('Eastern Palace - Big Chest', player),
lambda state: state.has('Big Key (Eastern Palace)', 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) 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 state._lttp_has_key('Small Key (Eastern Palace)', player, 2) and
ep_boss.parent_region.dungeon.boss.can_defeat(state)) ep_boss.parent_region.dungeon.boss.can_defeat(state))
ep_prize = world.get_location('Eastern Palace - Prize', player) 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 state._lttp_has_key('Small Key (Eastern Palace)', player, 2) and
ep_prize.parent_region.dungeon.boss.can_defeat(state)) ep_prize.parent_region.dungeon.boss.can_defeat(state))
if not world.enemy_shuffle[player]: if not world.enemy_shuffle[player]:
add_rule(ep_boss, lambda state: can_shoot_arrows(state, player)) add_rule(ep_boss, lambda state: can_shoot_arrows(state, player))
add_rule(ep_prize, 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 - 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_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_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 - 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)) 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)) 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))
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)) 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))
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)) 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 # 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)) 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 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)) 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 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)) set_rule(world.get_location('Tower of Hera - Big Key Chest', player), lambda state: has_fire_source(state, player))
if world.accessibility[player] != 'locations': 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 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_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_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_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)) 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) 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) if state.has('Hookshot', player)
else state._lttp_has_key('Small Key (Swamp Palace)', player, 4)) 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': if world.accessibility[player] != 'locations':
allow_self_locking_items(world.get_location('Swamp Palace - Big Chest', player), 'Big Key (Swamp Palace)') 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)) 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) 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 - 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)) 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)) 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": 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), 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)) 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 (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 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_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': if world.accessibility[player] != 'locations':
allow_self_locking_items(world.get_location('Skull Woods - Big Chest', player), 'Big Key (Skull Woods)') 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 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)) 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_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_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_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)))) 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)) 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 - 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_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', 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_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 - 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 - 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 - 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_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 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) (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_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)) 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_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)) 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]: if world.enemy_shuffle[player]:
set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: can_shoot_arrows(state, 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 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 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 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_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 ( 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))) 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': 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)) 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'] 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'] 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_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 (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))) 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 ( 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))) 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))) 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 # Actual requirements
for location in compass_room_chests: 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)))) 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 Chest', player), lambda state: state.has('Big Key (Ganons Tower)', player))
set_rule(world.get_location('Ganons Tower - Big Key Room - Left', 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), 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), 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]: if world.enemy_shuffle[player]:
set_rule(world.get_entrance('Ganons Tower Big Key Door', player), set_rule(world.get_entrance('Ganons Tower Big Key Door', player),
lambda state: state.has('Big Key (Ganons Tower)', 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), 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)) 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), 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), set_rule(world.get_location('Ganons Tower - Pre-Moldorm Chest', player),
lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 7)) lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 7))
set_rule(world.get_entrance('Ganons Tower Moldorm Door', player), 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)) set_defeat_dungeon_boss_rule(world.get_location('Agahnim 2', player))
ganon = world.get_location('Ganon', player) ganon = world.get_location('Ganon', player)
set_rule(ganon, lambda state: GanonDefeatRule(state, 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)) 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)) add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player))
else: else:
add_rule(ganon, lambda state: has_crystals(state, state.multiworld.crystals_needed_for_ganon[player], player)) 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): def default_rules(world, player):
"""Default world rules when world state is not inverted.""" """Default world rules when world state is not inverted."""
# overworld requirements # 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', 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 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)) 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_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_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 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 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('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('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('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)) # bomb required 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('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 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 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 # overworld requirements
set_rule(world.get_location('Maze Race', player), lambda state: state.has('Moon Pearl', player)) 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('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)) 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)) 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('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('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)) 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('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 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('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('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_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 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 (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('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('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 (!) 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): 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): def basement_key_rule(state):
if location_item_name(state, 'Sewers - Key Rat Key Drop', player) == ("Small Key (Hyrule Castle)", player): 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) return state._lttp_has_key("Small Key (Hyrule Castle)", player, 2)
else: else:
return state._lttp_has_key("Small Key (Hyrule Castle)", player, 3) 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('Hyrule Castle - Boomerang Chest', player), basement_key_rule)
set_rule(world.get_location('Sewers - Key Rat Key Drop', player), 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), 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), set_rule(world.get_location('Hyrule Castle - Zelda\'s Chest', player),
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4) and lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4) and
state.has('Big Key (Hyrule Castle)', player)) 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_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 - 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('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 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('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)) 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), set_rule(world.get_location('Hyrule Castle - Boomerang Guard Key Drop', player),
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 1)) lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 1))
set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player),
@ -1062,15 +1169,15 @@ def set_trock_key_rules(world, player):
return 6 return 6
# If TR is only accessible from the middle, the big key must be further restricted to prevent softlock potential # 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 # 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) forbid_item(world.get_location('Turtle Rock - Big Key Chest', player), 'Big Key (Turtle Rock)', player)
if not can_reach_big_chest: 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 # 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 - 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) 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.accessibility[player] == 'locations':
if world.bigkey_shuffle[player] and can_reach_big_chest: 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 # 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', for location in ['Turtle Rock - Chain Chomps', 'Turtle Rock - Compass Chest',
'Turtle Rock - Pokey 1 Key Drop', 'Turtle Rock - Pokey 2 Key Drop', '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 # 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. # 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)', bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)',
'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)'] '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', bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree',
'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', '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): def get_rule_to_add(region, location = None, connecting_entrance = None):
# In OWG, a location can potentially be superbunny-mirror accessible or # In OWG, a location can potentially be superbunny-mirror accessible or
# bunny revival accessible. # 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 if region.name == 'Swamp Palace (Entrance)': # Need to 0hp revive - not in logic
return lambda state: state.has('Moon Pearl', player) return lambda state: state.has('Moon Pearl', player)
if region.name == 'Tower of Hera (Bottom)': # Need to hit the crystal switch 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) seen.add(new_region)
if not is_link(new_region): if not is_link(new_region):
# For glitch rulesets, establish superbunny and revival rules. # 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(): 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)) 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() 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 # 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): for entrance in world.get_entrances(player):
if is_bunny(entrance.connected_region): 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.connected_region.type == LTTPRegionType.Dungeon:
if entrance.parent_region.type != LTTPRegionType.Dungeon and entrance.connected_region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): 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)) 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)': 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)) 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: 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 continue
if location.name in bunny_accessible_locations: if location.name in bunny_accessible_locations:
continue continue

View File

@ -5,11 +5,14 @@ import logging
from Utils import int16_as_bytes from Utils import int16_as_bytes
from worlds.generic.Rules import add_rule
from BaseClasses import CollectionState
from .SubClasses import ALttPLocation from .SubClasses import ALttPLocation
from .EntranceShuffle import door_addresses from .EntranceShuffle import door_addresses
from .Items import item_name_groups, item_table, ItemFactory, trap_replaceable, GetBeemizerItem from .Items import item_name_groups
from .Options import smallkey_shuffle from .Options import small_key_shuffle, RandomizeShopInventories
from .StateHelpers import has_hearts, can_use_bombs, can_hold_arrows
logger = logging.getLogger("Shops") logger = logging.getLogger("Shops")
@ -36,9 +39,9 @@ class ShopPriceType(IntEnum):
Item = 10 Item = 10
class Shop(): class Shop:
slots: int = 3 # slot count is not dynamic in asm, however inventory can have None as empty slots 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 type = ShopType.Shop
slot_names: Dict[int, str] = { slot_names: Dict[int, str] = {
0: " Left", 0: " Left",
@ -103,7 +106,7 @@ class Shop():
self.inventory = [None] * self.slots self.inventory = [None] * self.slots
def add_inventory(self, slot: int, item: str, price: int, max: int = 0, 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, player: int = 0, price_type: int = ShopPriceType.Rupees,
replacement_price_type: int = ShopPriceType.Rupees): replacement_price_type: int = ShopPriceType.Rupees):
self.inventory[slot] = { self.inventory[slot] = {
@ -114,33 +117,23 @@ class Shop():
'replacement': replacement, 'replacement': replacement,
'replacement_price': replacement_price, 'replacement_price': replacement_price,
'replacement_price_type': replacement_price_type, 'replacement_price_type': replacement_price_type,
'create_location': create_location,
'player': player 'player': player
} }
def push_inventory(self, slot: int, item: str, price: int, max: int = 1, player: int = 0, def push_inventory(self, slot: int, item: str, price: int, max: int = 1, player: int = 0,
price_type: int = ShopPriceType.Rupees): 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] = { self.inventory[slot] = {
'item': item, 'item': item,
'price': price, 'price': price,
'price_type': price_type, 'price_type': price_type,
'max': max, 'max': max,
'replacement': self.inventory[slot]["item"], 'replacement': self.inventory[slot]["item"] if self.inventory[slot] else None,
'replacement_price': self.inventory[slot]["price"], 'replacement_price': self.inventory[slot]["price"] if self.inventory[slot] else 0,
'replacement_price_type': self.inventory[slot]["price_type"], 'replacement_price_type': self.inventory[slot]["price_type"] if self.inventory[slot] else ShopPriceType.Rupees,
'create_location': self.inventory[slot]["create_location"],
'player': player 'player': player
} }
def can_push_inventory(self, slot: int):
return self.inventory[slot] and not self.inventory[slot]["replacement"]
class TakeAny(Shop): class TakeAny(Shop):
type = ShopType.TakeAny type = ShopType.TakeAny
@ -156,6 +149,10 @@ class UpgradeShop(Shop):
# Potions break due to VRAM flags set in UpgradeShop. # 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 # Didn't check for more things breaking as not much else can be shuffled here currently
blacklist = item_name_groups["Potions"] blacklist = item_name_groups["Potions"]
slot_names: Dict[int, str] = {
0: " Left",
1: " Right"
}
shop_class_mapping = {ShopType.UpgradeShop: UpgradeShop, shop_class_mapping = {ShopType.UpgradeShop: UpgradeShop,
@ -163,191 +160,84 @@ shop_class_mapping = {ShopType.UpgradeShop: UpgradeShop,
ShopType.TakeAny: TakeAny} ShopType.TakeAny: TakeAny}
def FillDisabledShopSlots(world): def push_shop_inventories(multiworld):
shop_slots: Set[ALttPLocation] = {location for shop_locations in (shop.region.locations for shop in world.shops) shop_slots = [location for shop_locations in (shop.region.locations for shop in multiworld.shops if shop.type
for location in shop_locations != ShopType.TakeAny) for location in shop_locations if location.shop_slot is not None]
if location.shop_slot is not None and location.shop_slot_disabled}
for location in shop_slots: for location in shop_slots:
location.shop_slot_disabled = True item_name = location.item.name
shop: Shop = location.parent_region.shop # Retro Bow arrows will already have been pushed
location.item = ItemFactory(shop.inventory[location.shop_slot]['item'], location.player) if (not multiworld.retro_bow[location.player]) or ((item_name, location.item.player)
location.item_rule = lambda item: item.name == location.item.name and item.player == location.player != ("Single Arrow", location.player)):
location.locked = True 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): def create_shops(multiworld, player: int):
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]
player_shop_table = shop_table.copy() 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) player_shop_table["Potion Shop"] = player_shop_table["Potion Shop"]._replace(locked=False)
dynamic_shop_slots = total_dynamic_shop_slots + 3 dynamic_shop_slots = total_dynamic_shop_slots + 3
else: else:
dynamic_shop_slots = total_dynamic_shop_slots 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) 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 default_shop_table = [i for l in
[shop_generation_types[x] for x in ['arrows', 'bombs', 'potions', 'shields', 'bottle'] if [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] not multiworld.retro_bow[player] or x != 'arrows'] for i in l]
new_basic_shop = world.random.sample(default_shop_table, k=3) new_basic_shop = multiworld.random.sample(default_shop_table, k=3)
new_dark_shop = world.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(): for name, shop in player_shop_table.items():
typ, shop_id, keeper, custom, locked, items, sram_offset = shop typ, shop_id, keeper, custom, locked, items, sram_offset = shop
if not locked: if not locked:
new_items = world.random.sample(default_shop_table, k=3) new_items = multiworld.random.sample(default_shop_table, k=len(items))
if 'f' not in option: if multiworld.randomize_shop_inventories[player] == RandomizeShopInventories.option_randomize_by_shop_type:
if items == _basic_shop_defaults: if items == _basic_shop_defaults:
new_items = new_basic_shop new_items = new_basic_shop
elif items == _dark_world_shop_defaults: elif items == _dark_world_shop_defaults:
new_items = new_dark_shop 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) 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. # 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"] = \
player_shop_table["Dark Lake Hylia Shop"]._replace(items=_inverted_hylia_shop_defaults, locked=None) 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(): 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) 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 # special case: allow shop slots, but do not allow overwriting of base inventory behind them
if locked is None: if locked is None:
shop.locked = True shop.locked = True
region.shop = shop region.shop = shop
world.shops.append(shop) multiworld.shops.append(shop)
for index, item in enumerate(inventory): for index, item in enumerate(inventory):
shop.add_inventory(index, *item) 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]}" slot_name = f"{region.name}{shop.slot_names[index]}"
loc = ALttPLocation(player, slot_name, address=shop_table_by_location[slot_name], loc = ALttPLocation(player, slot_name, address=shop_table_by_location[slot_name],
parent=region, hint_text="for sale") 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.shop_slot = index
loc.locked = True if ((not (multiworld.shuffle_capacity_upgrades[player] and type == ShopType.UpgradeShop))
if single_purchase_slots.pop(): and not 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)
loc.shop_slot_disabled = True loc.shop_slot_disabled = True
shop.region.locations.append(loc) loc.locked = True
else:
shop.region.locations.append(loc)
class ShopData(NamedTuple): 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_ID_START = 0x400000
shop_table_by_location_id = dict(enumerate( shop_table_by_location_id = dict(enumerate(
(f"{name}{Shop.slot_names[num]}" for name, shop_data in (f"{name}{UpgradeShop.slot_names[num]}" if shop_data.type == ShopType.UpgradeShop else
sorted(shop_table.items(), key=lambda item: item[1].sram_offset) f"{name}{Shop.slot_names[num]}" for name, shop_data in sorted(shop_table.items(),
for num in range(3)), start=SHOP_ID_START)) 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)] = "Old Man Sword Cave"
shop_table_by_location_id[(SHOP_ID_START + total_shop_slots + 1)] = "Take-Any #1" 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 # TODO: move hard+ mode changes for shields here, utilizing the new shops
if world.retro_bow[player]: if multiworld.retro_bow[player]:
rss = world.get_region('Red Shield Shop', player).shop rss = multiworld.get_region('Red Shield Shop', player).shop
replacement_items = [['Red Potion', 150], ['Green Potion', 75], ['Blue Potion', 200], ['Bombs (10)', 50], replacement_items = [['Red Potion', 150], ['Green Potion', 75], ['Blue Potion', 200], ['Bombs (10)', 50],
['Blue Shield', 50], ['Small Heart', ['Blue Shield', 50], ['Small Heart',
10]] # Can't just replace the single arrow with 10 arrows as retro doesn't need them. 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_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.add_inventory(2, 'Single Arrow', 80, 1, replacement_item[0], replacement_item[1])
rss.locked = True rss.locked = True
if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal or world.retro_bow[player]: if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal or multiworld.retro_bow[player]:
for shop in world.random.sample([s for s in world.shops if 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], s.custom and not s.locked and s.type == ShopType.Shop
5): and s.region.player == player], 5):
shop.locked = True shop.locked = True
slots = [0, 1, 2] slots = [0, 1, 2]
world.random.shuffle(slots) multiworld.random.shuffle(slots)
slots = iter(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) 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) shop.push_inventory(next(slots), 'Single Arrow', 80)
if multiworld.shuffle_capacity_upgrades[player]:
def shuffle_shops(world, items, player: int): for shop in multiworld.shops:
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 shop.type == ShopType.UpgradeShop and shop.region.player == player and \ if shop.type == ShopType.UpgradeShop and shop.region.player == player and \
shop.region.name == "Capacity Upgrade": shop.region.name == "Capacity Upgrade":
shop.clear_inventory() shop.clear_inventory()
capacityshop = shop
if world.goal[player] != 'icerodhunt': if (multiworld.shuffle_shop_inventories[player] or multiworld.randomize_shop_prices[player]
for i, item in enumerate(items): or multiworld.randomize_cost_types[player]):
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'):
shops = [] shops = []
upgrade_shops = []
total_inventory = [] total_inventory = []
for shop in world.shops: for shop in multiworld.shops:
if shop.region.player == player: if shop.region.player == player:
if shop.type == ShopType.UpgradeShop: if shop.type == ShopType.Shop and not shop.locked:
upgrade_shops.append(shop)
elif shop.type == ShopType.Shop and not shop.locked:
shops.append(shop) shops.append(shop)
total_inventory.extend(shop.inventory) total_inventory.extend(shop.inventory)
if 'p' in option: for item in total_inventory:
def price_adjust(price: int) -> int: item["price_type"], item["price"] = get_price(multiworld, item, player)
# 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
def adjust_item(item): if multiworld.shuffle_shop_inventories[player]:
if item: multiworld.random.shuffle(total_inventory)
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)
i = 0 i = 0
for shop in shops: for shop in shops:
@ -539,16 +370,18 @@ price_blacklist = {
} }
price_chart = { price_chart = {
ShopPriceType.Rupees: lambda p: p, ShopPriceType.Rupees: lambda p, d: p,
ShopPriceType.Hearts: lambda p: min(5, p // 5) * 8, # Each heart is 0x8 in memory, Max of 5 hearts (20 total??) # Each heart is 0x8 in memory, Max of 19 hearts on easy/normal, 9 on hard, 7 on expert
ShopPriceType.Magic: lambda p: min(15, p // 5) * 8, # Each pip is 0x8 in memory, Max of 15 pips (16 total...) ShopPriceType.Hearts: lambda p, d: max(8, min([19, 19, 9, 7][d], p // 14) * 8),
ShopPriceType.Bombs: lambda p: max(1, min(10, p // 5)), # 10 Bombs max # Each pip is 0x8 in memory, Max of 15 pips (16 total)
ShopPriceType.Arrows: lambda p: max(1, min(30, p // 5)), # 30 Arrows Max ShopPriceType.Magic: lambda p, d: max(8, min(15, p // 18) * 8),
ShopPriceType.HeartContainer: lambda p: 0x8, ShopPriceType.Bombs: lambda p, d: max(1, min(50, p // 5)), # 50 Bombs max
ShopPriceType.BombUpgrade: lambda p: 0x1, ShopPriceType.Arrows: lambda p, d: max(1, min(70, p // 4)), # 70 Arrows Max
ShopPriceType.ArrowUpgrade: lambda p: 0x1, ShopPriceType.HeartContainer: lambda p, d: 0x8,
ShopPriceType.Keys: lambda p: min(3, (p // 100) + 1), # Max of 3 keys for a price ShopPriceType.BombUpgrade: lambda p, d: 0x1,
ShopPriceType.Potion: lambda p: (p // 5) % 5, 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 = { price_type_display_name = {
@ -557,6 +390,8 @@ price_type_display_name = {
ShopPriceType.Bombs: "Bombs", ShopPriceType.Bombs: "Bombs",
ShopPriceType.Arrows: "Arrows", ShopPriceType.Arrows: "Arrows",
ShopPriceType.Keys: "Keys", ShopPriceType.Keys: "Keys",
ShopPriceType.Item: "Item",
ShopPriceType.Magic: "Magic"
} }
# price division # price division
@ -565,57 +400,74 @@ price_rate_display = {
ShopPriceType.Magic: 8, ShopPriceType.Magic: 8,
} }
# prices with no? logic requirements
simple_price_types = [ def get_price_modifier(item):
ShopPriceType.Rupees, if item.game == "A Link to the Past":
ShopPriceType.Hearts, if any(x in item.name for x in
ShopPriceType.Bombs, ['Compass', 'Map', 'Single Bomb', 'Single Arrow', 'Piece of Heart']):
ShopPriceType.Arrows, return 0.125
ShopPriceType.Keys 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): def get_price(multiworld, item, player: int, price_type=None):
""" """Converts a raw Rupee price into a special price type"""
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: if item:
price_types = [ # This is for a shop's regular inventory, the item is already determined, and we will decide the price here
ShopPriceType.Rupees, # included as a chance to not change price type price = item["price"]
ShopPriceType.Hearts, if multiworld.randomize_shop_prices[player]:
ShopPriceType.Bombs, adjust = 2 if price < 100 else 5
] price = int((price / adjust) * (0.5 + multiworld.random.random() * 1.5)) * adjust
# don't pay in universal keys to get access to universal keys multiworld.random.shuffle(price_types)
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)
for p_type in 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]): if any(x in item['item'] for x in price_blacklist[p_type]):
continue continue
else: return p_type, price_chart[p_type](price, diff)
item['price'] = min(price_chart[p_type](item['price']), 255) else:
item['price_type'] = p_type # This is an AP location and the price will be adjusted after an item is shuffled into it
break 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): def shop_price_rules(state: CollectionState, player: int, location: ALttPLocation):
for shop in world.shops: if location.shop_price_type == ShopPriceType.Hearts:
if shop.region.player == player: return has_hearts(state, player, (location.shop_price / 8) + 1)
for i, item in enumerate(shop.inventory): elif location.shop_price_type == ShopPriceType.Bombs:
if item is None: return can_use_bombs(state, player, location.shop_price)
continue elif location.shop_price_type == ShopPriceType.Arrows:
if item['create_location']: return can_hold_arrows(state, player, location.shop_price)
slot_name = f"{shop.region.name}{shop.slot_names[i]}" return True
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

View File

@ -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: 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: 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 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: def can_kill_most_things(state: CollectionState, player: int, enemies: int = 5) -> bool:
return (has_melee_weapon(state, player) if state.multiworld.enemy_shuffle[player]:
or state.has('Cane of Somaria', player) # I don't fully understand Enemizer's logic for placing enemies in spots where they need to be killable, if any.
or (state.has('Cane of Byrna', player) and (enemies < 6 or can_extend_magic(state, player))) # Just go with maximal requirements for now.
or can_shoot_arrows(state, player) return (has_melee_weapon(state, player)
or state.has('Fire Rod', player) and state.has('Cane of Somaria', player)
or (state.has('Bombs (10)', player) and enemies < 6)) 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: def can_get_good_bee(state: CollectionState, player: int) -> bool:

View File

@ -14,9 +14,12 @@ class ALttPLocation(Location):
crystal: bool crystal: bool
player_address: Optional[int] player_address: Optional[int]
_hint_text: Optional[str] _hint_text: Optional[str]
shop: None
shop_slot: Optional[int] = None shop_slot: Optional[int] = None
"""If given as integer, shop_slot is the shop's inventory index.""" """If given as integer, shop_slot is the shop's inventory index."""
shop_slot_disabled: bool = False shop_slot_disabled: bool = False
shop_price = 0
shop_price_type = None
parent_region: "LTTPRegion" parent_region: "LTTPRegion"
def __init__(self, player: int, name: str, address: Optional[int] = None, crystal: bool = False, def __init__(self, player: int, name: str, address: Optional[int] = None, crystal: bool = False,

View File

@ -42,7 +42,7 @@ def dungeon_reentry_rules(world, player, clip: Entrance, dungeon_region: str, du
fix_fake_worlds = world.fix_fake_world[player] 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] 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. # 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': 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 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 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. # 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)) 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. # 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))) add_rule(clip, lambda state: dungeon_entrance.access_rule(fake_pearl_state(state, player)))
# exiting restriction # exiting restriction
add_rule(world.get_entrance(dungeon_exit, player), lambda state: dungeon_entrance.can_reach(state)) 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. # 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. # 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. # First we require a certain type of entrance shuffle, then build the rule from its pieces.
if not world.swamp_patch_required[player]: 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 = { rule_map = {
'Misery Mire (Entrance)': (lambda state: True), 'Misery Mire (Entrance)': (lambda state: True),
'Tower of Hera (Bottom)': (lambda state: state.can_reach('Tower of Hera Big Key Door', 'Entrance', player)) 'Tower of Hera (Bottom)': (lambda state: state.can_reach('Tower of Hera Big Key Door', 'Entrance', player))

View File

@ -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 .InvertedRegions import create_inverted_regions, mark_dark_world_regions
from .ItemPool import generate_itempool, difficulties from .ItemPool import generate_itempool, difficulties
from .Items import item_init_table, item_name_groups, item_table, GetBeemizerItem 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, \ from .Regions import lookup_name_to_id, create_regions, mark_light_world_regions, lookup_vanilla_location_to_entrance, \
is_main_entrance, key_drop_data is_main_entrance, key_drop_data
from .Client import ALTTPSNIClient from .Client import ALTTPSNIClient
from .Rom import LocalRom, patch_rom, patch_race_rom, check_enemizer, patch_enemizer, apply_rom_settings, \ from .Rom import LocalRom, patch_rom, patch_race_rom, check_enemizer, patch_enemizer, apply_rom_settings, \
get_hash_string, get_base_rom_path, LttPDeltaPatch get_hash_string, get_base_rom_path, LttPDeltaPatch
from .Rules import set_rules 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 .SubClasses import ALttPItem, LTTPRegionType
from worlds.AutoWorld import World, WebWorld, LogicMixin from worlds.AutoWorld import World, WebWorld, LogicMixin
from .StateHelpers import can_buy_unlimited 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} 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 location_name_to_id = lookup_name_to_id
data_version = 8 data_version = 9
required_client_version = (0, 4, 1) required_client_version = (0, 4, 1)
web = ALTTPWeb() web = ALTTPWeb()
@ -290,33 +290,34 @@ class ALTTPWorld(World):
self.pyramid_fairy_bottle_fill = self.random.choice(bottle_options) self.pyramid_fairy_bottle_fill = self.random.choice(bottle_options)
if multiworld.mode[player] == 'standard': if multiworld.mode[player] == 'standard':
if multiworld.smallkey_shuffle[player]: if multiworld.small_key_shuffle[player]:
if (multiworld.smallkey_shuffle[player] not in if (multiworld.small_key_shuffle[player] not in
(smallkey_shuffle.option_universal, smallkey_shuffle.option_own_dungeons, (small_key_shuffle.option_universal, small_key_shuffle.option_own_dungeons,
smallkey_shuffle.option_start_with)): small_key_shuffle.option_start_with)):
self.multiworld.local_early_items[self.player]["Small Key (Hyrule Castle)"] = 1 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.local_items[self.player].value.add("Small Key (Hyrule Castle)")
self.multiworld.non_local_items[self.player].value.discard("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.local_items[self.player].value.add("Big Key (Hyrule Castle)")
self.multiworld.non_local_items[self.player].value.discard("Big Key (Hyrule Castle)") self.multiworld.non_local_items[self.player].value.discard("Big Key (Hyrule Castle)")
# system for sharing ER layouts # system for sharing ER layouts
self.er_seed = str(multiworld.random.randint(0, 2 ** 64)) self.er_seed = str(multiworld.random.randint(0, 2 ** 64))
if "-" in multiworld.shuffle[player]: if multiworld.entrance_shuffle[player] != "vanilla" and multiworld.entrance_shuffle_seed[player] != "random":
shuffle, seed = multiworld.shuffle[player].split("-", 1) shuffle = multiworld.entrance_shuffle[player].current_key
multiworld.shuffle[player] = shuffle
if shuffle == "vanilla": if shuffle == "vanilla":
self.er_seed = "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, ( 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. else: # not a race or group seed, use set seed as is.
self.er_seed = seed self.er_seed = int(multiworld.entrance_shuffle_seed[player].value)
elif multiworld.shuffle[player] == "vanilla": elif multiworld.entrance_shuffle[player] == "vanilla":
self.er_seed = "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] option = getattr(multiworld, dungeon_item)[player]
if option == "own_world": if option == "own_world":
multiworld.local_items[player].value |= self.item_name_groups[option.item_name_group] multiworld.local_items[player].value |= self.item_name_groups[option.item_name_group]
@ -329,10 +330,10 @@ class ALTTPWorld(World):
if option == "original_dungeon": if option == "original_dungeon":
self.dungeon_specific_item_names |= self.item_name_groups[option.item_name_group] 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. # 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') 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). # 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 player = self.player
world = self.multiworld world = self.multiworld
world.triforce_pieces_available[player] = max(world.triforce_pieces_available[player],
world.triforce_pieces_required[player])
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
create_regions(world, player) create_regions(world, player)
else: else:
@ -355,8 +353,8 @@ class ALTTPWorld(World):
create_shops(world, player) create_shops(world, player)
self.create_dungeons() self.create_dungeons()
if world.logic[player] not in ["noglitches", "minorglitches"] and world.shuffle[player] in \ if world.glitches_required[player] not in ["no_glitches", "minor_glitches"] and world.entrance_shuffle[player] in \
{"vanilla", "dungeonssimple", "dungeonsfull", "simple", "restricted", "full"}: {"vanilla", "dungeons_simple", "dungeons_full", "simple", "restricted", "full"}:
world.fix_fake_world[player] = False world.fix_fake_world[player] = False
# seeded entrance shuffle # seeded entrance shuffle
@ -455,7 +453,7 @@ class ALTTPWorld(World):
if state.has('Silver Bow', item.player): if state.has('Silver Bow', item.player):
return return
elif state.has('Bow', item.player) and (self.multiworld.difficulty_requirements[item.player].progressive_bow_limit >= 2 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 or self.multiworld.swordless[item.player]): # modes where silver bow is always required for ganon
return 'Silver Bow' return 'Silver Bow'
elif self.multiworld.difficulty_requirements[item.player].progressive_bow_limit >= 1: elif self.multiworld.difficulty_requirements[item.player].progressive_bow_limit >= 1:
@ -499,9 +497,9 @@ class ALTTPWorld(World):
break break
else: else:
raise FillError('Unable to place dungeon prizes') raise FillError('Unable to place dungeon prizes')
if world.mode[player] == 'standard' and world.smallkey_shuffle[player] \ if world.mode[player] == 'standard' and world.small_key_shuffle[player] \
and world.smallkey_shuffle[player] != smallkey_shuffle.option_universal and \ and world.small_key_shuffle[player] != small_key_shuffle.option_universal and \
world.smallkey_shuffle[player] != smallkey_shuffle.option_own_dungeons: world.small_key_shuffle[player] != small_key_shuffle.option_own_dungeons:
world.local_early_items[player]["Small Key (Hyrule Castle)"] = 1 world.local_early_items[player]["Small Key (Hyrule Castle)"] = 1
@classmethod @classmethod
@ -509,10 +507,9 @@ class ALTTPWorld(World):
from .Dungeons import fill_dungeons_restrictive from .Dungeons import fill_dungeons_restrictive
fill_dungeons_restrictive(world) fill_dungeons_restrictive(world)
@classmethod @classmethod
def stage_post_fill(cls, world): def stage_post_fill(cls, world):
ShopSlotFill(world) push_shop_inventories(world)
@property @property
def use_enemizer(self) -> bool: def use_enemizer(self) -> bool:
@ -579,7 +576,7 @@ class ALTTPWorld(World):
@classmethod @classmethod
def stage_extend_hint_information(cls, world, hint_data: typing.Dict[int, typing.Dict[int, str]]): 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 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: for region in world.regions:
if region.player in er_hint_data and region.locations: if region.player in er_hint_data and region.locations:
@ -645,9 +642,9 @@ class ALTTPWorld(World):
trash_counts = {} trash_counts = {}
for player in world.get_game_players("A Link to the Past"): for player in world.get_game_players("A Link to the Past"):
if not world.ganonstower_vanilla[player] or \ 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 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, trash_counts[player] = world.random.randint(world.crystals_needed_for_gt[player] * 2,
world.crystals_needed_for_gt[player] * 4) world.crystals_needed_for_gt[player] * 4)
else: else:
@ -681,35 +678,6 @@ class ALTTPWorld(World):
return variable return variable
return "Yes" if variable else "No" 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: def write_spoiler(self, spoiler_handle: typing.TextIO) -> None:
player_name = self.multiworld.get_player_name(self.player) player_name = self.multiworld.get_player_name(self.player)
spoiler_handle.write("\n\nMedallions:\n") spoiler_handle.write("\n\nMedallions:\n")
@ -783,7 +751,7 @@ class ALTTPWorld(World):
if item["replacement"] is None: if item["replacement"] is None:
continue continue
shop_data["item_{}".format(index)] +=\ 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']]}" f" {price_type_display_name[item['replacement_price_type']]}"
return shop_data return shop_data
@ -796,10 +764,7 @@ class ALTTPWorld(World):
item))) item)))
def get_filler_item_name(self) -> str: def get_filler_item_name(self) -> str:
if self.multiworld.goal[self.player] == "icerodhunt": item = self.multiworld.random.choice(extras_list)
item = "Nothing"
else:
item = self.multiworld.random.choice(extras_list)
return GetBeemizerItem(self.multiworld, self.player, item) return GetBeemizerItem(self.multiworld, self.player, item)
def get_pre_fill_items(self): 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 # 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", 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", "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 = {option_name: getattr(self.multiworld, option_name)[self.player].value for option_name in slot_options}
slot_data.update({ 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], 'mm_medalion': self.multiworld.required_medallions[self.player][0],
'tr_medalion': self.multiworld.required_medallions[self.player][1], '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 return slot_data
@ -849,8 +814,8 @@ def get_same_seed(world, seed_def: tuple) -> str:
class ALttPLogic(LogicMixin): class ALttPLogic(LogicMixin):
def _lttp_has_key(self, item, player, count: int = 1): 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 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 can_buy_unlimited(self, 'Small Key (Universal)', player)
return self.prog_items[player][item] >= count return self.prog_items[player][item] >= count

View File

@ -7,25 +7,25 @@ class TestAgahnimsTower(TestDungeon):
self.starting_regions = ['Agahnims Tower'] self.starting_regions = ['Agahnims Tower']
self.run_tests([ self.run_tests([
["Castle Tower - Room 03", False, []], ["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 - Room 03", True, ['Progressive Sword']],
["Castle Tower - Dark Maze", False, []], ["Castle Tower - Dark Maze", False, []],
["Castle Tower - Dark Maze", False, [], ['Small Key (Agahnims Tower)']], ["Castle Tower - Dark Maze", False, [], ['Small Key (Agahnims Tower)']],
["Castle Tower - Dark Maze", False, [], ['Lamp']], ["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 Maze", True, ['Progressive Sword', 'Small Key (Agahnims Tower)', 'Lamp']],
["Castle Tower - Dark Archer Key Drop", False, []], ["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, ['Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)']],
["Castle Tower - Dark Archer Key Drop", False, [], ['Lamp']], ["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 - 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, []],
["Castle Tower - Circle of Pots Key Drop", False, ['Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)']], ["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, [], ['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']], ["Castle Tower - Circle of Pots Key Drop", True, ['Progressive Sword', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Lamp']],
["Agahnim 1", False, []], ["Agahnim 1", False, []],

View File

@ -11,29 +11,37 @@ class TestDarkPalace(TestDungeon):
["Palace of Darkness - The Arena - Ledge", False, []], ["Palace of Darkness - The Arena - Ledge", False, []],
["Palace of Darkness - The Arena - Ledge", False, [], ['Progressive Bow']], ["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, []],
["Palace of Darkness - Map Chest", False, [], ['Progressive Bow']], ["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 #Lower requirement for self-locking key
#No lower requirement when bow/hammer is out of logic #No lower requirement when bow/hammer is out of logic
["Palace of Darkness - Big Key Chest", False, []], ["Palace of Darkness - Big Key Chest", False, []],
["Palace of Darkness - Big Key Chest", False, [key]*5, [key]], ["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, []],
["Palace of Darkness - The Arena - Bridge", False, [], [key, 'Progressive Bow']], ["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, '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, [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, []],
["Palace of Darkness - Stalfos Basement", False, [], [key, 'Progressive Bow']], ["Palace of Darkness - Stalfos Basement", False, [], [key, 'Progressive Bow']],
["Palace of Darkness - Stalfos Basement", False, [], [key, 'Hammer']], ["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, [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, []],
["Palace of Darkness - Compass Chest", False, [key]*3, [key]], ["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, []],
["Palace of Darkness - Big Chest", False, [], ['Lamp']], ["Palace of Darkness - Big Chest", False, [], ['Lamp']],
["Palace of Darkness - Big Chest", False, [], ['Big Key (Palace of Darkness)']], ["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", 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, []],
["Palace of Darkness - Boss", False, [], ['Lamp']], ["Palace of Darkness - Boss", False, [], ['Lamp']],

View File

@ -14,6 +14,8 @@ class TestDungeon(LTTPTestBase):
self.starting_regions = [] # Where to start exploring self.starting_regions = [] # Where to start exploring
self.remove_exits = [] # Block dungeon exits self.remove_exits = [] # Block dungeon exits
self.multiworld.difficulty_requirements[1] = difficulties['normal'] 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) create_regions(self.multiworld, 1)
self.multiworld.worlds[1].create_dungeons() self.multiworld.worlds[1].create_dungeons()
create_shops(self.multiworld, 1) create_shops(self.multiworld, 1)

View File

@ -18,8 +18,8 @@ class TestEasternPalace(TestDungeon):
["Eastern Palace - Big Key Chest", False, []], ["Eastern Palace - Big Key Chest", False, []],
["Eastern Palace - Big Key Chest", False, [], ['Lamp']], ["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', 'Small Key (Eastern Palace)', 'Small Key (Eastern Palace)', 'Progressive Sword']],
["Eastern Palace - Big Key Chest", True, ['Lamp', 'Big Key (Eastern Palace)']], ["Eastern Palace - Big Key Chest", True, ['Lamp', 'Big Key (Eastern Palace)', 'Progressive Sword']],
#@todo: Advanced? #@todo: Advanced?
["Eastern Palace - Boss", False, []], ["Eastern Palace - Boss", False, []],

View File

@ -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 - 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", 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, ['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, ['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)', 'Hookshot', 'Hammer']],
["Ganons Tower - Big Key Room - Left", False, []], ["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, ['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, ['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)', 'Hookshot', 'Hammer']],
["Ganons Tower - Big Key Room - Right", False, []], ["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, ['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, ['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)', 'Hookshot', 'Hammer']],
["Ganons Tower - Mini Helmasaur Room - Left", False, []], ["Ganons Tower - Mini Helmasaur Room - Left", False, []],
["Ganons Tower - Mini Helmasaur Room - Left", False, [], ['Progressive Bow']], ["Ganons Tower - Mini Helmasaur Room - Left", False, [], ['Progressive Bow']],

View File

@ -11,8 +11,9 @@ class TestIcePalace(TestDungeon):
["Ice Palace - Big Key Chest", False, [], ['Progressive Glove']], ["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', 'Bombos']],
["Ice Palace - Big Key Chest", False, [], ['Fire Rod', 'Progressive Sword']], ["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", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Big Key Chest", True, ['Progressive Glove', 'Bombos', 'Progressive Sword', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']], ["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 #@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', '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)']], #["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, [], ['Progressive Glove']],
["Ice Palace - Map Chest", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Map Chest", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Map Chest", False, [], ['Fire Rod', 'Progressive Sword']], ["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", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Map Chest", True, ['Progressive Glove', 'Bombos', 'Progressive Sword', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']], ["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', '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', '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)']], #["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, []],
["Ice Palace - Spike Room", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Spike Room", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Spike Room", False, [], ['Fire Rod', 'Progressive Sword']], ["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", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Spike Room", True, ['Bombos', 'Progressive Sword', 'Hookshot', 'Small Key (Ice Palace)']], ["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', '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, ['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)']], #["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, []],
["Ice Palace - Freezor Chest", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Freezor Chest", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Freezor Chest", False, [], ['Fire Rod', 'Progressive Sword']], ["Ice Palace - Freezor Chest", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Freezor Chest", True, ['Fire Rod']], ["Ice Palace - Freezor Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Freezor Chest", True, ['Bombos', 'Progressive Sword']], ["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, []],
["Ice Palace - Iced T Room", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Iced T Room", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Iced T Room", False, [], ['Fire Rod', 'Progressive Sword']], ["Ice Palace - Iced T Room", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Iced T Room", True, ['Fire Rod']], ["Ice Palace - Iced T Room", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Iced T Room", True, ['Bombos', 'Progressive Sword']], ["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, []],
["Ice Palace - Big Chest", False, [], ['Big Key (Ice Palace)']], ["Ice Palace - Big Chest", False, [], ['Big Key (Ice Palace)']],
["Ice Palace - Big Chest", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Big Chest", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Big Chest", False, [], ['Fire Rod', 'Progressive Sword']], ["Ice Palace - Big Chest", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Big Chest", True, ['Big Key (Ice Palace)', 'Fire Rod']], ["Ice Palace - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Big Chest", True, ['Big Key (Ice Palace)', 'Bombos', 'Progressive Sword']], ["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, []],
["Ice Palace - Boss", False, [], ['Hammer']], ["Ice Palace - Boss", False, [], ['Hammer']],
@ -72,9 +78,10 @@ class TestIcePalace(TestDungeon):
["Ice Palace - Boss", False, [], ['Big Key (Ice Palace)']], ["Ice Palace - Boss", False, [], ['Big Key (Ice Palace)']],
["Ice Palace - Boss", False, [], ['Fire Rod', 'Bombos']], ["Ice Palace - Boss", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Boss", False, [], ['Fire Rod', 'Progressive Sword']], ["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 # 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, ['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, ['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)', '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, ['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, ['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)', 'Bombos', 'Progressive Sword', 'Hammer', 'Cane of Somaria', 'Small Key (Ice Palace)', 'Hookshot']],
]) ])

View File

@ -78,7 +78,8 @@ class TestMiseryMire(TestDungeon):
["Misery Mire - Boss", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow']], ["Misery Mire - Boss", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow']],
["Misery Mire - Boss", False, [], ['Big Key (Misery Mire)']], ["Misery Mire - Boss", False, [], ['Big Key (Misery Mire)']],
["Misery Mire - Boss", False, [], ['Pegasus Boots', 'Hookshot']], ["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", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Misery Mire - Boss", True, ['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 Sword', 'Pegasus Boots']],
["Misery Mire - Boss", True, ['Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Progressive Bow', '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']],
]) ])

View File

@ -8,7 +8,8 @@ class TestSkullWoods(TestDungeon):
self.run_tests([ self.run_tests([
["Skull Woods - Big Chest", False, []], ["Skull Woods - Big Chest", False, []],
["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']], ["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, []], ["Skull Woods - Compass Chest", True, []],
@ -64,7 +65,8 @@ class TestSkullWoods(TestDungeon):
self.run_tests([ self.run_tests([
["Skull Woods - Big Chest", False, []], ["Skull Woods - Big Chest", False, []],
["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']], ["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, []],
["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)']], ["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)']],

View File

@ -30,7 +30,8 @@ class TestSwampPalace(TestDungeon):
["Swamp Palace - Map Chest", False, [], ['Flippers']], ["Swamp Palace - Map Chest", False, [], ['Flippers']],
["Swamp Palace - Map Chest", False, [], ['Open Floodgate']], ["Swamp Palace - Map Chest", False, [], ['Open Floodgate']],
["Swamp Palace - Map Chest", False, [], ['Small Key (Swamp Palace)']], ["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, []],
["Swamp Palace - West Chest", False, [], ['Flippers']], ["Swamp Palace - West Chest", False, [], ['Flippers']],

View File

@ -41,8 +41,9 @@ class TestThievesTown(TestDungeon):
["Thieves' Town - Boss", False, []], ["Thieves' Town - Boss", False, []],
["Thieves' Town - Boss", False, [], ['Big Key (Thieves Town)']], ["Thieves' Town - Boss", False, [], ['Big Key (Thieves Town)']],
["Thieves' Town - Boss", False, [], ['Hammer', 'Progressive Sword', 'Cane of Somaria', 'Cane of Byrna']], ["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", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Thieves' Town - Boss", True, ['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)', 'Hammer']],
["Thieves' Town - Boss", True, ['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)', 'Progressive Sword']],
["Thieves' Town - Boss", True, ['Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Cane of Byrna']], ["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']],
]) ])

View File

@ -18,11 +18,11 @@ class TestTowerOfHera(TestDungeon):
["Tower of Hera - Compass Chest", False, []], ["Tower of Hera - Compass Chest", False, []],
["Tower of Hera - Compass Chest", False, [], ['Big Key (Tower of Hera)']], ["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, []],
["Tower of Hera - Big Chest", False, [], ['Big Key (Tower of Hera)']], ["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, []],
["Tower of Hera - Boss", False, [], ['Big Key (Tower of Hera)']], ["Tower of Hera - Boss", False, [], ['Big Key (Tower of Hera)']],

View File

@ -14,7 +14,9 @@ class TestInverted(TestBase, LTTPTestBase):
def setUp(self): def setUp(self):
self.world_setup() self.world_setup()
self.multiworld.difficulty_requirements[1] = difficulties['normal'] 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) create_inverted_regions(self.multiworld, 1)
self.multiworld.worlds[1].create_dungeons() self.multiworld.worlds[1].create_dungeons()
create_shops(self.multiworld, 1) create_shops(self.multiworld, 1)

View File

@ -11,8 +11,8 @@ class TestInvertedBombRules(LTTPTestBase):
def setUp(self): def setUp(self):
self.world_setup() self.world_setup()
self.multiworld.mode[1] = "inverted"
self.multiworld.difficulty_requirements[1] = difficulties['normal'] self.multiworld.difficulty_requirements[1] = difficulties['normal']
self.multiworld.mode[1].value = 2
create_inverted_regions(self.multiworld, 1) create_inverted_regions(self.multiworld, 1)
self.multiworld.worlds[1].create_dungeons() self.multiworld.worlds[1].create_dungeons()

View File

@ -5,7 +5,8 @@ class TestInvertedDarkWorld(TestInverted):
def testNorthWest(self): def testNorthWest(self):
self.run_location_tests([ 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, []], ["C-Shaped House", True, []],
@ -77,15 +78,16 @@ class TestInvertedDarkWorld(TestInverted):
def testSouth(self): def testSouth(self):
self.run_location_tests([ self.run_location_tests([
["Hype Cave - Top", 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", True, []], ["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", True, []], ["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", True, []], ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)']],
["Hype Cave - Generous Guy", True, []], ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)']],
["Stumpy", True, []], ["Stumpy", True, []],

View File

@ -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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', '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, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["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, []],
["Paradox Cave Lower - Left", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', '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, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']],
["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["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, []],
["Paradox Cave Lower - Middle", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', '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, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["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, []],
["Paradox Cave Lower - Right", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', '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, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']],
["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["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, []],
["Paradox Cave Lower - Far Right", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', '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, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']], ["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, []],
["Paradox Cave Upper - Left", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', '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, []],
["Paradox Cave Upper - Right", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', '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, []],
["Mimic Cave", False, [], ['Moon Pearl']], ["Mimic Cave", False, [], ['Moon Pearl']],
["Mimic Cave", False, [], ['Hammer']], ["Mimic Cave", False, [], ['Hammer']],
["Mimic Cave", False, [], ['Progressive Glove', 'Flute']], ["Mimic Cave", False, [], ['Progressive Glove', 'Flute']],
["Mimic Cave", False, [], ['Lamp', 'Flute']], ["Mimic Cave", False, [], ['Lamp', 'Flute']],
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot']], ["Mimic Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Bow', 'Cane of Somaria', 'Progressive Sword']],
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']], ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Flute', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']], ["Mimic Cave", True, ['Progressive Bow', 'Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
["Mimic Cave", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', '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, []],
["Ether Tablet", False, [], ['Moon Pearl']], ["Ether Tablet", False, [], ['Moon Pearl']],

View File

@ -44,15 +44,17 @@ class TestInvertedLightWorld(TestInverted):
["Chicken House", False, []], ["Chicken House", False, []],
["Chicken House", False, [], ['Moon Pearl']], ["Chicken House", False, [], ['Moon Pearl']],
["Chicken House", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Chicken House", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Chicken House", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Chicken House", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Chicken House", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Kakariko Well - Top", False, [], ['Moon Pearl']], ["Kakariko Well - Top", False, [], ['Moon Pearl']],
["Kakariko Well - Top", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Kakariko Well - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Kakariko Well - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Kakariko Well - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Kakariko Well - Left", False, [], ['Moon Pearl']], ["Kakariko Well - Left", False, [], ['Moon Pearl']],
@ -80,9 +82,10 @@ class TestInvertedLightWorld(TestInverted):
["Blind's Hideout - Top", False, []], ["Blind's Hideout - Top", False, []],
["Blind's Hideout - Top", False, [], ['Moon Pearl']], ["Blind's Hideout - Top", False, [], ['Moon Pearl']],
["Blind's Hideout - Top", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Blind's Hideout - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Blind's Hideout - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Blind's Hideout - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Blind's Hideout - Left", False, [], ['Moon Pearl']], ["Blind's Hideout - Left", False, [], ['Moon Pearl']],
@ -161,9 +164,10 @@ class TestInvertedLightWorld(TestInverted):
["Maze Race", False, []], ["Maze Race", False, []],
["Maze Race", False, [], ['Moon Pearl']], ["Maze Race", False, [], ['Moon Pearl']],
["Maze Race", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Maze Race", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Maze Race", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Maze Race", True, ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']],
["Maze Race", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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): def testSouthLightWorld(self):
@ -184,9 +188,10 @@ class TestInvertedLightWorld(TestInverted):
["Aginah's Cave", False, []], ["Aginah's Cave", False, []],
["Aginah's Cave", False, [], ['Moon Pearl']], ["Aginah's Cave", False, [], ['Moon Pearl']],
["Aginah's Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Aginah's Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Aginah's Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Aginah's Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Aginah's Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Bombos Tablet", False, ['Progressive Sword'], ['Progressive Sword']], ["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, []],
["Mini Moldorm Cave - Far Left", False, [], ['Moon Pearl']], ["Mini Moldorm Cave - Far Left", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Mini Moldorm Cave - Far Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Sword']],
["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Mini Moldorm Cave - Left", False, [], ['Moon Pearl']], ["Mini Moldorm Cave - Left", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Mini Moldorm Cave - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Sword']],
["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']], ["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Mini Moldorm Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Sword']],
["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Mini Moldorm Cave - Right", False, [], ['Moon Pearl']], ["Mini Moldorm Cave - Right", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Mini Moldorm Cave - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Sword']],
["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Mini Moldorm Cave - Far Right", False, [], ['Moon Pearl']], ["Mini Moldorm Cave - Far Right", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Mini Moldorm Cave - Far Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Sword']],
["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Ice Rod Cave", False, [], ['Moon Pearl']], ["Ice Rod Cave", False, [], ['Moon Pearl']],
["Ice Rod Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Rod Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Ice Rod Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Ice Rod Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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): def testZoraArea(self):
@ -302,21 +313,24 @@ class TestInvertedLightWorld(TestInverted):
["Sahasrahla's Hut - Left", False, []], ["Sahasrahla's Hut - Left", False, []],
["Sahasrahla's Hut - Left", False, [], ['Moon Pearl']], ["Sahasrahla's Hut - Left", False, [], ['Moon Pearl']],
["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Sahasrahla's Hut - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl']], ["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl']],
["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Sahasrahla's Hut - Middle", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Sahasrahla's Hut - Middle", True, ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Sahasrahla's Hut - Right", False, [], ['Moon Pearl']], ["Sahasrahla's Hut - Right", False, [], ['Moon Pearl']],
["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Sahasrahla's Hut - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Sahasrahla's Hut - Right", True, ['Pegasus Boots', 'Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Sahasrahla", False, [], ['Green Pendant']], ["Sahasrahla", False, [], ['Green Pendant']],
@ -346,9 +360,10 @@ class TestInvertedLightWorld(TestInverted):
["Graveyard Cave", False, []], ["Graveyard Cave", False, []],
["Graveyard Cave", False, [], ['Moon Pearl']], ["Graveyard Cave", False, [], ['Moon Pearl']],
["Graveyard Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Graveyard Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Graveyard Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], ["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, []],
["Potion Shop", False, [], ['Mushroom']], ["Potion Shop", False, [], ['Mushroom']],

View File

@ -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", 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, ['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', '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, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']],
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Magic Mirror', '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, []],
["Turtle Rock - Roller Room - Left", False, [], ['Cane of Somaria']], ["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, [], ['Big Key (Turtle Rock)']],
["Turtle Rock - Big Chest", False, [], ['Magic Mirror', 'Cane of Somaria']], ["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", 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, ['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, ['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)', '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', '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', 'Progressive Glove', 'Hookshot']],
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', '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, ['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)']], ["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 # 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, ['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, ['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', '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, ['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, ['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', '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, []],
["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']], ["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', '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', '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)']] ["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): def testEyeBridge(self):
for location in ["Turtle Rock - Eye Bridge - Top Right", "Turtle Rock - Eye Bridge - Top Left", 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"]: "Turtle Rock - Eye Bridge - Bottom Right", "Turtle Rock - Eye Bridge - Bottom Left"]:

View File

@ -5,7 +5,8 @@ class TestInvertedDarkWorld(TestInvertedMinor):
def testNorthWest(self): def testNorthWest(self):
self.run_location_tests([ 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, []], ["C-Shaped House", True, []],
@ -67,15 +68,16 @@ class TestInvertedDarkWorld(TestInvertedMinor):
def testSouth(self): def testSouth(self):
self.run_location_tests([ self.run_location_tests([
["Hype Cave - Top", 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", True, []], ["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", True, []], ["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", True, []], ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)']],
["Hype Cave - Generous Guy", True, []], ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)']],
["Stumpy", True, []], ["Stumpy", True, []],

View File

@ -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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', '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, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Far Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Lower - Far Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', '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, []],
["Paradox Cave Lower - Left", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', '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, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Lower - Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', '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, []],
["Paradox Cave Lower - Middle", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', '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, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Middle", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Lower - Middle", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', '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, []],
["Paradox Cave Lower - Right", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', '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, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Lower - Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', '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, []],
["Paradox Cave Lower - Far Right", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', '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, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Lower - Far Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Lower - Far Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', '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, []],
["Paradox Cave Upper - Left", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', '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, []],
["Paradox Cave Upper - Right", False, [], ['Moon Pearl']], ["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'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']], ["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", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', '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, []],
["Mimic Cave", False, [], ['Moon Pearl']], ["Mimic Cave", False, [], ['Moon Pearl']],
["Mimic Cave", False, [], ['Hammer']], ["Mimic Cave", False, [], ['Hammer']],
["Mimic Cave", False, [], ['Progressive Glove', 'Flute']], ["Mimic Cave", False, [], ['Progressive Glove', 'Flute']],
["Mimic Cave", False, [], ['Lamp', 'Flute']], ["Mimic Cave", False, [], ['Lamp', 'Flute']],
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot']], ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Flute', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']], ["Mimic Cave", True, ['Progressive Sword', 'Progressive Sword', 'Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
["Mimic Cave", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']], ["Mimic Cave", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']], ["Mimic Cave", True, ['Cane of Somaria', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']],
["Ether Tablet", False, []], ["Ether Tablet", False, []],
["Ether Tablet", False, [], ['Moon Pearl']], ["Ether Tablet", False, [], ['Moon Pearl']],

View File

@ -43,16 +43,18 @@ class TestInvertedLightWorld(TestInvertedMinor):
["Chicken House", False, []], ["Chicken House", False, []],
["Chicken House", False, [], ['Moon Pearl']], ["Chicken House", False, [], ['Moon Pearl']],
["Chicken House", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Chicken House", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']],
["Chicken House", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Chicken House", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Chicken House", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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 # top can't be bombed as super bunny and needs Moon Pearl
["Kakariko Well - Top", False, []], ["Kakariko Well - Top", False, []],
["Kakariko Well - Top", False, [], ['Moon Pearl']], ["Kakariko Well - Top", False, [], ['Moon Pearl']],
["Kakariko Well - Top", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Kakariko Well - Top", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']],
["Kakariko Well - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Kakariko Well - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Kakariko Well - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Kakariko Well - Left", True, ['Beat Agahnim 1']], ["Kakariko Well - Left", True, ['Beat Agahnim 1']],
@ -76,9 +78,10 @@ class TestInvertedLightWorld(TestInvertedMinor):
["Blind's Hideout - Top", False, []], ["Blind's Hideout - Top", False, []],
["Blind's Hideout - Top", False, [], ['Moon Pearl', 'Magic Mirror']], ["Blind's Hideout - Top", False, [], ['Moon Pearl', 'Magic Mirror']],
["Blind's Hideout - Top", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Blind's Hideout - Top", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']],
["Blind's Hideout - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Blind's Hideout - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Blind's Hideout - Left", False, [], ['Moon Pearl', 'Magic Mirror']], ["Blind's Hideout - Left", False, [], ['Moon Pearl', 'Magic Mirror']],
@ -157,9 +160,10 @@ class TestInvertedLightWorld(TestInvertedMinor):
["Maze Race", False, []], ["Maze Race", False, []],
["Maze Race", False, [], ['Moon Pearl']], ["Maze Race", False, [], ['Moon Pearl']],
["Maze Race", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Maze Race", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)', 'Pegasus Boots']],
["Maze Race", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Maze Race", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Maze Race", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Maze Race", True, ['Pegasus Boots', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Maze Race", True, ['Pegasus Boots', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
]) ])
def testSouthLightWorld(self): def testSouthLightWorld(self):
@ -179,9 +183,10 @@ class TestInvertedLightWorld(TestInvertedMinor):
["Aginah's Cave", False, []], ["Aginah's Cave", False, []],
["Aginah's Cave", False, [], ['Moon Pearl']], ["Aginah's Cave", False, [], ['Moon Pearl']],
["Aginah's Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Aginah's Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Aginah's Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Aginah's Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Aginah's Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Bombos Tablet", False, ['Progressive Sword'], ['Progressive Sword']], ["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, []],
["Mini Moldorm Cave - Far Left", False, [], ['Moon Pearl']], ["Mini Moldorm Cave - Far Left", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Mini Moldorm Cave - Far Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Beat Agahnim 1']],
["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Mini Moldorm Cave - Left", False, [], ['Moon Pearl']], ["Mini Moldorm Cave - Left", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Mini Moldorm Cave - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Beat Agahnim 1']],
["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']], ["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Mini Moldorm Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Beat Agahnim 1']],
["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Mini Moldorm Cave - Right", False, [], ['Moon Pearl']], ["Mini Moldorm Cave - Right", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Mini Moldorm Cave - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Beat Agahnim 1']],
["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Mini Moldorm Cave - Far Right", False, [], ['Moon Pearl']], ["Mini Moldorm Cave - Far Right", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Mini Moldorm Cave - Far Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Beat Agahnim 1']],
["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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, []],
["Ice Rod Cave", False, [], ['Moon Pearl']], ["Ice Rod Cave", False, [], ['Moon Pearl']],
["Ice Rod Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Rod Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Ice Rod Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Ice Rod Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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): def testZoraArea(self):
@ -297,25 +308,28 @@ class TestInvertedLightWorld(TestInvertedMinor):
["Sahasrahla's Hut - Left", False, []], ["Sahasrahla's Hut - Left", False, []],
["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Magic Mirror']], ["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Magic Mirror']],
["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Sahasrahla's Hut - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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 # super bunny bonk
["Sahasrahla's Hut - Left", True, ['Magic Mirror', 'Beat Agahnim 1', 'Pegasus Boots']], ["Sahasrahla's Hut - Left", True, ['Magic Mirror', 'Beat Agahnim 1', 'Pegasus Boots']],
["Sahasrahla's Hut - Middle", False, []], ["Sahasrahla's Hut - Middle", False, []],
["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Magic Mirror']], ["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Magic Mirror']],
["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Sahasrahla's Hut - Middle", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Sahasrahla's Hut - Middle", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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 # super bunny bonk
["Sahasrahla's Hut - Middle", True, ['Magic Mirror', 'Beat Agahnim 1', 'Pegasus Boots']], ["Sahasrahla's Hut - Middle", True, ['Magic Mirror', 'Beat Agahnim 1', 'Pegasus Boots']],
["Sahasrahla's Hut - Right", False, []], ["Sahasrahla's Hut - Right", False, []],
["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Magic Mirror']], ["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Magic Mirror']],
["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Beat Agahnim 1']], ["Sahasrahla's Hut - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Sahasrahla's Hut - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["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 # super bunny bonk
["Sahasrahla's Hut - Right", True, ['Magic Mirror', 'Beat Agahnim 1', 'Pegasus Boots']], ["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, []],
["Graveyard Cave", False, [], ['Moon Pearl']], ["Graveyard Cave", False, [], ['Moon Pearl']],
["Graveyard Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Graveyard Cave", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Graveyard Cave", True, ['Moon Pearl', 'Beat Agahnim 1']], ["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, []],
["Potion Shop", False, [], ['Mushroom']], ["Potion Shop", False, [], ['Mushroom']],

View File

@ -13,8 +13,10 @@ from worlds.alttp.test import LTTPTestBase
class TestInvertedMinor(TestBase, LTTPTestBase): class TestInvertedMinor(TestBase, LTTPTestBase):
def setUp(self): def setUp(self):
self.world_setup() self.world_setup()
self.multiworld.mode[1] = "inverted" self.multiworld.mode[1].value = 2
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.difficulty_requirements[1] = difficulties['normal']
create_inverted_regions(self.multiworld, 1) create_inverted_regions(self.multiworld, 1)
self.multiworld.worlds[1].create_dungeons() self.multiworld.worlds[1].create_dungeons()

View File

@ -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", 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, ['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', '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, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']],
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Magic Mirror', '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, []],
["Turtle Rock - Roller Room - Left", False, [], ['Cane of Somaria']], ["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, [], ['Big Key (Turtle Rock)']],
["Turtle Rock - Big Chest", False, [], ['Magic Mirror', 'Cane of Somaria']], ["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", 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, ['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, ['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)', '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', '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', 'Progressive Glove', 'Hookshot']],
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', '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, ['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)']], ["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 # 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, ['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, ['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', '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, ['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, ['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', '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, []],
["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']], ["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, [], ['Big Key (Turtle Rock)']],
["Turtle Rock - Boss", False, [], ['Magic Mirror', 'Lamp']], ["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", 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', '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', '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', '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)']],

View File

@ -5,15 +5,16 @@ class TestDarkWorld(TestInvertedOWG):
def testSouthDarkWorld(self): def testSouthDarkWorld(self):
self.run_location_tests([ self.run_location_tests([
["Hype Cave - Top", 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 Right", True, []], ["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 - Middle Left", True, []], ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Top", True, ['Bomb Upgrade (+5)']],
["Hype Cave - Bottom", True, []], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)']],
["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)']],
["Hype Cave - Generous Guy", True, []], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)']],
["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)']],
["Stumpy", True, []], ["Stumpy", True, []],
@ -22,7 +23,8 @@ class TestDarkWorld(TestInvertedOWG):
def testWestDarkWorld(self): def testWestDarkWorld(self):
self.run_location_tests([ 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, []], ["C-Shaped House", True, []],

View File

@ -24,36 +24,38 @@ class TestDeathMountain(TestInvertedOWG):
["Paradox Cave Lower - Far Left", False, []], ["Paradox Cave Lower - Far Left", False, []],
["Paradox Cave Lower - Far Left", False, [], ['Moon Pearl']], ["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, []],
["Paradox Cave Lower - Left", False, [], ['Moon Pearl']], ["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, []],
["Paradox Cave Lower - Middle", False, [], ['Moon Pearl']], ["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, []],
["Paradox Cave Lower - Right", False, [], ['Moon Pearl']], ["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, []],
["Paradox Cave Lower - Far Right", False, [], ['Moon Pearl']], ["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, []],
["Paradox Cave Upper - Left", False, [], ['Moon Pearl']], ["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, []],
["Paradox Cave Upper - Right", False, [], ['Moon Pearl']], ["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, []],
["Mimic Cave", False, [], ['Moon Pearl']], ["Mimic Cave", False, [], ['Moon Pearl']],
["Mimic Cave", False, [], ['Hammer']], ["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, []],
["Ether Tablet", False, ['Progressive Sword'], ['Progressive Sword']], ["Ether Tablet", False, ['Progressive Sword'], ['Progressive Sword']],

View File

@ -13,16 +13,16 @@ class TestDungeons(TestInvertedOWG):
["Sanctuary", False, []], ["Sanctuary", False, []],
["Sanctuary", False, ['Beat Agahnim 1']], ["Sanctuary", False, ['Beat Agahnim 1']],
["Sanctuary", True, ['Magic Mirror', '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, ['Moon Pearl', 'Pegasus Boots']],
["Sanctuary", True, ['Magic Mirror', 'Pegasus Boots']], ["Sanctuary", True, ['Magic Mirror', 'Pegasus Boots']],
["Sewers - Secret Room - Left", False, []], ["Sewers - Secret Room - Left", False, []],
["Sewers - Secret Room - Left", True, ['Moon Pearl', 'Progressive Glove', 'Pegasus Boots']], ["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, ['Progressive Sword', 'Moon Pearl', 'Pegasus Boots', 'Lamp', 'Small Key (Hyrule Castle)']],
["Sewers - Secret Room - Left", True, ["Sewers - Secret Room - Left", True, ['Progressive Sword', 'Magic Mirror', 'Pegasus Boots', 'Lamp', 'Small Key (Hyrule Castle)']],
['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, ['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", False, []],
["Eastern Palace - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots']], ["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']], ["Tower of Hera - Basement Cage", True, ['Pegasus Boots', 'Moon Pearl']],
["Castle Tower - Room 03", False, []], ["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 Sword']],
["Castle Tower - Room 03", True, ['Pegasus Boots', 'Progressive Bow']], ["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, []],
["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']], ["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, []], ["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 - Compass Chest", True, ['Pegasus Boots', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
["Turtle Rock - Chain Chomps", False, []], ["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", False, []],
["Turtle Rock - Crystaroller Room", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl', 'Big Key (Turtle Rock)']], ["Turtle Rock - Crystaroller Room", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl', 'Big Key (Turtle Rock)']],

View File

@ -13,8 +13,10 @@ from worlds.alttp.test import LTTPTestBase
class TestInvertedOWG(TestBase, LTTPTestBase): class TestInvertedOWG(TestBase, LTTPTestBase):
def setUp(self): def setUp(self):
self.world_setup() self.world_setup()
self.multiworld.logic[1] = "owglitches" self.multiworld.glitches_required[1] = "overworld_glitches"
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
self.multiworld.difficulty_requirements[1] = difficulties['normal'] self.multiworld.difficulty_requirements[1] = difficulties['normal']
create_inverted_regions(self.multiworld, 1) create_inverted_regions(self.multiworld, 1)
self.multiworld.worlds[1].create_dungeons() self.multiworld.worlds[1].create_dungeons()

View File

@ -40,40 +40,46 @@ class TestLightWorld(TestInvertedOWG):
["Chicken House", False, []], ["Chicken House", False, []],
["Chicken House", False, [], ['Moon Pearl']], ["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, []],
["Aginah's Cave", False, [], ['Moon Pearl']], ["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, []],
["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Magic Mirror']], ["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Magic Mirror']],
["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Pegasus Boots']], ["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, ['Moon Pearl', 'Pegasus Boots']],
["Sahasrahla's Hut - Left", True, ['Magic Mirror', 'Pegasus Boots']], ["Sahasrahla's Hut - Left", True, ['Magic Mirror', 'Pegasus Boots']],
##todo: Damage boost superbunny not in logic ##todo: Damage boost superbunny not in logic
#["Sahasrahla's Hut - Left", True, ['Beat Agahnim 1', 'Pegasus Boots']], #["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, []],
["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Magic Mirror']], ["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Magic Mirror']],
["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Pegasus Boots']], ["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, ['Moon Pearl', 'Pegasus Boots']],
["Sahasrahla's Hut - Middle", True, ['Magic Mirror', '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, ['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, []],
["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Magic Mirror']], ["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Magic Mirror']],
["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Pegasus Boots']], ["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, ['Moon Pearl', 'Pegasus Boots']],
["Sahasrahla's Hut - Right", True, ['Magic Mirror', '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, ['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, []],
["Kakariko Well - Top", False, [], ['Moon Pearl']], ["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", False, []],
["Kakariko Well - Left", True, ['Moon Pearl', 'Pegasus Boots']], ["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, []],
["Blind's Hideout - Top", False, [], ['Moon Pearl']], ["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, []],
["Blind's Hideout - Left", False, [], ['Moon Pearl', 'Magic Mirror']], ["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, []],
["Mini Moldorm Cave - Far Left", False, [], ['Moon Pearl']], ["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, []],
["Mini Moldorm Cave - Left", False, [], ['Moon Pearl']], ["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, []],
["Mini Moldorm Cave - Right", False, [], ['Moon Pearl']], ["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, []],
["Mini Moldorm Cave - Far Right", False, [], ['Moon Pearl']], ["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, []],
["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']], ["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, []],
["Ice Rod Cave", False, [], ['Moon Pearl']], ["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 #I don't think so
#["Ice Rod Cave", True, ['Magic Mirror', 'Pegasus Boots', 'BigRedBomb']], #["Ice Rod Cave", True, ['Magic Mirror', 'Pegasus Boots', 'BigRedBomb']],
#["Ice Rod Cave", True, ['Magic Mirror', 'Beat Agahnim 1', 'BigRedBomb']], #["Ice Rod Cave", True, ['Magic Mirror', 'Beat Agahnim 1', 'BigRedBomb']],
@ -236,7 +249,8 @@ class TestLightWorld(TestInvertedOWG):
["Graveyard Cave", False, []], ["Graveyard Cave", False, []],
["Graveyard Cave", False, [], ['Moon Pearl']], ["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, []],
["Checkerboard Cave", False, [], ['Progressive Glove']], ["Checkerboard Cave", False, [], ['Progressive Glove']],

View File

@ -7,43 +7,48 @@ class TestDarkWorld(TestMinor):
self.run_location_tests([ self.run_location_tests([
["Hype Cave - Top", False, []], ["Hype Cave - Top", False, []],
["Hype Cave - Top", False, [], ['Moon Pearl']], ["Hype Cave - Top", False, [], ['Moon Pearl']],
["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Middle Right", False, [], ['Moon Pearl']], ["Hype Cave - Middle Right", False, [], ['Moon Pearl']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Middle Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Middle Left", False, [], ['Moon Pearl']], ["Hype Cave - Middle Left", False, [], ['Moon Pearl']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Middle Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Bottom", False, [], ['Moon Pearl']], ["Hype Cave - Bottom", False, [], ['Moon Pearl']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Generous Guy", False, [], ['Moon Pearl']], ["Hype Cave - Generous Guy", False, [], ['Moon Pearl']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Stumpy", False, [], ['Moon Pearl']], ["Stumpy", False, [], ['Moon Pearl']],
@ -66,10 +71,11 @@ class TestDarkWorld(TestMinor):
self.run_location_tests([ self.run_location_tests([
["Brewery", False, []], ["Brewery", False, []],
["Brewery", False, [], ['Moon Pearl']], ["Brewery", False, [], ['Moon Pearl']],
["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Brewery", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["C-Shaped House", False, [], ['Moon Pearl']], ["C-Shaped House", False, [], ['Moon Pearl']],

View File

@ -48,7 +48,8 @@ class TestDeathMountain(TestMinor):
["Mimic Cave", False, [], ['Moon Pearl']], ["Mimic Cave", False, [], ['Moon Pearl']],
["Mimic Cave", False, [], ['Cane of Somaria']], ["Mimic Cave", False, [], ['Cane of Somaria']],
["Mimic Cave", False, ['Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']], ["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, []],
["Spiral Cave", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Far Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Far Left", False, ['Flute', 'Hammer']], ["Paradox Cave Lower - Far Left", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot']], ["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, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Far Left", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Far Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Magic Mirror', 'Hammer']], ["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, []],
["Paradox Cave Lower - Left", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Left", False, ['Flute', 'Hammer']], ["Paradox Cave Lower - Left", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot']], ["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, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Left", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror', 'Hammer']], ["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, []],
["Paradox Cave Lower - Middle", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Middle", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Middle", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Middle", False, ['Flute', 'Hammer']], ["Paradox Cave Lower - Middle", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot']], ["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, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Middle", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Middle", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror', 'Hammer']], ["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, []],
["Paradox Cave Lower - Right", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Right", False, ['Flute', 'Hammer']], ["Paradox Cave Lower - Right", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot']], ["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, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Right", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror', 'Hammer']], ["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, []],
["Paradox Cave Lower - Far Right", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Far Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Far Right", False, ['Flute', 'Hammer']], ["Paradox Cave Lower - Far Right", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot']], ["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, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Far Right", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Far Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Magic Mirror', 'Hammer']], ["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, []],
["Paradox Cave Upper - Left", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Upper - Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Upper - Left", False, ['Flute', 'Hammer']], ["Paradox Cave Upper - Left", False, ['Flute', 'Hammer']],
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot']], ["Paradox Cave Upper - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Flute', 'Magic Mirror', 'Hammer']], ["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, []],
["Paradox Cave Upper - Right", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Upper - Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Upper - Right", False, ['Flute', 'Hammer']], ["Paradox Cave Upper - Right", False, ['Flute', 'Hammer']],
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot']], ["Paradox Cave Upper - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Flute', 'Magic Mirror', 'Hammer']], ["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): def testWestDarkWorldDeathMountain(self):

View File

@ -29,17 +29,21 @@ class TestLightWorld(TestMinor):
["Kakariko Tavern", True, []], ["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, []], ["Kakariko Well - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Kakariko Well - Top", True, ['Bomb Upgrade (+5)']],
["Sahasrahla's Hut - Right", True, []],
["Kakariko Well - Top", True, []],
["Kakariko Well - Left", True, []], ["Kakariko Well - Left", True, []],
@ -49,7 +53,8 @@ class TestLightWorld(TestMinor):
["Kakariko Well - Bottom", True, []], ["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, []], ["Blind's Hideout - Left", True, []],
@ -63,15 +68,19 @@ class TestLightWorld(TestMinor):
["Bonk Rock Cave", False, [], ['Pegasus Boots']], ["Bonk Rock Cave", False, [], ['Pegasus Boots']],
["Bonk Rock Cave", True, ['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, []], ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Rod Cave", True, ['Bomb Upgrade (+5)']],
["Mini Moldorm Cave - Right", True, []],
["Mini Moldorm Cave - Far Right", True, []],
["Ice Rod Cave", True, []],
["Bottle Merchant", True, []], ["Bottle Merchant", True, []],
@ -131,11 +140,12 @@ class TestLightWorld(TestMinor):
["Graveyard Cave", False, []], ["Graveyard Cave", False, []],
["Graveyard Cave", False, [], ['Magic Mirror']], ["Graveyard Cave", False, [], ['Magic Mirror']],
["Graveyard Cave", False, [], ['Moon Pearl']], ["Graveyard Cave", False, [], ['Moon Pearl']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', '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, []],
["Checkerboard Cave", False, [], ['Progressive Glove']], ["Checkerboard Cave", False, [], ['Progressive Glove']],
@ -143,8 +153,6 @@ class TestLightWorld(TestMinor):
["Checkerboard Cave", False, [], ['Magic Mirror']], ["Checkerboard Cave", False, [], ['Magic Mirror']],
["Checkerboard Cave", True, ['Flute', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], ["Checkerboard Cave", True, ['Flute', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
["Mini Moldorm Cave - Generous Guy", True, []],
["Library", False, []], ["Library", False, []],
["Library", False, [], ['Pegasus Boots']], ["Library", False, [], ['Pegasus Boots']],
["Library", True, ['Pegasus Boots']], ["Library", True, ['Pegasus Boots']],
@ -155,7 +163,10 @@ class TestLightWorld(TestMinor):
["Potion Shop", False, [], ['Mushroom']], ["Potion Shop", False, [], ['Mushroom']],
["Potion Shop", True, ['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, []],
["Desert Ledge", False, [], ['Book of Mudora', 'Flute']], ["Desert Ledge", False, [], ['Book of Mudora', 'Flute']],

View File

@ -10,7 +10,9 @@ from worlds.alttp.test import LTTPTestBase
class TestMinor(TestBase, LTTPTestBase): class TestMinor(TestBase, LTTPTestBase):
def setUp(self): def setUp(self):
self.world_setup() 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.difficulty_requirements[1] = difficulties['normal']
self.multiworld.worlds[1].er_seed = 0 self.multiworld.worlds[1].er_seed = 0
self.multiworld.worlds[1].create_regions() self.multiworld.worlds[1].create_regions()

View File

@ -7,48 +7,53 @@ class TestDarkWorld(TestVanillaOWG):
self.run_location_tests([ self.run_location_tests([
["Hype Cave - Top", False, []], ["Hype Cave - Top", False, []],
["Hype Cave - Top", False, [], ['Moon Pearl']], ["Hype Cave - Top", False, [], ['Moon Pearl']],
["Hype Cave - Top", True, ['Moon Pearl', 'Pegasus Boots']], ["Hype Cave - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Middle Right", False, [], ['Moon Pearl']], ["Hype Cave - Middle Right", False, [], ['Moon Pearl']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Pegasus Boots']], ["Hype Cave - Middle Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Middle Left", False, [], ['Moon Pearl']], ["Hype Cave - Middle Left", False, [], ['Moon Pearl']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Pegasus Boots']], ["Hype Cave - Middle Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Bottom", False, [], ['Moon Pearl']], ["Hype Cave - Bottom", False, [], ['Moon Pearl']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Pegasus Boots']], ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Generous Guy", False, [], ['Moon Pearl']], ["Hype Cave - Generous Guy", False, [], ['Moon Pearl']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Pegasus Boots']], ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Stumpy", False, [], ['Moon Pearl']], ["Stumpy", False, [], ['Moon Pearl']],
@ -129,13 +134,14 @@ class TestDarkWorld(TestVanillaOWG):
self.run_location_tests([ self.run_location_tests([
["Brewery", False, []], ["Brewery", False, []],
["Brewery", False, [], ['Moon Pearl']], ["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", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot', 'Progressive Glove']],
["Brewery", True, ['Moon Pearl', 'Pegasus Boots']], ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Brewery", True, ['Moon Pearl', 'Flute', 'Magic Mirror']], ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Flute', 'Magic Mirror']],
["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']],
["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']],
["C-Shaped House", False, []], ["C-Shaped House", False, []],
["C-Shaped House", False, [], ['Moon Pearl', 'Magic Mirror']], ["C-Shaped House", False, [], ['Moon Pearl', 'Magic Mirror']],

View File

@ -48,9 +48,10 @@ class TestDeathMountain(TestVanillaOWG):
["Mimic Cave", False, [], ['Hammer']], ["Mimic Cave", False, [], ['Hammer']],
["Mimic Cave", False, [], ['Pegasus Boots', 'Flute', 'Lamp']], ["Mimic Cave", False, [], ['Pegasus Boots', 'Flute', 'Lamp']],
["Mimic Cave", False, [], ['Pegasus Boots', 'Flute', 'Progressive Glove']], ["Mimic Cave", False, [], ['Pegasus Boots', 'Flute', 'Progressive Glove']],
["Mimic Cave", True, ['Magic Mirror', 'Hammer', 'Pegasus Boots']], ["Mimic Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Hookshot', 'Hammer']],
["Mimic Cave", True, ['Magic Mirror', 'Hammer', 'Progressive Glove', 'Lamp']], ["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Magic Mirror', 'Hammer', 'Pegasus Boots']],
["Mimic Cave", True, ['Magic Mirror', 'Hammer', 'Flute']], ["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, []],
["Spiral Cave", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["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, []],
["Paradox Cave Lower - Far Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["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", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Pegasus Boots']], ["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, ['Flute', 'Hookshot']], ["Paradox Cave Lower - Far Left", True, ['Fire Rod', 'Pegasus Boots']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Far Left", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], ["Paradox Cave Lower - Far Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Magic Mirror']], ["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, []],
["Paradox Cave Lower - Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Lower - Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']],
["Paradox Cave Lower - Left", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], ["Paradox Cave Lower - Left", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Pegasus Boots']], ["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, ['Flute', 'Hookshot']], ["Paradox Cave Lower - Left", True, ['Fire Rod', 'Pegasus Boots']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Left", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], ["Paradox Cave Lower - Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror']], ["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, []],
["Paradox Cave Lower - Middle", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Lower - Middle", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']],
["Paradox Cave Lower - Middle", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], ["Paradox Cave Lower - Middle", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Pegasus Boots']], ["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, ['Flute', 'Hookshot']], ["Paradox Cave Lower - Middle", True, ['Fire Rod', 'Pegasus Boots']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Middle", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], ["Paradox Cave Lower - Middle", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror']], ["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, []],
["Paradox Cave Lower - Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Lower - Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']],
["Paradox Cave Lower - Right", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], ["Paradox Cave Lower - Right", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Pegasus Boots']], ["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, ['Flute', 'Hookshot']], ["Paradox Cave Lower - Right", True, ['Fire Rod', 'Pegasus Boots']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Right", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], ["Paradox Cave Lower - Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror']], ["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, []],
["Paradox Cave Lower - Far Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["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", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Pegasus Boots']], ["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, ['Flute', 'Hookshot']], ["Paradox Cave Lower - Far Right", True, ['Fire Rod', 'Pegasus Boots']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Far Right", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], ["Paradox Cave Lower - Far Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Magic Mirror']], ["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, []],
["Paradox Cave Upper - Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Upper - Left", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']],
["Paradox Cave Upper - Left", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], ["Paradox Cave Upper - Left", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Pegasus Boots']], ["Paradox Cave Upper - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Pegasus Boots']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Flute', 'Magic Mirror']], ["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, []],
["Paradox Cave Upper - Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']], ["Paradox Cave Upper - Right", False, [], ['Pegasus Boots', 'Progressive Glove', 'Flute']],
["Paradox Cave Upper - Right", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']], ["Paradox Cave Upper - Right", False, [], ['Pegasus Boots', 'Magic Mirror', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Pegasus Boots']], ["Paradox Cave Upper - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Pegasus Boots']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Flute', 'Magic Mirror']], ["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): def testWestDarkWorldDeathMountain(self):

View File

@ -6,13 +6,14 @@ class TestDungeons(TestVanillaOWG):
def testFirstDungeonChests(self): def testFirstDungeonChests(self):
self.run_location_tests([ self.run_location_tests([
["Hyrule Castle - Map Chest", True, []], ["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, []], ["Sanctuary", True, []],
["Sewers - Secret Room - Left", False, []], ["Sewers - Secret Room - Left", False, []],
["Sewers - Secret Room - Left", True, ['Progressive Glove']], ["Sewers - Secret Room - Left", True, ['Pegasus Boots', 'Progressive Glove']],
["Sewers - Secret Room - Left", True, ['Lamp', 'Small Key (Hyrule Castle)']], ["Sewers - Secret Room - Left", True, ['Progressive Sword', 'Bomb Upgrade (+5)', 'Lamp', 'Small Key (Hyrule Castle)']],
["Eastern Palace - Compass Chest", True, []], ["Eastern Palace - Compass Chest", True, []],
@ -41,10 +42,9 @@ class TestDungeons(TestVanillaOWG):
["Castle Tower - Room 03", False, []], ["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'], ['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, ['Progressive Sword', 'Progressive Sword']],
["Castle Tower - Room 03", True, ['Cape', 'Progressive Bow']], ["Castle Tower - Room 03", True, ['Progressive Sword', 'Cape']],
["Castle Tower - Room 03", True, ['Beat Agahnim 1', 'Fire Rod']], ["Castle Tower - Room 03", True, ['Progressive Sword', 'Beat Agahnim 1']],
["Palace of Darkness - Shooter Room", False, []], ["Palace of Darkness - Shooter Room", False, []],
["Palace of Darkness - Shooter Room", False, [], ['Moon Pearl']], ["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, []],
["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']], ["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? #todo: Bomb Jump in logic?
#["Skull Woods - Big Chest", True, ['Magic Mirror', 'Pegasus Boots', 'Big Key (Skull Woods)']], #["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", False, []],
["Skull Woods - Big Key Chest", True, ['Magic Mirror', 'Pegasus Boots']], ["Skull Woods - Big Key Chest", True, ['Magic Mirror', 'Pegasus Boots']],
@ -111,8 +112,8 @@ class TestDungeons(TestVanillaOWG):
["Turtle Rock - Chain Chomps", False, []], ["Turtle Rock - Chain Chomps", False, []],
#todo: does clip require sword? #todo: does clip require sword?
#["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Pegasus Boots']], #["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, ['Moon Pearl', 'Pegasus Boots', 'Progressive Sword', 'Progressive Sword']],
["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror']], ["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror', 'Progressive Bow']],
["Turtle Rock - Crystaroller Room", False, []], ["Turtle Rock - Crystaroller Room", False, []],
["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)']], ["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)']],

View File

@ -25,17 +25,21 @@ class TestLightWorld(TestVanillaOWG):
["Kakariko Tavern", True, []], ["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, []], ["Kakariko Well - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Kakariko Well - Top", True, ['Bomb Upgrade (+5)']],
["Sahasrahla's Hut - Right", True, []],
["Kakariko Well - Top", True, []],
["Kakariko Well - Left", True, []], ["Kakariko Well - Left", True, []],
@ -45,7 +49,8 @@ class TestLightWorld(TestVanillaOWG):
["Kakariko Well - Bottom", True, []], ["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, []], ["Blind's Hideout - Left", True, []],
@ -59,15 +64,19 @@ class TestLightWorld(TestVanillaOWG):
["Bonk Rock Cave", False, [], ['Pegasus Boots']], ["Bonk Rock Cave", False, [], ['Pegasus Boots']],
["Bonk Rock Cave", True, ['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, []], ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Rod Cave", True, ['Bomb Upgrade (+5)']],
["Mini Moldorm Cave - Right", True, []],
["Mini Moldorm Cave - Far Right", True, []],
["Ice Rod Cave", True, []],
["Bottle Merchant", True, []], ["Bottle Merchant", True, []],
@ -126,12 +135,13 @@ class TestLightWorld(TestVanillaOWG):
["Graveyard Cave", False, []], ["Graveyard Cave", False, []],
["Graveyard Cave", False, [], ['Pegasus Boots', 'Magic Mirror']], ["Graveyard Cave", False, [], ['Pegasus Boots', 'Magic Mirror']],
["Graveyard Cave", False, [], ['Pegasus Boots', 'Moon Pearl']], ["Graveyard Cave", False, [], ['Pegasus Boots', 'Moon Pearl']],
["Graveyard Cave", True, ['Pegasus Boots']], ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Pegasus Boots']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', '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, []],
["Checkerboard Cave", False, [], ['Progressive Glove']], ["Checkerboard Cave", False, [], ['Progressive Glove']],
@ -140,8 +150,6 @@ class TestLightWorld(TestVanillaOWG):
["Checkerboard Cave", True, ['Pegasus Boots', 'Progressive Glove']], ["Checkerboard Cave", True, ['Pegasus Boots', 'Progressive Glove']],
["Checkerboard Cave", True, ['Flute', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], ["Checkerboard Cave", True, ['Flute', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
["Mini Moldorm Cave - Generous Guy", True, []],
["Library", False, []], ["Library", False, []],
["Library", False, [], ['Pegasus Boots']], ["Library", False, [], ['Pegasus Boots']],
["Library", True, ['Pegasus Boots']], ["Library", True, ['Pegasus Boots']],
@ -152,7 +160,10 @@ class TestLightWorld(TestVanillaOWG):
["Potion Shop", False, [], ['Mushroom']], ["Potion Shop", False, [], ['Mushroom']],
["Potion Shop", True, ['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, []],
["Desert Ledge", False, [], ['Pegasus Boots', 'Book of Mudora', 'Flute']], ["Desert Ledge", False, [], ['Pegasus Boots', 'Book of Mudora', 'Flute']],

View File

@ -11,7 +11,9 @@ class TestVanillaOWG(TestBase, LTTPTestBase):
def setUp(self): def setUp(self):
self.world_setup() self.world_setup()
self.multiworld.difficulty_requirements[1] = difficulties['normal'] 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].er_seed = 0
self.multiworld.worlds[1].create_regions() self.multiworld.worlds[1].create_regions()
self.multiworld.worlds[1].create_items() self.multiworld.worlds[1].create_items()

View File

@ -7,43 +7,48 @@ class TestDarkWorld(TestVanilla):
self.run_location_tests([ self.run_location_tests([
["Hype Cave - Top", False, []], ["Hype Cave - Top", False, []],
["Hype Cave - Top", False, [], ['Moon Pearl']], ["Hype Cave - Top", False, [], ['Moon Pearl']],
["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Top", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Top", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Middle Right", False, [], ['Moon Pearl']], ["Hype Cave - Middle Right", False, [], ['Moon Pearl']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Middle Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Middle Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Middle Right", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Middle Left", False, [], ['Moon Pearl']], ["Hype Cave - Middle Left", False, [], ['Moon Pearl']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Middle Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Middle Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Middle Left", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Bottom", False, [], ['Moon Pearl']], ["Hype Cave - Bottom", False, [], ['Moon Pearl']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Bottom", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Bottom", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Bottom", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Hype Cave - Generous Guy", False, [], ['Moon Pearl']], ["Hype Cave - Generous Guy", False, [], ['Moon Pearl']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Hammer']], ["Hype Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1', 'Hammer']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Hype Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Hype Cave - Generous Guy", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["Stumpy", False, [], ['Moon Pearl']], ["Stumpy", False, [], ['Moon Pearl']],
@ -66,10 +71,11 @@ class TestDarkWorld(TestVanilla):
self.run_location_tests([ self.run_location_tests([
["Brewery", False, []], ["Brewery", False, []],
["Brewery", False, [], ['Moon Pearl']], ["Brewery", False, [], ['Moon Pearl']],
["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove']], ["Brewery", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Brewery", True, ['Moon Pearl', 'Progressive Glove', 'Hammer']], ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Brewery", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
["Brewery", True, ['Moon Pearl', 'Beat Agahnim 1', 'Flippers', 'Hookshot']], ["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, []],
["C-Shaped House", False, [], ['Moon Pearl']], ["C-Shaped House", False, [], ['Moon Pearl']],

View File

@ -48,7 +48,8 @@ class TestDeathMountain(TestVanilla):
["Mimic Cave", False, [], ['Moon Pearl']], ["Mimic Cave", False, [], ['Moon Pearl']],
["Mimic Cave", False, [], ['Cane of Somaria']], ["Mimic Cave", False, [], ['Cane of Somaria']],
["Mimic Cave", False, ['Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']], ["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, []],
["Spiral Cave", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Far Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Far Left", False, ['Flute', 'Hammer']], ["Paradox Cave Lower - Far Left", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot']], ["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Cane of Somaria']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["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']], ["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']], ["Paradox Cave Lower - Far Left", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']],
["Paradox Cave Lower - Left", False, []], ["Paradox Cave Lower - Left", False, []],
["Paradox Cave Lower - Left", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Left", False, ['Flute', 'Hammer']], ["Paradox Cave Lower - Left", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot']], ["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Cane of Somaria']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']],
["Paradox Cave Lower - Middle", False, []], ["Paradox Cave Lower - Middle", False, []],
["Paradox Cave Lower - Middle", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Middle", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Middle", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Middle", False, ['Flute', 'Hammer']], ["Paradox Cave Lower - Middle", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot']], ["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Cane of Somaria']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']],
["Paradox Cave Lower - Right", False, []], ["Paradox Cave Lower - Right", False, []],
["Paradox Cave Lower - Right", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Right", False, ['Flute', 'Hammer']], ["Paradox Cave Lower - Right", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot']], ["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Cane of Somaria']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror', 'Hammer']], ["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']],
["Paradox Cave Lower - Far Right", False, []], ["Paradox Cave Lower - Far Right", False, []],
["Paradox Cave Lower - Far Right", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Lower - Far Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Far Right", False, ['Flute', 'Hammer']], ["Paradox Cave Lower - Far Right", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot']], ["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Cane of Somaria']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["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']], ["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']], ["Paradox Cave Lower - Far Right", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']],
["Paradox Cave Upper - Left", False, []], ["Paradox Cave Upper - Left", False, []],
["Paradox Cave Upper - Left", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Left", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Upper - Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Upper - Left", False, ['Flute', 'Hammer']], ["Paradox Cave Upper - Left", False, ['Flute', 'Hammer']],
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot']], ["Paradox Cave Upper - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Flute', 'Magic Mirror', 'Hammer']], ["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, []],
["Paradox Cave Upper - Right", False, [], ['Progressive Glove', 'Flute']], ["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, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Right", False, ['Flute', 'Magic Mirror']], ["Paradox Cave Upper - Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Upper - Right", False, ['Flute', 'Hammer']], ["Paradox Cave Upper - Right", False, ['Flute', 'Hammer']],
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot']], ["Paradox Cave Upper - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']], ["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Flute', 'Magic Mirror', 'Hammer']], ["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): def testWestDarkWorldDeathMountain(self):

View File

@ -29,17 +29,21 @@ class TestLightWorld(TestVanilla):
["Kakariko Tavern", True, []], ["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, []], ["Kakariko Well - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Kakariko Well - Top", True, ['Bomb Upgrade (+5)']],
["Sahasrahla's Hut - Right", True, []],
["Kakariko Well - Top", True, []],
["Kakariko Well - Left", True, []], ["Kakariko Well - Left", True, []],
@ -49,7 +53,8 @@ class TestLightWorld(TestVanilla):
["Kakariko Well - Bottom", True, []], ["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, []], ["Blind's Hideout - Left", True, []],
@ -63,15 +68,19 @@ class TestLightWorld(TestVanilla):
["Bonk Rock Cave", False, [], ['Pegasus Boots']], ["Bonk Rock Cave", False, [], ['Pegasus Boots']],
["Bonk Rock Cave", True, ['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, []], ["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Rod Cave", True, ['Bomb Upgrade (+5)']],
["Mini Moldorm Cave - Right", True, []],
["Mini Moldorm Cave - Far Right", True, []],
["Ice Rod Cave", True, []],
["Bottle Merchant", True, []], ["Bottle Merchant", True, []],
@ -136,11 +145,12 @@ class TestLightWorld(TestVanilla):
["Graveyard Cave", False, []], ["Graveyard Cave", False, []],
["Graveyard Cave", False, [], ['Magic Mirror']], ["Graveyard Cave", False, [], ['Magic Mirror']],
["Graveyard Cave", False, [], ['Moon Pearl']], ["Graveyard Cave", False, [], ['Moon Pearl']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], ["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Progressive Glove', 'Hammer']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Progressive Glove', 'Hookshot']], ["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Hammer', 'Hookshot']],
["Graveyard Cave", True, ['Moon Pearl', 'Magic Mirror', 'Beat Agahnim 1', 'Flippers', '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, []],
["Checkerboard Cave", False, [], ['Progressive Glove']], ["Checkerboard Cave", False, [], ['Progressive Glove']],
@ -148,7 +158,6 @@ class TestLightWorld(TestVanilla):
["Checkerboard Cave", False, [], ['Magic Mirror']], ["Checkerboard Cave", False, [], ['Magic Mirror']],
["Checkerboard Cave", True, ['Flute', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']], ["Checkerboard Cave", True, ['Flute', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
["Mini Moldorm Cave - Generous Guy", True, []],
["Library", False, []], ["Library", False, []],
["Library", False, [], ['Pegasus Boots']], ["Library", False, [], ['Pegasus Boots']],
@ -160,7 +169,10 @@ class TestLightWorld(TestVanilla):
["Potion Shop", False, [], ['Mushroom']], ["Potion Shop", False, [], ['Mushroom']],
["Potion Shop", True, ['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, []],
["Desert Ledge", False, [], ['Book of Mudora', 'Flute']], ["Desert Ledge", False, [], ['Book of Mudora', 'Flute']],

View File

@ -9,8 +9,10 @@ from worlds.alttp.test import LTTPTestBase
class TestVanilla(TestBase, LTTPTestBase): class TestVanilla(TestBase, LTTPTestBase):
def setUp(self): def setUp(self):
self.world_setup() self.world_setup()
self.multiworld.logic[1] = "noglitches" self.multiworld.glitches_required[1] = "no_glitches"
self.multiworld.difficulty_requirements[1] = difficulties['normal'] 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].er_seed = 0
self.multiworld.worlds[1].create_regions() self.multiworld.worlds[1].create_regions()
self.multiworld.worlds[1].create_items() self.multiworld.worlds[1].create_items()