Merge branch 'main' of https://github.com/Berserker66/MultiWorld-Utilities into triforce_changes
This commit is contained in:
commit
222784dbb6
141
Adjuster.py
141
Adjuster.py
|
@ -4,9 +4,11 @@ import os
|
|||
import logging
|
||||
import textwrap
|
||||
import sys
|
||||
import time
|
||||
|
||||
from Rom import Sprite, LocalRom, apply_rom_settings
|
||||
from Utils import output_path
|
||||
|
||||
from AdjusterMain import adjust
|
||||
from Rom import Sprite
|
||||
|
||||
class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
|
||||
|
||||
|
@ -34,6 +36,7 @@ def main():
|
|||
(Both can be revealed when speaking to Murahalda)
|
||||
(default: %(default)s)
|
||||
''')
|
||||
parser.add_argument('--enableflashing', help='Reenable flashing animations (unfriendly to epilepsy, always disabled in race roms)', action='store_false', dest="reduceflashing")
|
||||
parser.add_argument('--heartbeep', default='normal', const='normal', nargs='?', choices=['double', 'normal', 'half', 'quarter', 'off'],
|
||||
help='''\
|
||||
Select the rate at which the heart beep sound is played at
|
||||
|
@ -57,25 +60,127 @@ def main():
|
|||
parser.add_argument('--names', default='', type=str)
|
||||
args = parser.parse_args()
|
||||
|
||||
# ToDo: Validate files further than mere existance
|
||||
if not os.path.isfile(args.rom):
|
||||
input(
|
||||
'Could not find valid rom for patching at expected path %s. Please run with -h to see help for further information. \nPress Enter to exit.' % args.rom)
|
||||
sys.exit(1)
|
||||
if args.sprite is not None and not os.path.isfile(args.sprite) and not Sprite.get_sprite_from_name(args.sprite):
|
||||
input('Could not find link sprite sheet at given location. \nPress Enter to exit.')
|
||||
sys.exit(1)
|
||||
|
||||
# set up logger
|
||||
loglevel = {'error': logging.ERROR, 'info': logging.INFO, 'warning': logging.WARNING, 'debug': logging.DEBUG}[
|
||||
args.loglevel]
|
||||
logging.basicConfig(format='%(message)s', level=loglevel)
|
||||
args, path = adjust(args=args)
|
||||
from Utils import persistent_store
|
||||
from Rom import Sprite
|
||||
if isinstance(args.sprite, Sprite):
|
||||
args.sprite = args.sprite.name
|
||||
persistent_store("adjuster", "last_settings_3", args)
|
||||
|
||||
if not os.path.isfile(args.rom):
|
||||
adjustGUI()
|
||||
else:
|
||||
if args.sprite is not None and not os.path.isfile(args.sprite) and not Sprite.get_sprite_from_name(args.sprite):
|
||||
input('Could not find link sprite sheet at given location. \nPress Enter to exit.')
|
||||
sys.exit(1)
|
||||
|
||||
args, path = adjust(args=args)
|
||||
from Utils import persistent_store
|
||||
if isinstance(args.sprite, Sprite):
|
||||
args.sprite = args.sprite.name
|
||||
persistent_store("adjuster", "last_settings_3", args)
|
||||
|
||||
|
||||
def adjust(args):
|
||||
start = time.perf_counter()
|
||||
logger = logging.getLogger('Adjuster')
|
||||
logger.info('Patching ROM.')
|
||||
vanillaRom = args.baserom
|
||||
if os.path.splitext(args.rom)[-1].lower() == '.bmbp':
|
||||
import Patch
|
||||
meta, args.rom = Patch.create_rom_file(args.rom)
|
||||
|
||||
if os.stat(args.rom).st_size in (0x200000, 0x400000) and os.path.splitext(args.rom)[-1].lower() == '.sfc':
|
||||
rom = LocalRom(args.rom, patch=False, vanillaRom=vanillaRom)
|
||||
else:
|
||||
raise RuntimeError(
|
||||
'Provided Rom is not a valid Link to the Past Randomizer Rom. Please provide one for adjusting.')
|
||||
palettes_options={}
|
||||
palettes_options['dungeon']=args.uw_palettes
|
||||
|
||||
palettes_options['overworld']=args.ow_palettes
|
||||
palettes_options['hud']=args.hud_palettes
|
||||
palettes_options['sword']=args.sword_palettes
|
||||
palettes_options['shield']=args.shield_palettes
|
||||
# palettes_options['link']=args.link_palettesvera
|
||||
racerom = rom.read_byte(0x180213) > 0
|
||||
|
||||
apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic,
|
||||
args.sprite, palettes_options, reduceflashing=args.reduceflashing or racerom)
|
||||
path = output_path(f'{os.path.basename(args.rom)[:-4]}_adjusted.sfc')
|
||||
rom.write_to_file(path)
|
||||
|
||||
logger.info('Done. Enjoy.')
|
||||
logger.debug('Total Time: %s', time.perf_counter() - start)
|
||||
|
||||
return args, path
|
||||
|
||||
def adjustGUI():
|
||||
from tkinter import Checkbutton, OptionMenu, Toplevel, LabelFrame, PhotoImage, Tk, LEFT, RIGHT, BOTTOM, TOP, \
|
||||
StringVar, IntVar, Frame, Label, W, E, X, BOTH, Entry, Spinbox, Button, filedialog, messagebox, ttk
|
||||
from Gui import get_rom_options_frame, get_rom_frame
|
||||
from GuiUtils import set_icon
|
||||
from argparse import Namespace
|
||||
from Main import __version__ as MWVersion
|
||||
adjustWindow = Tk()
|
||||
adjustWindow.wm_title("Berserker's Multiworld %s LttP Adjuster" % MWVersion)
|
||||
set_icon(adjustWindow)
|
||||
|
||||
rom_options_frame, rom_vars, set_sprite = get_rom_options_frame(adjustWindow)
|
||||
|
||||
bottomFrame2 = Frame(adjustWindow)
|
||||
|
||||
romFrame, romVar = get_rom_frame(adjustWindow)
|
||||
|
||||
romDialogFrame = Frame(adjustWindow)
|
||||
baseRomLabel2 = Label(romDialogFrame, text='Rom to adjust')
|
||||
romVar2 = StringVar()
|
||||
romEntry2 = Entry(romDialogFrame, textvariable=romVar2)
|
||||
|
||||
def RomSelect2():
|
||||
rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".sfc", ".smc", ".bmbp")), ("All Files", "*")])
|
||||
romVar2.set(rom)
|
||||
romSelectButton2 = Button(romDialogFrame, text='Select Rom', command=RomSelect2)
|
||||
romDialogFrame.pack(side=TOP, expand=True, fill=X)
|
||||
baseRomLabel2.pack(side=LEFT)
|
||||
romEntry2.pack(side=LEFT, expand=True, fill=X)
|
||||
romSelectButton2.pack(side=LEFT)
|
||||
|
||||
def adjustRom():
|
||||
guiargs = Namespace()
|
||||
guiargs.heartbeep = rom_vars.heartbeepVar.get()
|
||||
guiargs.heartcolor = rom_vars.heartcolorVar.get()
|
||||
guiargs.fastmenu = rom_vars.fastMenuVar.get()
|
||||
guiargs.ow_palettes = rom_vars.owPalettesVar.get()
|
||||
guiargs.uw_palettes = rom_vars.uwPalettesVar.get()
|
||||
guiargs.hud_palettes = rom_vars.hudPalettesVar.get()
|
||||
guiargs.sword_palettes = rom_vars.swordPalettesVar.get()
|
||||
guiargs.shield_palettes = rom_vars.shieldPalettesVar.get()
|
||||
guiargs.quickswap = bool(rom_vars.quickSwapVar.get())
|
||||
guiargs.disablemusic = bool(rom_vars.disableMusicVar.get())
|
||||
guiargs.reduceflashing = bool(rom_vars.disableFlashingVar.get())
|
||||
guiargs.rom = romVar2.get()
|
||||
guiargs.baserom = romVar.get()
|
||||
guiargs.sprite = rom_vars.sprite
|
||||
try:
|
||||
guiargs, path = adjust(args=guiargs)
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
messagebox.showerror(title="Error while adjusting Rom", message=str(e))
|
||||
else:
|
||||
messagebox.showinfo(title="Success", message=f"Rom patched successfully to {path}")
|
||||
from Utils import persistent_store
|
||||
from Rom import Sprite
|
||||
if isinstance(guiargs.sprite, Sprite):
|
||||
guiargs.sprite = guiargs.sprite.name
|
||||
persistent_store("adjuster", "last_settings_3", guiargs)
|
||||
|
||||
adjustButton = Button(bottomFrame2, text='Adjust Rom', command=adjustRom)
|
||||
rom_options_frame.pack(side=TOP)
|
||||
adjustButton.pack(side=BOTTOM, padx=(5, 5))
|
||||
|
||||
bottomFrame2.pack(side=BOTTOM, pady=(5, 5))
|
||||
|
||||
adjustWindow.mainloop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
main()
|
|
@ -4,6 +4,7 @@ import copy
|
|||
from enum import Enum, unique
|
||||
import logging
|
||||
import json
|
||||
import functools
|
||||
from collections import OrderedDict, Counter, deque
|
||||
from typing import Union, Optional, List, Dict, NamedTuple, Iterable
|
||||
import secrets
|
||||
|
@ -24,8 +25,9 @@ class World(object):
|
|||
plando_texts: List[Dict[str, str]]
|
||||
plando_items: List[PlandoItem]
|
||||
plando_connections: List[PlandoConnection]
|
||||
er_seeds: Dict[int, str]
|
||||
|
||||
def __init__(self, players: int, shuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer,
|
||||
def __init__(self, players: int, shuffle, logic, mode, swords, difficulty, item_functionality, timer,
|
||||
progressive,
|
||||
goal, algorithm, accessibility, shuffle_ganon, retro, custom, customitemarray, hints):
|
||||
if self.debug_types:
|
||||
|
@ -46,7 +48,7 @@ class World(object):
|
|||
self.mode = mode.copy()
|
||||
self.swords = swords.copy()
|
||||
self.difficulty = difficulty.copy()
|
||||
self.difficulty_adjustments = difficulty_adjustments.copy()
|
||||
self.item_functionality = item_functionality.copy()
|
||||
self.timer = timer.copy()
|
||||
self.progressive = progressive
|
||||
self.goal = goal.copy()
|
||||
|
@ -160,6 +162,10 @@ class World(object):
|
|||
region.world = self
|
||||
self._region_cache[region.player][region.name] = region
|
||||
|
||||
@functools.cached_property
|
||||
def world_name_lookup(self):
|
||||
return {self.player_names[player_id][0]: player_id for player_id in self.player_ids}
|
||||
|
||||
def _recache(self):
|
||||
"""Rebuild world cache"""
|
||||
for region in self.regions:
|
||||
|
@ -450,7 +456,7 @@ class World(object):
|
|||
def get_spheres(self):
|
||||
state = CollectionState(self)
|
||||
|
||||
locations = {location for location in self.get_locations()}
|
||||
locations = set(self.get_locations())
|
||||
|
||||
while locations:
|
||||
sphere = set()
|
||||
|
@ -458,7 +464,10 @@ class World(object):
|
|||
for location in locations:
|
||||
if location.can_reach(state):
|
||||
sphere.add(location)
|
||||
yield sphere
|
||||
sphere_list = list(sphere)
|
||||
sphere_list.sort(key=lambda location: location.name)
|
||||
self.random.shuffle(sphere_list)
|
||||
yield sphere_list
|
||||
if not sphere:
|
||||
if locations:
|
||||
yield locations # unreachable locations
|
||||
|
@ -601,11 +610,13 @@ class CollectionState(object):
|
|||
if locations is None:
|
||||
locations = self.world.get_filled_locations()
|
||||
new_locations = True
|
||||
# since the loop has a good chance to run more than once, only filter the events once
|
||||
locations = {location for location in locations if location.event}
|
||||
while new_locations:
|
||||
reachable_events = {location for location in locations if location.event and
|
||||
(not key_only or (not self.world.keyshuffle[
|
||||
location.item.player] and location.item.smallkey) or (not self.world.bigkeyshuffle[
|
||||
location.item.player] and location.item.bigkey))
|
||||
reachable_events = {location for location in locations if
|
||||
(not key_only or
|
||||
(not self.world.keyshuffle[location.item.player] and location.item.smallkey)
|
||||
or (not self.world.bigkeyshuffle[location.item.player] and location.item.bigkey))
|
||||
and location.can_reach(self)}
|
||||
new_locations = reachable_events - self.events
|
||||
for event in new_locations:
|
||||
|
@ -688,9 +699,9 @@ class CollectionState(object):
|
|||
elif self.has('Magic Upgrade (1/2)', player):
|
||||
basemagic = 16
|
||||
if self.can_buy_unlimited('Green Potion', player) or self.can_buy_unlimited('Blue Potion', player):
|
||||
if self.world.difficulty_adjustments[player] == 'hard' and not fullrefill:
|
||||
if self.world.item_functionality[player] == 'hard' and not fullrefill:
|
||||
basemagic = basemagic + int(basemagic * 0.5 * self.bottle_count(player))
|
||||
elif self.world.difficulty_adjustments[player] == 'expert' and not fullrefill:
|
||||
elif self.world.item_functionality[player] == 'expert' and not fullrefill:
|
||||
basemagic = basemagic + int(basemagic * 0.25 * self.bottle_count(player))
|
||||
else:
|
||||
basemagic = basemagic + basemagic * self.bottle_count(player)
|
||||
|
@ -748,10 +759,6 @@ class CollectionState(object):
|
|||
def has_fire_source(self, player: int) -> bool:
|
||||
return self.has('Fire Rod', player) or self.has('Lamp', player)
|
||||
|
||||
def can_flute(self, player: int) -> bool:
|
||||
lw = self.world.get_region('Light World', player)
|
||||
return self.has('Flute', player) and lw.can_reach(self) and self.is_not_bunny(lw, player)
|
||||
|
||||
def can_melt_things(self, player: int) -> bool:
|
||||
return self.has('Fire Rod', player) or \
|
||||
(self.has('Bombos', player) and
|
||||
|
@ -808,7 +815,7 @@ class CollectionState(object):
|
|||
rules.append(self.has_Pearl(player))
|
||||
return all(rules)
|
||||
|
||||
def collect(self, item: Item, event=False, location=None):
|
||||
def collect(self, item: Item, event=False, location=None) -> bool:
|
||||
if location:
|
||||
self.locations_checked.add(location)
|
||||
changed = False
|
||||
|
@ -844,7 +851,7 @@ class CollectionState(object):
|
|||
elif self.has('Red Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 3:
|
||||
self.prog_items['Mirror Shield', item.player] += 1
|
||||
changed = True
|
||||
elif self.has('Blue Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 2:
|
||||
elif self.has('Blue Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 2:
|
||||
self.prog_items['Red Shield', item.player] += 1
|
||||
changed = True
|
||||
elif self.world.difficulty_requirements[item.player].progressive_shield_limit >= 1:
|
||||
|
@ -869,9 +876,10 @@ class CollectionState(object):
|
|||
|
||||
self.stale[item.player] = True
|
||||
|
||||
if changed:
|
||||
if not event:
|
||||
self.sweep_for_events()
|
||||
if changed and not event:
|
||||
self.sweep_for_events()
|
||||
|
||||
return changed
|
||||
|
||||
def remove(self, item):
|
||||
if item.advancement:
|
||||
|
@ -1077,6 +1085,7 @@ class Location():
|
|||
shop_slot_disabled: bool = False
|
||||
event: bool = False
|
||||
locked: bool = False
|
||||
spot_type = 'Location'
|
||||
|
||||
def __init__(self, player: int, name: str = '', address=None, crystal: bool = False,
|
||||
hint_text: Optional[str] = None, parent=None,
|
||||
|
@ -1087,7 +1096,6 @@ class Location():
|
|||
self.crystal = crystal
|
||||
self.address = address
|
||||
self.player_address = player_address
|
||||
self.spot_type = 'Location'
|
||||
self.hint_text: str = hint_text if hint_text else name
|
||||
self.recursion_count = 0
|
||||
self.always_allow = lambda item, state: False
|
||||
|
@ -1119,11 +1127,12 @@ class Location():
|
|||
|
||||
|
||||
class Item(object):
|
||||
location: Optional[Location] = None
|
||||
world: Optional[World] = None
|
||||
|
||||
def __init__(self, name='', advancement=False, priority=False, type=None, code=None, pedestal_hint=None, pedestal_credit=None, sickkid_credit=None, zora_credit=None, witch_credit=None, fluteboy_credit=None, hint_text=None, player=None):
|
||||
def __init__(self, name='', advancement=False, type=None, code=None, pedestal_hint=None, pedestal_credit=None, sickkid_credit=None, zora_credit=None, witch_credit=None, fluteboy_credit=None, hint_text=None, player=None):
|
||||
self.name = name
|
||||
self.advancement = advancement
|
||||
self.priority = priority
|
||||
self.type = type
|
||||
self.pedestal_hint_text = pedestal_hint
|
||||
self.pedestal_credit_text = pedestal_credit
|
||||
|
@ -1133,13 +1142,16 @@ class Item(object):
|
|||
self.fluteboy_credit_text = fluteboy_credit
|
||||
self.hint_text = hint_text
|
||||
self.code = code
|
||||
self.location = None
|
||||
self.world = None
|
||||
self.player = player
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name and self.player == other.player
|
||||
|
||||
def __lt__(self, other):
|
||||
if other.player != self.player:
|
||||
return other.player < self.player
|
||||
return self.name < other.name
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.name, self.player))
|
||||
|
||||
|
@ -1298,7 +1310,7 @@ class Spoiler(object):
|
|||
'goal': self.world.goal,
|
||||
'shuffle': self.world.shuffle,
|
||||
'item_pool': self.world.difficulty,
|
||||
'item_functionality': self.world.difficulty_adjustments,
|
||||
'item_functionality': self.world.item_functionality,
|
||||
'gt_crystals': self.world.crystals_needed_for_gt,
|
||||
'ganon_crystals': self.world.crystals_needed_for_ganon,
|
||||
'open_pyramid': self.world.open_pyramid,
|
||||
|
@ -1327,7 +1339,8 @@ class Spoiler(object):
|
|||
'shop_shuffle_slots': self.world.shop_shuffle_slots,
|
||||
'shuffle_prizes': self.world.shuffle_prizes,
|
||||
'sprite_pool': self.world.sprite_pool,
|
||||
'restrict_dungeon_item_on_boss': self.world.restrict_dungeon_item_on_boss
|
||||
'restrict_dungeon_item_on_boss': self.world.restrict_dungeon_item_on_boss,
|
||||
'er_seeds': self.world.er_seeds
|
||||
}
|
||||
|
||||
def to_json(self):
|
||||
|
@ -1391,6 +1404,8 @@ class Spoiler(object):
|
|||
outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player])
|
||||
outfile.write('Item Progression: %s\n' % self.metadata['progressive'][player])
|
||||
outfile.write('Entrance Shuffle: %s\n' % self.metadata['shuffle'][player])
|
||||
if self.metadata['shuffle'][player] != "vanilla":
|
||||
outfile.write('Entrance Shuffle Seed %s\n' % self.metadata['er_seeds'][player])
|
||||
outfile.write('Crystals required for GT: %s\n' % self.metadata['gt_crystals'][player])
|
||||
outfile.write('Crystals required for Ganon: %s\n' % self.metadata['ganon_crystals'][player])
|
||||
outfile.write('Pyramid hole pre-opened: %s\n' % (
|
||||
|
|
|
@ -132,8 +132,6 @@ def fill_dungeons_restrictive(world):
|
|||
if (item.smallkey and world.keyshuffle[item.player]) or (item.bigkey and world.bigkeyshuffle[item.player]):
|
||||
all_state_base.collect(item, True)
|
||||
item.advancement = True
|
||||
elif (item.map and world.mapshuffle[item.player]) or (item.compass and world.compassshuffle[item.player]):
|
||||
item.priority = True
|
||||
|
||||
dungeon_items = [item for item in get_dungeon_item_pool(world) if (((item.smallkey and not world.keyshuffle[item.player])
|
||||
or (item.bigkey and not world.bigkeyshuffle[item.player])
|
||||
|
|
|
@ -222,9 +222,16 @@ def parse_arguments(argv, no_defaults=False):
|
|||
Random: Picks a random value between 0 and 7 (inclusive).
|
||||
0-7: Number of crystals needed
|
||||
''')
|
||||
parser.add_argument('--open_pyramid', default=defval(False), help='''\
|
||||
Pre-opens the pyramid hole, this removes the Agahnim 2 requirement for it
|
||||
''', action='store_true')
|
||||
parser.add_argument('--open_pyramid', default=defval('auto'), help='''\
|
||||
Pre-opens the pyramid hole, this removes the Agahnim 2 requirement for it.
|
||||
Depending on goal, you might still need to beat Agahnim 2 in order to beat ganon.
|
||||
fast ganon goals are crystals, ganontriforcehunt, localganontriforcehunt, pedestalganon
|
||||
auto - Only opens pyramid hole if the goal specifies a fast ganon, and entrance shuffle
|
||||
is vanilla, dungeonssimple or dungeonsfull.
|
||||
goal - Opens pyramid hole if the goal specifies a fast ganon.
|
||||
yes - Always opens the pyramid hole.
|
||||
no - Never opens the pyramid hole.
|
||||
''', choices=['auto', 'goal', 'yes', 'no'])
|
||||
parser.add_argument('--rom', default=defval('Zelda no Densetsu - Kamigami no Triforce (Japan).sfc'),
|
||||
help='Path to an ALttP JAP(1.0) rom to use as a base.')
|
||||
parser.add_argument('--loglevel', default=defval('info'), const='info', nargs='?', choices=['error', 'info', 'warning', 'debug'], help='Select level of logging for output.')
|
||||
|
@ -251,6 +258,7 @@ def parse_arguments(argv, no_defaults=False):
|
|||
(Both can be revealed when speaking to Murahalda)
|
||||
(default: %(default)s)
|
||||
''')
|
||||
parser.add_argument('--enableflashing', help='Reenable flashing animations (unfriendly to epilepsy, always disabled in race roms)', action='store_false', dest="reduceflashing")
|
||||
parser.add_argument('--mapshuffle', default=defval(False),
|
||||
help='Maps are no longer restricted to their dungeons, but can be anywhere',
|
||||
action='store_true')
|
||||
|
@ -377,6 +385,7 @@ def parse_arguments(argv, no_defaults=False):
|
|||
ret.plando_items = []
|
||||
ret.plando_texts = {}
|
||||
ret.plando_connections = []
|
||||
ret.er_seeds = {}
|
||||
|
||||
ret.glitch_boots = not ret.disable_glitch_boots
|
||||
if ret.timer == "none":
|
||||
|
@ -407,10 +416,10 @@ def parse_arguments(argv, no_defaults=False):
|
|||
'heartbeep', "skip_progression_balancing", "triforce_pieces_available",
|
||||
"triforce_pieces_required", "shop_shuffle", "shop_shuffle_slots",
|
||||
"required_medallions",
|
||||
"plando_items", "plando_texts", "plando_connections",
|
||||
"plando_items", "plando_texts", "plando_connections", "er_seeds",
|
||||
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves',
|
||||
'tile_shuffle', 'bush_shuffle', 'shuffle_prizes', 'sprite_pool', 'dark_room_logic',
|
||||
'restrict_dungeon_item_on_boss',
|
||||
'restrict_dungeon_item_on_boss', 'reduceflashing',
|
||||
'hud_palettes', 'sword_palettes', 'shield_palettes', 'link_palettes', 'triforcehud']:
|
||||
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
||||
if player == 1:
|
||||
|
|
|
@ -2054,10 +2054,11 @@ def connect_doors(world, doors, targets, player):
|
|||
"""This works inplace"""
|
||||
world.random.shuffle(doors)
|
||||
world.random.shuffle(targets)
|
||||
while doors:
|
||||
door = doors.pop()
|
||||
target = targets.pop()
|
||||
placing = min(len(doors), len(targets))
|
||||
for door, target in zip(doors, targets):
|
||||
connect_entrance(world, door, target, player)
|
||||
doors[:] = doors[placing:]
|
||||
targets[:] = targets[placing:]
|
||||
|
||||
|
||||
def skull_woods_shuffle(world, player):
|
||||
|
|
80
Fill.py
80
Fill.py
|
@ -1,5 +1,7 @@
|
|||
import logging
|
||||
import typing
|
||||
import collections
|
||||
import itertools
|
||||
|
||||
from BaseClasses import CollectionState, PlandoItem, Location
|
||||
from Items import ItemFactory
|
||||
|
@ -77,21 +79,14 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
|||
# get items to distribute
|
||||
world.random.shuffle(world.itempool)
|
||||
progitempool = []
|
||||
localprioitempool = {player: [] for player in range(1, world.players + 1)}
|
||||
localrestitempool = {player: [] for player in range(1, world.players + 1)}
|
||||
prioitempool = []
|
||||
restitempool = []
|
||||
|
||||
for item in world.itempool:
|
||||
if item.advancement:
|
||||
progitempool.append(item)
|
||||
elif item.name in world.local_items[item.player]:
|
||||
if item.priority:
|
||||
localprioitempool[item.player].append(item)
|
||||
else:
|
||||
localrestitempool[item.player].append(item)
|
||||
elif item.priority:
|
||||
prioitempool.append(item)
|
||||
localrestitempool[item.player].append(item)
|
||||
else:
|
||||
restitempool.append(item)
|
||||
|
||||
|
@ -141,24 +136,13 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
|||
|
||||
fill_restrictive(world, world.state, fill_locations, progitempool)
|
||||
|
||||
if any(localprioitempool.values()) or \
|
||||
any(localrestitempool.values()): # we need to make sure some fills are limited to certain worlds
|
||||
if any(localrestitempool.values()): # we need to make sure some fills are limited to certain worlds
|
||||
local_locations = {player: [] for player in world.player_ids}
|
||||
for location in fill_locations:
|
||||
local_locations[location.player].append(location)
|
||||
for locations in local_locations.values():
|
||||
world.random.shuffle(locations)
|
||||
|
||||
for player, items in localprioitempool.items(): # items already shuffled
|
||||
player_local_locations = local_locations[player]
|
||||
for item_to_place in items:
|
||||
if not player_local_locations:
|
||||
logging.warning(f"Ran out of local locations for player {player}, "
|
||||
f"cannot place {item_to_place}.")
|
||||
break
|
||||
spot_to_fill = player_local_locations.pop()
|
||||
world.push_item(spot_to_fill, item_to_place, False)
|
||||
fill_locations.remove(spot_to_fill)
|
||||
for player, items in localrestitempool.items(): # items already shuffled
|
||||
player_local_locations = local_locations[player]
|
||||
for item_to_place in items:
|
||||
|
@ -172,10 +156,8 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
|||
|
||||
world.random.shuffle(fill_locations)
|
||||
|
||||
prioitempool, fill_locations = fast_fill(world, prioitempool, fill_locations)
|
||||
|
||||
restitempool, fill_locations = fast_fill(world, restitempool, fill_locations)
|
||||
unplaced = [item for item in progitempool + prioitempool + restitempool]
|
||||
unplaced = [item for item in progitempool + restitempool]
|
||||
unfilled = [location.name for location in fill_locations]
|
||||
|
||||
for location in fill_locations:
|
||||
|
@ -242,7 +224,7 @@ def flood_items(world):
|
|||
location_list = world.get_reachable_locations()
|
||||
world.random.shuffle(location_list)
|
||||
for location in location_list:
|
||||
if location.item is not None and not location.item.advancement and not location.item.priority and not location.item.smallkey and not location.item.bigkey:
|
||||
if location.item is not None and not location.item.advancement and not location.item.smallkey and not location.item.bigkey:
|
||||
# safe to replace
|
||||
replace_item = location.item
|
||||
replace_item.location = None
|
||||
|
@ -263,12 +245,7 @@ def balance_multiworld_progression(world):
|
|||
unchecked_locations = world.get_locations().copy()
|
||||
world.random.shuffle(unchecked_locations)
|
||||
|
||||
reachable_locations_count = {player: 0 for player in range(1, world.players + 1)}
|
||||
|
||||
def event_key(location):
|
||||
return location.event and (
|
||||
world.keyshuffle[location.item.player] or not location.item.smallkey) and (
|
||||
world.bigkeyshuffle[location.item.player] or not location.item.bigkey)
|
||||
reachable_locations_count = {player: 0 for player in world.player_ids}
|
||||
|
||||
def get_sphere_locations(sphere_state, locations):
|
||||
sphere_state.sweep_for_events(key_only=True, locations=locations)
|
||||
|
@ -289,33 +266,38 @@ def balance_multiworld_progression(world):
|
|||
balancing_unchecked_locations = unchecked_locations.copy()
|
||||
balancing_reachables = reachable_locations_count.copy()
|
||||
balancing_sphere = sphere_locations.copy()
|
||||
candidate_items = []
|
||||
candidate_items = collections.defaultdict(list)
|
||||
while True:
|
||||
for location in balancing_sphere:
|
||||
if event_key(location):
|
||||
if location.event:
|
||||
balancing_state.collect(location.item, True, location)
|
||||
if location.item.player in balancing_players and not location.locked:
|
||||
candidate_items.append(location)
|
||||
player = location.item.player
|
||||
# only replace items that end up in another player's world
|
||||
if not location.locked and player in balancing_players and location.player != player:
|
||||
candidate_items[player].append(location)
|
||||
balancing_sphere = get_sphere_locations(balancing_state, balancing_unchecked_locations)
|
||||
for location in balancing_sphere:
|
||||
balancing_unchecked_locations.remove(location)
|
||||
balancing_reachables[location.player] += 1
|
||||
if world.has_beaten_game(balancing_state) or all(
|
||||
[reachables >= threshold for reachables in balancing_reachables.values()]):
|
||||
reachables >= threshold for reachables in balancing_reachables.values()):
|
||||
break
|
||||
elif not balancing_sphere:
|
||||
raise RuntimeError('Not all required items reachable. Something went terribly wrong here.')
|
||||
|
||||
unlocked_locations = [l for l in unchecked_locations if l not in balancing_unchecked_locations]
|
||||
unlocked_locations = collections.defaultdict(list)
|
||||
for l in unchecked_locations:
|
||||
if l not in balancing_unchecked_locations:
|
||||
unlocked_locations[l.player].append(l)
|
||||
items_to_replace = []
|
||||
for player in balancing_players:
|
||||
locations_to_test = [l for l in unlocked_locations if l.player == player]
|
||||
# only replace items that end up in another player's world
|
||||
items_to_test = [l for l in candidate_items if l.item.player == player and l.player != player]
|
||||
locations_to_test = unlocked_locations[player]
|
||||
items_to_test = candidate_items[player]
|
||||
while items_to_test:
|
||||
testing = items_to_test.pop()
|
||||
reducing_state = state.copy()
|
||||
for location in [*[l for l in items_to_replace if l.item.player == player], *items_to_test]:
|
||||
for location in itertools.chain((l for l in items_to_replace if l.item.player == player),
|
||||
items_to_test):
|
||||
|
||||
reducing_state.collect(location.item, True, location)
|
||||
|
||||
reducing_state.sweep_for_events(locations=locations_to_test)
|
||||
|
@ -340,21 +322,20 @@ def balance_multiworld_progression(world):
|
|||
new_location = replacement_locations.pop()
|
||||
|
||||
swap_location_item(old_location, new_location)
|
||||
|
||||
new_location.event, old_location.event = True, False
|
||||
logging.debug(f"Progression balancing moved {new_location.item} to {new_location}, "
|
||||
f"displacing {old_location.item} in {old_location}")
|
||||
f"displacing {old_location.item} into {old_location}")
|
||||
state.collect(new_location.item, True, new_location)
|
||||
replaced_items = True
|
||||
|
||||
if replaced_items:
|
||||
for location in get_sphere_locations(state, [l for l in unlocked_locations if
|
||||
l.player in balancing_players]):
|
||||
unlocked = [fresh for player in balancing_players for fresh in unlocked_locations[player]]
|
||||
for location in get_sphere_locations(state, unlocked):
|
||||
unchecked_locations.remove(location)
|
||||
reachable_locations_count[location.player] += 1
|
||||
sphere_locations.append(location)
|
||||
|
||||
for location in sphere_locations:
|
||||
if event_key(location):
|
||||
if location.event:
|
||||
state.collect(location.item, True, location)
|
||||
checked_locations.extend(sphere_locations)
|
||||
|
||||
|
@ -365,7 +346,7 @@ def balance_multiworld_progression(world):
|
|||
|
||||
|
||||
def swap_location_item(location_1: Location, location_2: Location, check_locked=True):
|
||||
"""Swaps Items of locations. Does NOT swap flags like event, shop_slot or locked"""
|
||||
"""Swaps Items of locations. Does NOT swap flags like shop_slot or locked, but does swap event"""
|
||||
if check_locked:
|
||||
if location_1.locked:
|
||||
logging.warning(f"Swapping {location_1}, which is marked as locked.")
|
||||
|
@ -374,10 +355,11 @@ def swap_location_item(location_1: Location, location_2: Location, check_locked=
|
|||
location_2.item, location_1.item = location_1.item, location_2.item
|
||||
location_1.item.location = location_1
|
||||
location_2.item.location = location_2
|
||||
location_1.event, location_2.event = location_2.event, location_1.event
|
||||
|
||||
|
||||
def distribute_planned(world):
|
||||
world_name_lookup = {world.player_names[player_id][0]: player_id for player_id in world.player_ids}
|
||||
world_name_lookup = world.world_name_lookup
|
||||
|
||||
for player in world.player_ids:
|
||||
placement: PlandoItem
|
||||
|
|
509
Gui.py
509
Gui.py
|
@ -14,12 +14,11 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
|
|||
import ModuleUpdate
|
||||
ModuleUpdate.update()
|
||||
|
||||
from AdjusterMain import adjust
|
||||
from EntranceRandomizer import parse_arguments
|
||||
from GuiUtils import ToolTips, set_icon, BackgroundTaskProgress
|
||||
from Main import main, get_seed, __version__ as MWVersion
|
||||
from Rom import Sprite
|
||||
from Utils import is_bundled, local_path, output_path, open_file
|
||||
from Utils import local_path, output_path, open_file
|
||||
|
||||
|
||||
def guiMain(args=None):
|
||||
|
@ -30,10 +29,8 @@ def guiMain(args=None):
|
|||
|
||||
notebook = ttk.Notebook(mainWindow)
|
||||
randomizerWindow = ttk.Frame(notebook)
|
||||
adjustWindow = ttk.Frame(notebook)
|
||||
customWindow = ttk.Frame(notebook)
|
||||
notebook.add(randomizerWindow, text='Randomize')
|
||||
notebook.add(adjustWindow, text='Adjust')
|
||||
notebook.add(customWindow, text='Custom Items')
|
||||
notebook.pack()
|
||||
|
||||
|
@ -57,6 +54,8 @@ def guiMain(args=None):
|
|||
# randomizer controls
|
||||
|
||||
topFrame = Frame(randomizerWindow)
|
||||
romFrame, romVar = get_rom_frame(topFrame)
|
||||
|
||||
rightHalfFrame = Frame(topFrame)
|
||||
checkBoxFrame = Frame(rightHalfFrame)
|
||||
|
||||
|
@ -64,8 +63,13 @@ def guiMain(args=None):
|
|||
createSpoilerCheckbutton = Checkbutton(checkBoxFrame, text="Create Spoiler Log", variable=createSpoilerVar)
|
||||
suppressRomVar = IntVar()
|
||||
suppressRomCheckbutton = Checkbutton(checkBoxFrame, text="Do not create patched Rom", variable=suppressRomVar)
|
||||
openpyramidVar = IntVar()
|
||||
openpyramidCheckbutton = Checkbutton(checkBoxFrame, text="Pre-open Pyramid Hole", variable=openpyramidVar)
|
||||
openpyramidFrame = Frame(checkBoxFrame)
|
||||
openpyramidVar = StringVar()
|
||||
openpyramidVar.set('auto')
|
||||
openpyramidOptionMenu = OptionMenu(openpyramidFrame, openpyramidVar, 'auto', 'goal', 'yes', 'no')
|
||||
openpyramidLabel = Label(openpyramidFrame, text='Pre-open Pyramid Hole')
|
||||
openpyramidLabel.pack(side=LEFT)
|
||||
openpyramidOptionMenu.pack(side=LEFT)
|
||||
mcsbshuffleFrame = Frame(checkBoxFrame)
|
||||
mcsbLabel = Label(mcsbshuffleFrame, text="Shuffle: ")
|
||||
|
||||
|
@ -102,7 +106,7 @@ def guiMain(args=None):
|
|||
|
||||
createSpoilerCheckbutton.pack(expand=True, anchor=W)
|
||||
suppressRomCheckbutton.pack(expand=True, anchor=W)
|
||||
openpyramidCheckbutton.pack(expand=True, anchor=W)
|
||||
openpyramidFrame.pack(expand=True, anchor=W)
|
||||
mcsbshuffleFrame.pack(expand=True, anchor=W)
|
||||
mcsbLabel.grid(row=0, column=0)
|
||||
mapshuffleCheckbutton.grid(row=0, column=1)
|
||||
|
@ -114,154 +118,9 @@ def guiMain(args=None):
|
|||
hintsCheckbutton.pack(expand=True, anchor=W)
|
||||
tileShuffleButton.pack(expand=True, anchor=W)
|
||||
|
||||
|
||||
romOptionsFrame = LabelFrame(rightHalfFrame, text="Rom options")
|
||||
romOptionsFrame.columnconfigure(0, weight=1)
|
||||
romOptionsFrame.columnconfigure(1, weight=1)
|
||||
for i in range(5):
|
||||
romOptionsFrame.rowconfigure(i, weight=1)
|
||||
|
||||
disableMusicVar = IntVar()
|
||||
disableMusicCheckbutton = Checkbutton(romOptionsFrame, text="Disable music", variable=disableMusicVar)
|
||||
disableMusicCheckbutton.grid(row=0, column=0, sticky=E)
|
||||
|
||||
spriteDialogFrame = Frame(romOptionsFrame)
|
||||
spriteDialogFrame.grid(row=0, column=1)
|
||||
baseSpriteLabel = Label(spriteDialogFrame, text='Sprite:')
|
||||
|
||||
spriteNameVar = StringVar()
|
||||
sprite = None
|
||||
def set_sprite(sprite_param):
|
||||
nonlocal sprite
|
||||
if isinstance(sprite_param, str):
|
||||
sprite = sprite_param
|
||||
spriteNameVar.set(sprite_param)
|
||||
elif sprite_param is None or not sprite_param.valid:
|
||||
sprite = None
|
||||
spriteNameVar.set('(unchanged)')
|
||||
else:
|
||||
sprite = sprite_param
|
||||
spriteNameVar.set(sprite.name)
|
||||
|
||||
set_sprite(None)
|
||||
spriteNameVar.set('(unchanged)')
|
||||
spriteEntry = Label(spriteDialogFrame, textvariable=spriteNameVar)
|
||||
|
||||
def SpriteSelect():
|
||||
SpriteSelector(mainWindow, set_sprite)
|
||||
|
||||
spriteSelectButton = Button(spriteDialogFrame, text='...', command=SpriteSelect)
|
||||
|
||||
baseSpriteLabel.pack(side=LEFT)
|
||||
spriteEntry.pack(side=LEFT)
|
||||
spriteSelectButton.pack(side=LEFT)
|
||||
|
||||
quickSwapVar = IntVar(value=1)
|
||||
quickSwapCheckbutton = Checkbutton(romOptionsFrame, text="L/R Quickswapping", variable=quickSwapVar)
|
||||
quickSwapCheckbutton.grid(row=1, column=0, sticky=E)
|
||||
|
||||
fastMenuFrame = Frame(romOptionsFrame)
|
||||
fastMenuFrame.grid(row=1, column=1, sticky=E)
|
||||
fastMenuLabel = Label(fastMenuFrame, text='Menu speed')
|
||||
fastMenuLabel.pack(side=LEFT)
|
||||
fastMenuVar = StringVar()
|
||||
fastMenuVar.set('normal')
|
||||
fastMenuOptionMenu = OptionMenu(fastMenuFrame, fastMenuVar, 'normal', 'instant', 'double', 'triple', 'quadruple', 'half')
|
||||
fastMenuOptionMenu.pack(side=LEFT)
|
||||
|
||||
heartcolorFrame = Frame(romOptionsFrame)
|
||||
heartcolorFrame.grid(row=2, column=0, sticky=E)
|
||||
heartcolorLabel = Label(heartcolorFrame, text='Heart color')
|
||||
heartcolorLabel.pack(side=LEFT)
|
||||
heartcolorVar = StringVar()
|
||||
heartcolorVar.set('red')
|
||||
heartcolorOptionMenu = OptionMenu(heartcolorFrame, heartcolorVar, 'red', 'blue', 'green', 'yellow', 'random')
|
||||
heartcolorOptionMenu.pack(side=LEFT)
|
||||
|
||||
heartbeepFrame = Frame(romOptionsFrame)
|
||||
heartbeepFrame.grid(row=2, column=1, sticky=E)
|
||||
heartbeepLabel = Label(heartbeepFrame, text='Heartbeep')
|
||||
heartbeepLabel.pack(side=LEFT)
|
||||
heartbeepVar = StringVar()
|
||||
heartbeepVar.set('normal')
|
||||
heartbeepOptionMenu = OptionMenu(heartbeepFrame, heartbeepVar, 'double', 'normal', 'half', 'quarter', 'off')
|
||||
heartbeepOptionMenu.pack(side=LEFT)
|
||||
|
||||
owPalettesFrame = Frame(romOptionsFrame)
|
||||
owPalettesFrame.grid(row=3, column=0, sticky=E)
|
||||
owPalettesLabel = Label(owPalettesFrame, text='Overworld palettes')
|
||||
owPalettesLabel.pack(side=LEFT)
|
||||
owPalettesVar = StringVar()
|
||||
owPalettesVar.set('default')
|
||||
owPalettesOptionMenu = OptionMenu(owPalettesFrame, owPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
owPalettesOptionMenu.pack(side=LEFT)
|
||||
|
||||
uwPalettesFrame = Frame(romOptionsFrame)
|
||||
uwPalettesFrame.grid(row=3, column=1, sticky=E)
|
||||
uwPalettesLabel = Label(uwPalettesFrame, text='Dungeon palettes')
|
||||
uwPalettesLabel.pack(side=LEFT)
|
||||
uwPalettesVar = StringVar()
|
||||
uwPalettesVar.set('default')
|
||||
uwPalettesOptionMenu = OptionMenu(uwPalettesFrame, uwPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
uwPalettesOptionMenu.pack(side=LEFT)
|
||||
|
||||
hudPalettesFrame = Frame(romOptionsFrame)
|
||||
hudPalettesFrame.grid(row=4, column=0, sticky=E)
|
||||
hudPalettesLabel = Label(hudPalettesFrame, text='HUD palettes')
|
||||
hudPalettesLabel.pack(side=LEFT)
|
||||
hudPalettesVar = StringVar()
|
||||
hudPalettesVar.set('default')
|
||||
hudPalettesOptionMenu = OptionMenu(hudPalettesFrame, hudPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
hudPalettesOptionMenu.pack(side=LEFT)
|
||||
|
||||
swordPalettesFrame = Frame(romOptionsFrame)
|
||||
swordPalettesFrame.grid(row=4, column=1, sticky=E)
|
||||
swordPalettesLabel = Label(swordPalettesFrame, text='Sword palettes')
|
||||
swordPalettesLabel.pack(side=LEFT)
|
||||
swordPalettesVar = StringVar()
|
||||
swordPalettesVar.set('default')
|
||||
swordPalettesOptionMenu = OptionMenu(swordPalettesFrame, swordPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
swordPalettesOptionMenu.pack(side=LEFT)
|
||||
|
||||
shieldPalettesFrame = Frame(romOptionsFrame)
|
||||
shieldPalettesFrame.grid(row=5, column=0, sticky=E)
|
||||
shieldPalettesLabel = Label(shieldPalettesFrame, text='Shield palettes')
|
||||
shieldPalettesLabel.pack(side=LEFT)
|
||||
shieldPalettesVar = StringVar()
|
||||
shieldPalettesVar.set('default')
|
||||
shieldPalettesOptionMenu = OptionMenu(shieldPalettesFrame, shieldPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
shieldPalettesOptionMenu.pack(side=LEFT)
|
||||
|
||||
|
||||
|
||||
|
||||
romDialogFrame = Frame(romOptionsFrame)
|
||||
romDialogFrame.grid(row=6, column=0, columnspan=2, sticky=W+E)
|
||||
|
||||
baseRomLabel = Label(romDialogFrame, text='Base Rom: ')
|
||||
romVar = StringVar(value="Zelda no Densetsu - Kamigami no Triforce (Japan).sfc")
|
||||
romEntry = Entry(romDialogFrame, textvariable=romVar)
|
||||
|
||||
def RomSelect():
|
||||
rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".sfc", ".smc")), ("All Files", "*")])
|
||||
import Patch
|
||||
try:
|
||||
Patch.get_base_rom_bytes(rom) # throws error on checksum fail
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
messagebox.showerror(title="Error while reading ROM", message=str(e))
|
||||
else:
|
||||
romVar.set(rom)
|
||||
romSelectButton['state'] = "disabled"
|
||||
romSelectButton["text"] = "ROM verified"
|
||||
romSelectButton = Button(romDialogFrame, text='Select Rom', command=RomSelect)
|
||||
|
||||
baseRomLabel.pack(side=LEFT)
|
||||
romEntry.pack(side=LEFT, expand=True, fill=X)
|
||||
romSelectButton.pack(side=LEFT)
|
||||
|
||||
checkBoxFrame.pack(side=TOP, anchor=W, padx=5, pady=10)
|
||||
|
||||
romOptionsFrame, rom_vars, set_sprite = get_rom_options_frame(rightHalfFrame)
|
||||
romOptionsFrame.pack(expand=True, fill=BOTH, padx=3)
|
||||
|
||||
drowDownFrame = Frame(topFrame)
|
||||
|
@ -377,7 +236,8 @@ def guiMain(args=None):
|
|||
shuffleVar.set('vanilla')
|
||||
shuffleOptionMenu = OptionMenu(shuffleFrame, shuffleVar, 'vanilla', 'simple', 'restricted', 'full', 'crossed',
|
||||
'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy',
|
||||
'dungeonsfull', 'dungeonssimple')
|
||||
'dungeonsfull', 'dungeonssimple', "same simple", "same restricted", "same full",
|
||||
"same crossed", "same insanity", "same dungeonsfull", "same dungeonssimple")
|
||||
shuffleOptionMenu.pack(side=RIGHT)
|
||||
shuffleLabel = Label(shuffleFrame, text='Entrance shuffle')
|
||||
shuffleLabel.pack(side=LEFT)
|
||||
|
@ -558,25 +418,29 @@ def guiMain(args=None):
|
|||
guiargs.accessibility = accessibilityVar.get()
|
||||
guiargs.algorithm = algorithmVar.get()
|
||||
guiargs.shuffle = shuffleVar.get()
|
||||
guiargs.heartbeep = heartbeepVar.get()
|
||||
guiargs.heartcolor = heartcolorVar.get()
|
||||
guiargs.fastmenu = fastMenuVar.get()
|
||||
if "same " in guiargs.shuffle:
|
||||
guiargs.shuffle = guiargs.shuffle[5:] + "-" + str(seedVar.get() if seedVar.get() else
|
||||
random.randint(0, 2**64))
|
||||
guiargs.heartbeep = rom_vars.heartbeepVar.get()
|
||||
guiargs.heartcolor = rom_vars.heartcolorVar.get()
|
||||
guiargs.fastmenu = rom_vars.fastMenuVar.get()
|
||||
guiargs.create_spoiler = bool(createSpoilerVar.get())
|
||||
guiargs.skip_playthrough = not bool(createSpoilerVar.get())
|
||||
guiargs.suppress_rom = bool(suppressRomVar.get())
|
||||
guiargs.open_pyramid = bool(openpyramidVar.get())
|
||||
guiargs.open_pyramid = openpyramidVar.get()
|
||||
guiargs.mapshuffle = bool(mapshuffleVar.get())
|
||||
guiargs.compassshuffle = bool(compassshuffleVar.get())
|
||||
guiargs.keyshuffle = {"on": True, "universal": "universal", "off": False}[keyshuffleVar.get()]
|
||||
guiargs.bigkeyshuffle = bool(bigkeyshuffleVar.get())
|
||||
guiargs.retro = bool(retroVar.get())
|
||||
guiargs.quickswap = bool(quickSwapVar.get())
|
||||
guiargs.disablemusic = bool(disableMusicVar.get())
|
||||
guiargs.ow_palettes = owPalettesVar.get()
|
||||
guiargs.uw_palettes = uwPalettesVar.get()
|
||||
guiargs.hud_palettes = hudPalettesVar.get()
|
||||
guiargs.sword_palettes = swordPalettesVar.get()
|
||||
guiargs.shield_palettes = shieldPalettesVar.get()
|
||||
guiargs.quickswap = bool(rom_vars.quickSwapVar.get())
|
||||
guiargs.disablemusic = bool(rom_vars.disableMusicVar.get())
|
||||
guiargs.reduceflashing = bool(rom_vars.disableFlashingVar.get())
|
||||
guiargs.ow_palettes = rom_vars.owPalettesVar.get()
|
||||
guiargs.uw_palettes = rom_vars.uwPalettesVar.get()
|
||||
guiargs.hud_palettes = rom_vars.hudPalettesVar.get()
|
||||
guiargs.sword_palettes = rom_vars.swordPalettesVar.get()
|
||||
guiargs.shield_palettes = rom_vars.shieldPalettesVar.get()
|
||||
guiargs.shuffleganon = bool(shuffleGanonVar.get())
|
||||
guiargs.hints = bool(hintsVar.get())
|
||||
guiargs.enemizercli = enemizerCLIpathVar.get()
|
||||
|
@ -636,7 +500,7 @@ def guiMain(args=None):
|
|||
int(rupoorcostVar.get()), int(triforceVar.get())]
|
||||
guiargs.rom = romVar.get()
|
||||
guiargs.create_diff = patchesVar.get()
|
||||
guiargs.sprite = sprite
|
||||
guiargs.sprite = rom_vars.sprite
|
||||
# get default values for missing parameters
|
||||
for k,v in vars(parse_arguments(['--multi', str(guiargs.multi)])).items():
|
||||
if k not in vars(guiargs):
|
||||
|
@ -684,150 +548,6 @@ def guiMain(args=None):
|
|||
enemizerFrame.pack(side=BOTTOM, fill=BOTH)
|
||||
shopframe.pack(side=BOTTOM, expand=True, fill=X)
|
||||
|
||||
# Adjuster Controls
|
||||
|
||||
topFrame2 = Frame(adjustWindow)
|
||||
rightHalfFrame2 = Frame(topFrame2)
|
||||
checkBoxFrame2 = Frame(rightHalfFrame2)
|
||||
|
||||
quickSwapCheckbutton2 = Checkbutton(checkBoxFrame2, text="L/R Item quickswapping", variable=quickSwapVar)
|
||||
disableMusicCheckbutton2 = Checkbutton(checkBoxFrame2, text="Disable game music", variable=disableMusicVar)
|
||||
|
||||
quickSwapCheckbutton2.pack(expand=True, anchor=W)
|
||||
disableMusicCheckbutton2.pack(expand=True, anchor=W)
|
||||
|
||||
fileDialogFrame2 = Frame(rightHalfFrame2)
|
||||
|
||||
romDialogFrame2 = Frame(fileDialogFrame2)
|
||||
baseRomLabel2 = Label(romDialogFrame2, text='Rom to adjust')
|
||||
romVar2 = StringVar()
|
||||
romEntry2 = Entry(romDialogFrame2, textvariable=romVar2)
|
||||
|
||||
def RomSelect2():
|
||||
rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".sfc", ".smc", ".bmbp")), ("All Files", "*")])
|
||||
romVar2.set(rom)
|
||||
romSelectButton2 = Button(romDialogFrame2, text='Select Rom', command=RomSelect2)
|
||||
|
||||
baseRomLabel2.pack(side=LEFT)
|
||||
romEntry2.pack(side=LEFT)
|
||||
romSelectButton2.pack(side=LEFT)
|
||||
|
||||
spriteDialogFrame2 = Frame(fileDialogFrame2)
|
||||
baseSpriteLabel2 = Label(spriteDialogFrame2, text='Link Sprite')
|
||||
spriteEntry2 = Label(spriteDialogFrame2, textvariable=spriteNameVar)
|
||||
|
||||
def SpriteSelectAdjuster():
|
||||
SpriteSelector(mainWindow, set_sprite, adjuster=True)
|
||||
|
||||
spriteSelectButton2 = Button(spriteDialogFrame2, text='Select Sprite', command=SpriteSelectAdjuster)
|
||||
|
||||
baseSpriteLabel2.pack(side=LEFT)
|
||||
spriteEntry2.pack(side=LEFT)
|
||||
spriteSelectButton2.pack(side=LEFT)
|
||||
|
||||
romDialogFrame2.pack()
|
||||
spriteDialogFrame2.pack()
|
||||
|
||||
checkBoxFrame2.pack()
|
||||
fileDialogFrame2.pack()
|
||||
|
||||
drowDownFrame2 = Frame(topFrame2)
|
||||
heartbeepFrame2 = Frame(drowDownFrame2)
|
||||
heartbeepOptionMenu2 = OptionMenu(heartbeepFrame2, heartbeepVar, 'double', 'normal', 'half', 'quarter', 'off')
|
||||
heartbeepOptionMenu2.pack(side=RIGHT)
|
||||
heartbeepLabel2 = Label(heartbeepFrame2, text='Heartbeep sound rate')
|
||||
heartbeepLabel2.pack(side=LEFT)
|
||||
|
||||
heartcolorFrame2 = Frame(drowDownFrame2)
|
||||
heartcolorOptionMenu2 = OptionMenu(heartcolorFrame2, heartcolorVar, 'red', 'blue', 'green', 'yellow', 'random')
|
||||
heartcolorOptionMenu2.pack(side=RIGHT)
|
||||
heartcolorLabel2 = Label(heartcolorFrame2, text='Heart color')
|
||||
heartcolorLabel2.pack(side=LEFT)
|
||||
|
||||
fastMenuFrame2 = Frame(drowDownFrame2)
|
||||
fastMenuOptionMenu2 = OptionMenu(fastMenuFrame2, fastMenuVar, 'normal', 'instant', 'double', 'triple', 'quadruple', 'half')
|
||||
fastMenuOptionMenu2.pack(side=RIGHT)
|
||||
fastMenuLabel2 = Label(fastMenuFrame2, text='Menu speed')
|
||||
fastMenuLabel2.pack(side=LEFT)
|
||||
|
||||
owPalettesFrame2 = Frame(drowDownFrame2)
|
||||
owPalettesOptionMenu2 = OptionMenu(owPalettesFrame2, owPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
owPalettesOptionMenu2.pack(side=RIGHT)
|
||||
owPalettesLabel2 = Label(owPalettesFrame2, text='Overworld palettes')
|
||||
owPalettesLabel2.pack(side=LEFT)
|
||||
|
||||
uwPalettesFrame2 = Frame(drowDownFrame2)
|
||||
uwPalettesOptionMenu2 = OptionMenu(uwPalettesFrame2, uwPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
uwPalettesOptionMenu2.pack(side=RIGHT)
|
||||
uwPalettesLabel2 = Label(uwPalettesFrame2, text='Dungeon palettes')
|
||||
uwPalettesLabel2.pack(side=LEFT)
|
||||
|
||||
hudPalettesFrame2 = Frame(drowDownFrame2)
|
||||
hudPalettesOptionMenu2 = OptionMenu(hudPalettesFrame2, hudPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
hudPalettesOptionMenu2.pack(side=RIGHT)
|
||||
hudPalettesLabel2 = Label(hudPalettesFrame2, text='HUD palettes')
|
||||
hudPalettesLabel2.pack(side=LEFT)
|
||||
|
||||
swordPalettesFrame2 = Frame(drowDownFrame2)
|
||||
swordPalettesOptionMenu2 = OptionMenu(swordPalettesFrame2, swordPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
swordPalettesOptionMenu2.pack(side=RIGHT)
|
||||
swordPalettesLabel2 = Label(swordPalettesFrame2, text='Sword palettes')
|
||||
swordPalettesLabel2.pack(side=LEFT)
|
||||
|
||||
shieldPalettesFrame2 = Frame(drowDownFrame2)
|
||||
shieldPalettesOptionMenu2 = OptionMenu(shieldPalettesFrame2, shieldPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
shieldPalettesOptionMenu2.pack(side=RIGHT)
|
||||
shieldPalettesLabel2 = Label(shieldPalettesFrame2, text='Shield palettes')
|
||||
shieldPalettesLabel2.pack(side=LEFT)
|
||||
|
||||
heartbeepFrame2.pack(expand=True, anchor=E)
|
||||
heartcolorFrame2.pack(expand=True, anchor=E)
|
||||
fastMenuFrame2.pack(expand=True, anchor=E)
|
||||
owPalettesFrame2.pack(expand=True, anchor=E)
|
||||
uwPalettesFrame2.pack(expand=True, anchor=E)
|
||||
hudPalettesFrame2.pack(expand=True, anchor=E)
|
||||
swordPalettesFrame2.pack(expand=True, anchor=E)
|
||||
shieldPalettesFrame2.pack(expand=True, anchor=E)
|
||||
|
||||
bottomFrame2 = Frame(topFrame2)
|
||||
|
||||
def adjustRom():
|
||||
guiargs = Namespace()
|
||||
guiargs.heartbeep = heartbeepVar.get()
|
||||
guiargs.heartcolor = heartcolorVar.get()
|
||||
guiargs.fastmenu = fastMenuVar.get()
|
||||
guiargs.ow_palettes = owPalettesVar.get()
|
||||
guiargs.uw_palettes = uwPalettesVar.get()
|
||||
guiargs.hud_palettes = hudPalettesVar.get()
|
||||
guiargs.sword_palettes = swordPalettesVar.get()
|
||||
guiargs.shield_palettes = shieldPalettesVar.get()
|
||||
guiargs.quickswap = bool(quickSwapVar.get())
|
||||
guiargs.disablemusic = bool(disableMusicVar.get())
|
||||
guiargs.rom = romVar2.get()
|
||||
guiargs.baserom = romVar.get()
|
||||
guiargs.sprite = sprite
|
||||
try:
|
||||
guiargs, path = adjust(args=guiargs)
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
messagebox.showerror(title="Error while adjusting Rom", message=str(e))
|
||||
else:
|
||||
messagebox.showinfo(title="Success", message="Rom patched successfully")
|
||||
from Utils import persistent_store
|
||||
from Rom import Sprite
|
||||
if isinstance(guiargs.sprite, Sprite):
|
||||
guiargs.sprite = guiargs.sprite.name
|
||||
persistent_store("adjuster", "last_settings_3", guiargs)
|
||||
|
||||
adjustButton = Button(bottomFrame2, text='Adjust Rom', command=adjustRom)
|
||||
|
||||
adjustButton.pack(side=LEFT, padx=(5, 0))
|
||||
|
||||
drowDownFrame2.pack(side=LEFT, pady=(0, 40))
|
||||
rightHalfFrame2.pack(side=RIGHT)
|
||||
topFrame2.pack(side=TOP, pady=70)
|
||||
bottomFrame2.pack(side=BOTTOM, pady=(180, 0))
|
||||
|
||||
# Custom Controls
|
||||
|
||||
topFrame3 = Frame(customWindow)
|
||||
|
@ -1485,8 +1205,9 @@ def guiMain(args=None):
|
|||
keyshuffleVar.set(args.keyshuffle)
|
||||
bigkeyshuffleVar.set(args.bigkeyshuffle)
|
||||
retroVar.set(args.retro)
|
||||
quickSwapVar.set(int(args.quickswap))
|
||||
disableMusicVar.set(int(args.disablemusic))
|
||||
rom_vars.quickSwapVar.set(int(args.quickswap))
|
||||
rom_vars.disableMusicVar.set(int(args.disablemusic))
|
||||
rom_vars.disableFlashingVar.set(int(args.reduceflashing))
|
||||
if args.count:
|
||||
countVar.set(str(args.count))
|
||||
if args.seed:
|
||||
|
@ -1507,10 +1228,10 @@ def guiMain(args=None):
|
|||
crystalsGanonVar.set(args.crystals_ganon)
|
||||
algorithmVar.set(args.algorithm)
|
||||
shuffleVar.set(args.shuffle)
|
||||
heartbeepVar.set(args.heartbeep)
|
||||
fastMenuVar.set(args.fastmenu)
|
||||
rom_vars.heartbeepVar.set(args.heartbeep)
|
||||
rom_vars.fastMenuVar.set(args.fastmenu)
|
||||
logicVar.set(args.logic)
|
||||
romVar.set(args.rom)
|
||||
rom_vars.romVar.set(args.rom)
|
||||
shuffleGanonVar.set(args.shuffleganon)
|
||||
hintsVar.set(args.hints)
|
||||
if args.sprite is not None:
|
||||
|
@ -1518,11 +1239,165 @@ def guiMain(args=None):
|
|||
|
||||
mainWindow.mainloop()
|
||||
|
||||
def get_rom_frame(parent=None):
|
||||
romFrame = Frame(parent)
|
||||
baseRomLabel = Label(romFrame, text='LttP Base Rom: ')
|
||||
romVar = StringVar(value="Zelda no Densetsu - Kamigami no Triforce (Japan).sfc")
|
||||
romEntry = Entry(romFrame, textvariable=romVar)
|
||||
|
||||
def RomSelect():
|
||||
rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".sfc", ".smc")), ("All Files", "*")])
|
||||
import Patch
|
||||
try:
|
||||
Patch.get_base_rom_bytes(rom) # throws error on checksum fail
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
messagebox.showerror(title="Error while reading ROM", message=str(e))
|
||||
else:
|
||||
romVar.set(rom)
|
||||
romSelectButton['state'] = "disabled"
|
||||
romSelectButton["text"] = "ROM verified"
|
||||
romSelectButton = Button(romFrame, text='Select Rom', command=RomSelect)
|
||||
|
||||
baseRomLabel.pack(side=LEFT)
|
||||
romEntry.pack(side=LEFT, expand=True, fill=X)
|
||||
romSelectButton.pack(side=LEFT)
|
||||
romFrame.pack(side=TOP, expand=True, fill=X)
|
||||
|
||||
return romFrame, romVar
|
||||
|
||||
|
||||
def get_rom_options_frame(parent=None):
|
||||
romOptionsFrame = LabelFrame(parent, text="Rom options")
|
||||
romOptionsFrame.columnconfigure(0, weight=1)
|
||||
romOptionsFrame.columnconfigure(1, weight=1)
|
||||
for i in range(5):
|
||||
romOptionsFrame.rowconfigure(i, weight=1)
|
||||
vars = Namespace()
|
||||
|
||||
vars.disableMusicVar = IntVar()
|
||||
disableMusicCheckbutton = Checkbutton(romOptionsFrame, text="Disable music", variable=vars.disableMusicVar)
|
||||
disableMusicCheckbutton.grid(row=0, column=0, sticky=E)
|
||||
|
||||
vars.disableFlashingVar = IntVar(value=1)
|
||||
disableFlashingCheckbutton = Checkbutton(romOptionsFrame, text="Disable flashing (anti-epilepsy)", variable=vars.disableFlashingVar)
|
||||
disableFlashingCheckbutton.grid(row=6, column=0, sticky=E)
|
||||
|
||||
spriteDialogFrame = Frame(romOptionsFrame)
|
||||
spriteDialogFrame.grid(row=0, column=1)
|
||||
baseSpriteLabel = Label(spriteDialogFrame, text='Sprite:')
|
||||
|
||||
|
||||
|
||||
vars.spriteNameVar = StringVar()
|
||||
vars.sprite = None
|
||||
def set_sprite(sprite_param):
|
||||
nonlocal vars
|
||||
if isinstance(sprite_param, str):
|
||||
vars.sprite = sprite_param
|
||||
vars.spriteNameVar.set(sprite_param)
|
||||
elif sprite_param is None or not sprite_param.valid:
|
||||
vars.sprite = None
|
||||
vars.spriteNameVar.set('(unchanged)')
|
||||
else:
|
||||
vars.sprite = sprite_param
|
||||
vars.spriteNameVar.set(vars.sprite.name)
|
||||
|
||||
set_sprite(None)
|
||||
vars.spriteNameVar.set('(unchanged)')
|
||||
spriteEntry = Label(spriteDialogFrame, textvariable=vars.spriteNameVar)
|
||||
|
||||
def SpriteSelect():
|
||||
SpriteSelector(parent, set_sprite)
|
||||
|
||||
spriteSelectButton = Button(spriteDialogFrame, text='...', command=SpriteSelect)
|
||||
|
||||
baseSpriteLabel.pack(side=LEFT)
|
||||
spriteEntry.pack(side=LEFT)
|
||||
spriteSelectButton.pack(side=LEFT)
|
||||
|
||||
vars.quickSwapVar = IntVar(value=1)
|
||||
quickSwapCheckbutton = Checkbutton(romOptionsFrame, text="L/R Quickswapping", variable=vars.quickSwapVar)
|
||||
quickSwapCheckbutton.grid(row=1, column=0, sticky=E)
|
||||
|
||||
fastMenuFrame = Frame(romOptionsFrame)
|
||||
fastMenuFrame.grid(row=1, column=1, sticky=E)
|
||||
fastMenuLabel = Label(fastMenuFrame, text='Menu speed')
|
||||
fastMenuLabel.pack(side=LEFT)
|
||||
vars.fastMenuVar = StringVar()
|
||||
vars.fastMenuVar.set('normal')
|
||||
fastMenuOptionMenu = OptionMenu(fastMenuFrame, vars.fastMenuVar, 'normal', 'instant', 'double', 'triple', 'quadruple', 'half')
|
||||
fastMenuOptionMenu.pack(side=LEFT)
|
||||
|
||||
heartcolorFrame = Frame(romOptionsFrame)
|
||||
heartcolorFrame.grid(row=2, column=0, sticky=E)
|
||||
heartcolorLabel = Label(heartcolorFrame, text='Heart color')
|
||||
heartcolorLabel.pack(side=LEFT)
|
||||
vars.heartcolorVar = StringVar()
|
||||
vars.heartcolorVar.set('red')
|
||||
heartcolorOptionMenu = OptionMenu(heartcolorFrame, vars.heartcolorVar, 'red', 'blue', 'green', 'yellow', 'random')
|
||||
heartcolorOptionMenu.pack(side=LEFT)
|
||||
|
||||
heartbeepFrame = Frame(romOptionsFrame)
|
||||
heartbeepFrame.grid(row=2, column=1, sticky=E)
|
||||
heartbeepLabel = Label(heartbeepFrame, text='Heartbeep')
|
||||
heartbeepLabel.pack(side=LEFT)
|
||||
vars.heartbeepVar = StringVar()
|
||||
vars.heartbeepVar.set('normal')
|
||||
heartbeepOptionMenu = OptionMenu(heartbeepFrame, vars.heartbeepVar, 'double', 'normal', 'half', 'quarter', 'off')
|
||||
heartbeepOptionMenu.pack(side=LEFT)
|
||||
|
||||
owPalettesFrame = Frame(romOptionsFrame)
|
||||
owPalettesFrame.grid(row=3, column=0, sticky=E)
|
||||
owPalettesLabel = Label(owPalettesFrame, text='Overworld palettes')
|
||||
owPalettesLabel.pack(side=LEFT)
|
||||
vars.owPalettesVar = StringVar()
|
||||
vars.owPalettesVar.set('default')
|
||||
owPalettesOptionMenu = OptionMenu(owPalettesFrame, vars.owPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
owPalettesOptionMenu.pack(side=LEFT)
|
||||
|
||||
uwPalettesFrame = Frame(romOptionsFrame)
|
||||
uwPalettesFrame.grid(row=3, column=1, sticky=E)
|
||||
uwPalettesLabel = Label(uwPalettesFrame, text='Dungeon palettes')
|
||||
uwPalettesLabel.pack(side=LEFT)
|
||||
vars.uwPalettesVar = StringVar()
|
||||
vars.uwPalettesVar.set('default')
|
||||
uwPalettesOptionMenu = OptionMenu(uwPalettesFrame, vars.uwPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
uwPalettesOptionMenu.pack(side=LEFT)
|
||||
|
||||
hudPalettesFrame = Frame(romOptionsFrame)
|
||||
hudPalettesFrame.grid(row=4, column=0, sticky=E)
|
||||
hudPalettesLabel = Label(hudPalettesFrame, text='HUD palettes')
|
||||
hudPalettesLabel.pack(side=LEFT)
|
||||
vars.hudPalettesVar = StringVar()
|
||||
vars.hudPalettesVar.set('default')
|
||||
hudPalettesOptionMenu = OptionMenu(hudPalettesFrame, vars.hudPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
hudPalettesOptionMenu.pack(side=LEFT)
|
||||
|
||||
swordPalettesFrame = Frame(romOptionsFrame)
|
||||
swordPalettesFrame.grid(row=4, column=1, sticky=E)
|
||||
swordPalettesLabel = Label(swordPalettesFrame, text='Sword palettes')
|
||||
swordPalettesLabel.pack(side=LEFT)
|
||||
vars.swordPalettesVar = StringVar()
|
||||
vars.swordPalettesVar.set('default')
|
||||
swordPalettesOptionMenu = OptionMenu(swordPalettesFrame, vars.swordPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
swordPalettesOptionMenu.pack(side=LEFT)
|
||||
|
||||
shieldPalettesFrame = Frame(romOptionsFrame)
|
||||
shieldPalettesFrame.grid(row=5, column=0, sticky=E)
|
||||
shieldPalettesLabel = Label(shieldPalettesFrame, text='Shield palettes')
|
||||
shieldPalettesLabel.pack(side=LEFT)
|
||||
vars.shieldPalettesVar = StringVar()
|
||||
vars.shieldPalettesVar.set('default')
|
||||
shieldPalettesOptionMenu = OptionMenu(shieldPalettesFrame, vars.shieldPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||
shieldPalettesOptionMenu.pack(side=LEFT)
|
||||
|
||||
return romOptionsFrame, vars, set_sprite
|
||||
|
||||
|
||||
class SpriteSelector():
|
||||
def __init__(self, parent, callback, adjuster=False):
|
||||
if is_bundled():
|
||||
self.deploy_icons()
|
||||
self.deploy_icons()
|
||||
self.parent = parent
|
||||
self.window = Toplevel(parent)
|
||||
self.callback = callback
|
||||
|
|
|
@ -25,7 +25,7 @@ class BackgroundTask(object):
|
|||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
#safe to call from worker
|
||||
# safe to call from worker
|
||||
def queue_event(self, event):
|
||||
self.queue.put(event)
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ def create_inverted_regions(world, player):
|
|||
create_cave_region(player, 'Dark Lake Hylia Ledge Spike Cave', 'a spiky hint'),
|
||||
create_cave_region(player, 'Hype Cave', 'a bounty of five items', ['Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left',
|
||||
'Hype Cave - Bottom', 'Hype Cave - Generous Guy']),
|
||||
create_dw_region(player, 'West Dark World', ['Frog'], ['Village of Outcasts Drop', 'East Dark World River Pier', 'Brewery', 'C-Shaped House', 'Chest Game', 'Thieves Town', 'Bumper Cave Entrance Rock',
|
||||
create_dw_region(player, 'West Dark World', ['Frog', 'Flute Activation Spot'], ['Village of Outcasts Drop', 'East Dark World River Pier', 'Brewery', 'C-Shaped House', 'Chest Game', 'Thieves Town', 'Bumper Cave Entrance Rock',
|
||||
'Skull Woods Forest', 'Village of Outcasts Pegs', 'Village of Outcasts Eastern Rocks', 'Red Shield Shop', 'Inverted Dark Sanctuary', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop',
|
||||
'West Dark World Teleporter', 'WDW Flute']),
|
||||
create_dw_region(player, 'Dark Grassy Lawn', None, ['Grassy Lawn Pegs', 'Dark World Shop', 'Dark Grassy Lawn Flute']),
|
||||
|
|
170
ItemPool.py
170
ItemPool.py
|
@ -2,12 +2,12 @@ from collections import namedtuple
|
|||
import logging
|
||||
|
||||
from BaseClasses import Region, RegionType, Location
|
||||
from Shops import ShopType, Shop, TakeAny, total_shop_slots
|
||||
from Shops import TakeAny, total_shop_slots, set_up_shops, shuffle_shops
|
||||
from Bosses import place_bosses
|
||||
from Dungeons import get_dungeon_item_pool
|
||||
from EntranceShuffle import connect_entrance
|
||||
from Fill import FillError, fill_restrictive
|
||||
from Items import ItemFactory
|
||||
from Items import ItemFactory, GetBeemizerItem
|
||||
from Rules import forbid_items_for_player
|
||||
|
||||
# This file sets the item pools for various modes. Timed modes and triforce hunt are enforced first, and then extra items are specified per mode to fill in the remaining space.
|
||||
|
@ -297,24 +297,22 @@ def generate_itempool(world, player: int):
|
|||
|
||||
world.get_location('Ganon', player).event = True
|
||||
world.get_location('Ganon', player).locked = True
|
||||
world.push_item(world.get_location('Agahnim 1', player), ItemFactory('Beat Agahnim 1', player), False)
|
||||
world.get_location('Agahnim 1', player).event = True
|
||||
world.get_location('Agahnim 1', player).locked = True
|
||||
world.push_item(world.get_location('Agahnim 2', player), ItemFactory('Beat Agahnim 2', player), False)
|
||||
world.get_location('Agahnim 2', player).event = True
|
||||
world.get_location('Agahnim 2', player).locked = True
|
||||
world.push_item(world.get_location('Dark Blacksmith Ruins', player), ItemFactory('Pick Up Purple Chest', player), False)
|
||||
world.get_location('Dark Blacksmith Ruins', player).event = True
|
||||
world.get_location('Dark Blacksmith Ruins', player).locked = True
|
||||
world.push_item(world.get_location('Frog', player), ItemFactory('Get Frog', player), False)
|
||||
world.get_location('Frog', player).event = True
|
||||
world.get_location('Frog', player).locked = True
|
||||
world.push_item(world.get_location('Missing Smith', player), ItemFactory('Return Smith', player), False)
|
||||
world.get_location('Missing Smith', player).event = True
|
||||
world.get_location('Missing Smith', player).locked = True
|
||||
world.push_item(world.get_location('Floodgate', player), ItemFactory('Open Floodgate', player), False)
|
||||
world.get_location('Floodgate', player).event = True
|
||||
world.get_location('Floodgate', player).locked = True
|
||||
event_pairs = [
|
||||
('Agahnim 1', 'Beat Agahnim 1'),
|
||||
('Agahnim 2', 'Beat Agahnim 2'),
|
||||
('Dark Blacksmith Ruins', 'Pick Up Purple Chest'),
|
||||
('Frog', 'Get Frog'),
|
||||
('Missing Smith', 'Return Smith'),
|
||||
('Floodgate', 'Open Floodgate'),
|
||||
('Agahnim 1', 'Beat Agahnim 1'),
|
||||
('Flute Activation Spot', 'Activated Flute')
|
||||
]
|
||||
for location_name, event_name in event_pairs:
|
||||
location = world.get_location(location_name, player)
|
||||
event = ItemFactory(event_name, player)
|
||||
world.push_item(location, event, False)
|
||||
location.event = location.locked = True
|
||||
|
||||
|
||||
# set up item pool
|
||||
additional_triforce_pieces = 0
|
||||
|
@ -375,7 +373,7 @@ def generate_itempool(world, player: int):
|
|||
|
||||
if world.goal[player] == 'icerodhunt':
|
||||
for item in dungeon_items:
|
||||
world.itempool.append(ItemFactory('Nothing', player))
|
||||
world.itempool.append(ItemFactory(GetBeemizerItem(world, player, 'Nothing'), player))
|
||||
world.push_precollected(item)
|
||||
else:
|
||||
world.itempool.extend([item for item in dungeon_items])
|
||||
|
@ -390,27 +388,14 @@ def generate_itempool(world, player: int):
|
|||
for i in range(4):
|
||||
next(adv_heart_pieces).advancement = True
|
||||
|
||||
beeweights = {0: {None: 100},
|
||||
1: {None: 75, 'trap': 25},
|
||||
2: {None: 40, 'trap': 40, 'bee': 20},
|
||||
3: {'trap': 50, 'bee': 50},
|
||||
4: {'trap': 100}}
|
||||
|
||||
def beemizer(item):
|
||||
if world.beemizer[item.player] and not item.advancement and not item.priority and not item.type:
|
||||
choice = world.random.choices(list(beeweights[world.beemizer[item.player]].keys()),
|
||||
weights=list(beeweights[world.beemizer[item.player]].values()))[0]
|
||||
return item if not choice else ItemFactory("Bee Trap", player) if choice == 'trap' else ItemFactory("Bee",
|
||||
player)
|
||||
return item
|
||||
|
||||
progressionitems = []
|
||||
nonprogressionitems = []
|
||||
for item in items:
|
||||
if item.advancement or item.priority or item.type:
|
||||
if item.advancement or item.type:
|
||||
progressionitems.append(item)
|
||||
else:
|
||||
nonprogressionitems.append(beemizer(item))
|
||||
nonprogressionitems.append(GetBeemizerItem(world, item.player, item))
|
||||
world.random.shuffle(nonprogressionitems)
|
||||
|
||||
if additional_triforce_pieces:
|
||||
|
@ -427,10 +412,10 @@ def generate_itempool(world, player: int):
|
|||
mm_medallion = world.random.choice(['Ether', 'Quake', 'Bombos'])
|
||||
else:
|
||||
mm_medallion = world.required_medallions[player][0]
|
||||
if world.required_medallions[player][0] == "random":
|
||||
if world.required_medallions[player][1] == "random":
|
||||
tr_medallion = world.random.choice(['Ether', 'Quake', 'Bombos'])
|
||||
else:
|
||||
tr_medallion = world.required_medallions[player][0]
|
||||
tr_medallion = world.required_medallions[player][1]
|
||||
world.required_medallions[player] = (mm_medallion, tr_medallion)
|
||||
|
||||
place_bosses(world, player)
|
||||
|
@ -446,89 +431,6 @@ def generate_itempool(world, player: int):
|
|||
set_up_take_anys(world, player) # depends on world.itempool to be set
|
||||
|
||||
|
||||
def shuffle_shops(world, items, player: int):
|
||||
option = world.shop_shuffle[player]
|
||||
if 'u' in option:
|
||||
progressive = world.progressive[player]
|
||||
progressive = world.random.choice([True, False]) if progressive == '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[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: Shop = None
|
||||
for shop in world.shops:
|
||||
if shop.type == ShopType.UpgradeShop and shop.region.player == player and \
|
||||
shop.region.name == "Capacity Upgrade":
|
||||
shop.clear_inventory()
|
||||
capacityshop = shop
|
||||
|
||||
if world.goal[player] != 'icerodhunt':
|
||||
for i, item in enumerate(items):
|
||||
if "Heart" not in item.name:
|
||||
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)
|
||||
if bombupgrades:
|
||||
capacityshop.add_inventory(1, 'Bomb Upgrade (+5)', 100, bombupgrades)
|
||||
if arrowupgrades:
|
||||
capacityshop.add_inventory(1, 'Arrow Upgrade (+5)', 100, arrowupgrades)
|
||||
else:
|
||||
for item in new_items:
|
||||
world.push_precollected(ItemFactory(item, player))
|
||||
|
||||
if 'p' in option or 'i' in option:
|
||||
shops = []
|
||||
upgrade_shops = []
|
||||
total_inventory = []
|
||||
for shop in world.shops:
|
||||
if shop.region.player == player:
|
||||
if shop.type == ShopType.UpgradeShop:
|
||||
upgrade_shops.append(shop)
|
||||
elif shop.type == ShopType.Shop:
|
||||
if shop.region.name == 'Potion Shop' and not 'w' in option:
|
||||
# don't modify potion shop
|
||||
pass
|
||||
else:
|
||||
shops.append(shop)
|
||||
total_inventory.extend(shop.inventory)
|
||||
|
||||
if 'p' in option:
|
||||
def price_adjust(price: int) -> int:
|
||||
# it is important that a base price of 0 always returns 0 as new price!
|
||||
adjust = 2 if price < 100 else 5
|
||||
return int((price / adjust) * (0.5 + world.random.random() * 1.5)) * adjust
|
||||
|
||||
def adjust_item(item):
|
||||
if item:
|
||||
item["price"] = price_adjust(item["price"])
|
||||
item['replacement_price'] = price_adjust(item["price"])
|
||||
|
||||
for item in total_inventory:
|
||||
adjust_item(item)
|
||||
for shop in upgrade_shops:
|
||||
for item in shop.inventory:
|
||||
adjust_item(item)
|
||||
|
||||
if 'i' in option:
|
||||
world.random.shuffle(total_inventory)
|
||||
|
||||
i = 0
|
||||
for shop in shops:
|
||||
slots = shop.slots
|
||||
shop.inventory = total_inventory[i:i + slots]
|
||||
i += slots
|
||||
|
||||
|
||||
take_any_locations = {
|
||||
'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut',
|
||||
'Fortune Teller (Light)', 'Lake Hylia Fortune Teller', 'Lumberjack House', 'Bonk Fairy (Light)',
|
||||
|
@ -639,32 +541,6 @@ def fill_prizes(world, attempts=15):
|
|||
raise FillError('Unable to place dungeon prizes')
|
||||
|
||||
|
||||
def set_up_shops(world, player: int):
|
||||
# TODO: move hard+ mode changes for shields here, utilizing the new shops
|
||||
|
||||
if world.retro[player]:
|
||||
rss = world.get_region('Red Shield Shop', player).shop
|
||||
replacement_items = [['Red Potion', 150], ['Green Potion', 75], ['Blue Potion', 200], ['Bombs (10)', 50],
|
||||
['Blue Shield', 50], ['Small Heart', 10]] # Can't just replace the single arrow with 10 arrows as retro doesn't need them.
|
||||
if world.keyshuffle[player] == "universal":
|
||||
replacement_items.append(['Small Key (Universal)', 100])
|
||||
replacement_item = world.random.choice(replacement_items)
|
||||
rss.add_inventory(2, 'Single Arrow', 80, 1, replacement_item[0], replacement_item[1])
|
||||
rss.locked = True
|
||||
|
||||
if world.keyshuffle[player] == "universal" or world.retro[player]:
|
||||
for shop in world.random.sample([s for s in world.shops if
|
||||
s.custom and not s.locked and s.type == ShopType.Shop and s.region.player == player],
|
||||
5):
|
||||
shop.locked = True
|
||||
slots = [0, 0, 1, 1, 2, 2]
|
||||
world.random.shuffle(slots)
|
||||
slots = iter(slots)
|
||||
if world.keyshuffle[player] == "universal":
|
||||
shop.add_inventory(next(slots), 'Small Key (Universal)', 100)
|
||||
if world.retro[player]:
|
||||
shop.push_inventory(next(slots), 'Single Arrow', 80)
|
||||
|
||||
def get_pool_core(world, player: int):
|
||||
progressive = world.progressive[player]
|
||||
shuffle = world.shuffle[player]
|
||||
|
|
352
Items.py
352
Items.py
|
@ -1,6 +1,19 @@
|
|||
import logging
|
||||
|
||||
|
||||
def GetBeemizerItem(world, player, item):
|
||||
item_name = item if isinstance(item, str) else item.name
|
||||
if world.beemizer[player] and item_name in trap_replaceable:
|
||||
if world.random.random() < world.beemizer[player] * 0.25:
|
||||
if world.random.random() < (0.5 + world.beemizer[player] * 0.1):
|
||||
return "Bee Trap" if isinstance(item, str) else ItemFactory("Bee Trap", player)
|
||||
else:
|
||||
return "Bee" if isinstance(item, str) else ItemFactory("Bee", player)
|
||||
else:
|
||||
return item
|
||||
else:
|
||||
return item
|
||||
|
||||
|
||||
def ItemFactory(items, player):
|
||||
from BaseClasses import Item
|
||||
|
@ -11,184 +24,183 @@ def ItemFactory(items, player):
|
|||
singleton = True
|
||||
for item in items:
|
||||
if item in item_table:
|
||||
advancement, priority, type, code, pedestal_hint, pedestal_credit, sickkid_credit, zora_credit, witch_credit, fluteboy_credit, hint_text = item_table[item]
|
||||
ret.append(Item(item, advancement, priority, type, code, pedestal_hint, pedestal_credit, sickkid_credit, zora_credit, witch_credit, fluteboy_credit, hint_text, player))
|
||||
ret.append(Item(item, *item_table[item], player))
|
||||
else:
|
||||
logging.getLogger('').warning('Unknown Item: %s', item)
|
||||
return None
|
||||
raise Exception(f"Unknown item {item}")
|
||||
|
||||
if singleton:
|
||||
return ret[0]
|
||||
return ret
|
||||
|
||||
|
||||
# Format: Name: (Advancement, Priority, Type, ItemCode, Pedestal Hint Text, Pedestal Credit Text, Sick Kid Credit Text, Zora Credit Text, Witch Credit Text, Flute Boy Credit Text, Hint Text)
|
||||
item_table = {'Bow': (True, False, None, 0x0B, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'the Bow'),
|
||||
'Progressive Bow': (True, False, None, 0x64, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),
|
||||
'Progressive Bow (Alt)': (True, False, None, 0x65, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),
|
||||
'Silver Arrows': (True, False, None, 0x58, 'Do you fancy\nsilver tipped\narrows?', 'and the ganonsbane','ganon-killing kid', 'ganon doom for sale', 'fungus for pork','archer boy shines again', 'the Silver Arrows'),
|
||||
'Silver Bow': (True, False, None, 0x3B, 'Buy 1 Silver\nget Archery\nfor free.', 'the baconmaker', 'ganon-killing kid', 'ganon doom for sale', 'fungus for pork', 'archer boy shines again', 'the Silver Bow'),
|
||||
'Book of Mudora': (True, False, None, 0x1D, 'Hylian\nfor\nDingusses.', 'and the story book', 'the scholarly kid', 'moon runes for sale', 'drugs for literacy', 'book-worm boy can read again', 'the Book'),
|
||||
'Hammer': (True, False, None, 0x09, 'stop\nhammer time!', 'and m c hammer', 'hammer-smashing kid', 'm c hammer for sale', 'stop... hammer time', 'stop, hammer time', 'the Hammer'),
|
||||
'Hookshot': (True, False, None, 0x0A, 'BOING!!!\nBOING!!!\nBOING!!!', 'and the tickle beam', 'tickle-monster kid', 'tickle beam for sale', 'witch and tickle boy', 'beam boy tickles again', 'the Hookshot'),
|
||||
'Magic Mirror': (True, False, None, 0x1A, 'Isn\'t your\nreflection so\npretty?', 'the face reflector', 'the narcissistic kid', 'your face for sale', 'trades looking-glass', 'narcissistic boy is happy again', 'the Mirror'),
|
||||
'Flute': (True, False, None, 0x14, 'Save the duck\nand fly to\nfreedom!', 'and the duck call', 'the duck-call kid', 'duck call for sale', 'duck-calls for trade', 'flute boy plays again', 'the Flute'),
|
||||
'Pegasus Boots': (True, False, None, 0x4B, 'Gotta go fast!', 'and the sprint shoes', 'the running-man kid', 'sprint shoe for sale', 'shrooms for speed', 'gotta-go-fast boy runs again', 'the Boots'),
|
||||
'Power Glove': (True, False, None, 0x1B, 'Now you can\nlift weak\nstuff!', 'and the grey mittens', 'body-building kid', 'lift glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'the Glove'),
|
||||
'Cape': (True, False, None, 0x19, 'Wear this to\nbecome\ninvisible!', 'the camouflage cape', 'red riding-hood kid', 'red hood for sale', 'hood from a hood', 'dapper boy hides again', 'the Cape'),
|
||||
'Mushroom': (True, False, None, 0x29, 'I\'m a fun guy!\n\nI\'m a funghi!', 'and the legal drugs', 'the drug-dealing kid', 'legal drugs for sale', 'shroom swap', 'shroom boy sells drugs again', 'the Mushroom'),
|
||||
'Shovel': (True, False, None, 0x13, 'Can\n You\n Dig it?', 'and the spade', 'archaeologist kid', 'dirt spade for sale', 'can you dig it', 'shovel boy digs again', 'the Shovel'),
|
||||
'Lamp': (True, False, None, 0x12, 'Baby, baby,\nbaby.\nLight my way!', 'and the flashlight', 'light-shining kid', 'flashlight for sale', 'fungus for illumination', 'illuminated boy can see again', 'the Lamp'),
|
||||
'Magic Powder': (True, False, None, 0x0D, 'you can turn\nanti-faeries\ninto faeries', 'and the magic sack', 'the sack-holding kid', 'magic sack for sale', 'the witch and assistant', 'magic boy plays marbles again', 'the Powder'),
|
||||
'Moon Pearl': (True, False, None, 0x1F, ' Bunny Link\n be\n gone!', 'and the jaw breaker', 'fortune-telling kid', 'lunar orb for sale', 'shrooms for moon rock', 'moon boy plays ball again', 'the Moon Pearl'),
|
||||
'Cane of Somaria': (True, False, None, 0x15, 'I make blocks\nto hold down\nswitches!', 'and the red blocks', 'the block-making kid', 'block stick for sale', 'block stick for trade', 'cane boy makes blocks again', 'the Red Cane'),
|
||||
'Fire Rod': (True, False, None, 0x07, 'I\'m the hot\nrod. I make\nthings burn!', 'and the flamethrower', 'fire-starting kid', 'rage rod for sale', 'fungus for rage-rod', 'firestarter boy burns again', 'the Fire Rod'),
|
||||
'Flippers': (True, False, None, 0x1E, 'fancy a swim?', 'and the toewebs', 'the swimming kid', 'finger webs for sale', 'shrooms let you swim', 'swimming boy swims again', 'the Flippers'),
|
||||
'Ice Rod': (True, False, None, 0x08, 'I\'m the cold\nrod. I make\nthings freeze!', 'and the freeze ray', 'the ice-bending kid', 'freeze ray for sale', 'fungus for ice-rod', 'ice-cube boy freezes again', 'the Ice Rod'),
|
||||
'Titans Mitts': (True, False, None, 0x1C, 'Now you can\nlift heavy\nstuff!', 'and the golden glove', 'body-building kid', 'carry glove for sale', 'fungus for bling-gloves', 'body-building boy has gold again', 'the Mitts'),
|
||||
'Bombos': (True, False, None, 0x0F, 'Burn, baby,\nburn! Fear my\nring of fire!', 'and the swirly coin', 'coin-collecting kid', 'swirly coin for sale', 'shrooms for swirly-coin', 'medallion boy melts room again', 'Bombos'),
|
||||
'Ether': (True, False, None, 0x10, 'This magic\ncoin freezes\neverything!', 'and the bolt coin', 'coin-collecting kid', 'bolt coin for sale', 'shrooms for bolt-coin', 'medallion boy sees floor again', 'Ether'),
|
||||
'Quake': (True, False, None, 0x11, 'Maxing out the\nRichter scale\nis what I do!', 'and the wavy coin', 'coin-collecting kid', 'wavy coin for sale', 'shrooms for wavy-coin', 'medallion boy shakes dirt again', 'Quake'),
|
||||
'Bottle': (True, False, None, 0x16, 'Now you can\nstore potions\nand stuff!', 'and the terrarium', 'the terrarium kid', 'terrarium for sale', 'special promotion', 'bottle boy has terrarium again', 'a bottle'),
|
||||
'Bottle (Red Potion)': (True, False, None, 0x2B, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a bottle'),
|
||||
'Bottle (Green Potion)': (True, False, None, 0x2C, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a bottle'),
|
||||
'Bottle (Blue Potion)': (True, False, None, 0x2D, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a bottle'),
|
||||
'Bottle (Fairy)': (True, False, None, 0x3D, 'Save me and I will revive you', 'and the captive', 'the tingle kid','hostage for sale', 'fairy dust and shrooms', 'bottle boy has friend again', 'a bottle'),
|
||||
'Bottle (Bee)': (True, False, None, 0x3C, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bottle'),
|
||||
'Bottle (Good Bee)': (True, False, None, 0x48, 'I will sting your foes a whole lot!', 'and the sparkle sting', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has beetor again', 'a bottle'),
|
||||
'Master Sword': (True, False, 'Sword', 0x50, 'I beat barries and pigs alike', 'and the master sword', 'sword-wielding kid', 'glow sword for sale', 'fungus for blue slasher', 'sword boy fights again', 'the Master Sword'),
|
||||
'Tempered Sword': (True, False, 'Sword', 0x02, 'I stole the\nblacksmith\'s\njob!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'sword boy fights again', 'the Tempered Sword'),
|
||||
'Fighter Sword': (True, False, 'Sword', 0x49, 'A pathetic\nsword rests\nhere!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again', 'the Small Sword'),
|
||||
'Golden Sword': (True, False, 'Sword', 0x03, 'The butter\nsword rests\nhere!', 'and the butter sword', 'sword-wielding kid', 'butter for sale', 'cap churned to butter', 'sword boy fights again', 'the Golden Sword'),
|
||||
'Progressive Sword': (True, False, 'Sword', 0x5E, 'a better copy\nof your sword\nfor your time', 'the unknown sword', 'sword-wielding kid', 'sword for sale', 'fungus for some slasher', 'sword boy fights again', 'a Sword'),
|
||||
'Progressive Glove': (True, False, None, 0x61, 'a way to lift\nheavier things', 'and the lift upgrade', 'body-building kid', 'some glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'a Glove'),
|
||||
'Green Pendant': (True, False, 'Crystal', (0x04, 0x38, 0x62, 0x00, 0x69, 0x01), None, None, None, None, None, None, None),
|
||||
'Blue Pendant': (True, False, 'Crystal', (0x02, 0x34, 0x60, 0x00, 0x69, 0x02), None, None, None, None, None, None, None),
|
||||
'Red Pendant': (True, False, 'Crystal', (0x01, 0x32, 0x60, 0x00, 0x69, 0x03), None, None, None, None, None, None, None),
|
||||
'Triforce': (True, False, None, 0x6A, '\n YOU WIN!', 'and the triforce', 'victorious kid', 'victory for sale', 'fungus for the win', 'greedy boy wins game again', 'the Triforce'),
|
||||
'Power Star': (True, False, None, 0x6B, 'a small victory', 'and the power star', 'star-struck kid', 'star for sale', 'see stars with shroom', 'mario powers up again', 'a Power Star'),
|
||||
'Triforce Piece': (True, False, None, 0x6C, 'a small victory', 'and the thirdforce', 'triangular kid', 'triangle for sale', 'fungus for triangle', 'wise boy has triangle again', 'a Triforce Piece'),
|
||||
'Crystal 1': (True, False, 'Crystal', (0x02, 0x34, 0x64, 0x40, 0x7F, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 2': (True, False, 'Crystal', (0x10, 0x34, 0x64, 0x40, 0x79, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 3': (True, False, 'Crystal', (0x40, 0x34, 0x64, 0x40, 0x6C, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 4': (True, False, 'Crystal', (0x20, 0x34, 0x64, 0x40, 0x6D, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 5': (True, False, 'Crystal', (0x04, 0x32, 0x64, 0x40, 0x6E, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 6': (True, False, 'Crystal', (0x01, 0x32, 0x64, 0x40, 0x6F, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 7': (True, False, 'Crystal', (0x08, 0x34, 0x64, 0x40, 0x7C, 0x06), None, None, None, None, None, None, None),
|
||||
'Single Arrow': (False, False, 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)': (False, False, 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)': (False, False, 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)': (False, False, 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'),
|
||||
'Single Bomb': (False, False, 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)': (False, False, 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)': (False, False, 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)': (False, False, 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)': (False, False, 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'),
|
||||
'Blue Mail': (False, True, 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': (False, True, 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': (False, True, 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'),
|
||||
'Blue Boomerang': (True, False, None, 0x0C, 'No matter what\nyou do, blue\nreturns to you', 'and the bluemarang', 'the bat-throwing kid', 'bent stick for sale', 'fungus for puma-stick', 'throwing boy plays fetch again', 'the Blue Boomerang'),
|
||||
'Red Boomerang': (True, False, None, 0x2A, 'No matter what\nyou do, red\nreturns to you', 'and the badmarang', 'the bat-throwing kid', 'air foil for sale', 'fungus for return-stick', 'magical boy plays fetch again', 'the Red Boomerang'),
|
||||
'Blue Shield': (False, True, None, 0x04, 'Now you can\ndefend against\npebbles!', 'and the stone blocker', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'the Blue Shield'),
|
||||
'Red Shield': (False, True, None, 0x05, 'Now you can\ndefend against\nfireballs!', 'and the shot blocker', 'shield-wielding kid', 'fire shield for sale', 'fungus for fire shield', 'shield boy defends again', 'the Red Shield'),
|
||||
'Mirror Shield': (True, False, None, 0x06, 'Now you can\ndefend against\nlasers!', 'and the laser blocker', 'shield-wielding kid', 'face shield for sale', 'fungus for face shield', 'shield boy defends again', 'the Mirror Shield'),
|
||||
'Progressive Shield': (True, False, None, 0x5F, 'have a better\nblocker in\nfront of you', 'and the new shield', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a shield'),
|
||||
'Bug Catching Net': (True, False, None, 0x21, 'Let\'s catch\nsome bees and\nfaeries!', 'and the bee catcher', 'the bug-catching kid', 'stick web for sale', 'fungus for butterflies', 'wrong boy catches bees again', 'the Bug Net'),
|
||||
'Cane of Byrna': (True, False, None, 0x18, 'Use this to\nbecome\ninvincible!', 'and the bad cane', 'the spark-making kid', 'spark stick for sale', 'spark-stick for trade', 'cane boy encircles again', 'the Blue Cane'),
|
||||
'Boss Heart Container': (False, False, None, 0x3E, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'),
|
||||
'Sanctuary Heart Container': (False, False, None, 0x3F, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'),
|
||||
'Piece of Heart': (False, False, None, 0x17, 'Just a little\npiece of love!', 'and the broken heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart piece'),
|
||||
'Rupee (1)': (False, False, None, 0x34, 'Just pocket\nchange. Move\nright along.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a green rupee'),
|
||||
'Rupees (5)': (False, False, None, 0x35, 'Just pocket\nchange. Move\nright along.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a blue rupee'),
|
||||
'Rupees (20)': (False, False, None, 0x36, 'Just couch\ncash. Move\nright along.', 'and the couch cash', 'the piggy-bank kid', 'life lesson for sale', 'the witch buying drugs', 'destitute boy has lunch again', 'a red rupee'),
|
||||
'Rupees (50)': (False, False, None, 0x41, 'A rupee pile!\nOkay?', 'and the rupee pile', 'the well-off kid', 'life lesson for sale', 'buying okay drugs', 'destitute boy has dinner again', 'fifty rupees'),
|
||||
'Rupees (100)': (False, False, None, 0x40, 'A rupee stash!\nHell yeah!', 'and the rupee stash', 'the kind-of-rich kid', 'life lesson for sale', 'buying good drugs', 'affluent boy goes drinking again', 'one hundred rupees'),
|
||||
'Rupees (300)': (False, False, None, 0x46, 'A rupee hoard!\nHell yeah!', 'and the rupee hoard', 'the really-rich kid', 'life lesson for sale', 'buying the best drugs', 'fat-cat boy is rich again', 'three hundred rupees'),
|
||||
'Rupoor': (False, False, None, 0x59, 'a debt collector', 'and the toll-booth', 'the toll-booth kid', 'double loss for sale', 'witch stole your rupees', 'affluent boy steals rupees', 'a rupoor'),
|
||||
'Red Clock': (False, True, None, 0x5B, 'a waste of time', 'the ruby clock', 'the ruby-time kid', 'red time for sale', 'for ruby time', 'moment boy travels time again', 'a red clock'),
|
||||
'Blue Clock': (False, True, None, 0x5C, 'a bit of time', 'the sapphire clock', 'sapphire-time kid', 'blue time for sale', 'for sapphire time', 'moment boy time travels again', 'a blue clock'),
|
||||
'Green Clock': (False, True, None, 0x5D, 'a lot of time', 'the emerald clock', 'the emerald-time kid', 'green time for sale', 'for emerald time', 'moment boy adjusts time again', 'a red clock'),
|
||||
'Single RNG': (False, True, None, 0x62, 'something you don\'t yet have', None, None, None, None, 'unknown boy somethings again', 'a new mystery'),
|
||||
'Multi RNG': (False, True, None, 0x63, 'something you may already have', None, None, None, None, 'unknown boy somethings again', 'a total mystery'),
|
||||
'Magic Upgrade (1/2)': (True, False, None, 0x4E, 'Your magic\npower has been\ndoubled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'Half Magic'), # can be required to beat mothula in an open seed in very very rare circumstance
|
||||
'Magic Upgrade (1/4)': (True, False, None, 0x4F, 'Your magic\npower has been\nquadrupled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'Quarter Magic'), # can be required to beat mothula in an open seed in very very rare circumstance
|
||||
'Small Key (Eastern Palace)': (False, False, 'SmallKey', 0xA2, 'A small key to Armos Knights', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Eastern Palace'),
|
||||
'Big Key (Eastern Palace)': (False, False, 'BigKey', 0x9D, 'A big key to Armos Knights', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Eastern Palace'),
|
||||
'Compass (Eastern Palace)': (False, True, 'Compass', 0x8D, 'Now you can find the Armos Knights!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Eastern Palace'),
|
||||
'Map (Eastern Palace)': (False, True, 'Map', 0x7D, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Eastern Palace'),
|
||||
'Small Key (Desert Palace)': (False, False, 'SmallKey', 0xA3, 'A small key to the desert', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Desert Palace'),
|
||||
'Big Key (Desert Palace)': (False, False, 'BigKey', 0x9C, 'A big key to the desert', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Desert Palace'),
|
||||
'Compass (Desert Palace)': (False, True, 'Compass', 0x8C, 'Now you can find Lanmolas!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Desert Palace'),
|
||||
'Map (Desert Palace)': (False, True, 'Map', 0x7C, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Desert Palace'),
|
||||
'Small Key (Tower of Hera)': (False, False, 'SmallKey', 0xAA, 'A small key to Hera', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Tower of Hera'),
|
||||
'Big Key (Tower of Hera)': (False, False, 'BigKey', 0x95, 'A big key to Hera', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Tower of Hera'),
|
||||
'Compass (Tower of Hera)': (False, True, 'Compass', 0x85, 'Now you can find Moldorm!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Tower of Hera'),
|
||||
'Map (Tower of Hera)': (False, True, 'Map', 0x75, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Tower of Hera'),
|
||||
'Small Key (Hyrule Castle)': (False, False, 'SmallKey', 0xA0, 'A small key to the castle', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Hyrule Castle'),
|
||||
'Big Key (Hyrule Castle)': (False, False, 'BigKey', 0x9F, 'A big key to the castle', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Hyrule Castle'),
|
||||
'Compass (Hyrule Castle)': (False, True, 'Compass', 0x8F, 'Now you can find no boss!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Hyrule Castle'),
|
||||
'Map (Hyrule Castle)': (False, True, 'Map', 0x7F, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Hyrule Castle'),
|
||||
'Small Key (Agahnims Tower)': (False, False, 'SmallKey', 0xA4, 'A small key to Agahnim', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Castle Tower'),
|
||||
# Format: Name: (Advancement, Type, ItemCode, Pedestal Hint Text, Pedestal Credit Text, Sick Kid Credit Text, Zora Credit Text, Witch Credit Text, Flute Boy Credit Text, Hint Text)
|
||||
item_table = {'Bow': (True, None, 0x0B, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'the Bow'),
|
||||
'Progressive Bow': (True, None, 0x64, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),
|
||||
'Progressive Bow (Alt)': (True, None, 0x65, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),
|
||||
'Silver Arrows': (True, None, 0x58, 'Do you fancy\nsilver tipped\narrows?', 'and the ganonsbane','ganon-killing kid', 'ganon doom for sale', 'fungus for pork','archer boy shines again', 'the Silver Arrows'),
|
||||
'Silver Bow': (True, None, 0x3B, 'Buy 1 Silver\nget Archery\nfor free.', 'the baconmaker', 'ganon-killing kid', 'ganon doom for sale', 'fungus for pork', 'archer boy shines again', 'the Silver Bow'),
|
||||
'Book of Mudora': (True, None, 0x1D, 'Hylian\nfor\nDingusses.', 'and the story book', 'the scholarly kid', 'moon runes for sale', 'drugs for literacy', 'book-worm boy can read again', 'the Book'),
|
||||
'Hammer': (True, None, 0x09, 'stop\nhammer time!', 'and m c hammer', 'hammer-smashing kid', 'm c hammer for sale', 'stop... hammer time', 'stop, hammer time', 'the Hammer'),
|
||||
'Hookshot': (True, None, 0x0A, 'BOING!!!\nBOING!!!\nBOING!!!', 'and the tickle beam', 'tickle-monster kid', 'tickle beam for sale', 'witch and tickle boy', 'beam boy tickles again', 'the Hookshot'),
|
||||
'Magic Mirror': (True, None, 0x1A, 'Isn\'t your\nreflection so\npretty?', 'the face reflector', 'the narcissistic kid', 'your face for sale', 'trades looking-glass', 'narcissistic boy is happy again', 'the Mirror'),
|
||||
'Flute': (True, None, 0x14, 'Save the duck\nand fly to\nfreedom!', 'and the duck call', 'the duck-call kid', 'duck call for sale', 'duck-calls for trade', 'flute boy plays again', 'the Flute'),
|
||||
'Pegasus Boots': (True, None, 0x4B, 'Gotta go fast!', 'and the sprint shoes', 'the running-man kid', 'sprint shoe for sale', 'shrooms for speed', 'gotta-go-fast boy runs again', 'the Boots'),
|
||||
'Power Glove': (True, None, 0x1B, 'Now you can\nlift weak\nstuff!', 'and the grey mittens', 'body-building kid', 'lift glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'the Glove'),
|
||||
'Cape': (True, None, 0x19, 'Wear this to\nbecome\ninvisible!', 'the camouflage cape', 'red riding-hood kid', 'red hood for sale', 'hood from a hood', 'dapper boy hides again', 'the Cape'),
|
||||
'Mushroom': (True, None, 0x29, 'I\'m a fun guy!\n\nI\'m a funghi!', 'and the legal drugs', 'the drug-dealing kid', 'legal drugs for sale', 'shroom swap', 'shroom boy sells drugs again', 'the Mushroom'),
|
||||
'Shovel': (True, None, 0x13, 'Can\n You\n Dig it?', 'and the spade', 'archaeologist kid', 'dirt spade for sale', 'can you dig it', 'shovel boy digs again', 'the Shovel'),
|
||||
'Lamp': (True, None, 0x12, 'Baby, baby,\nbaby.\nLight my way!', 'and the flashlight', 'light-shining kid', 'flashlight for sale', 'fungus for illumination', 'illuminated boy can see again', 'the Lamp'),
|
||||
'Magic Powder': (True, None, 0x0D, 'you can turn\nanti-faeries\ninto faeries', 'and the magic sack', 'the sack-holding kid', 'magic sack for sale', 'the witch and assistant', 'magic boy plays marbles again', 'the Powder'),
|
||||
'Moon Pearl': (True, None, 0x1F, ' Bunny Link\n be\n gone!', 'and the jaw breaker', 'fortune-telling kid', 'lunar orb for sale', 'shrooms for moon rock', 'moon boy plays ball again', 'the Moon Pearl'),
|
||||
'Cane of Somaria': (True, None, 0x15, 'I make blocks\nto hold down\nswitches!', 'and the red blocks', 'the block-making kid', 'block stick for sale', 'block stick for trade', 'cane boy makes blocks again', 'the Red Cane'),
|
||||
'Fire Rod': (True, None, 0x07, 'I\'m the hot\nrod. I make\nthings burn!', 'and the flamethrower', 'fire-starting kid', 'rage rod for sale', 'fungus for rage-rod', 'firestarter boy burns again', 'the Fire Rod'),
|
||||
'Flippers': (True, None, 0x1E, 'fancy a swim?', 'and the toewebs', 'the swimming kid', 'finger webs for sale', 'shrooms let you swim', 'swimming boy swims again', 'the Flippers'),
|
||||
'Ice Rod': (True, None, 0x08, 'I\'m the cold\nrod. I make\nthings freeze!', 'and the freeze ray', 'the ice-bending kid', 'freeze ray for sale', 'fungus for ice-rod', 'ice-cube boy freezes again', 'the Ice Rod'),
|
||||
'Titans Mitts': (True, None, 0x1C, 'Now you can\nlift heavy\nstuff!', 'and the golden glove', 'body-building kid', 'carry glove for sale', 'fungus for bling-gloves', 'body-building boy has gold again', 'the Mitts'),
|
||||
'Bombos': (True, None, 0x0F, 'Burn, baby,\nburn! Fear my\nring of fire!', 'and the swirly coin', 'coin-collecting kid', 'swirly coin for sale', 'shrooms for swirly-coin', 'medallion boy melts room again', 'Bombos'),
|
||||
'Ether': (True, None, 0x10, 'This magic\ncoin freezes\neverything!', 'and the bolt coin', 'coin-collecting kid', 'bolt coin for sale', 'shrooms for bolt-coin', 'medallion boy sees floor again', 'Ether'),
|
||||
'Quake': (True, None, 0x11, 'Maxing out the\nRichter scale\nis what I do!', 'and the wavy coin', 'coin-collecting kid', 'wavy coin for sale', 'shrooms for wavy-coin', 'medallion boy shakes dirt again', 'Quake'),
|
||||
'Bottle': (True, None, 0x16, 'Now you can\nstore potions\nand stuff!', 'and the terrarium', 'the terrarium kid', 'terrarium for sale', 'special promotion', 'bottle boy has terrarium again', 'a bottle'),
|
||||
'Bottle (Red Potion)': (True, None, 0x2B, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a bottle'),
|
||||
'Bottle (Green Potion)': (True, None, 0x2C, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a bottle'),
|
||||
'Bottle (Blue Potion)': (True, None, 0x2D, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a bottle'),
|
||||
'Bottle (Fairy)': (True, None, 0x3D, 'Save me and I will revive you', 'and the captive', 'the tingle kid','hostage for sale', 'fairy dust and shrooms', 'bottle boy has friend again', 'a bottle'),
|
||||
'Bottle (Bee)': (True, None, 0x3C, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bottle'),
|
||||
'Bottle (Good Bee)': (True, None, 0x48, 'I will sting your foes a whole lot!', 'and the sparkle sting', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has beetor again', 'a bottle'),
|
||||
'Master Sword': (True, 'Sword', 0x50, 'I beat barries and pigs alike', 'and the master sword', 'sword-wielding kid', 'glow sword for sale', 'fungus for blue slasher', 'sword boy fights again', 'the Master Sword'),
|
||||
'Tempered Sword': (True, 'Sword', 0x02, 'I stole the\nblacksmith\'s\njob!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'sword boy fights again', 'the Tempered Sword'),
|
||||
'Fighter Sword': (True, 'Sword', 0x49, 'A pathetic\nsword rests\nhere!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again', 'the Small Sword'),
|
||||
'Golden Sword': (True, 'Sword', 0x03, 'The butter\nsword rests\nhere!', 'and the butter sword', 'sword-wielding kid', 'butter for sale', 'cap churned to butter', 'sword boy fights again', 'the Golden Sword'),
|
||||
'Progressive Sword': (True, 'Sword', 0x5E, 'a better copy\nof your sword\nfor your time', 'the unknown sword', 'sword-wielding kid', 'sword for sale', 'fungus for some slasher', 'sword boy fights again', 'a Sword'),
|
||||
'Progressive Glove': (True, None, 0x61, 'a way to lift\nheavier things', 'and the lift upgrade', 'body-building kid', 'some glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'a Glove'),
|
||||
'Green Pendant': (True, 'Crystal', (0x04, 0x38, 0x62, 0x00, 0x69, 0x01), None, None, None, None, None, None, None),
|
||||
'Blue Pendant': (True, 'Crystal', (0x02, 0x34, 0x60, 0x00, 0x69, 0x02), None, None, None, None, None, None, None),
|
||||
'Red Pendant': (True, 'Crystal', (0x01, 0x32, 0x60, 0x00, 0x69, 0x03), None, None, None, None, None, None, None),
|
||||
'Triforce': (True, None, 0x6A, '\n YOU WIN!', 'and the triforce', 'victorious kid', 'victory for sale', 'fungus for the win', 'greedy boy wins game again', 'the Triforce'),
|
||||
'Power Star': (True, None, 0x6B, 'a small victory', 'and the power star', 'star-struck kid', 'star for sale', 'see stars with shroom', 'mario powers up again', 'a Power Star'),
|
||||
'Triforce Piece': (True, None, 0x6C, 'a small victory', 'and the thirdforce', 'triangular kid', 'triangle for sale', 'fungus for triangle', 'wise boy has triangle again', 'a Triforce Piece'),
|
||||
'Crystal 1': (True, 'Crystal', (0x02, 0x34, 0x64, 0x40, 0x7F, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 2': (True, 'Crystal', (0x10, 0x34, 0x64, 0x40, 0x79, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 3': (True, 'Crystal', (0x40, 0x34, 0x64, 0x40, 0x6C, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 4': (True, 'Crystal', (0x20, 0x34, 0x64, 0x40, 0x6D, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 5': (True, 'Crystal', (0x04, 0x32, 0x64, 0x40, 0x6E, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 6': (True, 'Crystal', (0x01, 0x32, 0x64, 0x40, 0x6F, 0x06), None, None, None, None, None, None, None),
|
||||
'Crystal 7': (True, 'Crystal', (0x08, 0x34, 0x64, 0x40, 0x7C, 0x06), None, None, None, None, None, None, None),
|
||||
'Single Arrow': (False, 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)': (False, 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)': (False, 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)': (False, 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'),
|
||||
'Single Bomb': (False, 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)': (False, 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)': (False, 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)': (False, 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)': (False, 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'),
|
||||
'Blue Mail': (False, 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': (False, 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': (False, 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'),
|
||||
'Blue Boomerang': (True, None, 0x0C, 'No matter what\nyou do, blue\nreturns to you', 'and the bluemarang', 'the bat-throwing kid', 'bent stick for sale', 'fungus for puma-stick', 'throwing boy plays fetch again', 'the Blue Boomerang'),
|
||||
'Red Boomerang': (True, None, 0x2A, 'No matter what\nyou do, red\nreturns to you', 'and the badmarang', 'the bat-throwing kid', 'air foil for sale', 'fungus for return-stick', 'magical boy plays fetch again', 'the Red Boomerang'),
|
||||
'Blue Shield': (False, None, 0x04, 'Now you can\ndefend against\npebbles!', 'and the stone blocker', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'the Blue Shield'),
|
||||
'Red Shield': (False, None, 0x05, 'Now you can\ndefend against\nfireballs!', 'and the shot blocker', 'shield-wielding kid', 'fire shield for sale', 'fungus for fire shield', 'shield boy defends again', 'the Red Shield'),
|
||||
'Mirror Shield': (True, None, 0x06, 'Now you can\ndefend against\nlasers!', 'and the laser blocker', 'shield-wielding kid', 'face shield for sale', 'fungus for face shield', 'shield boy defends again', 'the Mirror Shield'),
|
||||
'Progressive Shield': (True, None, 0x5F, 'have a better\nblocker in\nfront of you', 'and the new shield', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a shield'),
|
||||
'Bug Catching Net': (True, None, 0x21, 'Let\'s catch\nsome bees and\nfaeries!', 'and the bee catcher', 'the bug-catching kid', 'stick web for sale', 'fungus for butterflies', 'wrong boy catches bees again', 'the Bug Net'),
|
||||
'Cane of Byrna': (True, None, 0x18, 'Use this to\nbecome\ninvincible!', 'and the bad cane', 'the spark-making kid', 'spark stick for sale', 'spark-stick for trade', 'cane boy encircles again', 'the Blue Cane'),
|
||||
'Boss Heart Container': (False, None, 0x3E, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'),
|
||||
'Sanctuary Heart Container': (False, None, 0x3F, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'),
|
||||
'Piece of Heart': (False, None, 0x17, 'Just a little\npiece of love!', 'and the broken heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart piece'),
|
||||
'Rupee (1)': (False, None, 0x34, 'Just pocket\nchange. Move\nright along.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a green rupee'),
|
||||
'Rupees (5)': (False, None, 0x35, 'Just pocket\nchange. Move\nright along.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a blue rupee'),
|
||||
'Rupees (20)': (False, None, 0x36, 'Just couch\ncash. Move\nright along.', 'and the couch cash', 'the piggy-bank kid', 'life lesson for sale', 'the witch buying drugs', 'destitute boy has lunch again', 'a red rupee'),
|
||||
'Rupees (50)': (False, None, 0x41, 'A rupee pile!\nOkay?', 'and the rupee pile', 'the well-off kid', 'life lesson for sale', 'buying okay drugs', 'destitute boy has dinner again', 'fifty rupees'),
|
||||
'Rupees (100)': (False, None, 0x40, 'A rupee stash!\nHell yeah!', 'and the rupee stash', 'the kind-of-rich kid', 'life lesson for sale', 'buying good drugs', 'affluent boy goes drinking again', 'one hundred rupees'),
|
||||
'Rupees (300)': (False, None, 0x46, 'A rupee hoard!\nHell yeah!', 'and the rupee hoard', 'the really-rich kid', 'life lesson for sale', 'buying the best drugs', 'fat-cat boy is rich again', 'three hundred rupees'),
|
||||
'Rupoor': (False, None, 0x59, 'a debt collector', 'and the toll-booth', 'the toll-booth kid', 'double loss for sale', 'witch stole your rupees', 'affluent boy steals rupees', 'a rupoor'),
|
||||
'Red Clock': (False, None, 0x5B, 'a waste of time', 'the ruby clock', 'the ruby-time kid', 'red time for sale', 'for ruby time', 'moment boy travels time again', 'a red clock'),
|
||||
'Blue Clock': (False, None, 0x5C, 'a bit of time', 'the sapphire clock', 'sapphire-time kid', 'blue time for sale', 'for sapphire time', 'moment boy time travels again', 'a blue clock'),
|
||||
'Green Clock': (False, None, 0x5D, 'a lot of time', 'the emerald clock', 'the emerald-time kid', 'green time for sale', 'for emerald time', 'moment boy adjusts time again', 'a red clock'),
|
||||
'Single RNG': (False, None, 0x62, 'something you don\'t yet have', None, None, None, None, 'unknown boy somethings again', 'a new mystery'),
|
||||
'Multi RNG': (False, None, 0x63, 'something you may already have', None, None, None, None, 'unknown boy somethings again', 'a total mystery'),
|
||||
'Magic Upgrade (1/2)': (True, None, 0x4E, 'Your magic\npower has been\ndoubled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'Half Magic'), # can be required to beat mothula in an open seed in very very rare circumstance
|
||||
'Magic Upgrade (1/4)': (True, None, 0x4F, 'Your magic\npower has been\nquadrupled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'Quarter Magic'), # can be required to beat mothula in an open seed in very very rare circumstance
|
||||
'Small Key (Eastern Palace)': (False, 'SmallKey', 0xA2, 'A small key to Armos Knights', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Eastern Palace'),
|
||||
'Big Key (Eastern Palace)': (False, 'BigKey', 0x9D, 'A big key to Armos Knights', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Eastern Palace'),
|
||||
'Compass (Eastern Palace)': (False, 'Compass', 0x8D, 'Now you can find the Armos Knights!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Eastern Palace'),
|
||||
'Map (Eastern Palace)': (False, 'Map', 0x7D, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Eastern Palace'),
|
||||
'Small Key (Desert Palace)': (False, 'SmallKey', 0xA3, 'A small key to the desert', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Desert Palace'),
|
||||
'Big Key (Desert Palace)': (False, 'BigKey', 0x9C, 'A big key to the desert', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Desert Palace'),
|
||||
'Compass (Desert Palace)': (False, 'Compass', 0x8C, 'Now you can find Lanmolas!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Desert Palace'),
|
||||
'Map (Desert Palace)': (False, 'Map', 0x7C, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Desert Palace'),
|
||||
'Small Key (Tower of Hera)': (False, 'SmallKey', 0xAA, 'A small key to Hera', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Tower of Hera'),
|
||||
'Big Key (Tower of Hera)': (False, 'BigKey', 0x95, 'A big key to Hera', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Tower of Hera'),
|
||||
'Compass (Tower of Hera)': (False, 'Compass', 0x85, 'Now you can find Moldorm!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Tower of Hera'),
|
||||
'Map (Tower of Hera)': (False, 'Map', 0x75, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Tower of Hera'),
|
||||
'Small Key (Hyrule Castle)': (False, 'SmallKey', 0xA0, 'A small key to the castle', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Hyrule Castle'),
|
||||
'Big Key (Hyrule Castle)': (False, 'BigKey', 0x9F, 'A big key to the castle', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Hyrule Castle'),
|
||||
'Compass (Hyrule Castle)': (False, 'Compass', 0x8F, 'Now you can find no boss!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Hyrule Castle'),
|
||||
'Map (Hyrule Castle)': (False, 'Map', 0x7F, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Hyrule Castle'),
|
||||
'Small Key (Agahnims Tower)': (False, 'SmallKey', 0xA4, 'A small key to Agahnim', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Castle Tower'),
|
||||
# doors-specific items, baserom will not be able to understand these
|
||||
'Big Key (Agahnims Tower)': (False, False, 'BigKey', 0x9B, 'A big key to Agahnim', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Castle Tower'),
|
||||
'Compass (Agahnims Tower)': (False, True, 'Compass', 0x8B, 'Now you can find Aga1!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a compass to Castle Tower'),
|
||||
'Map (Agahnims Tower)': (False, True, 'Map', 0x7B, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Castle Tower'),
|
||||
'Big Key (Agahnims Tower)': (False, 'BigKey', 0x9B, 'A big key to Agahnim', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Castle Tower'),
|
||||
'Compass (Agahnims Tower)': (False, 'Compass', 0x8B, 'Now you can find Aga1!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a compass to Castle Tower'),
|
||||
'Map (Agahnims Tower)': (False, 'Map', 0x7B, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Castle Tower'),
|
||||
# end of doors-specific items
|
||||
'Small Key (Palace of Darkness)': (False, False, 'SmallKey', 0xA6, 'A small key to darkness', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Palace of Darkness'),
|
||||
'Big Key (Palace of Darkness)': (False, False, 'BigKey', 0x99, 'A big key to darkness', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Palace of Darkness'),
|
||||
'Compass (Palace of Darkness)': (False, True, 'Compass', 0x89, 'Now you can find Helmasaur King!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Palace of Darkness'),
|
||||
'Map (Palace of Darkness)': (False, True, 'Map', 0x79, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Palace of Darkness'),
|
||||
'Small Key (Thieves Town)': (False, False, 'SmallKey', 0xAB, 'A small key to thievery', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Thieves\' Town'),
|
||||
'Big Key (Thieves Town)': (False, False, 'BigKey', 0x94, 'A big key to thievery', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Thieves\' Town'),
|
||||
'Compass (Thieves Town)': (False, True, 'Compass', 0x84, 'Now you can find Blind!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Thieves\' Town'),
|
||||
'Map (Thieves Town)': (False, True, 'Map', 0x74, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Thieves\' Town'),
|
||||
'Small Key (Skull Woods)': (False, False, 'SmallKey', 0xA8, 'A small key to the woods', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Skull Woods'),
|
||||
'Big Key (Skull Woods)': (False, False, 'BigKey', 0x97, 'A big key to the woods', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Skull Woods'),
|
||||
'Compass (Skull Woods)': (False, True, 'Compass', 0x87, 'Now you can find Mothula!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Skull Woods'),
|
||||
'Map (Skull Woods)': (False, True, 'Map', 0x77, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Skull Woods'),
|
||||
'Small Key (Swamp Palace)': (False, False, 'SmallKey', 0xA5, 'A small key to the swamp', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Swamp Palace'),
|
||||
'Big Key (Swamp Palace)': (False, False, 'BigKey', 0x9A, 'A big key to the swamp', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Swamp Palace'),
|
||||
'Compass (Swamp Palace)': (False, True, 'Compass', 0x8A, 'Now you can find Arrghus!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Swamp Palace'),
|
||||
'Map (Swamp Palace)': (False, True, 'Map', 0x7A, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Swamp Palace'),
|
||||
'Small Key (Ice Palace)': (False, False, 'SmallKey', 0xA9, 'A small key to the iceberg', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Ice Palace'),
|
||||
'Big Key (Ice Palace)': (False, False, 'BigKey', 0x96, 'A big key to the iceberg', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Ice Palace'),
|
||||
'Compass (Ice Palace)': (False, True, 'Compass', 0x86, 'Now you can find Kholdstare!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Ice Palace'),
|
||||
'Map (Ice Palace)': (False, True, 'Map', 0x76, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Ice Palace'),
|
||||
'Small Key (Misery Mire)': (False, False, 'SmallKey', 0xA7, 'A small key to the mire', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Misery Mire'),
|
||||
'Big Key (Misery Mire)': (False, False, 'BigKey', 0x98, 'A big key to the mire', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Misery Mire'),
|
||||
'Compass (Misery Mire)': (False, True, 'Compass', 0x88, 'Now you can find Vitreous!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Misery Mire'),
|
||||
'Map (Misery Mire)': (False, True, 'Map', 0x78, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Misery Mire'),
|
||||
'Small Key (Turtle Rock)': (False, False, 'SmallKey', 0xAC, 'A small key to the pipe maze', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Turtle Rock'),
|
||||
'Big Key (Turtle Rock)': (False, False, 'BigKey', 0x93, 'A big key to the pipe maze', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Turtle Rock'),
|
||||
'Compass (Turtle Rock)': (False, True, 'Compass', 0x83, 'Now you can find Trinexx!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Turtle Rock'),
|
||||
'Map (Turtle Rock)': (False, True, 'Map', 0x73, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Turtle Rock'),
|
||||
'Small Key (Ganons Tower)': (False, False, 'SmallKey', 0xAD, 'A small key to the evil tower', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Ganon\'s Tower'),
|
||||
'Big Key (Ganons Tower)': (False, False, 'BigKey', 0x92, 'A big key to the evil tower', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Ganon\'s Tower'),
|
||||
'Compass (Ganons Tower)': (False, True, 'Compass', 0x82, 'Now you can find Agahnim!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Ganon\'s Tower'),
|
||||
'Map (Ganons Tower)': (False, True, 'Map', 0x72, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Ganon\'s Tower'),
|
||||
'Small Key (Universal)': (False, True, None, 0xAF, 'A small key for any door', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key'),
|
||||
'Nothing': (False, False, None, 0x5A, 'Some Hot Air', 'and the Nothing', 'the zen kid', 'outright theft', 'shroom theft', 'empty boy is bored again', 'nothing'),
|
||||
'Bee Trap': (False, False, None, 0xB0, 'We will sting your face a whole lot!', 'and the sting buddies', 'the beekeeper kid', 'insects for sale', 'shroom pollenation', 'bottle boy has mad bees again', 'Friendship'),
|
||||
'Faerie': (False, False, None, 0xB1, 'Save me and I will revive you', 'and the captive', 'the tingle kid','hostage for sale', 'fairy dust and shrooms', 'bottle boy has friend again', 'a faerie'),
|
||||
'Good Bee': (False, False, None, 0xB2, 'Save me and I will sting you (sometimes)', 'and the captive', 'the tingle kid','hostage for sale', 'good dust and shrooms', 'bottle boy has friend again', 'a bee'),
|
||||
'Magic Jar': (False, False, None, 0xB3, '', '', '','', '', '', ''),
|
||||
'Apple': (False, False, None, 0xB4, '', '', '','', '', '', ''),
|
||||
# 'Hint': (False, False, None, 0xB5, '', '', '','', '', '', ''),
|
||||
# 'Bomb Trap': (False, False, None, 0xB6, '', '', '','', '', '', ''),
|
||||
'Red Potion': (False, False, None, 0x2E, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a red potion'),
|
||||
'Green Potion': (False, False, None, 0x2F, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a green potion'),
|
||||
'Blue Potion': (False, False, None, 0x30, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a blue potion'),
|
||||
'Bee': (False, False, None, 0x0E, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bee'),
|
||||
'Small Heart': (False, False, None, 0x42, 'Just a little\npiece of love!', 'and the heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart'),
|
||||
'Beat Agahnim 1': (True, False, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Beat Agahnim 2': (True, False, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Get Frog': (True, False, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Return Smith': (True, False, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Pick Up Purple Chest': (True, False, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Open Floodgate': (True, False, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Small Key (Palace of Darkness)': (False, 'SmallKey', 0xA6, 'A small key to darkness', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Palace of Darkness'),
|
||||
'Big Key (Palace of Darkness)': (False, 'BigKey', 0x99, 'A big key to darkness', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Palace of Darkness'),
|
||||
'Compass (Palace of Darkness)': (False, 'Compass', 0x89, 'Now you can find Helmasaur King!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Palace of Darkness'),
|
||||
'Map (Palace of Darkness)': (False, 'Map', 0x79, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Palace of Darkness'),
|
||||
'Small Key (Thieves Town)': (False, 'SmallKey', 0xAB, 'A small key to thievery', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Thieves\' Town'),
|
||||
'Big Key (Thieves Town)': (False, 'BigKey', 0x94, 'A big key to thievery', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Thieves\' Town'),
|
||||
'Compass (Thieves Town)': (False, 'Compass', 0x84, 'Now you can find Blind!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Thieves\' Town'),
|
||||
'Map (Thieves Town)': (False, 'Map', 0x74, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Thieves\' Town'),
|
||||
'Small Key (Skull Woods)': (False, 'SmallKey', 0xA8, 'A small key to the woods', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Skull Woods'),
|
||||
'Big Key (Skull Woods)': (False, 'BigKey', 0x97, 'A big key to the woods', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Skull Woods'),
|
||||
'Compass (Skull Woods)': (False, 'Compass', 0x87, 'Now you can find Mothula!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Skull Woods'),
|
||||
'Map (Skull Woods)': (False, 'Map', 0x77, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Skull Woods'),
|
||||
'Small Key (Swamp Palace)': (False, 'SmallKey', 0xA5, 'A small key to the swamp', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Swamp Palace'),
|
||||
'Big Key (Swamp Palace)': (False, 'BigKey', 0x9A, 'A big key to the swamp', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Swamp Palace'),
|
||||
'Compass (Swamp Palace)': (False, 'Compass', 0x8A, 'Now you can find Arrghus!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Swamp Palace'),
|
||||
'Map (Swamp Palace)': (False, 'Map', 0x7A, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Swamp Palace'),
|
||||
'Small Key (Ice Palace)': (False, 'SmallKey', 0xA9, 'A small key to the iceberg', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Ice Palace'),
|
||||
'Big Key (Ice Palace)': (False, 'BigKey', 0x96, 'A big key to the iceberg', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Ice Palace'),
|
||||
'Compass (Ice Palace)': (False, 'Compass', 0x86, 'Now you can find Kholdstare!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Ice Palace'),
|
||||
'Map (Ice Palace)': (False, 'Map', 0x76, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Ice Palace'),
|
||||
'Small Key (Misery Mire)': (False, 'SmallKey', 0xA7, 'A small key to the mire', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Misery Mire'),
|
||||
'Big Key (Misery Mire)': (False, 'BigKey', 0x98, 'A big key to the mire', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Misery Mire'),
|
||||
'Compass (Misery Mire)': (False, 'Compass', 0x88, 'Now you can find Vitreous!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Misery Mire'),
|
||||
'Map (Misery Mire)': (False, 'Map', 0x78, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Misery Mire'),
|
||||
'Small Key (Turtle Rock)': (False, 'SmallKey', 0xAC, 'A small key to the pipe maze', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Turtle Rock'),
|
||||
'Big Key (Turtle Rock)': (False, 'BigKey', 0x93, 'A big key to the pipe maze', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Turtle Rock'),
|
||||
'Compass (Turtle Rock)': (False, 'Compass', 0x83, 'Now you can find Trinexx!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Turtle Rock'),
|
||||
'Map (Turtle Rock)': (False, 'Map', 0x73, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Turtle Rock'),
|
||||
'Small Key (Ganons Tower)': (False, 'SmallKey', 0xAD, 'A small key to the evil tower', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Ganon\'s Tower'),
|
||||
'Big Key (Ganons Tower)': (False, 'BigKey', 0x92, 'A big key to the evil tower', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Ganon\'s Tower'),
|
||||
'Compass (Ganons Tower)': (False, 'Compass', 0x82, 'Now you can find Agahnim!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Ganon\'s Tower'),
|
||||
'Map (Ganons Tower)': (False, 'Map', 0x72, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Ganon\'s Tower'),
|
||||
'Small Key (Universal)': (False, None, 0xAF, 'A small key for any door', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key'),
|
||||
'Nothing': (False, None, 0x5A, 'Some Hot Air', 'and the Nothing', 'the zen kid', 'outright theft', 'shroom theft', 'empty boy is bored again', 'nothing'),
|
||||
'Bee Trap': (False, None, 0xB0, 'We will sting your face a whole lot!', 'and the sting buddies', 'the beekeeper kid', 'insects for sale', 'shroom pollenation', 'bottle boy has mad bees again', 'Friendship'),
|
||||
'Faerie': (False, None, 0xB1, 'Save me and I will revive you', 'and the captive', 'the tingle kid','hostage for sale', 'fairy dust and shrooms', 'bottle boy has friend again', 'a faerie'),
|
||||
'Good Bee': (False, None, 0xB2, 'Save me and I will sting you (sometimes)', 'and the captive', 'the tingle kid','hostage for sale', 'good dust and shrooms', 'bottle boy has friend again', 'a bee'),
|
||||
'Magic Jar': (False, None, 0xB3, '', '', '','', '', '', ''),
|
||||
'Apple': (False, None, 0xB4, '', '', '','', '', '', ''),
|
||||
# 'Hint': (False, None, 0xB5, '', '', '','', '', '', ''),
|
||||
# 'Bomb Trap': (False, None, 0xB6, '', '', '','', '', '', ''),
|
||||
'Red Potion': (False, None, 0x2E, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a red potion'),
|
||||
'Green Potion': (False, None, 0x2F, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a green potion'),
|
||||
'Blue Potion': (False, None, 0x30, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a blue potion'),
|
||||
'Bee': (False, None, 0x0E, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bee'),
|
||||
'Small Heart': (False, None, 0x42, 'Just a little\npiece of love!', 'and the heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart'),
|
||||
'Activated Flute': (True, None, 0x4A, 'Save the duck\nand fly to\nfreedom!', 'and the duck call', 'the duck-call kid', 'duck call for sale', 'duck-calls for trade', 'flute boy plays again', 'the Flute'),
|
||||
'Beat Agahnim 1': (True, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Beat Agahnim 2': (True, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Get Frog': (True, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Return Smith': (True, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Pick Up Purple Chest': (True, 'Event', None, None, None, None, None, None, None, None),
|
||||
'Open Floodgate': (True, 'Event', None, None, None, None, None, None, None, None),
|
||||
}
|
||||
|
||||
lookup_id_to_name = {data[3]: name for name, data in item_table.items()}
|
||||
lookup_id_to_name = {data[2]: name for name, data in item_table.items()}
|
||||
|
||||
hint_blacklist = {"Triforce"}
|
||||
|
||||
|
@ -230,7 +242,9 @@ for basename, substring in _simple_groups:
|
|||
|
||||
del (_simple_groups)
|
||||
|
||||
progression_items = {name for name, data in item_table.items() if type(data[3]) == int and data[0]}
|
||||
item_name_groups['Everything'] = {name for name, data in item_table.items() if type(data[3]) == int}
|
||||
progression_items = {name for name, data in item_table.items() if type(data[2]) == int and data[0]}
|
||||
item_name_groups['Everything'] = {name for name, data in item_table.items() if type(data[2]) == int}
|
||||
item_name_groups['Progression Items'] = progression_items
|
||||
item_name_groups['Non Progression Items'] = item_name_groups['Everything'] - progression_items
|
||||
|
||||
trap_replaceable = item_name_groups['Rupees'] | {'Arrows (10)', 'Single Bomb', 'Bombs (3)', 'Bombs (10)', 'Nothing'}
|
||||
|
|
4
LICENSE
4
LICENSE
|
@ -1,8 +1,8 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 LLCoolDave
|
||||
Copyright (c) 2020 Berserker66
|
||||
Copyright (c) 2020 CaitSith2
|
||||
Copyright (c) 2021 Berserker66
|
||||
Copyright (c) 2021 CaitSith2
|
||||
Copyright (c) 2020 LegendaryLinux
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
|
110
Main.py
110
Main.py
|
@ -10,7 +10,7 @@ import zlib
|
|||
import concurrent.futures
|
||||
|
||||
from BaseClasses import World, CollectionState, Item, Region, Location
|
||||
from Shops import ShopSlotFill, create_shops, SHOP_ID_START, FillDisabledShopSlots
|
||||
from Shops import ShopSlotFill, create_shops, SHOP_ID_START, FillDisabledShopSlots, total_shop_slots
|
||||
from Items import ItemFactory, item_table, item_name_groups
|
||||
from Regions import create_regions, mark_light_world_regions, lookup_vanilla_location_to_entrance
|
||||
from InvertedRegions import create_inverted_regions, mark_dark_world_regions
|
||||
|
@ -21,6 +21,7 @@ from Dungeons import create_dungeons, fill_dungeons, fill_dungeons_restrictive
|
|||
from Fill import distribute_items_restrictive, flood_items, balance_multiworld_progression, distribute_planned
|
||||
from ItemPool import generate_itempool, difficulties, fill_prizes
|
||||
from Utils import output_path, parse_player_names, get_options, __version__, _version_tuple
|
||||
from typing import Dict
|
||||
import Patch
|
||||
|
||||
seeddigits = 20
|
||||
|
@ -33,6 +34,14 @@ def get_seed(seed=None):
|
|||
return seed
|
||||
|
||||
|
||||
seeds: Dict[tuple, str] = dict()
|
||||
def get_same_seed(world: World, seed_def: tuple) -> str:
|
||||
if seed_def in seeds:
|
||||
return seeds[seed_def]
|
||||
seeds[seed_def] = str(world.random.randint(0, 2 ** 64))
|
||||
return seeds[seed_def]
|
||||
|
||||
|
||||
def main(args, seed=None):
|
||||
if args.outputpath:
|
||||
os.makedirs(args.outputpath, exist_ok=True)
|
||||
|
@ -92,11 +101,23 @@ def main(args, seed=None):
|
|||
world.plando_items = args.plando_items.copy()
|
||||
world.plando_texts = args.plando_texts.copy()
|
||||
world.plando_connections = args.plando_connections.copy()
|
||||
world.er_seeds = args.er_seeds.copy()
|
||||
world.restrict_dungeon_item_on_boss = args.restrict_dungeon_item_on_boss.copy()
|
||||
world.required_medallions = args.required_medallions.copy()
|
||||
|
||||
world.rom_seeds = {player: random.Random(world.random.randint(0, 999999999)) for player in range(1, world.players + 1)}
|
||||
|
||||
for player in range(1, world.players+1):
|
||||
world.er_seeds[player] = str(world.random.randint(0, 2 ** 64))
|
||||
|
||||
if "-" in world.shuffle[player]:
|
||||
shuffle, seed = world.shuffle[player].split("-", 1)
|
||||
world.shuffle[player] = shuffle
|
||||
if seed.startswith("team-"):
|
||||
world.er_seeds[player] = get_same_seed(world, (shuffle, seed, world.retro[player], world.mode[player], world.logic[player]))
|
||||
else:
|
||||
world.er_seeds[player] = seed
|
||||
|
||||
logger.info('ALttP Berserker\'s Multiworld Version %s - Seed: %s\n', __version__, world.seed)
|
||||
|
||||
parsed_names = parse_player_names(args.names, world.players, args.teams)
|
||||
|
@ -112,6 +133,14 @@ def main(args, seed=None):
|
|||
for player in range(1, world.players + 1):
|
||||
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
|
||||
|
||||
if world.open_pyramid[player] == 'goal':
|
||||
world.open_pyramid[player] = world.goal[player] in {'crystals', 'ganontriforcehunt', 'localganontriforcehunt', 'ganonpedestal'}
|
||||
elif world.open_pyramid[player] == 'auto':
|
||||
world.open_pyramid[player] = world.goal[player] in {'crystals', 'ganontriforcehunt', 'localganontriforcehunt', 'ganonpedestal'} and \
|
||||
(world.shuffle[player] in {'vanilla', 'dungeonssimple', 'dungeonsfull'} or not world.shuffle_ganon)
|
||||
else:
|
||||
world.open_pyramid[player] = {'on': True, 'off': False, 'yes': True, 'no': False}.get(world.open_pyramid[player], world.open_pyramid[player])
|
||||
|
||||
for tok in filter(None, args.startinventory[player].split(',')):
|
||||
item = ItemFactory(tok.strip(), player)
|
||||
if item:
|
||||
|
@ -162,12 +191,18 @@ def main(args, seed=None):
|
|||
{"vanilla", "dungeonssimple", "dungeonsfull", "simple", "restricted", "full"}:
|
||||
world.fix_fake_world[player] = False
|
||||
|
||||
# seeded entrance shuffle
|
||||
old_random = world.random
|
||||
world.random = random.Random(world.er_seeds[player])
|
||||
|
||||
if world.mode[player] != 'inverted':
|
||||
link_entrances(world, player)
|
||||
mark_light_world_regions(world, player)
|
||||
else:
|
||||
link_inverted_entrances(world, player)
|
||||
mark_dark_world_regions(world, player)
|
||||
|
||||
world.random = old_random
|
||||
plando_connect(world, player)
|
||||
|
||||
logger.info('Generating Item Pool.')
|
||||
|
@ -208,13 +243,13 @@ def main(args, seed=None):
|
|||
elif args.algorithm == 'balanced':
|
||||
distribute_items_restrictive(world, True)
|
||||
|
||||
if world.players > 1:
|
||||
balance_multiworld_progression(world)
|
||||
|
||||
logger.info("Filling Shop Slots")
|
||||
|
||||
ShopSlotFill(world)
|
||||
|
||||
if world.players > 1:
|
||||
balance_multiworld_progression(world)
|
||||
|
||||
logger.info('Patching ROM.')
|
||||
|
||||
|
||||
|
@ -251,7 +286,7 @@ def main(args, seed=None):
|
|||
|
||||
apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player],
|
||||
args.fastmenu[player], args.disablemusic[player], args.triforcehud[player], args.sprite[player],
|
||||
palettes_options, world, player, True)
|
||||
palettes_options, world, player, True, reduceflashing=args.reduceflashing[player] if not args.race else True)
|
||||
|
||||
mcsb_name = ''
|
||||
if all([world.mapshuffle[player], world.compassshuffle[player], world.keyshuffle[player],
|
||||
|
@ -277,7 +312,7 @@ def main(args, seed=None):
|
|||
outfilestuffs = {
|
||||
"logic": world.logic[player], # 0
|
||||
"difficulty": world.difficulty[player], # 1
|
||||
"difficulty_adjustments": world.difficulty_adjustments[player], # 2
|
||||
"item_functionality": world.item_functionality[player], # 2
|
||||
"mode": world.mode[player], # 3
|
||||
"goal": world.goal[player], # 4
|
||||
"timer": str(world.timer[player]), # 5
|
||||
|
@ -298,7 +333,7 @@ def main(args, seed=None):
|
|||
outfilestuffs["logic"], # 0
|
||||
|
||||
outfilestuffs["difficulty"], # 1
|
||||
outfilestuffs["difficulty_adjustments"], # 2
|
||||
outfilestuffs["item_functionality"], # 2
|
||||
outfilestuffs["mode"], # 3
|
||||
outfilestuffs["goal"], # 4
|
||||
"" if outfilestuffs["timer"] in ['False', 'none', 'display'] else "-" + outfilestuffs["timer"], # 5
|
||||
|
@ -371,19 +406,22 @@ def main(args, seed=None):
|
|||
checks_in_area[location.player]["Total"] += 1
|
||||
|
||||
oldmancaves = []
|
||||
for region in [world.get_region("Old Man Sword Cave", player) for player in range(1, world.players + 1) if world.retro[player]]:
|
||||
item = ItemFactory(region.shop.inventory[0]['item'], region.player)
|
||||
player = region.player
|
||||
location_id = SHOP_ID_START + 33
|
||||
takeanyregions = ["Old Man Sword Cave", "Take-Any #1", "Take-Any #2", "Take-Any #3", "Take-Any #4"]
|
||||
for index, take_any in enumerate(takeanyregions):
|
||||
for region in [world.get_region(take_any, player) for player in range(1, world.players + 1) if world.retro[player]]:
|
||||
item = ItemFactory(region.shop.inventory[(0 if take_any == "Old Man Sword Cave" else 1)]['item'], region.player)
|
||||
player = region.player
|
||||
location_id = SHOP_ID_START + total_shop_slots + index
|
||||
|
||||
if region.type == RegionType.LightWorld:
|
||||
checks_in_area[player]["Light World"].append(location_id)
|
||||
else:
|
||||
checks_in_area[player]["Dark World"].append(location_id)
|
||||
checks_in_area[player]["Total"] += 1
|
||||
main_entrance = get_entrance_to_region(region)
|
||||
if main_entrance.parent_region.type == RegionType.LightWorld:
|
||||
checks_in_area[player]["Light World"].append(location_id)
|
||||
else:
|
||||
checks_in_area[player]["Dark World"].append(location_id)
|
||||
checks_in_area[player]["Total"] += 1
|
||||
|
||||
er_hint_data[player][location_id] = get_entrance_to_region(region).name
|
||||
oldmancaves.append(((location_id, player), (item.code, player)))
|
||||
er_hint_data[player][location_id] = main_entrance.name
|
||||
oldmancaves.append(((location_id, player), (item.code, player)))
|
||||
|
||||
precollected_items = [[] for player in range(world.players)]
|
||||
for item in world.precollected_items:
|
||||
|
@ -449,9 +487,10 @@ def main(args, seed=None):
|
|||
return world
|
||||
|
||||
|
||||
|
||||
def copy_world(world):
|
||||
# ToDo: Not good yet
|
||||
ret = World(world.players, world.shuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.retro, world.custom, world.customitemarray, world.hints)
|
||||
ret = World(world.players, world.shuffle, world.logic, world.mode, world.swords, world.difficulty, world.item_functionality, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.retro, world.custom, world.customitemarray, world.hints)
|
||||
ret.teams = world.teams
|
||||
ret.player_names = copy.deepcopy(world.player_names)
|
||||
ret.remote_items = world.remote_items.copy()
|
||||
|
@ -524,7 +563,7 @@ def copy_world(world):
|
|||
# fill locations
|
||||
for location in world.get_locations():
|
||||
if location.item is not None:
|
||||
item = Item(location.item.name, location.item.advancement, location.item.priority, location.item.type, player = location.item.player)
|
||||
item = Item(location.item.name, location.item.advancement, location.item.type, player = location.item.player)
|
||||
ret.get_location(location.name, location.player).item = item
|
||||
item.location = ret.get_location(location.name, location.player)
|
||||
item.world = ret
|
||||
|
@ -535,7 +574,7 @@ def copy_world(world):
|
|||
|
||||
# copy remaining itempool. No item in itempool should have an assigned location
|
||||
for item in world.itempool:
|
||||
ret.itempool.append(Item(item.name, item.advancement, item.priority, item.type, player = item.player))
|
||||
ret.itempool.append(Item(item.name, item.advancement, item.type, player = item.player))
|
||||
|
||||
for item in world.precollected_items:
|
||||
ret.push_precollected(ItemFactory(item.name, item.player))
|
||||
|
@ -593,11 +632,11 @@ def create_playthrough(world):
|
|||
while sphere_candidates:
|
||||
state.sweep_for_events(key_only=True)
|
||||
|
||||
sphere = []
|
||||
sphere = set()
|
||||
# build up spheres of collection radius. Everything in each sphere is independent from each other in dependencies and only depends on lower spheres
|
||||
for location in sphere_candidates:
|
||||
if state.can_reach(location):
|
||||
sphere.append(location)
|
||||
sphere.add(location)
|
||||
|
||||
for location in sphere:
|
||||
sphere_candidates.remove(location)
|
||||
|
@ -621,25 +660,24 @@ def create_playthrough(world):
|
|||
break
|
||||
|
||||
# in the second phase, we cull each sphere such that the game is still beatable, reducing each range of influence to the bare minimum required inside it
|
||||
for num, sphere in reversed(list(enumerate(collection_spheres))):
|
||||
to_delete = []
|
||||
for num, sphere in reversed(tuple(enumerate(collection_spheres))):
|
||||
to_delete = set()
|
||||
for location in sphere:
|
||||
# we remove the item at location and check if game is still beatable
|
||||
logging.getLogger('').debug('Checking if %s (Player %d) is required to beat the game.', location.item.name, location.item.player)
|
||||
old_item = location.item
|
||||
location.item = None
|
||||
if world.can_beat_game(state_cache[num]):
|
||||
to_delete.append(location)
|
||||
to_delete.add(location)
|
||||
else:
|
||||
# still required, got to keep it around
|
||||
location.item = old_item
|
||||
|
||||
# cull entries in spheres for spoiler walkthrough at end
|
||||
for location in to_delete:
|
||||
sphere.remove(location)
|
||||
sphere -= to_delete
|
||||
|
||||
# second phase, sphere 0
|
||||
for item in [i for i in world.precollected_items if i.advancement]:
|
||||
for item in (i for i in world.precollected_items if i.advancement):
|
||||
logging.getLogger('').debug('Checking if %s (Player %d) is required to beat the game.', item.name, item.player)
|
||||
world.precollected_items.remove(item)
|
||||
world.state.remove(item)
|
||||
|
@ -652,13 +690,13 @@ def create_playthrough(world):
|
|||
# used to access it was deemed not required.) So we need to do one final sphere collection pass
|
||||
# to build up the correct spheres
|
||||
|
||||
required_locations = [item for sphere in collection_spheres for item in sphere]
|
||||
required_locations = {item for sphere in collection_spheres for item in sphere}
|
||||
state = CollectionState(world)
|
||||
collection_spheres = []
|
||||
while required_locations:
|
||||
state.sweep_for_events(key_only=True)
|
||||
|
||||
sphere = list(filter(state.can_reach, required_locations))
|
||||
sphere = set(filter(state.can_reach, required_locations))
|
||||
|
||||
for location in sphere:
|
||||
required_locations.remove(location)
|
||||
|
@ -670,9 +708,6 @@ def create_playthrough(world):
|
|||
if not sphere:
|
||||
raise RuntimeError('Not all required items reachable. Something went terribly wrong here.')
|
||||
|
||||
# store the required locations for statistical analysis
|
||||
old_world.required_locations = [(location.name, location.player) for sphere in collection_spheres for location in sphere]
|
||||
|
||||
def flist_to_iter(node):
|
||||
while node:
|
||||
value, node = node
|
||||
|
@ -689,7 +724,7 @@ def create_playthrough(world):
|
|||
old_world.spoiler.paths = dict()
|
||||
for player in range(1, world.players + 1):
|
||||
old_world.spoiler.paths.update({ str(location) : get_path(state, location.parent_region) for sphere in collection_spheres for location in sphere if location.player == player})
|
||||
for _, path in dict(old_world.spoiler.paths).items():
|
||||
for path in dict(old_world.spoiler.paths).values():
|
||||
if any(exit == 'Pyramid Fairy' for (_, exit) in path):
|
||||
if world.mode[player] != 'inverted':
|
||||
old_world.spoiler.paths[str(world.get_region('Big Bomb Shop', player))] = get_path(state, world.get_region('Big Bomb Shop', player))
|
||||
|
@ -697,6 +732,7 @@ def create_playthrough(world):
|
|||
old_world.spoiler.paths[str(world.get_region('Inverted Big Bomb Shop', player))] = get_path(state, world.get_region('Inverted Big Bomb Shop', player))
|
||||
|
||||
# we can finally output our playthrough
|
||||
old_world.spoiler.playthrough = OrderedDict([("0", [str(item) for item in world.precollected_items if item.advancement])])
|
||||
old_world.spoiler.playthrough = {"0": sorted([str(item) for item in world.precollected_items if item.advancement])}
|
||||
|
||||
for i, sphere in enumerate(collection_spheres):
|
||||
old_world.spoiler.playthrough[str(i + 1)] = {str(location): str(location.item) for location in sphere}
|
||||
old_world.spoiler.playthrough[str(i + 1)] = {str(location): str(location.item) for location in sorted(sphere)}
|
||||
|
|
|
@ -37,6 +37,7 @@ import WebUI
|
|||
|
||||
import Regions
|
||||
import Utils
|
||||
import Items
|
||||
|
||||
# logging note:
|
||||
# logging.* gets send to only the text console, logger.* gets send to the WebUI as well, if it's initialized.
|
||||
|
@ -140,6 +141,13 @@ def color(text, *args):
|
|||
return color_code(*args) + text + color_code('reset')
|
||||
|
||||
|
||||
def color_item(item_id: int, green: bool = False) -> str:
|
||||
item_name = get_item_name_from_id(item_id)
|
||||
item_colors = ['green' if green else 'cyan']
|
||||
if item_name in Items.progression_items:
|
||||
item_colors.append("white_bg")
|
||||
return color(item_name, *item_colors)
|
||||
|
||||
START_RECONNECT_DELAY = 5
|
||||
SNES_RECONNECT_DELAY = 5
|
||||
SERVER_RECONNECT_DELAY = 5
|
||||
|
@ -931,8 +939,9 @@ async def process_server_cmd(ctx: Context, cmd, args):
|
|||
player_sent, location, player_recvd, item = args
|
||||
ctx.ui_node.notify_item_sent(ctx.player_names[player_sent], ctx.player_names[player_recvd],
|
||||
get_item_name_from_id(item), get_location_name_from_address(location),
|
||||
player_sent == ctx.slot, player_recvd == ctx.slot)
|
||||
item = color(get_item_name_from_id(item), 'cyan' if player_sent != ctx.slot else 'green')
|
||||
player_sent == ctx.slot, player_recvd == ctx.slot,
|
||||
get_item_name_from_id(item) in Items.progression_items)
|
||||
item = color_item(item, player_sent == ctx.slot)
|
||||
player_sent = color(ctx.player_names[player_sent], 'yellow' if player_sent != ctx.slot else 'magenta')
|
||||
player_recvd = color(ctx.player_names[player_recvd], 'yellow' if player_recvd != ctx.slot else 'magenta')
|
||||
logging.info(
|
||||
|
@ -942,8 +951,9 @@ async def process_server_cmd(ctx: Context, cmd, args):
|
|||
elif cmd == 'ItemFound':
|
||||
found = ReceivedItem(*args)
|
||||
ctx.ui_node.notify_item_found(ctx.player_names[found.player], get_item_name_from_id(found.item),
|
||||
get_location_name_from_address(found.location), found.player == ctx.slot)
|
||||
item = color(get_item_name_from_id(found.item), 'cyan' if found.player != ctx.slot else 'green')
|
||||
get_location_name_from_address(found.location), found.player == ctx.slot,
|
||||
get_item_name_from_id(found.item) in Items.progression_items)
|
||||
item = color_item(found.item, found.player == ctx.slot)
|
||||
player_sent = color(ctx.player_names[found.player], 'yellow' if found.player != ctx.slot else 'magenta')
|
||||
logging.info('%s found %s (%s)' % (player_sent, item, color(get_location_name_from_address(found.location),
|
||||
'blue_bg', 'white')))
|
||||
|
@ -968,7 +978,7 @@ async def process_server_cmd(ctx: Context, cmd, args):
|
|||
get_item_name_from_id(hint.item), get_location_name_from_address(hint.location),
|
||||
hint.found, hint.finding_player == ctx.slot, hint.receiving_player == ctx.slot,
|
||||
hint.entrance if hint.entrance else None)
|
||||
item = color(get_item_name_from_id(hint.item), 'green' if hint.found else 'cyan')
|
||||
item = color_item(hint.item, hint.found)
|
||||
player_find = color(ctx.player_names[hint.finding_player],
|
||||
'yellow' if hint.finding_player != ctx.slot else 'magenta')
|
||||
player_recvd = color(ctx.player_names[hint.receiving_player],
|
||||
|
@ -1078,7 +1088,8 @@ class ClientCommandProcessor(CommandProcessor):
|
|||
for index, item in enumerate(self.ctx.items_received, 1):
|
||||
self.ctx.ui_node.notify_item_received(self.ctx.player_names[item.player], get_item_name_from_id(item.item),
|
||||
get_location_name_from_address(item.location), index,
|
||||
len(self.ctx.items_received))
|
||||
len(self.ctx.items_received),
|
||||
get_item_name_from_id(item.item) in Items.progression_items)
|
||||
logging.info('%s from %s (%s) (%d/%d in list)' % (
|
||||
color(get_item_name_from_id(item.item), 'red', 'bold'),
|
||||
color(self.ctx.player_names[item.player], 'yellow'),
|
||||
|
@ -1336,7 +1347,8 @@ async def game_watcher(ctx : Context):
|
|||
item = ctx.items_received[recv_index]
|
||||
ctx.ui_node.notify_item_received(ctx.player_names[item.player], get_item_name_from_id(item.item),
|
||||
get_location_name_from_address(item.location), recv_index + 1,
|
||||
len(ctx.items_received))
|
||||
len(ctx.items_received),
|
||||
get_item_name_from_id(item.item) in Items.progression_items)
|
||||
logging.info('Received %s from %s (%s) (%d/%d in list)' % (
|
||||
color(get_item_name_from_id(item.item), 'red', 'bold'), color(ctx.player_names[item.player], 'yellow'),
|
||||
get_location_name_from_address(item.location), recv_index + 1, len(ctx.items_received)))
|
||||
|
|
|
@ -539,7 +539,7 @@ def notify_team(ctx: Context, team: int, text: str):
|
|||
|
||||
def collect_hints(ctx: Context, team: int, slot: int, item: str) -> typing.List[Utils.Hint]:
|
||||
hints = []
|
||||
seeked_item_id = Items.item_table[item][3]
|
||||
seeked_item_id = Items.item_table[item][2]
|
||||
for check, result in ctx.locations.items():
|
||||
item_id, receiving_player = result
|
||||
if receiving_player == slot and item_id == seeked_item_id:
|
||||
|
@ -875,7 +875,7 @@ class ClientMessageProcessor(CommonCommandProcessor):
|
|||
if self.ctx.item_cheat:
|
||||
item_name, usable, response = get_intended_text(item_name, Items.item_table.keys())
|
||||
if usable:
|
||||
new_item = ReceivedItem(Items.item_table[item_name][3], -1, self.client.slot)
|
||||
new_item = ReceivedItem(Items.item_table[item_name][2], -1, self.client.slot)
|
||||
get_received_items(self.ctx, self.client.team, self.client.slot).append(new_item)
|
||||
self.ctx.notify_all('Cheat console: sending "' + item_name + '" to ' + self.ctx.get_aliased_name(self.client.team, self.client.slot))
|
||||
send_new_items(self.ctx)
|
||||
|
@ -1075,7 +1075,7 @@ async def process_client_cmd(ctx: Context, client: Client, cmd, args):
|
|||
target_item, target_player = ctx.locations[(Regions.location_table[loc_name][0], client.slot)]
|
||||
|
||||
replacements = {'SmallKey': 0xA2, 'BigKey': 0x9D, 'Compass': 0x8D, 'Map': 0x7D}
|
||||
item_type = [i[2] for i in Items.item_table.values() if type(i[3]) is int and i[3] == target_item]
|
||||
item_type = [i[1] for i in Items.item_table.values() if type(i[2]) is int and i[2] == target_item]
|
||||
if item_type:
|
||||
target_item = replacements.get(item_type[0], target_item)
|
||||
|
||||
|
@ -1228,7 +1228,7 @@ class ServerCommandProcessor(CommonCommandProcessor):
|
|||
if usable:
|
||||
for client in self.ctx.endpoints:
|
||||
if client.name == seeked_player:
|
||||
new_item = ReceivedItem(Items.item_table[item][3], -1, client.slot)
|
||||
new_item = ReceivedItem(Items.item_table[item][2], -1, client.slot)
|
||||
get_received_items(self.ctx, client.team, client.slot).append(new_item)
|
||||
self.ctx.notify_all('Cheat console: sending "' + item + '" to ' + self.ctx.get_aliased_name(client.team, client.slot))
|
||||
send_new_items(self.ctx)
|
||||
|
|
91
Mystery.py
91
Mystery.py
|
@ -199,10 +199,10 @@ def main(args=None, callback=ERmain):
|
|||
for option, player_settings in vars(erargs).items():
|
||||
if type(player_settings) == dict:
|
||||
if all(type(value) != list for value in player_settings.values()):
|
||||
if len(frozenset(player_settings.values())) > 1:
|
||||
if len(player_settings.values()) > 1:
|
||||
important[option] = {player: value for player, value in player_settings.items() if
|
||||
player <= args.yaml_output}
|
||||
elif len(frozenset(player_settings.values())) > 0:
|
||||
elif len(player_settings.values()) > 0:
|
||||
important[option] = player_settings[1]
|
||||
else:
|
||||
logging.debug(f"No player settings defined for option '{option}'")
|
||||
|
@ -291,31 +291,71 @@ def roll_percentage(percentage: typing.Union[int, float]) -> bool:
|
|||
percentage is expected to be in range [0, 100]"""
|
||||
return random.random() < (float(percentage) / 100)
|
||||
|
||||
def update_weights(weights: dict, new_weights: dict, type: str, name: str) -> dict:
|
||||
logging.debug(f'Applying {new_weights}')
|
||||
new_options = set(new_weights) - set(weights)
|
||||
weights.update(new_weights)
|
||||
if new_options:
|
||||
for new_option in new_options:
|
||||
logging.warning(f'{type} Suboption "{new_option}" of "{name}" did not '
|
||||
f'overwrite a root option. '
|
||||
f'This is probably in error.')
|
||||
return weights
|
||||
|
||||
def roll_settings(weights, plando_options: typing.Set[str] = frozenset(("bosses"))):
|
||||
ret = argparse.Namespace()
|
||||
def roll_linked_options(weights: dict) -> dict:
|
||||
weights = weights.copy() # make sure we don't write back to other weights sets in same_settings
|
||||
for option_set in weights["linked_options"]:
|
||||
if "name" not in option_set:
|
||||
raise ValueError("One of your linked options does not have a name.")
|
||||
try:
|
||||
if roll_percentage(option_set["percentage"]):
|
||||
logging.debug(f"Linked option {option_set['name']} triggered.")
|
||||
if "options" in option_set:
|
||||
weights = update_weights(weights, option_set["options"], "Linked", option_set["name"])
|
||||
if "rom_options" in option_set:
|
||||
rom_weights = weights.get("rom", dict())
|
||||
rom_weights = update_weights(rom_weights, option_set["rom_options"], "Linked Rom", option_set["name"])
|
||||
weights["rom"] = rom_weights
|
||||
else:
|
||||
logging.debug(f"linked option {option_set['name']} skipped.")
|
||||
except Exception as e:
|
||||
raise ValueError(f"Linked option {option_set['name']} is destroyed. "
|
||||
f"Please fix your linked option.") from e
|
||||
return weights
|
||||
|
||||
def roll_triggers(weights: dict) -> dict:
|
||||
weights = weights.copy() # make sure we don't write back to other weights sets in same_settings
|
||||
weights["_Generator_Version"] = "Main" # Some means for triggers to know if the seed is on main or doors.
|
||||
for option_set in weights["triggers"]:
|
||||
try:
|
||||
key = get_choice("option_name", option_set)
|
||||
if key not in weights:
|
||||
logging.warning(f'Specified option name {option_set["option_name"]} did not '
|
||||
f'match with a root option. '
|
||||
f'This is probably in error.')
|
||||
trigger_result = get_choice("option_result", option_set)
|
||||
result = get_choice(key, weights)
|
||||
if result == trigger_result and roll_percentage(get_choice("percentage", option_set, 100)):
|
||||
if "options" in option_set:
|
||||
weights = update_weights(weights, option_set["options"], "Triggered", option_set["option_name"])
|
||||
if "rom_options" in option_set:
|
||||
rom_weights = weights.get("rom", dict())
|
||||
rom_weights = update_weights(rom_weights, option_set["rom_options"], "Triggered Rom", option_set["option_name"])
|
||||
weights["rom"] = rom_weights
|
||||
weights[key] = result
|
||||
except Exception as e:
|
||||
raise ValueError(f"A trigger is destroyed. "
|
||||
f"Please fix your triggers.") from e
|
||||
return weights
|
||||
|
||||
def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("bosses"))):
|
||||
if "linked_options" in weights:
|
||||
weights = weights.copy() # make sure we don't write back to other weights sets in same_settings
|
||||
for option_set in weights["linked_options"]:
|
||||
if "name" not in option_set:
|
||||
raise ValueError("One of your linked options does not have a name.")
|
||||
try:
|
||||
if roll_percentage(option_set["percentage"]):
|
||||
logging.debug(f"Linked option {option_set['name']} triggered.")
|
||||
logging.debug(f'Applying {option_set["options"]}')
|
||||
new_options = set(option_set["options"]) - set(weights)
|
||||
weights.update(option_set["options"])
|
||||
if new_options:
|
||||
for new_option in new_options:
|
||||
logging.warning(f'Linked Suboption "{new_option}" of "{option_set["name"]}" did not '
|
||||
f'overwrite a root option. '
|
||||
f"This is probably in error.")
|
||||
else:
|
||||
logging.debug(f"linked option {option_set['name']} skipped.")
|
||||
except Exception as e:
|
||||
raise ValueError(f"Linked option {option_set['name']} is destroyed. "
|
||||
f"Please fix your linked option.") from e
|
||||
weights = roll_linked_options(weights)
|
||||
|
||||
if "triggers" in weights:
|
||||
weights = roll_triggers(weights)
|
||||
|
||||
ret = argparse.Namespace()
|
||||
ret.name = get_choice('name', weights)
|
||||
if ret.name:
|
||||
ret.name = handle_name(ret.name)
|
||||
|
@ -379,7 +419,7 @@ def roll_settings(weights, plando_options: typing.Set[str] = frozenset(("bosses"
|
|||
|
||||
# TODO consider moving open_pyramid to an automatic variable in the core roller, set to True when
|
||||
# fast ganon + ganon at hole
|
||||
ret.open_pyramid = ret.goal in {'crystals', 'ganontriforcehunt', 'localganontriforcehunt', 'ganonpedestal'}
|
||||
ret.open_pyramid = get_choice('open_pyramid', weights, 'goal')
|
||||
|
||||
ret.crystals_gt = prefer_int(get_choice('tower_open', weights))
|
||||
|
||||
|
@ -653,6 +693,7 @@ def roll_settings(weights, plando_options: typing.Set[str] = frozenset(("bosses"
|
|||
ret.triforcehud = get_choice('triforcehud', romweights, 'hide_goal')
|
||||
ret.quickswap = get_choice('quickswap', romweights, True)
|
||||
ret.fastmenu = get_choice('menuspeed', romweights, "normal")
|
||||
ret.reduceflashing = get_choice('reduceflashing', romweights, False)
|
||||
ret.heartcolor = get_choice('heartcolor', romweights, "red")
|
||||
ret.heartbeep = convert_to_on_off(get_choice('heartbeep', romweights, "normal"))
|
||||
ret.ow_palettes = get_choice('ow_palettes', romweights, "default")
|
||||
|
|
|
@ -9,7 +9,8 @@ def create_regions(world, player):
|
|||
|
||||
world.regions += [
|
||||
create_lw_region(player, 'Menu', None, ['Links House S&Q', 'Sanctuary S&Q', 'Old Man S&Q']),
|
||||
create_lw_region(player, 'Light World', ['Mushroom', 'Bottle Merchant', 'Flute Spot', 'Sunken Treasure', 'Purple Chest'],
|
||||
create_lw_region(player, 'Light World', ['Mushroom', 'Bottle Merchant', 'Flute Spot', 'Sunken Treasure',
|
||||
'Purple Chest', 'Flute Activation Spot'],
|
||||
["Blinds Hideout", "Hyrule Castle Secret Entrance Drop", 'Zoras River', 'Kings Grave Outer Rocks', 'Dam',
|
||||
'Links House', 'Tavern North', 'Chicken House', 'Aginahs Cave', 'Sahasrahlas Hut', 'Kakariko Well Drop', 'Kakariko Well Cave',
|
||||
'Blacksmiths Hut', 'Bat Cave Drop Ledge', 'Bat Cave Cave', 'Sick Kids House', 'Hobo Bridge', 'Lost Woods Hideout Drop', 'Lost Woods Hideout Stump',
|
||||
|
@ -653,6 +654,7 @@ location_table: typing.Dict[str,
|
|||
'Frog': (None, None, False, None),
|
||||
'Missing Smith': (None, None, False, None),
|
||||
'Dark Blacksmith Ruins': (None, None, False, None),
|
||||
'Flute Activation Spot': (None, None, False, None),
|
||||
'Eastern Palace - Prize': ([0x1209D, 0x53EF8, 0x53EF9, 0x180052, 0x18007C, 0xC6FE], None, True, 'Eastern Palace'),
|
||||
'Desert Palace - Prize': ([0x1209E, 0x53F1C, 0x53F1D, 0x180053, 0x180078, 0xC6FF], None, True, 'Desert Palace'),
|
||||
'Tower of Hera - Prize': (
|
||||
|
|
172
Rom.py
172
Rom.py
|
@ -1,7 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = '9cbbc0876dd5748125eda8b315347ad2'
|
||||
RANDOMIZERBASEHASH = 'a0a9511a2a59e5e8009b38718f8da1bf'
|
||||
|
||||
import io
|
||||
import json
|
||||
|
@ -18,7 +18,7 @@ import concurrent.futures
|
|||
from typing import Optional
|
||||
|
||||
from BaseClasses import CollectionState, Region, Location
|
||||
from Shops import ShopType
|
||||
from Shops import ShopType, total_shop_slots
|
||||
from Dungeons import dungeon_music_addresses
|
||||
from Regions import location_table, old_location_address_to_new_location_address
|
||||
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
|
||||
|
@ -674,6 +674,14 @@ class Sprite(object):
|
|||
rom.write_bytes(0x307000, self.palette)
|
||||
rom.write_bytes(0x307078, self.glove_palette)
|
||||
|
||||
bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028, 0x4D03C, 0x4D059, 0x4D07A,
|
||||
0x4D09E, 0x4D0A8, 0x4D0AB, 0x4D0AE, 0x4D0BE, 0x4D0DD,
|
||||
0x4D16A, 0x4D1E5, 0x4D1EE, 0x4D20B, 0x4CBBF, 0x4CBBF, 0x4CC17, 0x4CC1A, 0x4CC4A, 0x4CC4D,
|
||||
0x4CC53, 0x4CC69, 0x4CC6F, 0x4CC7C, 0x4CCEF, 0x4CD51,
|
||||
0x4CDC0, 0x4CDC3, 0x4CDC6, 0x4CE37, 0x4D2DE, 0x4D32F, 0x4D355, 0x4D367, 0x4D384, 0x4D387,
|
||||
0x4D397, 0x4D39E, 0x4D3AB, 0x4D3AE, 0x4D3D1, 0x4D3D7,
|
||||
0x4D3F8, 0x4D416, 0x4D420, 0x4D423, 0x4D42D, 0x4D449, 0x4D48C, 0x4D4D9, 0x4D4DC, 0x4D4E3,
|
||||
0x4D504, 0x4D507, 0x4D55E, 0x4D56A]
|
||||
|
||||
def patch_rom(world, rom, player, team, enemized):
|
||||
local_random = world.rom_seeds[player]
|
||||
|
@ -791,6 +799,27 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
|
||||
write_custom_shops(rom, world, player)
|
||||
|
||||
def credits_digit(num):
|
||||
# top: $54 is 1, 55 2, etc , so 57=4, 5C=9
|
||||
# bot: $7A is 1, 7B is 2, etc so 7D=4, 82=9 (zero unknown...)
|
||||
return 0x53 + int(num), 0x79 + int(num)
|
||||
|
||||
credits_total = 216
|
||||
if world.retro[player]: # Old man cave and Take any caves will count towards collection rate.
|
||||
credits_total += 5
|
||||
if world.shop_shuffle_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
|
||||
|
||||
rom.write_byte(0x187010, credits_total) # dynamic credits
|
||||
# collection rate address: 238C37
|
||||
first_top, first_bot = credits_digit((credits_total / 100) % 10)
|
||||
mid_top, mid_bot = credits_digit((credits_total / 10) % 10)
|
||||
last_top, last_bot = credits_digit(credits_total % 10)
|
||||
# top half
|
||||
rom.write_bytes(0x118C46, [first_top, mid_top, last_top])
|
||||
# bottom half
|
||||
rom.write_bytes(0x118C64, [first_bot, mid_bot, last_bot])
|
||||
|
||||
# patch medallion requirements
|
||||
if world.required_medallions[player][0] == 'Bombos':
|
||||
rom.write_byte(0x180022, 0x00) # requirement
|
||||
|
@ -847,8 +876,8 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
|
||||
rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on
|
||||
|
||||
# handle difficulty_adjustments
|
||||
if world.difficulty_adjustments[player] == 'hard':
|
||||
# handle item_functionality
|
||||
if world.item_functionality[player] == 'hard':
|
||||
rom.write_byte(0x180181, 0x01) # Make silver arrows work only on ganon
|
||||
rom.write_byte(0x180182, 0x00) # Don't auto equip silvers on pickup
|
||||
# Powdered Fairies Prize
|
||||
|
@ -868,7 +897,7 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
rom.write_int16(0x180036, world.rupoor_cost)
|
||||
# Set stun items
|
||||
rom.write_byte(0x180180, 0x02) # Hookshot only
|
||||
elif world.difficulty_adjustments[player] == 'expert':
|
||||
elif world.item_functionality[player] == 'expert':
|
||||
rom.write_byte(0x180181, 0x01) # Make silver arrows work only on ganon
|
||||
rom.write_byte(0x180182, 0x00) # Don't auto equip silvers on pickup
|
||||
# Powdered Fairies Prize
|
||||
|
@ -937,6 +966,15 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
|
||||
# set up game internal RNG seed
|
||||
rom.write_bytes(0x178000, local_random.getrandbits(8 * 1024).to_bytes(1024, 'big'))
|
||||
prize_replacements = {}
|
||||
if world.item_functionality[player] in ['hard', 'expert']:
|
||||
prize_replacements[0xE0] = 0xDF # Fairy -> heart
|
||||
prize_replacements[0xE3] = 0xD8 # Big magic -> small magic
|
||||
|
||||
if world.retro[player]:
|
||||
prize_replacements[0xE1] = 0xDA # 5 Arrows -> Blue Rupee
|
||||
prize_replacements[0xE2] = 0xDB # 10 Arrows -> Red Rupee
|
||||
|
||||
if "g" in world.shuffle_prizes[player]:
|
||||
# shuffle prize packs
|
||||
prizes = [0xD8, 0xD8, 0xD8, 0xD8, 0xD9, 0xD8, 0xD8, 0xD9, 0xDA, 0xD9, 0xDA, 0xDB, 0xDA, 0xD9, 0xDA, 0xDA, 0xE0,
|
||||
|
@ -962,18 +1000,10 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
packs = chunk(prizes[:56], 8)
|
||||
local_random.shuffle(packs)
|
||||
prizes[:56] = [drop for pack in packs for drop in pack]
|
||||
|
||||
if world.difficulty_adjustments[player] in ['hard', 'expert']:
|
||||
prize_replacements = {0xE0: 0xDF, # Fairy -> heart
|
||||
0xE3: 0xD8} # Big magic -> small magic
|
||||
if prize_replacements:
|
||||
prizes = [prize_replacements.get(prize, prize) for prize in prizes]
|
||||
dig_prizes = [prize_replacements.get(prize, prize) for prize in dig_prizes]
|
||||
|
||||
if world.retro[player]:
|
||||
prize_replacements = {0xE1: 0xDA, # 5 Arrows -> Blue Rupee
|
||||
0xE2: 0xDB} # 10 Arrows -> Red Rupee
|
||||
prizes = [prize_replacements.get(prize, prize) for prize in prizes]
|
||||
dig_prizes = [prize_replacements.get(prize, prize) for prize in dig_prizes]
|
||||
rom.write_bytes(0x180100, dig_prizes)
|
||||
|
||||
# write tree pull prizes
|
||||
|
@ -994,6 +1024,19 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
# fill enemy prize packs
|
||||
rom.write_bytes(0x37A78, prizes)
|
||||
|
||||
elif prize_replacements:
|
||||
dig_prizes = list(rom.read_bytes(0x180100, 64))
|
||||
dig_prizes = [prize_replacements.get(byte, byte) for byte in dig_prizes]
|
||||
rom.write_bytes(0x180100, dig_prizes)
|
||||
|
||||
prizes = list(rom.read_bytes(0x37A78, 56))
|
||||
prizes = [prize_replacements.get(byte, byte) for byte in prizes]
|
||||
rom.write_bytes(0x37A78, prizes)
|
||||
|
||||
for address in (0xEFBD4, 0xEFBD5, 0xEFBD6, 0x329C8, 0x329C4, 0x37993, 0xE82CC):
|
||||
byte = int(rom.read_byte(address))
|
||||
rom.write_byte(address, prize_replacements.get(byte, byte))
|
||||
|
||||
if "b" in world.shuffle_prizes[player]:
|
||||
# set bonk prizes
|
||||
bonk_prizes = [0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xAC, 0xE3, 0xE3, 0xDA, 0xE3, 0xDA, 0xD8, 0xAC,
|
||||
|
@ -1001,18 +1044,21 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
0xE3, 0xE3,
|
||||
0xDA, 0x79, 0xAC, 0xAC, 0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xE3, 0x79, 0xDE, 0xE3,
|
||||
0xAC, 0xDB, 0x79, 0xE3, 0xD8, 0xAC, 0x79, 0xE3, 0xDB, 0xDB, 0xE3, 0xE3, 0x79, 0xD8, 0xDD]
|
||||
bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028, 0x4D03C, 0x4D059, 0x4D07A,
|
||||
0x4D09E, 0x4D0A8, 0x4D0AB, 0x4D0AE, 0x4D0BE, 0x4D0DD,
|
||||
0x4D16A, 0x4D1E5, 0x4D1EE, 0x4D20B, 0x4CBBF, 0x4CBBF, 0x4CC17, 0x4CC1A, 0x4CC4A, 0x4CC4D,
|
||||
0x4CC53, 0x4CC69, 0x4CC6F, 0x4CC7C, 0x4CCEF, 0x4CD51,
|
||||
0x4CDC0, 0x4CDC3, 0x4CDC6, 0x4CE37, 0x4D2DE, 0x4D32F, 0x4D355, 0x4D367, 0x4D384, 0x4D387,
|
||||
0x4D397, 0x4D39E, 0x4D3AB, 0x4D3AE, 0x4D3D1, 0x4D3D7,
|
||||
0x4D3F8, 0x4D416, 0x4D420, 0x4D423, 0x4D42D, 0x4D449, 0x4D48C, 0x4D4D9, 0x4D4DC, 0x4D4E3,
|
||||
0x4D504, 0x4D507, 0x4D55E, 0x4D56A]
|
||||
|
||||
local_random.shuffle(bonk_prizes)
|
||||
|
||||
if prize_replacements:
|
||||
bonk_prizes = [prize_replacements.get(prize, prize) for prize in bonk_prizes]
|
||||
|
||||
for prize, address in zip(bonk_prizes, bonk_addresses):
|
||||
rom.write_byte(address, prize)
|
||||
|
||||
elif prize_replacements:
|
||||
for address in bonk_addresses:
|
||||
byte = int(rom.read_byte(address))
|
||||
rom.write_byte(address, prize_replacements.get(byte, byte))
|
||||
|
||||
|
||||
# Fill in item substitutions table
|
||||
rom.write_bytes(0x184000, [
|
||||
# original_item, limit, replacement_item, filler
|
||||
|
@ -1071,7 +1117,7 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
rom.write_byte(0x180043, 0xFF if world.swords[player] == 'swordless' else 0x00) # starting sword for link
|
||||
rom.write_byte(0x180044, 0x01 if world.swords[player] == 'swordless' else 0x00) # hammer activates tablets
|
||||
|
||||
if world.difficulty_adjustments[player] == 'easy':
|
||||
if world.item_functionality[player] == 'easy':
|
||||
rom.write_byte(0x18003F, 0x01) # hammer can harm ganon
|
||||
rom.write_byte(0x180041, 0x02) # Allow swordless medallion use EVERYWHERE.
|
||||
rom.write_byte(0x180044, 0x01) # hammer activates tablets
|
||||
|
@ -1250,7 +1296,9 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
'Big Key (Ganons Tower)': (0x366, 0x04), 'Compass (Ganons Tower)': (0x364, 0x04),
|
||||
'Map (Ganons Tower)': (0x368, 0x04)}
|
||||
set_or_table = {'Flippers': (0x356, 1, 0x379, 0x02), 'Pegasus Boots': (0x355, 1, 0x379, 0x04),
|
||||
'Shovel': (0x34C, 1, 0x38C, 0x04), 'Flute': (0x34C, 3, 0x38C, 0x01),
|
||||
'Shovel': (0x34C, 1, 0x38C, 0x04),
|
||||
'Flute': (0x34C, 2, 0x38C, 0x02),
|
||||
'Activated Flute': (0x34C, 3, 0x38C, 0x01),
|
||||
'Mushroom': (0x344, 1, 0x38C, 0x20 | 0x08), 'Magic Powder': (0x344, 2, 0x38C, 0x10),
|
||||
'Blue Boomerang': (0x341, 1, 0x38C, 0x80), 'Red Boomerang': (0x341, 2, 0x38C, 0x40)}
|
||||
keys = {'Small Key (Eastern Palace)': [0x37E], 'Small Key (Desert Palace)': [0x37F],
|
||||
|
@ -1560,6 +1608,7 @@ def write_custom_shops(rom, world, player):
|
|||
|
||||
shop_data = bytearray()
|
||||
items_data = bytearray()
|
||||
retro_shop_slots = bytearray()
|
||||
|
||||
for shop_id, shop in enumerate(shops):
|
||||
if shop_id == len(shops) - 1:
|
||||
|
@ -1568,10 +1617,27 @@ def write_custom_shops(rom, world, player):
|
|||
bytes[0] = shop_id
|
||||
bytes[-1] = shop.sram_offset
|
||||
shop_data.extend(bytes)
|
||||
# [id][item][price-low][price-high][max][repl_id][repl_price-low][repl_price-high][player]
|
||||
for item in shop.inventory:
|
||||
|
||||
arrow_mask = 0x00
|
||||
for index, item in enumerate(shop.inventory):
|
||||
slot = 0 if shop.type == ShopType.TakeAny else index
|
||||
if item is None:
|
||||
break
|
||||
if world.shop_shuffle_slots[player] or shop.type == ShopType.TakeAny:
|
||||
count_shop = (shop.region.name != 'Potion Shop' or 'w' in world.shop_shuffle[player]) and \
|
||||
shop.region.name != 'Capacity Upgrade'
|
||||
rom.write_byte(0x186560 + shop.sram_offset + slot, 1 if count_shop else 0)
|
||||
if item['item'] == 'Single Arrow' and item['player'] == 0:
|
||||
arrow_mask |= 1 << index
|
||||
retro_shop_slots.append(shop.sram_offset + slot)
|
||||
|
||||
# [id][item][price-low][price-high][max][repl_id][repl_price-low][repl_price-high][player]
|
||||
for index, item in enumerate(shop.inventory):
|
||||
slot = 0 if shop.type == ShopType.TakeAny else index
|
||||
if item is None:
|
||||
break
|
||||
if item['item'] == 'Single Arrow' and item['player'] == 0 and world.retro[player]:
|
||||
rom.write_byte(0x186500 + shop.sram_offset + slot, arrow_mask)
|
||||
item_data = [shop_id, ItemFactory(item['item'], player).code] + int16_as_bytes(item['price']) + \
|
||||
[item['max'], ItemFactory(item['replacement'], player).code if item['replacement'] else 0xFF] + \
|
||||
int16_as_bytes(item['replacement_price']) + [0 if item['player'] == player else item['player']]
|
||||
|
@ -1582,6 +1648,10 @@ def write_custom_shops(rom, world, player):
|
|||
items_data.extend([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
||||
rom.write_bytes(0x184900, items_data)
|
||||
|
||||
if world.retro[player]:
|
||||
retro_shop_slots.append(0xFF)
|
||||
rom.write_bytes(0x186540, retro_shop_slots)
|
||||
|
||||
|
||||
def hud_format_text(text):
|
||||
output = bytes()
|
||||
|
@ -1602,7 +1672,7 @@ def hud_format_text(text):
|
|||
|
||||
|
||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, triforcehud, sprite: str, palettes_options,
|
||||
world=None, player=1, allow_random_on_event=False):
|
||||
world=None, player=1, allow_random_on_event=False, reduceflashing=False):
|
||||
local_random = random if not world else world.rom_seeds[player]
|
||||
|
||||
# enable instant item menu
|
||||
|
@ -1627,6 +1697,23 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, tri
|
|||
else:
|
||||
rom.write_byte(0x180048, 0x08)
|
||||
|
||||
|
||||
# Reduce flashing by nopping out instructions
|
||||
if reduceflashing:
|
||||
rom.write_bytes(0x17E07, [0x06]) # reduce amount of colors changed, add this branch if we need to reduce more ""+ [0x80] + [(0x81-0x08)]""
|
||||
rom.write_bytes(0x17EAB, [0xD0, 0x03, 0xA9, 0x40, 0x29, 0x60]) # nullifies aga lightning, cutscene, vitreous, bat, ether
|
||||
# ONLY write to black values with this low pale blue to indicate flashing, that's IT. ""BNE + : LDA #$2940 : + : RTS""
|
||||
rom.write_bytes(0x123FE, [0x72]) # set lightning flash in misery mire (and standard) to brightness 0x72
|
||||
rom.write_bytes(0x3FA7B, [0x80, 0xac-0x7b]) # branch from palette writing lightning on death mountain
|
||||
rom.write_byte(0x10817F, 0x01) # internal rom option
|
||||
else:
|
||||
rom.write_bytes(0x17E07, [0x00])
|
||||
rom.write_bytes(0x17EAB, [0x85, 0x00, 0x29, 0x1F, 0x00, 0x18])
|
||||
rom.write_bytes(0x123FE, [0x32]) # original weather flash value
|
||||
rom.write_bytes(0x3FA7B, [0xc2, 0x20]) # rep #$20
|
||||
rom.write_byte(0x10817F, 0x00) # internal rom option
|
||||
|
||||
|
||||
rom.write_byte(0x18004B, 0x01 if quickswap else 0x00)
|
||||
|
||||
rom.write_byte(0x0CFE18, 0x00 if disable_music else rom.orig_buffer[0x0CFE18] if rom.orig_buffer else 0x70)
|
||||
|
@ -1911,6 +1998,9 @@ def write_strings(rom, world, player, team):
|
|||
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.'
|
||||
|
||||
if world.mode[player] == 'inverted':
|
||||
tt['sign_village_of_outcasts'] = 'attention\nferal ducks sighted\nhiding in statues\n\nflute players beware\n'
|
||||
|
||||
def hint_text(dest, ped_hint=False):
|
||||
if not dest:
|
||||
return "nothing"
|
||||
|
@ -1929,6 +2019,15 @@ def write_strings(rom, world, player, team):
|
|||
|
||||
# For hints, first we write hints about entrances, some from the inconvenient list others from all reasonable entrances.
|
||||
if world.hints[player]:
|
||||
# Zora hint
|
||||
zora_location = world.get_location("King Zora", player)
|
||||
tt['zora_tells_cost'] = f"You got 500 rupees to buy {hint_text(zora_location.item)}" \
|
||||
f"\n ≥ Duh\n Oh carp\n{{CHOICE}}"
|
||||
# Bottle Vendor hint
|
||||
vendor_location = world.get_location("Bottle Merchant", player)
|
||||
tt['bottle_vendor_choice'] = f"I gots {hint_text(vendor_location.item)}\nYous gots 100 rupees?"\
|
||||
f"\n ≥ I want\n no way!\n{{CHOICE}}"
|
||||
|
||||
tt['sign_north_of_links_house'] = '> Randomizer The telepathic tiles can have hints!'
|
||||
hint_locations = HintLocations.copy()
|
||||
local_random.shuffle(hint_locations)
|
||||
|
@ -1961,7 +2060,7 @@ def write_strings(rom, world, player, team):
|
|||
hint_count = 4
|
||||
for entrance in all_entrances:
|
||||
if entrance.name in entrances_to_hint:
|
||||
if hint_count > 0:
|
||||
if hint_count:
|
||||
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(
|
||||
entrance.connected_region) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
|
@ -1998,7 +2097,7 @@ def write_strings(rom, world, player, team):
|
|||
hint_count = 4 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 0
|
||||
for entrance in all_entrances:
|
||||
if entrance.name in entrances_to_hint:
|
||||
if hint_count > 0:
|
||||
if hint_count:
|
||||
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(
|
||||
entrance.connected_region) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
|
@ -2013,10 +2112,9 @@ def write_strings(rom, world, player, team):
|
|||
locations_to_hint.extend(InconvenientVanillaLocations)
|
||||
local_random.shuffle(locations_to_hint)
|
||||
hint_count = 3 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 5
|
||||
del locations_to_hint[hint_count:]
|
||||
for location in locations_to_hint:
|
||||
for location in locations_to_hint[:hint_count]:
|
||||
if location == 'Swamp Left':
|
||||
if local_random.randint(0, 1) == 0:
|
||||
if local_random.randint(0, 1):
|
||||
first_item = hint_text(world.get_location('Swamp Palace - West Chest', player).item)
|
||||
second_item = hint_text(world.get_location('Swamp Palace - Big Key Chest', player).item)
|
||||
else:
|
||||
|
@ -2025,7 +2123,7 @@ def write_strings(rom, world, player, team):
|
|||
this_hint = ('The westmost chests in Swamp Palace contain ' + first_item + ' and ' + second_item + '.')
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
elif location == 'Mire Left':
|
||||
if local_random.randint(0, 1) == 0:
|
||||
if local_random.randint(0, 1):
|
||||
first_item = hint_text(world.get_location('Misery Mire - Compass Chest', player).item)
|
||||
second_item = hint_text(world.get_location('Misery Mire - Big Key Chest', player).item)
|
||||
else:
|
||||
|
@ -2085,8 +2183,8 @@ def write_strings(rom, world, player, team):
|
|||
# All remaining hint slots are filled with junk hints. It is done this way to ensure the same junk hint isn't selected twice.
|
||||
junk_hints = junk_texts.copy()
|
||||
local_random.shuffle(junk_hints)
|
||||
for location in hint_locations:
|
||||
tt[location] = junk_hints.pop(0)
|
||||
for location, text in zip(hint_locations, junk_hints):
|
||||
tt[location] = text
|
||||
|
||||
# We still need the older hints of course. Those are done here.
|
||||
|
||||
|
@ -2273,6 +2371,10 @@ def set_inverted_mode(world, player, rom):
|
|||
rom.write_byte(snes_to_pc(0x05AF79), 0xF0)
|
||||
rom.write_byte(snes_to_pc(0x0DB3C5), 0xC6)
|
||||
rom.write_byte(snes_to_pc(0x07A3F4), 0xF0) # duck
|
||||
rom.write_byte(0xDC21D, 0x6B) # inverted mode flute activation (skip weathervane overlay)
|
||||
rom.write_bytes(0x48DB3, [0xF8, 0x01]) # inverted mode (bird X)
|
||||
rom.write_byte(0x48D5E, 0x01) # inverted mode (rock X)
|
||||
rom.write_bytes(0x48CC1+36, bytes([0xF8]*12)) # (rock X)
|
||||
rom.write_int16s(snes_to_pc(0x02E849),
|
||||
[0x0043, 0x0056, 0x0058, 0x006C, 0x006F, 0x0070, 0x007B, 0x007F, 0x001B]) # dw flute
|
||||
rom.write_int16(snes_to_pc(0x02E8D5), 0x07C8)
|
||||
|
|
80
Rules.py
80
Rules.py
|
@ -429,6 +429,8 @@ def global_rules(world, player):
|
|||
add_rule(ganon, lambda state: state.has_crystals(world.crystals_needed_for_ganon[player], player))
|
||||
set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop
|
||||
|
||||
set_rule(world.get_location('Flute Activation Spot', player), lambda state: state.has('Flute', player))
|
||||
|
||||
|
||||
def default_rules(world, player):
|
||||
"""Default world rules when world state is not inverted."""
|
||||
|
@ -447,9 +449,9 @@ def default_rules(world, player):
|
|||
set_rule(world.get_entrance('50 Rupee Cave', player), lambda state: state.can_lift_rocks(player))
|
||||
set_rule(world.get_entrance('Death Mountain Entrance Rock', player), lambda state: state.can_lift_rocks(player))
|
||||
set_rule(world.get_entrance('Bumper Cave Entrance Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Flute Spot 1', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('Flute Spot 1', player), lambda state: state.has('Activated Flute', player))
|
||||
set_rule(world.get_entrance('Lake Hylia Central Island Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
|
||||
set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.can_flute(player) and state.can_lift_heavy_rocks(player))
|
||||
set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Activated Flute', player) and state.can_lift_heavy_rocks(player))
|
||||
set_rule(world.get_entrance('East Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot use hammer
|
||||
set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot use hammer
|
||||
set_rule(world.get_entrance('Kakariko Teleporter', player), lambda state: ((state.has('Hammer', player) and state.can_lift_rocks(player)) or state.can_lift_heavy_rocks(player)) and state.has_Pearl(player)) # bunny cannot lift bushes
|
||||
|
@ -575,7 +577,7 @@ def inverted_rules(world, player):
|
|||
set_rule(world.get_entrance('Bumper Cave Entrance Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Dark Lake Hylia Central Island Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
|
||||
set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.can_flute(player) and state.can_lift_heavy_rocks(player))
|
||||
set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Activated Flute', player) and state.can_lift_heavy_rocks(player))
|
||||
set_rule(world.get_entrance('East Dark World Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot use hammer
|
||||
set_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot use hammer
|
||||
set_rule(world.get_entrance('West Dark World Teleporter', player), lambda state: ((state.has('Hammer', player) and state.can_lift_rocks(player)) or state.can_lift_heavy_rocks(player)) and state.has_Pearl(player))
|
||||
|
@ -676,16 +678,16 @@ def inverted_rules(world, player):
|
|||
|
||||
# inverted flute spots
|
||||
|
||||
set_rule(world.get_entrance('DDM Flute', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('NEDW Flute', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('WDW Flute', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('SDW Flute', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('EDW Flute', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('DLHL Flute', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('DD Flute', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('EDDM Flute', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('Dark Grassy Lawn Flute', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('Hammer Peg Area Flute', player), lambda state: state.can_flute(player))
|
||||
set_rule(world.get_entrance('DDM Flute', player), lambda state: state.has('Activated Flute', player))
|
||||
set_rule(world.get_entrance('NEDW Flute', player), lambda state: state.has('Activated Flute', player))
|
||||
set_rule(world.get_entrance('WDW Flute', player), lambda state: state.has('Activated Flute', player))
|
||||
set_rule(world.get_entrance('SDW Flute', player), lambda state: state.has('Activated Flute', player))
|
||||
set_rule(world.get_entrance('EDW Flute', player), lambda state: state.has('Activated Flute', player))
|
||||
set_rule(world.get_entrance('DLHL Flute', player), lambda state: state.has('Activated Flute', player))
|
||||
set_rule(world.get_entrance('DD Flute', player), lambda state: state.has('Activated Flute', player))
|
||||
set_rule(world.get_entrance('EDDM Flute', player), lambda state: state.has('Activated Flute', player))
|
||||
set_rule(world.get_entrance('Dark Grassy Lawn Flute', player), lambda state: state.has('Activated Flute', player))
|
||||
set_rule(world.get_entrance('Hammer Peg Area Flute', player), lambda state: state.has('Activated Flute', player))
|
||||
|
||||
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player])
|
||||
|
||||
|
@ -1125,52 +1127,52 @@ def set_big_bomb_rules(world, player):
|
|||
elif bombshop_entrance.name in Isolated_DW_entrances:
|
||||
# 1. mirror then flute then basic routes
|
||||
# -> M and Flute and BR
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and state.can_flute(player) and basic_routes(state))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and state.has('Activated Flute', player) and basic_routes(state))
|
||||
elif bombshop_entrance.name in Isolated_LW_entrances:
|
||||
# 1. flute then basic routes
|
||||
# Prexisting mirror spot is not permitted, because mirror might have been needed to reach these isolated locations.
|
||||
# -> Flute and BR
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and basic_routes(state))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) and basic_routes(state))
|
||||
elif bombshop_entrance.name in West_LW_DM_entrances:
|
||||
# 1. flute then basic routes or mirror
|
||||
# Prexisting mirror spot is permitted, because flute can be used to reach west DM directly.
|
||||
# -> Flute and (M or BR)
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and (state.has_Mirror(player) or basic_routes(state)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) and (state.has_Mirror(player) or basic_routes(state)))
|
||||
elif bombshop_entrance.name in East_LW_DM_entrances:
|
||||
# 1. flute then basic routes or mirror and hookshot
|
||||
# Prexisting mirror spot is permitted, because flute can be used to reach west DM directly and then east DM via Hookshot
|
||||
# -> Flute and ((M and Hookshot) or BR)
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and ((state.has_Mirror(player) and state.has('Hookshot', player)) or basic_routes(state)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) and ((state.has_Mirror(player) and state.has('Hookshot', player)) or basic_routes(state)))
|
||||
elif bombshop_entrance.name == 'Fairy Ascension Cave (Bottom)':
|
||||
# Same as East_LW_DM_entrances except navigation without BR requires Mitts
|
||||
# -> Flute and ((M and Hookshot and Mitts) or BR)
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and ((state.has_Mirror(player) and state.has('Hookshot', player) and state.can_lift_heavy_rocks(player)) or basic_routes(state)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) and ((state.has_Mirror(player) and state.has('Hookshot', player) and state.can_lift_heavy_rocks(player)) or basic_routes(state)))
|
||||
elif bombshop_entrance.name in Castle_ledge_entrances:
|
||||
# 1. mirror on pyramid to castle ledge, grab bomb, return through mirror spot: Needs mirror
|
||||
# 2. flute then basic routes
|
||||
# -> M or (Flute and BR)
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) or (state.can_flute(player) and basic_routes(state)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) or (state.has('Activated Flute', player) and basic_routes(state)))
|
||||
elif bombshop_entrance.name in Desert_mirrorable_ledge_entrances:
|
||||
# Cases when you have mire access: Mirror to reach locations, return via mirror spot, move to center of desert, mirror anagin and:
|
||||
# 1. Have mire access, Mirror to reach locations, return via mirror spot, move to center of desert, mirror again and then basic routes
|
||||
# 2. flute then basic routes
|
||||
# -> (Mire access and M) or Flute) and BR
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: ((state.can_reach('Dark Desert', 'Region', player) and state.has_Mirror(player)) or state.can_flute(player)) and basic_routes(state))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: ((state.can_reach('Dark Desert', 'Region', player) and state.has_Mirror(player)) or state.has('Activated Flute', player)) and basic_routes(state))
|
||||
elif bombshop_entrance.name == 'Old Man Cave (West)':
|
||||
# 1. Lift rock then basic_routes
|
||||
# 2. flute then basic_routes
|
||||
# -> (Flute or G) and BR
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or state.can_lift_rocks(player)) and basic_routes(state))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Activated Flute', player) or state.can_lift_rocks(player)) and basic_routes(state))
|
||||
elif bombshop_entrance.name == 'Graveyard Cave':
|
||||
# 1. flute then basic routes
|
||||
# 2. (has west dark world access) use existing mirror spot (required Pearl), mirror again off ledge
|
||||
# -> (Flute or (M and P and West Dark World access) and BR
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or (state.can_reach('West Dark World', 'Region', player) and state.has_Pearl(player) and state.has_Mirror(player))) and basic_routes(state))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Activated Flute', player) or (state.can_reach('West Dark World', 'Region', player) and state.has_Pearl(player) and state.has_Mirror(player))) and basic_routes(state))
|
||||
elif bombshop_entrance.name in Mirror_from_SDW_entrances:
|
||||
# 1. flute then basic routes
|
||||
# 2. (has South dark world access) use existing mirror spot, mirror again off ledge
|
||||
# -> (Flute or (M and South Dark World access) and BR
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or (state.can_reach('South Dark World', 'Region', player) and state.has_Mirror(player))) and basic_routes(state))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Activated Flute', player) or (state.can_reach('South Dark World', 'Region', player) and state.has_Mirror(player))) and basic_routes(state))
|
||||
elif bombshop_entrance.name == 'Dark World Potion Shop':
|
||||
# 1. walk down by lifting rock: needs gloves and pearl`
|
||||
# 2. walk down by hammering peg: needs hammer and pearl
|
||||
|
@ -1182,11 +1184,11 @@ def set_big_bomb_rules(world, player):
|
|||
# (because otherwise mirror was used to reach the grave, so would cancel a pre-existing mirror spot)
|
||||
# to account for insanity, must consider a way to escape without a cave for basic_routes
|
||||
# -> (M and Mitts) or ((Mitts or Flute or (M and P and West Dark World access)) and BR)
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and state.has_Mirror(player)) or ((state.can_lift_heavy_rocks(player) or state.can_flute(player) or (state.can_reach('West Dark World', 'Region', player) and state.has_Pearl(player) and state.has_Mirror(player))) and basic_routes(state)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and state.has_Mirror(player)) or ((state.can_lift_heavy_rocks(player) or state.has('Activated Flute', player) or (state.can_reach('West Dark World', 'Region', player) and state.has_Pearl(player) and state.has_Mirror(player))) and basic_routes(state)))
|
||||
elif bombshop_entrance.name == 'Waterfall of Wishing':
|
||||
# same as the Normal_LW_entrances case except in insanity it's possible you could be here without Flippers which
|
||||
# means you need an escape route of either Flippers or Flute
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Flippers', player) or state.can_flute(player)) and (basic_routes(state) or state.has_Mirror(player)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Flippers', player) or state.has('Activated Flute', player)) and (basic_routes(state) or state.has_Mirror(player)))
|
||||
|
||||
|
||||
def set_inverted_big_bomb_rules(world, player):
|
||||
|
@ -1325,50 +1327,50 @@ def set_inverted_big_bomb_rules(world, player):
|
|||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player))
|
||||
elif bombshop_entrance.name in Isolated_LW_entrances:
|
||||
# For these entrances, you cannot walk to the castle/pyramid and thus must use Mirror and then Flute.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and state.has_Mirror(player))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) and state.has_Mirror(player))
|
||||
elif bombshop_entrance.name in Northern_DW_entrances:
|
||||
# You can just fly with the Flute, you can take a long walk with Mitts and Hammer,
|
||||
# or you can leave a Mirror portal nearby and then walk to the castle to Mirror again.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player)))
|
||||
elif bombshop_entrance.name in Southern_DW_entrances:
|
||||
# This is the same as north DW without the Mitts rock present.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Hammer', player) or state.can_flute(player) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Hammer', player) or state.has('Activated Flute', player) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player)))
|
||||
elif bombshop_entrance.name in Isolated_DW_entrances:
|
||||
# There's just no way to escape these places with the bomb and no Flute.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player))
|
||||
elif bombshop_entrance.name in LW_walkable_entrances:
|
||||
# You can fly with the flute, or leave a mirror portal and walk through the light world
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player)))
|
||||
elif bombshop_entrance.name in LW_bush_entrances:
|
||||
# These entrances are behind bushes in LW so you need either Pearl or the tools to solve NDW bomb shop locations.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and (state.can_flute(player) or state.has_Pearl(player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player))))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and (state.has('Activated Flute', player) or state.has_Pearl(player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player))))
|
||||
elif bombshop_entrance.name == 'Dark World Shop':
|
||||
# This is mostly the same as NDW but the Mirror path requires the Pearl, or using the Hammer
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player) and (state.has_Pearl(player) or state.has('Hammer', player))))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_reach('Light World', 'Region', player) and (state.has_Pearl(player) or state.has('Hammer', player))))
|
||||
elif bombshop_entrance.name == 'Bumper Cave (Bottom)':
|
||||
# This is mostly the same as NDW but the Mirror path requires being able to lift a rock.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_lift_rocks(player) and state.can_reach('Light World', 'Region', player)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_lift_rocks(player) and state.can_reach('Light World', 'Region', player)))
|
||||
elif bombshop_entrance.name == 'Old Man Cave (West)':
|
||||
# The three paths back are Mirror and DW walk, Mirror and Flute, or LW walk and then Mirror.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and ((state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.can_lift_rocks(player) and state.has_Pearl(player)) or state.can_flute(player)))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and ((state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.can_lift_rocks(player) and state.has_Pearl(player)) or state.has('Activated Flute', player)))
|
||||
elif bombshop_entrance.name == 'Dark World Potion Shop':
|
||||
# You either need to Flute to 5 or cross the rock/hammer choice pass to the south.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) or state.has('Hammer', player) or state.can_lift_rocks(player))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or state.has('Hammer', player) or state.can_lift_rocks(player))
|
||||
elif bombshop_entrance.name == 'Kings Grave':
|
||||
# Either lift the rock and walk to the castle to Mirror or Mirror immediately and Flute.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or state.can_lift_heavy_rocks(player)) and state.has_Mirror(player))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Activated Flute', player) or state.can_lift_heavy_rocks(player)) and state.has_Mirror(player))
|
||||
elif bombshop_entrance.name == 'Waterfall of Wishing':
|
||||
# You absolutely must be able to swim to return it from here.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player) and state.has_Mirror(player))
|
||||
elif bombshop_entrance.name == 'Ice Palace':
|
||||
# You can swim to the dock or use the Flute to get off the island.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Flippers', player) or state.can_flute(player))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Flippers', player) or state.has('Activated Flute', player))
|
||||
elif bombshop_entrance.name == 'Capacity Upgrade':
|
||||
# You must Mirror but then can use either Ice Palace return path.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Flippers', player) or state.can_flute(player)) and state.has_Mirror(player))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Flippers', player) or state.has('Activated Flute', player)) and state.has_Mirror(player))
|
||||
elif bombshop_entrance.name == 'Two Brothers House (West)':
|
||||
# First you must Mirror. Then you can either Flute, cross the peg bridge, or use the Agah 1 portal to Mirror again.
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or state.has('Hammer', player) or state.has('Beat Agahnim 1', player)) and state.has_Mirror(player))
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Activated Flute', player) or state.has('Hammer', player) or state.has('Beat Agahnim 1', player)) and state.has_Mirror(player))
|
||||
elif bombshop_entrance.name in LW_inaccessible_entrances:
|
||||
# You can't get to the pyramid from these entrances without bomb duping.
|
||||
raise Exception('No valid path to open Pyramid Fairy. (Could not route from %s)' % bombshop_entrance.name)
|
||||
|
|
200
Shops.py
200
Shops.py
|
@ -5,7 +5,7 @@ import logging
|
|||
|
||||
from BaseClasses import Location
|
||||
from EntranceShuffle import door_addresses
|
||||
from Items import item_name_groups, item_table, ItemFactory
|
||||
from Items import item_name_groups, item_table, ItemFactory, trap_replaceable, GetBeemizerItem
|
||||
from Utils import int16_as_bytes
|
||||
|
||||
logger = logging.getLogger("Shops")
|
||||
|
@ -96,6 +96,9 @@ class Shop():
|
|||
if not self.inventory[slot]:
|
||||
raise ValueError("Inventory can't be pushed back if it doesn't exist")
|
||||
|
||||
if not self.can_push_inventory(slot):
|
||||
logging.warning(f'Warning, there is already an item pushed into this slot.')
|
||||
|
||||
self.inventory[slot] = {
|
||||
'item': item,
|
||||
'price': price,
|
||||
|
@ -145,45 +148,66 @@ def ShopSlotFill(world):
|
|||
slot_num = int(location.name[-1]) - 1
|
||||
shop: Shop = location.parent_region.shop
|
||||
if not shop.can_push_inventory(slot_num) or location.shop_slot_disabled:
|
||||
location.shop_slot_disabled = True
|
||||
removed.add(location)
|
||||
|
||||
if removed:
|
||||
shop_slots -= removed
|
||||
|
||||
if 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")
|
||||
candidates_per_sphere = list(list(sphere) for sphere in world.get_spheres())
|
||||
|
||||
candidate_condition = lambda location: not location.locked and \
|
||||
not location.shop_slot and \
|
||||
not location.item.name in blacklist_words
|
||||
locations_per_sphere = list(list(sphere) for sphere in world.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 = []
|
||||
|
||||
for sphere in 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 location.shop_slot:
|
||||
if not location.shop_slot_disabled:
|
||||
current_shops_slots.append(location)
|
||||
elif not location.locked and not location.item.name in blacklist_words:
|
||||
current_candidates.append(location)
|
||||
if cumu_weights:
|
||||
x = cumu_weights[-1]
|
||||
else:
|
||||
x = 0
|
||||
cumu_weights.append(len(sphere) + x)
|
||||
world.random.shuffle(sphere)
|
||||
cumu_weights.append(len(current_candidates) + x)
|
||||
|
||||
for i, sphere in enumerate(candidates_per_sphere):
|
||||
current_shop_slots = [location for location in sphere if location.shop_slot and not location.shop_slot_disabled]
|
||||
world.random.shuffle(current_candidates)
|
||||
|
||||
del locations_per_sphere
|
||||
|
||||
total_spheres = len(candidates_per_sphere)
|
||||
|
||||
for i, current_shop_slots in enumerate(shops_per_sphere):
|
||||
if current_shop_slots:
|
||||
|
||||
candidate_sphere_ids = list(range(i, total_spheres))
|
||||
for location in current_shop_slots:
|
||||
shop: Shop = location.parent_region.shop
|
||||
swapping_sphere = world.random.choices(candidates_per_sphere[i:], cum_weights=cumu_weights[i:])[0]
|
||||
swapping_sphere_id = world.random.choices(candidate_sphere_ids,
|
||||
cum_weights=cumu_weights[i:])[0]
|
||||
swapping_sphere: list = candidates_per_sphere[swapping_sphere_id]
|
||||
for c in swapping_sphere: # chosen item locations
|
||||
if candidate_condition(c) and c.item_rule(location.item) and location.item_rule(c.item):
|
||||
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}')
|
||||
break
|
||||
|
@ -193,18 +217,22 @@ def ShopSlotFill(world):
|
|||
logger.warning("Ran out of ShopShuffle Item candidate locations.")
|
||||
location.shop_slot_disabled = True
|
||||
continue
|
||||
item_name = location.item.name
|
||||
if any(x in item_name for x in ['Single Bomb', 'Single Arrow']):
|
||||
price = world.random.randrange(1, 7)
|
||||
elif any(x in item_name for x in ['Arrows', 'Bombs', 'Clock']):
|
||||
price = world.random.randrange(4, 24)
|
||||
elif any(x in item_name for x in ['Compass', 'Map', 'Small Key', 'Piece of Heart']):
|
||||
price = world.random.randrange(10, 30)
|
||||
else:
|
||||
price = world.random.randrange(10, 60)
|
||||
|
||||
price *= 5
|
||||
shop.push_inventory(int(location.name[-1]) - 1, item_name, price, 1,
|
||||
# remove candidate
|
||||
swapping_sphere.remove(c)
|
||||
cumu_weights[swapping_sphere_id] -= 1
|
||||
|
||||
item_name = location.item.name
|
||||
if any(x in item_name for x in ['Compass', 'Map', 'Single Bomb', 'Single Arrow', 'Piece of Heart']):
|
||||
price = world.random.randrange(1, 7)
|
||||
elif any(x in item_name for x in ['Arrow', 'Bomb', 'Clock']):
|
||||
price = world.random.randrange(2, 14)
|
||||
elif any(x in item_name for x in ['Small Key', 'Heart']):
|
||||
price = world.random.randrange(4, 28)
|
||||
else:
|
||||
price = world.random.randrange(8, 56)
|
||||
|
||||
shop.push_inventory(int(location.name[-1]) - 1, item_name, price * 5, 1,
|
||||
location.item.player if location.item.player != location.player else 0)
|
||||
|
||||
|
||||
|
@ -238,11 +266,16 @@ def create_shops(world, player: int):
|
|||
keeper = world.random.choice([0xA0, 0xC1, 0xFF])
|
||||
player_shop_table[name] = ShopData(typ, shop_id, keeper, custom, locked, new_items, sram_offset)
|
||||
if world.mode[player] == "inverted":
|
||||
# make sure that blue potion is available in inverted, special case locked = None; lock when done.
|
||||
player_shop_table["Dark Lake Hylia Shop"] = \
|
||||
player_shop_table["Dark Lake Hylia Shop"]._replace(locked=True, items=_inverted_hylia_shop_defaults)
|
||||
player_shop_table["Dark Lake Hylia Shop"]._replace(items=_inverted_hylia_shop_defaults, locked=None)
|
||||
chance_100 = int(world.retro[player])*0.25+int(world.keyshuffle[player] == "universal") * 0.5
|
||||
for region_name, (room_id, type, shopkeeper, custom, locked, inventory, sram_offset) in player_shop_table.items():
|
||||
region = world.get_region(region_name, player)
|
||||
shop: Shop = shop_class_mapping[type](region, room_id, shopkeeper, custom, locked, sram_offset)
|
||||
# special case: allow shop slots, but do not allow overwriting of base inventory behind them
|
||||
if locked is None:
|
||||
shop.locked = True
|
||||
region.shop = shop
|
||||
world.shops.append(shop)
|
||||
for index, item in enumerate(inventory):
|
||||
|
@ -255,12 +288,15 @@ def create_shops(world, player: int):
|
|||
loc.locked = True
|
||||
if single_purchase_slots.pop():
|
||||
if world.goal[player] != 'icerodhunt':
|
||||
additional_item = 'Rupees (50)' # world.random.choice(['Rupees (50)', 'Rupees (100)', 'Rupees (300)'])
|
||||
if world.random.random() < chance_100:
|
||||
additional_item = 'Rupees (100)'
|
||||
else:
|
||||
additional_item = 'Rupees (50)'
|
||||
else:
|
||||
additional_item = 'Nothing'
|
||||
additional_item = GetBeemizerItem(world, player, 'Nothing')
|
||||
loc.item = ItemFactory(additional_item, player)
|
||||
else:
|
||||
loc.item = ItemFactory('Nothing', player)
|
||||
loc.item = ItemFactory(GetBeemizerItem(world, player, 'Nothing'), player)
|
||||
loc.shop_slot_disabled = True
|
||||
shop.region.locations.append(loc)
|
||||
world.dynamic_locations.append(loc)
|
||||
|
@ -272,7 +308,7 @@ class ShopData(NamedTuple):
|
|||
type: ShopType
|
||||
shopkeeper: int
|
||||
custom: bool
|
||||
locked: bool
|
||||
locked: Optional[bool]
|
||||
items: List
|
||||
sram_offset: int
|
||||
|
||||
|
@ -322,3 +358,109 @@ shop_generation_types = {
|
|||
'bottle': [('Small Heart', 10), ('Apple', 50), ('Bee', 10), ('Good Bee', 100), ('Faerie', 100), ('Magic Jar', 100)],
|
||||
'time': [('Red Clock', 100), ('Blue Clock', 200), ('Green Clock', 300)],
|
||||
}
|
||||
|
||||
|
||||
def set_up_shops(world, player: int):
|
||||
# TODO: move hard+ mode changes for shields here, utilizing the new shops
|
||||
|
||||
if world.retro[player]:
|
||||
rss = world.get_region('Red Shield Shop', player).shop
|
||||
replacement_items = [['Red Potion', 150], ['Green Potion', 75], ['Blue Potion', 200], ['Bombs (10)', 50],
|
||||
['Blue Shield', 50], ['Small Heart', 10]] # Can't just replace the single arrow with 10 arrows as retro doesn't need them.
|
||||
if world.keyshuffle[player] == "universal":
|
||||
replacement_items.append(['Small Key (Universal)', 100])
|
||||
replacement_item = world.random.choice(replacement_items)
|
||||
rss.add_inventory(2, 'Single Arrow', 80, 1, replacement_item[0], replacement_item[1])
|
||||
rss.locked = True
|
||||
|
||||
if world.keyshuffle[player] == "universal" or world.retro[player]:
|
||||
for shop in world.random.sample([s for s in world.shops if
|
||||
s.custom and not s.locked and s.type == ShopType.Shop and s.region.player == player],
|
||||
5):
|
||||
shop.locked = True
|
||||
slots = [0, 1, 2]
|
||||
world.random.shuffle(slots)
|
||||
slots = iter(slots)
|
||||
if world.keyshuffle[player] == "universal":
|
||||
shop.add_inventory(next(slots), 'Small Key (Universal)', 100)
|
||||
if world.retro[player]:
|
||||
shop.push_inventory(next(slots), 'Single Arrow', 80)
|
||||
|
||||
|
||||
def shuffle_shops(world, items, player: int):
|
||||
option = world.shop_shuffle[player]
|
||||
if 'u' in option:
|
||||
progressive = world.progressive[player]
|
||||
progressive = world.random.choice([True, False]) if progressive == '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[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 \
|
||||
shop.region.name == "Capacity Upgrade":
|
||||
shop.clear_inventory()
|
||||
capacityshop = shop
|
||||
|
||||
if world.goal[player] != 'icerodhunt':
|
||||
for i, item in enumerate(items):
|
||||
if item.name in trap_replaceable:
|
||||
items[i] = ItemFactory(new_items.pop(), player)
|
||||
if not new_items:
|
||||
break
|
||||
else:
|
||||
logging.warning(f"Not all upgrades put into Player{player}' item pool. Putting remaining items in Capacity Upgrade shop instead.")
|
||||
bombupgrades = sum(1 for item in new_items if 'Bomb Upgrade' in item)
|
||||
arrowupgrades = sum(1 for item in new_items if 'Arrow Upgrade' in item)
|
||||
if bombupgrades:
|
||||
capacityshop.add_inventory(1, 'Bomb Upgrade (+5)', 100, bombupgrades)
|
||||
if arrowupgrades:
|
||||
capacityshop.add_inventory(1, 'Arrow Upgrade (+5)', 100, arrowupgrades)
|
||||
else:
|
||||
for item in new_items:
|
||||
world.push_precollected(ItemFactory(item, player))
|
||||
|
||||
if 'p' in option or 'i' in option:
|
||||
shops = []
|
||||
upgrade_shops = []
|
||||
total_inventory = []
|
||||
for shop in world.shops:
|
||||
if shop.region.player == player:
|
||||
if shop.type == ShopType.UpgradeShop:
|
||||
upgrade_shops.append(shop)
|
||||
elif shop.type == ShopType.Shop and not shop.locked:
|
||||
shops.append(shop)
|
||||
total_inventory.extend(shop.inventory)
|
||||
|
||||
if 'p' in option:
|
||||
def price_adjust(price: int) -> int:
|
||||
# it is important that a base price of 0 always returns 0 as new price!
|
||||
adjust = 2 if price < 100 else 5
|
||||
return int((price / adjust) * (0.5 + world.random.random() * 1.5)) * adjust
|
||||
|
||||
def adjust_item(item):
|
||||
if item:
|
||||
item["price"] = price_adjust(item["price"])
|
||||
item['replacement_price'] = price_adjust(item["price"])
|
||||
|
||||
for item in total_inventory:
|
||||
adjust_item(item)
|
||||
for shop in upgrade_shops:
|
||||
for item in shop.inventory:
|
||||
adjust_item(item)
|
||||
|
||||
if 'i' in option:
|
||||
world.random.shuffle(total_inventory)
|
||||
|
||||
i = 0
|
||||
for shop in shops:
|
||||
slots = shop.slots
|
||||
shop.inventory = total_inventory[i:i + slots]
|
||||
i += slots
|
||||
|
|
6
Text.py
6
Text.py
|
@ -1443,7 +1443,7 @@ class TextTable(object):
|
|||
'zora_meeting',
|
||||
'zora_tells_cost',
|
||||
'zora_get_flippers',
|
||||
#'zora_no_cash',
|
||||
'zora_no_cash',
|
||||
'zora_no_buy_item',
|
||||
'agahnim_zelda_teleport',
|
||||
'agahnim_magic_running_away',
|
||||
|
@ -1725,7 +1725,7 @@ class TextTable(object):
|
|||
text['game_race_boy_already_won'] = CompressedTextMapper.convert("You already have your prize, dingus!")
|
||||
# D0
|
||||
text['game_race_boy_sneaky'] = CompressedTextMapper.convert("Thought you could sneak in, eh?")
|
||||
text['bottle_vendor_choice'] = CompressedTextMapper.convert("I gots bottles.\nYous gots 100 rupees?\n ≥ I want\n no way!")
|
||||
text['bottle_vendor_choice'] = CompressedTextMapper.convert("I gots bottles.\nYous gots 100 rupees?\n ≥ I want\n no way!\n{CHOICE}")
|
||||
text['bottle_vendor_get'] = CompressedTextMapper.convert("Nice! Hold it up son! Show the world what you got!")
|
||||
text['bottle_vendor_no'] = CompressedTextMapper.convert("Fine! I didn't want your money anyway.")
|
||||
text['bottle_vendor_already_collected'] = CompressedTextMapper.convert("Dude! You already have it.")
|
||||
|
@ -1884,7 +1884,7 @@ class TextTable(object):
|
|||
text['item_get_whole_heart'] = CompressedTextMapper.convert("You got a whole ♥!!\nGo you!")
|
||||
text['item_get_sanc_heart'] = CompressedTextMapper.convert("You got a whole ♥!\nGo you!")
|
||||
text['fairy_fountain_refill'] = CompressedTextMapper.convert("Well done, lettuce have a cup of tea…")
|
||||
text['death_mountain_bullied_no_pearl'] = CompressedTextMapper.convert("The following license applies to the base patch for the randomizer.\n\nCopyright (c) 2017 LLCoolDave\n\nCopyright (c) 2020 Berserker66\n\nCopyright (c) 2020 CaitSith2\n\nCopyright 2016, 2017 Equilateral IT\n\n Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.")
|
||||
text['death_mountain_bullied_no_pearl'] = CompressedTextMapper.convert("The following license applies to the base patch for the randomizer.\n\nCopyright (c) 2017 LLCoolDave\n\nCopyright (c) 2021 Berserker66\n\nCopyright (c) 2021 CaitSith2\n\nCopyright 2016, 2017 Equilateral IT\n\n Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.")
|
||||
text['death_mountain_bullied_with_pearl'] = CompressedTextMapper.convert("The software is provided \"as is\", without warranty of any kind, express or implied, including but not limited to the warranties of\nmerchantability,\nfitness for a particular purpose and\nnoninfringement.\nIn no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the software.")
|
||||
text['death_mountain_bully_no_pearl'] = CompressedTextMapper.convert("Add garlic, ginger and apple and cook for 2 minutes. Add carrots, potatoes, garam masala and curry powder and stir well. Add tomato paste, stir well and slowly add red wine and bring to a boil. Add sugar, soy sauce and water, stir and bring to a boil again.")
|
||||
text['death_mountain_bully_with_pearl'] = CompressedTextMapper.convert("I think I forgot how to smile…")
|
||||
|
|
6
Utils.py
6
Utils.py
|
@ -13,7 +13,7 @@ class Version(typing.NamedTuple):
|
|||
micro: int
|
||||
|
||||
|
||||
__version__ = "4.0.0"
|
||||
__version__ = "4.1.0"
|
||||
_version_tuple = tuplize_version(__version__)
|
||||
|
||||
import os
|
||||
|
@ -343,8 +343,8 @@ def get_adjuster_settings(romfile: str) -> typing.Tuple[str, bool]:
|
|||
f"Enter yes, no or never: ")
|
||||
if adjust_wanted and adjust_wanted.startswith("y"):
|
||||
adjusted = True
|
||||
import AdjusterMain
|
||||
_, romfile = AdjusterMain.adjust(adjuster_settings)
|
||||
import Adjuster
|
||||
_, romfile = Adjuster.adjust(adjuster_settings)
|
||||
elif adjust_wanted and "never" in adjust_wanted:
|
||||
persistent_store("adjuster", "never_adjust", True)
|
||||
return romfile, False
|
||||
|
|
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
|||
import logging
|
||||
import multiprocessing
|
||||
from datetime import timedelta, datetime
|
||||
import concurrent.futures
|
||||
import sys
|
||||
import typing
|
||||
import time
|
||||
|
@ -136,6 +137,7 @@ def autohost(config: dict):
|
|||
|
||||
multiworlds = {}
|
||||
|
||||
guardians = concurrent.futures.ThreadPoolExecutor(2, thread_name_prefix="Guardian")
|
||||
|
||||
class MultiworldInstance():
|
||||
def __init__(self, room: Room, config: dict):
|
||||
|
@ -153,12 +155,18 @@ class MultiworldInstance():
|
|||
args=(self.room_id, self.ponyconfig),
|
||||
name="MultiHost")
|
||||
self.process.start()
|
||||
self.guardian = guardians.submit(self._collect)
|
||||
|
||||
def stop(self):
|
||||
if self.process:
|
||||
self.process.terminate()
|
||||
self.process = None
|
||||
|
||||
def _collect(self):
|
||||
self.process.join() # wait for process to finish
|
||||
self.process = None
|
||||
self.guardian = None
|
||||
|
||||
|
||||
from .models import Room, Generation, STATE_QUEUED, STATE_STARTED, STATE_ERROR, db, Seed
|
||||
from .customserver import run_server_process
|
||||
|
|
|
@ -55,7 +55,7 @@ window.addEventListener('load', () => {
|
|||
|
||||
window.addEventListener('resize', () => {
|
||||
adjustTableHeight();
|
||||
tables.draw()
|
||||
tables.draw();
|
||||
});
|
||||
|
||||
$(".table-wrapper").scrollsync({
|
||||
|
|
|
@ -126,10 +126,8 @@ done so already, please do this now. SD2SNES and FXPak Pro users may download th
|
|||
[on this page](http://usb2snes.com/#supported-platforms).
|
||||
|
||||
1. Close your emulator, which may have auto-launched.
|
||||
2. Close QUsb2Snes, which launched automatically with the client.
|
||||
3. Launch the appropriate version of QUsb2Snes (v0.7.16).
|
||||
4. Power on your device and load the ROM.
|
||||
5. Observe the client window now shows "SNES Device: Connected", and lists the name of your device.
|
||||
2. Power on your device and load the ROM.
|
||||
3. Observe the client window now shows "SNES Device: Connected", and lists the name of your device.
|
||||
|
||||
### Connect to the MultiServer
|
||||
The patch file which launched your client should have automatically connected you to the MultiServer.
|
||||
|
|
|
@ -2,9 +2,17 @@ let spriteData = null;
|
|||
|
||||
window.addEventListener('load', () => {
|
||||
const gameSettings = document.getElementById('weighted-settings');
|
||||
Promise.all([fetchPlayerSettingsYaml(), fetchPlayerSettingsJson(), fetchSpriteData()]).then((results) => {
|
||||
Promise.all([fetchWeightedSettingsYaml(), fetchWeightedSettingsJson(), fetchSpriteData()]).then((results) => {
|
||||
// Load YAML into object
|
||||
const sourceData = jsyaml.safeLoad(results[0], { json: true });
|
||||
const wsVersion = sourceData.ws_version;
|
||||
delete sourceData.ws_version; // Do not include the settings version number in the export
|
||||
|
||||
// Check if settings exist in localStorage. If no settings are present, this is a first load (or reset to default)
|
||||
// and the version number should be silently updated
|
||||
if (!localStorage.getItem('weightedSettings1')) {
|
||||
localStorage.setItem('wsVersion', wsVersion);
|
||||
}
|
||||
|
||||
// Update localStorage with three settings objects. Preserve original objects if present.
|
||||
for (let i=1; i<=3; i++) {
|
||||
|
@ -25,6 +33,16 @@ window.addEventListener('load', () => {
|
|||
document.getElementById('export-button').addEventListener('click', exportSettings);
|
||||
document.getElementById('reset-to-default').addEventListener('click', resetToDefaults);
|
||||
adjustHeaderWidth();
|
||||
|
||||
if (localStorage.getItem('wsVersion') !== wsVersion) {
|
||||
const userWarning = document.getElementById('user-warning');
|
||||
const messageSpan = document.createElement('span');
|
||||
messageSpan.innerHTML = "A new version of the weighted settings file is available. Click here to update!" +
|
||||
"<br />Be aware this will also reset your presets, so you should export them now if you want to save them.";
|
||||
userWarning.appendChild(messageSpan);
|
||||
userWarning.style.display = 'block';
|
||||
userWarning.addEventListener('click', resetToDefaults);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
gameSettings.innerHTML = `
|
||||
|
@ -37,7 +55,7 @@ window.addEventListener('load', () => {
|
|||
document.getElementById('generate-race').addEventListener('click', () => generateGame(true));
|
||||
});
|
||||
|
||||
const fetchPlayerSettingsYaml = () => new Promise((resolve, reject) => {
|
||||
const fetchWeightedSettingsYaml = () => new Promise((resolve, reject) => {
|
||||
const ajax = new XMLHttpRequest();
|
||||
ajax.onreadystatechange = () => {
|
||||
if (ajax.readyState !== 4) { return; }
|
||||
|
@ -51,7 +69,7 @@ const fetchPlayerSettingsYaml = () => new Promise((resolve, reject) => {
|
|||
ajax.send();
|
||||
});
|
||||
|
||||
const fetchPlayerSettingsJson = () => new Promise((resolve, reject) => {
|
||||
const fetchWeightedSettingsJson = () => new Promise((resolve, reject) => {
|
||||
const ajax = new XMLHttpRequest();
|
||||
ajax.onreadystatechange = () => {
|
||||
if (ajax.readyState !== 4) { return; }
|
||||
|
@ -113,6 +131,7 @@ const handleOptionChange = (event) => {
|
|||
};
|
||||
|
||||
const populateSettings = () => {
|
||||
buildSpriteOptions();
|
||||
const presetNumber = document.getElementById('preset-number').value;
|
||||
const settings = JSON.parse(localStorage.getItem(`weightedSettings${presetNumber}`))
|
||||
const settingsInputs = Array.from(document.querySelectorAll('.setting'));
|
||||
|
@ -206,7 +225,21 @@ const buildUI = (settings, spriteData) => {
|
|||
settingsWrapper.appendChild(spriteOptionsHeader);
|
||||
|
||||
const spriteOptionsWrapper = document.createElement('div');
|
||||
spriteOptionsWrapper.setAttribute('id', 'sprite-options-wrapper');
|
||||
spriteOptionsWrapper.className = 'setting-wrapper';
|
||||
settingsWrapper.appendChild(spriteOptionsWrapper);
|
||||
|
||||
// Append sprite picker
|
||||
settingsWrapper.appendChild(buildSpritePicker(spriteData));
|
||||
};
|
||||
|
||||
const buildSpriteOptions = () => {
|
||||
const spriteOptionsWrapper = document.getElementById('sprite-options-wrapper');
|
||||
|
||||
// Clear the contents of the wrapper div
|
||||
while(spriteOptionsWrapper.firstChild){
|
||||
spriteOptionsWrapper.removeChild(spriteOptionsWrapper.lastChild);
|
||||
}
|
||||
|
||||
const spriteOptionsTitle = document.createElement('span');
|
||||
spriteOptionsTitle.className = 'title-span';
|
||||
|
@ -240,11 +273,6 @@ const buildUI = (settings, spriteData) => {
|
|||
|
||||
spriteOptionsTable.appendChild(tbody);
|
||||
spriteOptionsWrapper.appendChild(spriteOptionsTable);
|
||||
|
||||
settingsWrapper.appendChild(spriteOptionsWrapper);
|
||||
|
||||
// Append sprite picker
|
||||
settingsWrapper.appendChild(buildSpritePicker(spriteData));
|
||||
};
|
||||
|
||||
const buildRangeSettings = (parentElement, settings) => {
|
||||
|
|
|
@ -406,6 +406,38 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"pyramid_open": {
|
||||
"keyString": "pyramid_open",
|
||||
"friendlyName": "Pyramid Open",
|
||||
"description": "",
|
||||
"inputType": "range",
|
||||
"subOptions": {
|
||||
"goal": {
|
||||
"keyString": "pyramid_open.goal",
|
||||
"friendlyName": "Goal",
|
||||
"description": "Opens the pyramid if the goal requires you to kill Ganon, unless the goal is Slow Ganon or All Dungeons.",
|
||||
"defaultValue": 50
|
||||
},
|
||||
"auto": {
|
||||
"keyString": "pyramid_open.auto",
|
||||
"friendlyName": "Auto",
|
||||
"description": "Same as Goal, but also opens when any non-dungeon entrance shuffle is used.",
|
||||
"defaultValue": 0
|
||||
},
|
||||
"yes": {
|
||||
"keyString": "pyramid_open.yes",
|
||||
"friendlyName": "Always Open",
|
||||
"description": "Pyramid hole is always open. Ganon's vulnerable condition is still required before he can he hurt.",
|
||||
"defaultValue": 0
|
||||
},
|
||||
"no": {
|
||||
"keyString": "pyramid_open.no",
|
||||
"friendlyName": "Always Closed",
|
||||
"description": "Pyramid hole is always closed until you defeat Agahnim atop Ganon's Tower.",
|
||||
"defaultValue": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"triforce_pieces_required": {
|
||||
"keyString": "triforce_pieces_required",
|
||||
"friendlyName": "Triforce Pieces Required",
|
||||
|
@ -1135,7 +1167,7 @@
|
|||
"beemizer": {
|
||||
"keyString": "beemizer",
|
||||
"friendlyName": "Beemizer",
|
||||
"description": "Remove items from the global item pool and replace them with single bees and bee traps.",
|
||||
"description": "Remove non-health items from the global item pool and replace them with single bees and bee traps.",
|
||||
"inputType": "range",
|
||||
"subOptions": {
|
||||
"0": {
|
||||
|
@ -1147,25 +1179,25 @@
|
|||
"1": {
|
||||
"keyString": "beemizer.1",
|
||||
"friendlyName": "Level 1",
|
||||
"description": "25% of the non-essential item pool is replaced with bee traps.",
|
||||
"description": "25% of rupees, bombs and arrows are replaced with bees, of which 60% are traps and 40% single bees",
|
||||
"defaultValue": 1
|
||||
},
|
||||
"2": {
|
||||
"keyString": "beemizer.2",
|
||||
"friendlyName": "Level 2",
|
||||
"description": "60% of the non-essential item pool is replaced with bee traps, of which 20% could be single bees.",
|
||||
"description": "50% of rupees, bombs and arrows are replaced with bees, of which 70% are traps and 30% single bees",
|
||||
"defaultValue": 2
|
||||
},
|
||||
"3": {
|
||||
"keyString": "beemizer.3",
|
||||
"friendlyName": "Level 3",
|
||||
"description": "100% of the non-essential item pool is replaced with bee traps, of which 50% could be single bees.",
|
||||
"description": "75% of rupees, bombs and arrows are replaced with bees, of which 80% are traps and 20% single bees",
|
||||
"defaultValue": 3
|
||||
},
|
||||
"4": {
|
||||
"keyString": "beemizer.4",
|
||||
"friendlyName": "Level 4",
|
||||
"description": "100% of the non-essential item pool is replaced with bee traps.",
|
||||
"description": "100% of rupees, bombs and arrows are replaced with bees, of which 90% are traps and 10% single bees",
|
||||
"defaultValue": 4
|
||||
}
|
||||
}
|
||||
|
@ -1250,19 +1282,19 @@
|
|||
"description": "No items are moved",
|
||||
"defaultValue": 50
|
||||
},
|
||||
"1": {
|
||||
"10": {
|
||||
"keyString": "shop_shuffle_slots.10",
|
||||
"friendlyName": "Level 1",
|
||||
"description": "10 Items are moved into shops.",
|
||||
"defaultValue": 0
|
||||
},
|
||||
"2": {
|
||||
"20": {
|
||||
"keyString": "shop_shuffle_slots.20",
|
||||
"friendlyName": "Level 2",
|
||||
"description": "20 Items are moved into shops.",
|
||||
"defaultValue": 0
|
||||
},
|
||||
"3": {
|
||||
"30": {
|
||||
"keyString": "shop_shuffle_slots.30",
|
||||
"friendlyName": "Level 3",
|
||||
"description": "30 Items are moved into shops.",
|
||||
|
@ -1600,6 +1632,25 @@
|
|||
"description": "Hide both of the above options",
|
||||
"defaultValue": 0
|
||||
}
|
||||
},
|
||||
"reduceflashing": {
|
||||
"keyString": "rom.reduceflashing",
|
||||
"friendlyName": "Full-Screen Flashing Effects",
|
||||
"description": "Enable or disable full-screen flashing effects in game.",
|
||||
"inputType": "range",
|
||||
"subOptions": {
|
||||
"on": {
|
||||
"keyString": "rom.reduceflashing.on",
|
||||
"friendlyName": "Disabled",
|
||||
"description": "Disables flashing.",
|
||||
"defaultValue": 50
|
||||
},
|
||||
"off": {
|
||||
"keyString": "rom.reduceflashing.off",
|
||||
"friendlyName": "Enabled",
|
||||
"description": "Enables flashing.",
|
||||
"defaultValue": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"quickswap": {
|
||||
|
@ -1797,7 +1848,7 @@
|
|||
"defaultValue": 0
|
||||
},
|
||||
"puke": {
|
||||
"keyString": "rom.ow_palettes.Puke",
|
||||
"keyString": "rom.ow_palettes.puke",
|
||||
"friendlyName": "Puke",
|
||||
"description": "No logic at all.",
|
||||
"defaultValue": 0
|
||||
|
@ -1859,7 +1910,7 @@
|
|||
"defaultValue": 0
|
||||
},
|
||||
"puke": {
|
||||
"keyString": "rom.uw_palettes.Puke",
|
||||
"keyString": "rom.uw_palettes.puke",
|
||||
"friendlyName": "Puke",
|
||||
"description": "No logic at all.",
|
||||
"defaultValue": 0
|
||||
|
@ -1921,7 +1972,7 @@
|
|||
"defaultValue": 0
|
||||
},
|
||||
"puke": {
|
||||
"keyString": "rom.hud_palettes.Puke",
|
||||
"keyString": "rom.hud_palettes.puke",
|
||||
"friendlyName": "Puke",
|
||||
"description": "No logic at all.",
|
||||
"defaultValue": 0
|
||||
|
@ -1983,7 +2034,7 @@
|
|||
"defaultValue": 0
|
||||
},
|
||||
"puke": {
|
||||
"keyString": "rom.shield_palettes.Puke",
|
||||
"keyString": "rom.shield_palettes.puke",
|
||||
"friendlyName": "Puke",
|
||||
"description": "No logic at all.",
|
||||
"defaultValue": 0
|
||||
|
@ -2045,7 +2096,7 @@
|
|||
"defaultValue": 0
|
||||
},
|
||||
"puke": {
|
||||
"keyString": "rom.sword_palettes.Puke",
|
||||
"keyString": "rom.sword_palettes.puke",
|
||||
"friendlyName": "Puke",
|
||||
"description": "No logic at all.",
|
||||
"defaultValue": 0
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
# To test if your yaml is valid or not, you can use this website:
|
||||
# http://www.yamllint.com/
|
||||
|
||||
# For use with the weighted-settings page on the website. Changing this value will cause all users to be prompted
|
||||
# to update their settings. The version number should match the current released version number, and the revision
|
||||
# should be updated manually by whoever edits this file.
|
||||
ws_version: 4.0.1 rev1
|
||||
|
||||
description: Template Name # Used to describe your yaml. Useful if you have multiple files
|
||||
name: YourName # Your name in-game. Spaces will be replaced with underscores and there is a 16 character limit
|
||||
### Logic Section ###
|
||||
|
@ -97,6 +102,11 @@ goals:
|
|||
ganon_triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout the worlds, then kill Ganon
|
||||
local_ganon_triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout your world, then kill Ganon
|
||||
ice_rod_hunt: 0 # You start with everything needed to 216 the seed. Find the Ice rod, then kill Trinexx at Turtle rock.
|
||||
pyramid_open:
|
||||
goal: 50 # Opens the pyramid if the goal requires you to kill Ganon, unless the goal is Slow Ganon or All Dungeons
|
||||
auto: 0 # Same as Goal, but also opens when any non-dungeon entrance shuffle is used
|
||||
yes: 0 # Pyramid hole is always open. Ganon's vulnerable condition is still required before he can he hurt
|
||||
no: 0 # Pyramid hole is always closed until you defeat Agahnim atop Ganon's Tower
|
||||
triforce_pieces_mode: #Determine how to calculate the extra available triforce pieces.
|
||||
extra: 0 # available = triforce_pieces_extra + triforce_pieces_required
|
||||
percentage: 0 # available = (triforce_pieces_percentage /100) * triforce_pieces_required
|
||||
|
@ -218,10 +228,10 @@ pot_shuffle:
|
|||
### End of Enemizer Section ###
|
||||
beemizer: # Remove items from the global item pool and replace them with single bees and bee traps
|
||||
0: 50 # No bee traps are placed
|
||||
1: 0 # 25% of the non-essential item pool is replaced with bee traps
|
||||
2: 0 # 60% of the non-essential item pool is replaced with bee traps, of which 20% could be single bees
|
||||
3: 0 # 100% of the non-essential item pool is replaced with bee traps, of which 50% could be single bees
|
||||
4: 0 # 100% of the non-essential item pool is replaced with bee traps
|
||||
1: 0 # 25% of rupees, bombs and arrows are replaced with bees, of which 60% are traps and 40% single bees
|
||||
2: 0 # 50% of rupees, bombs and arrows are replaced with bees, of which 70% are traps and 30% single bees
|
||||
3: 0 # 75% of rupees, bombs and arrows are replaced with bees, of which 80% are traps and 20% single bees
|
||||
4: 0 # 100% of rupees, bombs and arrows are replaced with bees, of which 90% are traps and 10% single bees
|
||||
### Shop Settings ###
|
||||
shop_shuffle_slots: # Maximum amount of shop slots to be filled with regular item pool items (such as Moon Pearl)
|
||||
0: 50
|
||||
|
@ -353,6 +363,9 @@ rom:
|
|||
quickswap: # Enable switching items by pressing the L+R shoulder buttons
|
||||
on: 50
|
||||
off: 0
|
||||
reduceflashing: # Reduces instances of flashing such as lightning attacks, weather, ether and more.
|
||||
on: 50
|
||||
off: 0
|
||||
menuspeed: # Controls how fast the item menu opens and closes
|
||||
normal: 50
|
||||
instant: 0
|
||||
|
|
|
@ -14,6 +14,17 @@ html{
|
|||
color: #eeffeb;
|
||||
}
|
||||
|
||||
#user-warning{
|
||||
display: none;
|
||||
width: calc(100% - 8px);
|
||||
background-color: #ffe86b;
|
||||
border-radius: 4px;
|
||||
color: #000000;
|
||||
padding: 4px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#weighted-settings code{
|
||||
background-color: #d9cd8e;
|
||||
border-radius: 4px;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends 'tablepage.html' %}
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<title>Multiworld Tracker for Room {{ room.id }}</title>
|
||||
<title>Multiworld Tracker</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ static_autoversion("styles/tracker.css") }}"/>
|
||||
<script type="application/ecmascript" src="{{ static_autoversion("assets/jquery.scrollsync.js") }}"></script>
|
||||
<script type="application/ecmascript" src="{{ static_autoversion("assets/tracker.js") }}"></script>
|
||||
|
@ -151,7 +151,7 @@
|
|||
{% endfor %}
|
||||
{% for team, hints in hints.items() %}
|
||||
<div class="table-wrapper">
|
||||
<table class="table non-unique-item-table">
|
||||
<table class="table non-unique-item-table" data-order='[[5, "asc"], [0, "asc"]]'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Finder</th>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
{% block body %}
|
||||
{% include 'header/grassHeader.html' %}
|
||||
<div id="weighted-settings">
|
||||
<header id="user-warning"></header>
|
||||
<h1>Weighted Settings</h1>
|
||||
<div id="instructions">
|
||||
This page is used to configure your weighted settings. You have three presets you can control, which
|
||||
|
|
|
@ -13,7 +13,7 @@ from Utils import Hint
|
|||
|
||||
|
||||
def get_id(item_name):
|
||||
return Items.item_table[item_name][3]
|
||||
return Items.item_table[item_name][2]
|
||||
|
||||
|
||||
app.jinja_env.filters["location_name"] = lambda location: Regions.lookup_id_to_name.get(location, location)
|
||||
|
@ -233,9 +233,9 @@ for item_name, data in Items.item_table.items():
|
|||
if "Key" in item_name:
|
||||
area = item_name.split("(")[1][:-1]
|
||||
if "Small" in item_name:
|
||||
small_key_ids[area] = data[3]
|
||||
small_key_ids[area] = data[2]
|
||||
else:
|
||||
big_key_ids[area] = data[3]
|
||||
big_key_ids[area] = data[2]
|
||||
|
||||
from MultiServer import get_item_name_from_id
|
||||
|
||||
|
|
17
WebUI.py
17
WebUI.py
|
@ -51,31 +51,36 @@ class WebUiClient(Node, logging.Handler):
|
|||
def poll_for_server_ip(self):
|
||||
self.broadcast_all(self.build_message('serverAddress', {}))
|
||||
|
||||
def notify_item_sent(self, finder, recipient, item, location, i_am_finder: bool, i_am_recipient: bool):
|
||||
def notify_item_sent(self, finder, recipient, item, location, i_am_finder: bool, i_am_recipient: bool,
|
||||
item_is_unique: bool = False):
|
||||
self.broadcast_all(self.build_message('itemSent', {
|
||||
'finder': finder,
|
||||
'recipient': recipient,
|
||||
'item': item,
|
||||
'location': location,
|
||||
'iAmFinder': 1 if i_am_finder else 0,
|
||||
'iAmRecipient': 1 if i_am_recipient else 0,
|
||||
'iAmFinder': int(i_am_finder),
|
||||
'iAmRecipient': int(i_am_recipient),
|
||||
'itemIsUnique': int(item_is_unique),
|
||||
}))
|
||||
|
||||
def notify_item_found(self, finder: str, item: str, location: str, i_am_finder: bool):
|
||||
def notify_item_found(self, finder: str, item: str, location: str, i_am_finder: bool, item_is_unique: bool = False):
|
||||
self.broadcast_all(self.build_message('itemFound', {
|
||||
'finder': finder,
|
||||
'item': item,
|
||||
'location': location,
|
||||
'iAmFinder': 1 if i_am_finder else 0,
|
||||
'iAmFinder': int(i_am_finder),
|
||||
'itemIsUnique': int(item_is_unique),
|
||||
}))
|
||||
|
||||
def notify_item_received(self, finder: str, item: str, location: str, item_index: int, queue_length: int):
|
||||
def notify_item_received(self, finder: str, item: str, location: str, item_index: int, queue_length: int,
|
||||
item_is_unique: bool = False):
|
||||
self.broadcast_all(self.build_message('itemReceived', {
|
||||
'finder': finder,
|
||||
'item': item,
|
||||
'location': location,
|
||||
'itemIndex': item_index,
|
||||
'queueLength': queue_length,
|
||||
'itemIsUnique': int(item_is_unique),
|
||||
}))
|
||||
|
||||
def send_hint(self, finder, recipient, item, location, found, i_am_finder: bool, i_am_recipient: bool,
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -10,38 +10,39 @@
|
|||
"author": "LegendaryLinux",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.28",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.13.0",
|
||||
"@fortawesome/react-fontawesome": "^0.1.10",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.34",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.2",
|
||||
"@fortawesome/react-fontawesome": "^0.1.14",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"crypto-js": "^4.0.0",
|
||||
"css-loader": "^3.5.3",
|
||||
"lodash-es": "^4.17.15",
|
||||
"css-loader": "^5.0.1",
|
||||
"lodash-es": "^4.17.20",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-redux": "^7.2.1",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-redux": "^7.2.2",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"redux": "^4.0.5",
|
||||
"redux-devtools-extension": "^2.13.8",
|
||||
"sass-loader": "^8.0.2",
|
||||
"style-loader": "^1.2.1",
|
||||
"webpack-cli": "^3.3.11"
|
||||
"sass-loader": "^10.1.1",
|
||||
"style-loader": "^2.0.0",
|
||||
"webpack-cli": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.11.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.10.4",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-react": "^7.10.4",
|
||||
"@babel/core": "^7.12.13",
|
||||
"@babel/plugin-proposal-class-properties": "^7.12.13",
|
||||
"@babel/preset-env": "^7.12.13",
|
||||
"@babel/preset-react": "^7.12.13",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-airbnb": "^18.2.0",
|
||||
"eslint-plugin-import": "^2.22.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.3.1",
|
||||
"eslint-plugin-react": "^7.20.6",
|
||||
"eslint-plugin-react-hooks": "^2.5.1",
|
||||
"file-loader": "^6.0.0",
|
||||
"node-sass": "^4.14.1",
|
||||
"webpack": "^4.44.1"
|
||||
"babel-loader": "^8.2.2",
|
||||
"eslint": "^7.19.0",
|
||||
"eslint-config-airbnb": "^18.2.1",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-react": "^7.22.0",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"node-sass": "^5.0.0",
|
||||
"webpack": "^5.20.0"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -7,7 +7,7 @@ const finderSpan = (finder, possessive = false, ownItem = false) => (
|
|||
const recipientSpan = (recipient, possessive = false, ownItem = false) => (
|
||||
<span className={ `recipient-span ${ownItem ? 'mine' : null}` }>{recipient}{possessive ? "'s" : null}</span>
|
||||
);
|
||||
const itemSpan = (item) => <span className="item-span">{item}</span>;
|
||||
const itemSpan = (item, unique) => <span className={ `item-span ${unique ? 'unique' : ''}` }>{item}</span>;
|
||||
const locationSpan = (location) => <span className="location-span">{location}</span>;
|
||||
const entranceSpan = (entrance) => <span className="entrance-span">{entrance}</span>;
|
||||
|
||||
|
@ -20,34 +20,34 @@ class MonitorTools {
|
|||
);
|
||||
|
||||
/** Sent an item to another player */
|
||||
static sentItem = (finder, recipient, item, location, iAmFinder = false, iAmRecipient = false) => (
|
||||
static sentItem = (finder, recipient, item, location, iAmFinder = false, iAmRecipient = false, unique = false) => (
|
||||
<div
|
||||
key={ `${md5(finder + recipient + item + location)}${Math.floor((Math.random() * 1000000))}` }
|
||||
className={ (iAmFinder || iAmRecipient) ? 'relevant' : null }
|
||||
>
|
||||
{finderSpan(finder, false, iAmFinder)} found {recipientSpan(recipient, true, iAmRecipient)}
|
||||
{itemSpan(item)} at {locationSpan(location)}
|
||||
{itemSpan(item, unique)} at {locationSpan(location)}
|
||||
</div>
|
||||
)
|
||||
|
||||
/** Received item from another player */
|
||||
static receivedItem = (finder, item, location, itemIndex, queueLength) => (
|
||||
static receivedItem = (finder, item, location, itemIndex, queueLength, unique = false) => (
|
||||
<div
|
||||
key={ `${md5(finder + item + location)}${Math.floor((Math.random() * 1000000))}` }
|
||||
className="relevant"
|
||||
>
|
||||
({itemIndex}/{queueLength}) {finderSpan(finder, false)} found your
|
||||
{itemSpan(item)} at {locationSpan(location)}
|
||||
{itemSpan(item, unique)} at {locationSpan(location)}
|
||||
</div>
|
||||
)
|
||||
|
||||
/** Player found their own item (local or remote player) */
|
||||
static foundItem = (finder, item, location, iAmFinder = false) => (
|
||||
static foundItem = (finder, item, location, iAmFinder = false, unique = false) => (
|
||||
<div
|
||||
key={ `${md5(finder + item + location)}${Math.floor((Math.random() * 1000000))}` }
|
||||
className={ iAmFinder ? 'relevant' : null }
|
||||
>
|
||||
{finderSpan(finder, false, iAmFinder)} found their own {itemSpan(item)} at {locationSpan(location)}
|
||||
{finderSpan(finder, false, iAmFinder)} found their own {itemSpan(item, unique)} at {locationSpan(location)}
|
||||
</div>
|
||||
)
|
||||
|
||||
|
|
|
@ -44,15 +44,16 @@ class WebSocketUtils {
|
|||
case 'itemSent':
|
||||
return appendMessage(MonitorTools.sentItem(data.content.finder, data.content.recipient,
|
||||
data.content.item, data.content.location, parseInt(data.content.iAmFinder, 10) === 1,
|
||||
parseInt(data.content.iAmRecipient, 10) === 1));
|
||||
parseInt(data.content.iAmRecipient, 10) === 1, parseInt(data.content.itemIsUnique, 10) === 1));
|
||||
|
||||
case 'itemReceived':
|
||||
return appendMessage(MonitorTools.receivedItem(data.content.finder, data.content.item,
|
||||
data.content.location, data.content.itemIndex, data.content.queueLength));
|
||||
data.content.location, data.content.itemIndex, data.content.queueLength,
|
||||
parseInt(data.content.itemIsUnique, 10) === 1));
|
||||
|
||||
case 'itemFound':
|
||||
return appendMessage(MonitorTools.foundItem(data.content.finder, data.content.item, data.content.location,
|
||||
parseInt(data.content.iAmFinder, 10) === 1));
|
||||
parseInt(data.content.iAmFinder, 10) === 1, parseInt(data.content.itemIsUnique, 10) === 1));
|
||||
|
||||
case 'hint':
|
||||
return appendMessage(MonitorTools.hintMessage(data.content.finder, data.content.recipient,
|
||||
|
|
|
@ -25,9 +25,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
.item-span{ color: #67e9ff; }
|
||||
.item-span{
|
||||
color: #67e9ff;
|
||||
|
||||
&.unique{
|
||||
color: #ff884e;
|
||||
text-shadow: #000000 2px 2px;
|
||||
}
|
||||
}
|
||||
.location-span{ color: #f5e63c; }
|
||||
.entrance-span{ color: #73ae38 }
|
||||
.entrance-span{ color: #73ae38; }
|
||||
.finder-span{ color: #f96cb8; }
|
||||
.recipient-span{ color: #9b8aff; }
|
||||
.mine{ color: #ffa500; }
|
||||
|
|
|
@ -9,7 +9,7 @@ module.exports = {
|
|||
{
|
||||
test: /\.(js|jsx|es6)$/,
|
||||
loader: 'babel-loader',
|
||||
query: {
|
||||
options: {
|
||||
compact: true,
|
||||
minified: true,
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@ module.exports = {
|
|||
{
|
||||
test: /\.(js|jsx|es6)$/,
|
||||
loader: 'babel-loader',
|
||||
query: {
|
||||
options: {
|
||||
compact: false,
|
||||
minified: false,
|
||||
},
|
||||
|
@ -42,5 +42,4 @@ module.exports = {
|
|||
publicPath: '/',
|
||||
filename: '[name].bundle.js',
|
||||
},
|
||||
devtool: 'source-map',
|
||||
};
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
description: Template Name # Used to describe your yaml. Useful if you have multiple files
|
||||
name: YourName # Your name in-game. Spaces will be replaced with underscores and there is a 16 character limit
|
||||
### Logic Section ###
|
||||
# Warning: overworld_glitches is not available and minor_glitches is only partially implemented on the door-rando version
|
||||
glitches_required: # Determine the logic required to complete the seed
|
||||
none: 50 # No glitches required
|
||||
minor_glitches: 0 # Puts fake flipper, waterwalk, super bunny shenanigans, and etc into logic
|
||||
overworld_glitches: 0 # Assumes the player has knowledge of both overworld major glitches (boots clips, mirror clips) and minor glitches (fake flipper, super bunny shenanigans, water walk and etc.)
|
||||
overworld_glitches: 0 # Assumes the player has knowledge of both overworld major glitches (boots clips, mirror clips) and minor glitches
|
||||
no_logic: 0 # Your own items are placed with no regard to any logic; such as your Fire Rod can be on your Trinexx.
|
||||
# Other players items are placed into your world under OWG logic
|
||||
dark_room_logic: # Logic for unlit dark rooms
|
||||
|
@ -86,9 +87,12 @@ entrance_shuffle: # Documentation: https://alttpr.com/en/options#entrance_shuffl
|
|||
full: 0 # Less strict than restricted
|
||||
crossed: 0 # Less strict than full
|
||||
insanity: 0 # Very few grouping rules. Good luck
|
||||
# you can also define entrance shuffle seed, like so:
|
||||
crossed-1000: 0 # using this method, you can have the same layout as another player and share entrance information
|
||||
# however, many other settings like logic, world state, retro etc. may affect the shuffle result as well.
|
||||
goals:
|
||||
ganon: 50 # Climb GT, defeat Agahnim 2, and then kill Ganon
|
||||
fast_ganon: 0 # Only killing Ganon is required. The hole is always open. However, items may still be placed in GT
|
||||
fast_ganon: 0 # Only killing Ganon is required. However, items may still be placed in GT
|
||||
dungeons: 0 # Defeat the boss of all dungeons, including Agahnim's tower and GT (Aga 2)
|
||||
pedestal: 0 # Pull the Triforce from the Master Sword pedestal
|
||||
ganon_pedestal: 0 # Pull the Master Sword pedestal, then kill Ganon
|
||||
|
@ -97,11 +101,16 @@ goals:
|
|||
ganon_triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout the worlds, then kill Ganon
|
||||
local_ganon_triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout your world, then kill Ganon
|
||||
ice_rod_hunt: 0 # You start with everything needed to 216 the seed. Find the Ice rod, then kill Trinexx at Turtle rock.
|
||||
open_pyramid:
|
||||
goal: 50 # Opens the pyramid if the goal requires you to kill Ganon, unless the goal is Slow Ganon or All Dungeons
|
||||
auto: 0 # Same as Goal, but also is closed if holes are shuffled and ganon is part of the shuffle pool
|
||||
yes: 0 # Pyramid hole is always open. Ganon's vulnerable condition is still required before he can he hurt
|
||||
no: 0 # Pyramid hole is always closed until you defeat Agahnim atop Ganon's Tower
|
||||
triforce_pieces_mode: #Determine how to calculate the extra available triforce pieces.
|
||||
extra: 0 # available = triforce_pieces_extra + triforce_pieces_required
|
||||
percentage: 0 # available = (triforce_pieces_percentage /100) * triforce_pieces_required
|
||||
available: 50 # available = triforce_pieces_available
|
||||
triforce_pieces_extra: # Set to how many extra triforces pieces are available to collect in the world.
|
||||
triforce_pieces_extra: # Set to how many extra triforces pieces are available to collect in the world.
|
||||
# Format "pieces: chance"
|
||||
0: 0
|
||||
5: 50
|
||||
|
@ -216,12 +225,12 @@ pot_shuffle:
|
|||
'on': 0 # Keys, items, and buttons hidden under pots in dungeons are shuffled with other pots in their supertile
|
||||
'off': 50 # Default pot item locations
|
||||
### End of Enemizer Section ###
|
||||
beemizer: # Remove items from the global item pool and replace them with single bees and bee traps
|
||||
beemizer: # Remove items from the global item pool and replace them with single bees (fill bottles) and bee traps
|
||||
0: 50 # No bee traps are placed
|
||||
1: 0 # 25% of the non-essential item pool is replaced with bee traps
|
||||
2: 0 # 60% of the non-essential item pool is replaced with bee traps, of which 20% could be single bees
|
||||
3: 0 # 100% of the non-essential item pool is replaced with bee traps, of which 50% could be single bees
|
||||
4: 0 # 100% of the non-essential item pool is replaced with bee traps
|
||||
1: 0 # 25% of rupees, bombs and arrows are replaced with bees, of which 60% are traps and 40% single bees
|
||||
2: 0 # 50% of rupees, bombs and arrows are replaced with bees, of which 70% are traps and 30% single bees
|
||||
3: 0 # 75% of rupees, bombs and arrows are replaced with bees, of which 80% are traps and 20% single bees
|
||||
4: 0 # 100% of rupees, bombs and arrows are replaced with bees, of which 90% are traps and 10% single bees
|
||||
### Shop Settings ###
|
||||
shop_shuffle_slots: # Maximum amount of shop slots to be filled with regular item pool items (such as Moon Pearl)
|
||||
0: 50
|
||||
|
@ -243,8 +252,8 @@ shop_shuffle:
|
|||
### End of Shop Section ###
|
||||
shuffle_prizes: # aka drops
|
||||
none: 0 # do not shuffle prize packs
|
||||
g: 50 # shuffle "general" price packs, as in enemy, tree pull, dig etc.
|
||||
b: 0 # shuffle "bonk" price packs
|
||||
g: 50 # shuffle "general" prize packs, as in enemy, tree pull, dig etc.
|
||||
b: 0 # shuffle "bonk" prize packs
|
||||
bg: 0 # shuffle both
|
||||
timer:
|
||||
none: 50 # No timer will be displayed.
|
||||
|
@ -317,6 +326,13 @@ linked_options:
|
|||
hard: 1
|
||||
expert: 1
|
||||
percentage: 0 # Set this to the percentage chance you want enemizer
|
||||
# triggers that replace options upon rolling certain options
|
||||
triggers:
|
||||
- option_name: enemy_damage # targets enemy_damage
|
||||
option_result: shuffled # if it rolls shuffled
|
||||
percentage: 0 # AND has a 0 percent chance (meaning this is default disabled, just to show how it works)
|
||||
options: # then inserts these options
|
||||
swords: assured
|
||||
### door rando only options ###
|
||||
door_shuffle: # Only available if the host uses the doors branch, it is ignored otherwise
|
||||
vanilla: 50 # Everything should be like in vanilla
|
||||
|
@ -393,6 +409,9 @@ rom:
|
|||
hide_goal: 50 # hide counter until a piece is collected or speaking to Murahalda
|
||||
hide_required: 0 # Always visible, but required amount is invisible until determined by Murahalda
|
||||
hide_both: 0 # Hide both under above circumstances
|
||||
reduceflashing: # Reduces instances of flashing such as lightning attacks, weather, ether and more.
|
||||
on: 50
|
||||
off: 0
|
||||
menuspeed: # Controls how fast the item menu opens and closes
|
||||
normal: 50
|
||||
instant: 0
|
||||
|
@ -461,4 +480,4 @@ rom:
|
|||
classic: 0
|
||||
dizzy: 0
|
||||
sick: 0
|
||||
puke: 0
|
||||
puke: 0
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
colorama>=0.4.4
|
||||
websockets>=8.1
|
||||
PyYAML>=5.4
|
||||
PyYAML>=5.4.1
|
||||
fuzzywuzzy>=0.18.0
|
||||
bsdiff4>=1.2.0
|
||||
prompt_toolkit>=3.0.10
|
||||
prompt_toolkit>=3.0.16
|
||||
appdirs>=1.4.4
|
||||
maseya-z3pr>=1.0.0rc1
|
||||
xxtea>=2.0.0.post0
|
||||
|
|
7
setup.py
7
setup.py
|
@ -48,8 +48,8 @@ def manifest_creation():
|
|||
path = os.path.join(dirpath, filename)
|
||||
hashes[os.path.relpath(path, start=buildfolder)] = pool.submit(_threaded_hash, path)
|
||||
import json
|
||||
manifest = {"buildtime": buildtime.isoformat(sep=" ", timespec="seconds")}
|
||||
manifest["hashes"] = {path: hash.result() for path, hash in hashes.items()}
|
||||
manifest = {"buildtime": buildtime.isoformat(sep=" ", timespec="seconds"),
|
||||
"hashes": {path: hash.result() for path, hash in hashes.items()}}
|
||||
json.dump(manifest, open(manifestpath, "wt"), indent=4)
|
||||
print("Created Manifest")
|
||||
|
||||
|
@ -58,7 +58,8 @@ scripts = {"MultiClient.py": "BerserkerMultiClient",
|
|||
"MultiMystery.py": "BerserkerMultiMystery",
|
||||
"MultiServer.py": "BerserkerMultiServer",
|
||||
"gui.py": "BerserkerMultiCreator",
|
||||
"Mystery.py": "BerserkerMystery"}
|
||||
"Mystery.py": "BerserkerMystery",
|
||||
"Adjuster.py": "BerserkerLttPAdjuster"}
|
||||
|
||||
exes = []
|
||||
|
||||
|
|
|
@ -19,55 +19,70 @@ class TestBase(unittest.TestCase):
|
|||
self._state_cache[self.world, tuple(items)] = state
|
||||
return state
|
||||
|
||||
def get_path(self, state, region):
|
||||
def flist_to_iter(node):
|
||||
while node:
|
||||
value, node = node
|
||||
yield value
|
||||
|
||||
from itertools import zip_longest
|
||||
reversed_path_as_flist = state.path.get(region, (region, None))
|
||||
string_path_flat = reversed(list(map(str, flist_to_iter(reversed_path_as_flist))))
|
||||
# Now we combine the flat string list into (region, exit) pairs
|
||||
pathsiter = iter(string_path_flat)
|
||||
pathpairs = zip_longest(pathsiter, pathsiter)
|
||||
return list(pathpairs)
|
||||
|
||||
def run_location_tests(self, access_pool):
|
||||
for location, access, *item_pool in access_pool:
|
||||
for i, (location, access, *item_pool) in enumerate(access_pool):
|
||||
items = item_pool[0]
|
||||
all_except = item_pool[1] if len(item_pool) > 1 else None
|
||||
with self.subTest(msg="Reach Location", location=location, access=access, items=items, all_except=all_except):
|
||||
if all_except and len(all_except) > 0:
|
||||
items = self.world.itempool[:]
|
||||
items = [item for item in items if item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)]
|
||||
items.extend(ItemFactory(item_pool[0], 1))
|
||||
else:
|
||||
items = ItemFactory(items, 1)
|
||||
state = self.get_state(items)
|
||||
state = self._get_items(item_pool, all_except)
|
||||
path = self.get_path(state, self.world.get_location(location, 1).parent_region)
|
||||
with self.subTest(msg="Reach Location", location=location, access=access, items=items,
|
||||
all_except=all_except, path=path, entry=i):
|
||||
|
||||
self.assertEqual(self.world.get_location(location, 1).can_reach(state), access)
|
||||
|
||||
|
||||
#check for partial solution
|
||||
if not all_except and access:# we are not supposed to be able to reach location with partial inventory
|
||||
# check for partial solution
|
||||
if not all_except and access: # we are not supposed to be able to reach location with partial inventory
|
||||
for missing_item in item_pool[0]:
|
||||
with self.subTest(msg="Location reachable without required item", location=location,
|
||||
items=item_pool[0], missing_item=missing_item):
|
||||
new_items = item_pool[0].copy()
|
||||
new_items.remove(missing_item)
|
||||
items = ItemFactory(new_items, 1)
|
||||
state = self.get_state(items)
|
||||
items=item_pool[0], missing_item=missing_item, entry=i):
|
||||
state = self._get_items_partial(item_pool, missing_item)
|
||||
self.assertEqual(self.world.get_location(location, 1).can_reach(state), False)
|
||||
|
||||
def run_entrance_tests(self, access_pool):
|
||||
for entrance, access, *item_pool in access_pool:
|
||||
for i, (entrance, access, *item_pool) in enumerate(access_pool):
|
||||
items = item_pool[0]
|
||||
all_except = item_pool[1] if len(item_pool) > 1 else None
|
||||
with self.subTest(msg="Reach Entrance", entrance=entrance, access=access, items=items, all_except=all_except):
|
||||
if all_except and len(all_except) > 0:
|
||||
items = self.world.itempool[:]
|
||||
items = [item for item in items if item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)]
|
||||
items.extend(ItemFactory(item_pool[0], 1))
|
||||
else:
|
||||
items = ItemFactory(items, 1)
|
||||
state = self.get_state(items)
|
||||
state = self._get_items(item_pool, all_except)
|
||||
path = self.get_path(state, self.world.get_entrance(entrance, 1).parent_region)
|
||||
with self.subTest(msg="Reach Entrance", entrance=entrance, access=access, items=items,
|
||||
all_except=all_except, path=path, entry=i):
|
||||
|
||||
self.assertEqual(self.world.get_entrance(entrance, 1).can_reach(state), access)
|
||||
|
||||
#check for partial solution
|
||||
if not all_except and access:# we are not supposed to be able to reach location with partial inventory
|
||||
# check for partial solution
|
||||
if not all_except and access: # we are not supposed to be able to reach location with partial inventory
|
||||
for missing_item in item_pool[0]:
|
||||
with self.subTest(msg="Entrance reachable without required item", entrance=entrance,
|
||||
items=item_pool[0], missing_item=missing_item):
|
||||
new_items = item_pool[0].copy()
|
||||
new_items.remove(missing_item)
|
||||
items = ItemFactory(new_items, 1)
|
||||
state = self.get_state(items)
|
||||
self.assertEqual(self.world.get_entrance(entrance, 1).can_reach(state), False)
|
||||
items=item_pool[0], missing_item=missing_item, entry=i):
|
||||
state = self._get_items_partial(item_pool, missing_item)
|
||||
self.assertEqual(self.world.get_entrance(entrance, 1).can_reach(state), False)
|
||||
|
||||
def _get_items(self, item_pool, all_except):
|
||||
if all_except and len(all_except) > 0:
|
||||
items = self.world.itempool[:]
|
||||
items = [item for item in items if
|
||||
item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)]
|
||||
items.extend(ItemFactory(item_pool[0], 1))
|
||||
else:
|
||||
items = ItemFactory(item_pool[0], 1)
|
||||
return self.get_state(items)
|
||||
|
||||
def _get_items_partial(self, item_pool, missing_item):
|
||||
new_items = item_pool[0].copy()
|
||||
new_items.remove(missing_item)
|
||||
items = ItemFactory(new_items, 1)
|
||||
return self.get_state(items)
|
||||
|
|
|
@ -97,16 +97,11 @@ class TestInvertedDarkWorld(TestInverted):
|
|||
def testMireArea(self):
|
||||
self.run_location_tests([
|
||||
["Mire Shed - Left", False, []],
|
||||
["Mire Shed - Left", False, [], ['Flute', 'Magic Mirror']],
|
||||
["Mire Shed - Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove']],
|
||||
["Mire Shed - Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Hammer']],
|
||||
["Mire Shed - Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1']],
|
||||
["Mire Shed - Left", True, ['Flute']],
|
||||
["Mire Shed - Left", True, ['Magic Mirror', 'Beat Agahnim 1']],
|
||||
|
||||
["Mire Shed - Right", False, []],
|
||||
["Mire Shed - Right", False, [], ['Flute', 'Magic Mirror']],
|
||||
["Mire Shed - Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove']],
|
||||
["Mire Shed - Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Hammer']],
|
||||
["Mire Shed - Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1']],
|
||||
["Mire Shed - Right", True, ['Flute']],
|
||||
["Mire Shed - Right", True, ['Magic Mirror', 'Beat Agahnim 1']],
|
||||
|
||||
])
|
|
@ -9,16 +9,13 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Old Man", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Old Man", False, [], ['Lamp']],
|
||||
["Old Man", True, ['Progressive Glove', 'Lamp']],
|
||||
["Old Man", False, ['Flute', 'Lamp']],
|
||||
["Old Man", True, ['Flute', 'Lamp']],
|
||||
|
||||
["Spectacle Rock Cave", False, []],
|
||||
["Spectacle Rock Cave", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Spectacle Rock Cave", False, [], ['Lamp', 'Flute']],
|
||||
["Spectacle Rock Cave", False, ['Flute', 'Progressive Glove', 'Hammer']],
|
||||
["Spectacle Rock Cave", False, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
|
||||
["Spectacle Rock Cave", False, ['Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Spectacle Rock Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
|
||||
["Spectacle Rock Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
|
||||
["Spectacle Rock Cave", True, ['Flute']],
|
||||
["Spectacle Rock Cave", True, ['Progressive Glove', 'Lamp']],
|
||||
])
|
||||
|
||||
|
@ -31,12 +28,10 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Spiral Cave", False, ['Progressive Glove'], ['Hookshot', 'Progressive Glove']],
|
||||
["Spiral Cave", False, ['Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Spiral Cave", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Spiral Cave", False, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
|
||||
["Spiral Cave", False, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Spiral Cave", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
|
||||
["Spiral Cave", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hookshot']],
|
||||
["Spiral Cave", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Spiral Cave", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
["Spiral Cave", True, ['Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Spiral Cave", True, ['Moon Pearl', 'Progressive Glove', 'Lamp', 'Hookshot']],
|
||||
["Spiral Cave", True, ['Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Lamp']],
|
||||
["Spiral Cave", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove']],
|
||||
|
||||
["Paradox Cave Lower - Far Left", False, []],
|
||||
["Paradox Cave Lower - Far Left", False, [], ['Moon Pearl']],
|
||||
|
@ -45,7 +40,7 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Paradox Cave Lower - Far Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -57,7 +52,7 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Paradox Cave Lower - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -69,7 +64,7 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Paradox Cave Lower - Middle", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -81,7 +76,7 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Paradox Cave Lower - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -93,7 +88,7 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Paradox Cave Lower - Far Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -105,7 +100,7 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Paradox Cave Upper - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -117,7 +112,7 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Paradox Cave Upper - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -127,7 +122,7 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Mimic Cave", False, [], ['Hammer']],
|
||||
["Mimic Cave", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Mimic Cave", False, [], ['Lamp', 'Flute']],
|
||||
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Hammer', 'Hookshot']],
|
||||
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot']],
|
||||
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
|
||||
["Mimic Cave", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']],
|
||||
["Mimic Cave", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']],
|
||||
|
@ -140,7 +135,7 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Ether Tablet", False, [], ['Hammer']],
|
||||
["Ether Tablet", False, ['Progressive Sword'], ['Progressive Sword']],
|
||||
["Ether Tablet", False, [], ['Book of Mudora']],
|
||||
["Ether Tablet", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Ether Tablet", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Ether Tablet", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Ether Tablet", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Ether Tablet", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
|
@ -151,7 +146,7 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Spectacle Rock", False, [], ['Lamp', 'Flute']],
|
||||
["Spectacle Rock", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Spectacle Rock", False, [], ['Hammer']],
|
||||
["Spectacle Rock", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Hammer', 'Hookshot']],
|
||||
["Spectacle Rock", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot']],
|
||||
["Spectacle Rock", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
|
||||
["Spectacle Rock", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']],
|
||||
["Spectacle Rock", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']],
|
||||
|
@ -160,47 +155,38 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
def testEastDarkWorldDeathMountain(self):
|
||||
self.run_location_tests([
|
||||
["Superbunny Cave - Top", False, []],
|
||||
["Superbunny Cave - Top", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Superbunny Cave - Top", True, ['Flute']],
|
||||
["Superbunny Cave - Top", True, ['Progressive Glove', 'Lamp']],
|
||||
["Superbunny Cave - Top", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute']],
|
||||
["Superbunny Cave - Top", True, ['Hammer', 'Progressive Glove', 'Moon Pearl', 'Flute']],
|
||||
|
||||
["Superbunny Cave - Bottom", False, []],
|
||||
["Superbunny Cave - Bottom", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Superbunny Cave - Bottom", True, ['Flute']],
|
||||
["Superbunny Cave - Bottom", True, ['Progressive Glove', 'Lamp']],
|
||||
["Superbunny Cave - Bottom", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute']],
|
||||
["Superbunny Cave - Bottom", True, ['Hammer', 'Progressive Glove', 'Moon Pearl', 'Flute']],
|
||||
|
||||
["Hookshot Cave - Bottom Right", False, []],
|
||||
["Hookshot Cave - Bottom Right", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Hookshot Cave - Bottom Right", False, [], ['Pegasus Boots', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Lamp', 'Pegasus Boots']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute', 'Pegasus Boots']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Hammer', 'Moon Pearl', 'Flute', 'Pegasus Boots']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Flute', 'Pegasus Boots']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Hammer', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Flute', 'Hookshot']],
|
||||
|
||||
["Hookshot Cave - Bottom Left", False, []],
|
||||
["Hookshot Cave - Bottom Left", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Hookshot Cave - Bottom Left", False, [], ['Pegasus Boots', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Left", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Left", True, ['Progressive Glove', 'Hammer', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Left", True, ['Progressive Glove', 'Flute', 'Hookshot']],
|
||||
|
||||
["Hookshot Cave - Top Left", False, []],
|
||||
["Hookshot Cave - Top Left", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Hookshot Cave - Top Left", False, [], ['Pegasus Boots', 'Hookshot']],
|
||||
["Hookshot Cave - Top Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
|
||||
["Hookshot Cave - Top Left", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Top Left", True, ['Progressive Glove', 'Hammer', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Top Left", True, ['Progressive Glove', 'Flute', 'Hookshot']],
|
||||
|
||||
["Hookshot Cave - Top Right", False, []],
|
||||
["Hookshot Cave - Top Right", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Hookshot Cave - Top Right", False, [], ['Pegasus Boots', 'Hookshot']],
|
||||
["Hookshot Cave - Top Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
|
||||
["Hookshot Cave - Top Right", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Top Right", True, ['Progressive Glove', 'Hammer', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Top Right", True, ['Progressive Glove', 'Flute', 'Hookshot']],
|
||||
])
|
||||
|
||||
def testWestDarkWorldDeathMountain(self):
|
||||
|
@ -211,20 +197,20 @@ class TestInvertedDeathMountain(TestInverted):
|
|||
["Spike Cave", False, [], ['Cape', 'Cane of Byrna']],
|
||||
["Spike Cave", False, [], ['Cane of Byrna', 'AnyBottle', 'Magic Upgrade (1/2)']],
|
||||
["Spike Cave", False, [], ['AnyBottle', 'Magic Upgrade (1/2)', 'Pegasus Boots', 'Boss Heart Container', 'Piece of Heart', 'Sanctuary Heart Container']],
|
||||
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']],
|
||||
# Change from base ER - this fork places a blue potion in dark world
|
||||
#["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Cape']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cape']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Flute', 'Cape']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
#["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cape']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Cape']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
|
||||
["Spike Cave", True, ['Pegasus Boots', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Pegasus Boots', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Pegasus Boots', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Boss Heart Container', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Boss Heart Container', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Boss Heart Container', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
])
|
||||
|
||||
|
|
|
@ -6,29 +6,32 @@ class TestEntrances(TestInverted):
|
|||
def testDungeonEntrances(self):
|
||||
self.run_entrance_tests([
|
||||
["Hyrule Castle Entrance (South)", False, []],
|
||||
["Hyrule Castle Entrance (South)", False, [], ["Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Hyrule Castle Entrance (South)", False, [], ["Beat Agahnim 1", "Progressive Glove"]],
|
||||
["Hyrule Castle Entrance (South)", False, [], ["Flute", "Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Hyrule Castle Entrance (South)", False, [], ["Flute", "Beat Agahnim 1", "Progressive Glove"]],
|
||||
["Hyrule Castle Entrance (South)", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]],
|
||||
["Hyrule Castle Entrance (South)", True, ["Beat Agahnim 1"]],
|
||||
["Hyrule Castle Entrance (South)", True, ["Moon Pearl", "Hammer", "Progressive Glove"]],
|
||||
["Hyrule Castle Entrance (South)", True, ["Moon Pearl", "Progressive Glove", "Progressive Glove"]],
|
||||
["Hyrule Castle Entrance (South)", True, ["Flute", "Progressive Glove", "Progressive Glove"]],
|
||||
|
||||
["Eastern Palace", False, []],
|
||||
["Eastern Palace", False, [], ["Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Eastern Palace", False, [], ["Beat Agahnim 1", "Progressive Glove"]],
|
||||
["Eastern Palace", False, [], ["Flute", "Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Eastern Palace", False, [], ["Flute", "Beat Agahnim 1", "Progressive Glove"]],
|
||||
["Eastern Palace", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]],
|
||||
["Eastern Palace", True, ["Beat Agahnim 1"]],
|
||||
["Eastern Palace", True, ["Moon Pearl", "Hammer", "Progressive Glove"]],
|
||||
["Eastern Palace", True, ["Moon Pearl", "Progressive Glove", "Progressive Glove"]],
|
||||
["Eastern Palace", True, ["Flute", "Progressive Glove", "Progressive Glove"]],
|
||||
|
||||
["Desert Palace Entrance (South)", False, []],
|
||||
["Desert Palace Entrance (South)", False, [], ["Book of Mudora"]],
|
||||
["Desert Palace Entrance (South)", False, [], ["Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Desert Palace Entrance (South)", False, [], ["Flute", "Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Desert Palace Entrance (South)", False, [], ["Beat Agahnim 1", "Progressive Glove"]],
|
||||
["Desert Palace Entrance (South)", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]],
|
||||
["Desert Palace Entrance (South)", True, ["Book of Mudora", "Beat Agahnim 1"]],
|
||||
["Desert Palace Entrance (South)", True, ["Book of Mudora", "Moon Pearl", "Hammer", "Progressive Glove"]],
|
||||
["Desert Palace Entrance (South)", True, ["Book of Mudora", "Moon Pearl", "Progressive Glove", "Progressive Glove"]],
|
||||
["Desert Palace Entrance (South)", True, ["Book of Mudora", "Flute", "Progressive Glove", "Progressive Glove"]],
|
||||
["Desert Palace Entrance (North)", False, []],
|
||||
["Desert Palace Entrance (North)", False, [], ["Book of Mudora"]],
|
||||
["Desert Palace Entrance (North)", False, [], ["Progressive Glove"]],
|
||||
|
@ -46,26 +49,21 @@ class TestEntrances(TestInverted):
|
|||
["Tower of Hera", False, [], ["Flute", "Progressive Glove"]],
|
||||
["Tower of Hera", True, ["Moon Pearl", "Hammer", "Progressive Glove", "Progressive Glove", "Lamp"]],
|
||||
["Tower of Hera", True, ["Moon Pearl", "Hammer", "Hookshot", "Progressive Glove", "Lamp"]],
|
||||
["Tower of Hera", True, ["Moon Pearl", "Hammer", "Hookshot", "Progressive Glove", "Flute"]],
|
||||
["Tower of Hera", True, ["Moon Pearl", "Hammer", "Beat Agahnim 1", "Flute", "Hookshot"]],
|
||||
["Tower of Hera", True, ["Moon Pearl", "Hammer", "Hookshot", "Flute"]],
|
||||
|
||||
["Inverted Agahnims Tower", False, []],
|
||||
["Inverted Agahnims Tower", False, [], ["Flute", "Lamp"]],
|
||||
["Inverted Agahnims Tower", False, [], ["Flute", "Progressive Glove"]],
|
||||
["Inverted Agahnims Tower", False, [], ["Moon Pearl", "Lamp"]],
|
||||
["Inverted Agahnims Tower", False, [], ["Moon Pearl", "Progressive Glove"]],
|
||||
["Inverted Agahnims Tower", True, ["Lamp", "Progressive Glove"]],
|
||||
["Inverted Agahnims Tower", True, ["Flute", "Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Inverted Agahnims Tower", True, ["Flute", "Progressive Glove", "Progressive Glove", "Moon Pearl"]],
|
||||
["Inverted Agahnims Tower", True, ["Flute", "Progressive Glove", "Hammer", "Moon Pearl"]],
|
||||
["Inverted Agahnims Tower", True, ["Flute"]],
|
||||
|
||||
["Palace of Darkness", False, []],
|
||||
["Palace of Darkness", False, [], ["Hammer", "Flippers", "Magic Mirror", "Flute"]],
|
||||
["Palace of Darkness", True, ["Hammer"]],
|
||||
["Palace of Darkness", True, ["Flippers"]],
|
||||
["Palace of Darkness", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl", "Flute"]],
|
||||
["Palace of Darkness", True, ["Flute"]],
|
||||
["Palace of Darkness", True, ["Progressive Glove", "Progressive Glove", "Moon Pearl", "Magic Mirror"]],
|
||||
["Palace of Darkness", True, ["Beat Agahnim 1", "Moon Pearl", "Flute"]],
|
||||
["Palace of Darkness", True, ["Flute"]],
|
||||
# Moon Pearl not needed, you can mirror as Bunny
|
||||
["Palace of Darkness", True, ["Beat Agahnim 1", "Magic Mirror"]],
|
||||
|
||||
|
@ -85,15 +83,12 @@ class TestEntrances(TestInverted):
|
|||
|
||||
["Misery Mire", False, []],
|
||||
["Misery Mire", False, [], ["Flute", "Magic Mirror"]],
|
||||
["Misery Mire", False, [], ["Moon Pearl", "Magic Mirror"]],
|
||||
["Misery Mire", False, [], ["Ether"]],
|
||||
["Misery Mire", False, [], ["Progressive Sword"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Beat Agahnim 1", "Magic Mirror"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Beat Agahnim 1", "Moon Pearl", "Flute"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Flute"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Hammer", "Progressive Glove", "Magic Mirror"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Hammer", "Progressive Glove", "Flute"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Progressive Glove", "Progressive Glove", "Magic Mirror"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Progressive Glove", "Progressive Glove", "Flute"]],
|
||||
|
||||
["Turtle Rock", False, []],
|
||||
["Turtle Rock", False, [], ["Quake"]],
|
||||
|
@ -101,9 +96,7 @@ class TestEntrances(TestInverted):
|
|||
["Turtle Rock", False, [], ["Lamp", "Flute"]],
|
||||
["Turtle Rock", False, [], ["Progressive Glove", "Flute"]],
|
||||
["Turtle Rock", True, ["Quake", "Progressive Sword", "Progressive Glove", "Lamp"]],
|
||||
["Turtle Rock", True, ["Quake", "Progressive Sword", "Progressive Glove", "Progressive Glove", "Moon Pearl", "Flute"]],
|
||||
["Turtle Rock", True, ["Quake", "Progressive Sword", "Progressive Glove", "Hammer", "Moon Pearl", "Flute"]],
|
||||
["Turtle Rock", True, ["Quake", "Progressive Sword", "Beat Agahnim 1", "Moon Pearl", "Flute"]],
|
||||
["Turtle Rock", True, ["Quake", "Progressive Sword", "Flute"]],
|
||||
|
||||
["Inverted Ganons Tower", False, []],
|
||||
["Inverted Ganons Tower", False, [], ["Crystal 1"]],
|
||||
|
|
|
@ -191,7 +191,8 @@ class TestInvertedLightWorld(TestInverted):
|
|||
["Bombos Tablet", False, []],
|
||||
["Bombos Tablet", False, ['Progressive Sword'], ['Progressive Sword']],
|
||||
["Bombos Tablet", False, [], ['Book of Mudora']],
|
||||
["Bombos Tablet", False, [], ['Moon Pearl', 'Beat Agahnim 1']],
|
||||
# Flute to Mire, take portal
|
||||
["Bombos Tablet", True, ['Flute', 'Book of Mudora', 'Progressive Glove', 'Progressive Glove', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Bombos Tablet", True, ['Beat Agahnim 1', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Bombos Tablet", True, ['Moon Pearl', 'Book of Mudora', 'Progressive Glove', 'Progressive Glove', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Bombos Tablet", True, ['Moon Pearl', 'Book of Mudora', 'Progressive Glove', 'Hammer', 'Progressive Sword', 'Progressive Sword']],
|
||||
|
|
|
@ -9,70 +9,70 @@ class TestInvertedTurtleRock(TestInverted):
|
|||
["Turtle Rock - Compass Chest", False, [], ['Cane of Somaria']],
|
||||
["Turtle Rock - Compass Chest", False, [], ['Quake', 'Magic Mirror']],
|
||||
["Turtle Rock - Compass Chest", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Quake', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Compass Chest", True, ['Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Compass Chest", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Compass Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
|
||||
["Turtle Rock - Chain Chomps", False, []],
|
||||
["Turtle Rock - Chain Chomps", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
# Item rando only needs 1 key. ER needs to consider the case when the back is accessible, but not the middle (key wasted on Trinexx door)
|
||||
["Turtle Rock - Chain Chomps", False, ['Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', '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)']],
|
||||
["Turtle Rock - Chain Chomps", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', '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, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']],
|
||||
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
|
||||
["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 - Roller Room - Left", False, []],
|
||||
["Turtle Rock - Roller Room - Left", False, [], ['Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Left", False, [], ['Fire Rod']],
|
||||
["Turtle Rock - Roller Room - Left", False, [], ['Quake', 'Magic Mirror']],
|
||||
["Turtle Rock - Roller Room - Left", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Quake', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
|
||||
["Turtle Rock - Roller Room - Left", True, ['Moon Pearl', 'Fire Rod', 'Flute', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
|
||||
["Turtle Rock - Roller Room - Right", False, []],
|
||||
["Turtle Rock - Roller Room - Right", False, [], ['Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Right", False, [], ['Fire Rod']],
|
||||
["Turtle Rock - Roller Room - Right", False, [], ['Quake', 'Magic Mirror']],
|
||||
["Turtle Rock - Roller Room - Right", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Quake', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Moon Pearl', 'Fire Rod', 'Flute', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
|
||||
["Turtle Rock - Big Chest", False, []],
|
||||
["Turtle Rock - Big Chest", False, [], ['Big Key (Turtle Rock)']],
|
||||
["Turtle Rock - Big Chest", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Big Chest", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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)']],
|
||||
["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)']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Hookshot']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hookshot']],
|
||||
|
||||
["Turtle Rock - Big Key Chest", False, []],
|
||||
["Turtle Rock - Big Key Chest", False, ['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', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', '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)']],
|
||||
["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)']],
|
||||
# Mirror in from ledge, use left side entrance, have enough keys to get to the chest
|
||||
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Big Key Chest", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', '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, ['Moon Pearl', '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, ['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 - Crystaroller Room", False, []],
|
||||
["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
|
@ -80,117 +80,15 @@ class TestInvertedTurtleRock(TestInverted):
|
|||
["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)', 'Lamp']],
|
||||
["Turtle Rock - Crystaroller Room", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Crystaroller Room", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Crystaroller Room", 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)']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Somaria']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Lamp', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Somaria']],
|
||||
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, []],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, ['Progressive Shield', 'Progressive Shield'], ['Progressive Shield', 'Cape', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, [], ['Magic Mirror', 'Lamp']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", 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)', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", 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)', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", 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)', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
|
||||
# Mirroring into Eye Bridge does not require Cane of Somaria
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, []],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, ['Progressive Shield', 'Progressive Shield'], ['Progressive Shield', 'Cape', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, [], ['Magic Mirror', 'Lamp']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", 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)', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", 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)', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", 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)', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, []],
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, ['Progressive Shield', 'Progressive Shield'], ['Progressive Shield', 'Cape', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, [], ['Magic Mirror', 'Lamp']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", 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)', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", 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)', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", 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)', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, []],
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, ['Progressive Shield', 'Progressive Shield'], ['Progressive Shield', 'Cape', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, [], ['Magic Mirror', 'Lamp']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", 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)', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", 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)', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", 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)', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Lamp', 'Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Cane of Somaria']],
|
||||
|
||||
["Turtle Rock - Boss", False, []],
|
||||
["Turtle Rock - Boss", False, [], ['Cane of Somaria']],
|
||||
|
@ -200,9 +98,42 @@ class TestInvertedTurtleRock(TestInverted):
|
|||
["Turtle Rock - Boss", False, [], ['Big Key (Turtle Rock)']],
|
||||
["Turtle Rock - Boss", False, [], ['Magic Mirror', 'Lamp']],
|
||||
["Turtle Rock - Boss", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', '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)', '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)', '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)', '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)', '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', 'Beat Agahnim 1', '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):
|
||||
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"]:
|
||||
self.run_location_tests([
|
||||
[location, False, []],
|
||||
[location, False, ['Progressive Shield', 'Progressive Shield'], ['Progressive Shield', 'Cape', 'Cane of Byrna']],
|
||||
[location, False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
[location, False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
[location, False, [], ['Magic Mirror', 'Lamp']],
|
||||
[location, False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
[location, True, ['Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cane of Byrna']],
|
||||
[location, 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)', 'Cane of Byrna']],
|
||||
[location, True, ['Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cape']],
|
||||
[location, 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)', 'Cape']],
|
||||
[location, True, ['Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
[location, 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)', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
|
||||
# Mirroring into Eye Bridge does not require Cane of Somaria
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Byrna']],
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Byrna']],
|
||||
[location, True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Cane of Byrna']],
|
||||
[location, True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Byrna']],
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cape']],
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cape']],
|
||||
[location, True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Cape']],
|
||||
[location, True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cape']],
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
[location, True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
[location, True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
]
|
||||
)
|
||||
|
|
|
@ -88,15 +88,9 @@ class TestInvertedDarkWorld(TestInvertedMinor):
|
|||
self.run_location_tests([
|
||||
["Mire Shed - Left", False, []],
|
||||
["Mire Shed - Left", False, [], ['Flute', 'Magic Mirror']],
|
||||
["Mire Shed - Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove']],
|
||||
["Mire Shed - Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Hammer']],
|
||||
["Mire Shed - Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1']],
|
||||
["Mire Shed - Left", True, ['Magic Mirror', 'Beat Agahnim 1']],
|
||||
["Mire Shed - Left", True, ['Flute']],
|
||||
|
||||
["Mire Shed - Right", False, []],
|
||||
["Mire Shed - Right", False, [], ['Flute', 'Magic Mirror']],
|
||||
["Mire Shed - Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove']],
|
||||
["Mire Shed - Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Hammer']],
|
||||
["Mire Shed - Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1']],
|
||||
["Mire Shed - Right", True, ['Magic Mirror', 'Beat Agahnim 1']],
|
||||
["Mire Shed - Right", True, ['Flute']],
|
||||
])
|
|
@ -9,19 +9,16 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Old Man", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Old Man", False, [], ['Lamp']],
|
||||
["Old Man", True, ['Progressive Glove', 'Lamp']],
|
||||
["Old Man", False, ['Flute', 'Lamp']],
|
||||
["Old Man", True, ['Flute', 'Lamp']],
|
||||
|
||||
["Spectacle Rock Cave", False, []],
|
||||
["Spectacle Rock Cave", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Spectacle Rock Cave", False, [], ['Lamp', 'Flute']],
|
||||
["Spectacle Rock Cave", False, ['Flute', 'Progressive Glove', 'Hammer']],
|
||||
["Spectacle Rock Cave", False, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
|
||||
["Spectacle Rock Cave", False, ['Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Spectacle Rock Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
|
||||
["Spectacle Rock Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove']],
|
||||
["Spectacle Rock Cave", True, ['Flute']],
|
||||
["Spectacle Rock Cave", True, ['Progressive Glove', 'Lamp']],
|
||||
])
|
||||
|
||||
|
||||
def testEastDeathMountain(self):
|
||||
self.run_location_tests([
|
||||
["Spiral Cave", False, []],
|
||||
|
@ -31,8 +28,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Spiral Cave", False, ['Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Spiral Cave", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Spiral Cave", False, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
|
||||
["Spiral Cave", False, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Spiral Cave", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Progressive Glove', 'Hammer']],
|
||||
["Spiral Cave", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Spiral Cave", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hookshot']],
|
||||
["Spiral Cave", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Spiral Cave", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -44,7 +40,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Paradox Cave Lower - Far Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -56,7 +52,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Paradox Cave Lower - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -68,7 +64,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Paradox Cave Lower - Middle", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -80,7 +76,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Paradox Cave Lower - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -92,7 +88,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Paradox Cave Lower - Far Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -104,7 +100,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Paradox Cave Upper - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -116,7 +112,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Paradox Cave Upper - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", True, ['Flute', 'Progressive Glove', 'Hammer', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
|
||||
["Paradox Cave Upper - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
|
||||
|
@ -126,7 +122,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Mimic Cave", False, [], ['Hammer']],
|
||||
["Mimic Cave", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Mimic Cave", False, [], ['Lamp', 'Flute']],
|
||||
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Hammer', 'Hookshot']],
|
||||
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot']],
|
||||
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
|
||||
["Mimic Cave", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']],
|
||||
["Mimic Cave", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']],
|
||||
|
@ -139,7 +135,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Ether Tablet", False, [], ['Hammer']],
|
||||
["Ether Tablet", False, ['Progressive Sword'], ['Progressive Sword']],
|
||||
["Ether Tablet", False, [], ['Book of Mudora']],
|
||||
["Ether Tablet", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Ether Tablet", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Ether Tablet", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Ether Tablet", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Ether Tablet", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
|
@ -150,7 +146,7 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Spectacle Rock", False, [], ['Lamp', 'Flute']],
|
||||
["Spectacle Rock", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
|
||||
["Spectacle Rock", False, [], ['Hammer']],
|
||||
["Spectacle Rock", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Hammer', 'Hookshot']],
|
||||
["Spectacle Rock", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot']],
|
||||
["Spectacle Rock", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
|
||||
["Spectacle Rock", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']],
|
||||
["Spectacle Rock", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']],
|
||||
|
@ -161,45 +157,38 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Superbunny Cave - Top", False, []],
|
||||
["Superbunny Cave - Top", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Superbunny Cave - Top", True, ['Progressive Glove', 'Lamp']],
|
||||
["Superbunny Cave - Top", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute']],
|
||||
["Superbunny Cave - Top", True, ['Hammer', 'Progressive Glove', 'Moon Pearl', 'Flute']],
|
||||
["Superbunny Cave - Top", True, ['Flute']],
|
||||
|
||||
["Superbunny Cave - Bottom", False, []],
|
||||
["Superbunny Cave - Bottom", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Superbunny Cave - Bottom", True, ['Progressive Glove', 'Lamp']],
|
||||
["Superbunny Cave - Bottom", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute']],
|
||||
["Superbunny Cave - Bottom", True, ['Hammer', 'Progressive Glove', 'Moon Pearl', 'Flute']],
|
||||
["Superbunny Cave - Bottom", True, ['Flute']],
|
||||
|
||||
["Hookshot Cave - Bottom Right", False, []],
|
||||
["Hookshot Cave - Bottom Right", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Hookshot Cave - Bottom Right", False, [], ['Pegasus Boots', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Lamp', 'Pegasus Boots']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute', 'Pegasus Boots']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Hammer', 'Moon Pearl', 'Flute', 'Pegasus Boots']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Flute', 'Pegasus Boots']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Hammer', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Right", True, ['Progressive Glove', 'Flute', 'Hookshot']],
|
||||
|
||||
["Hookshot Cave - Bottom Left", False, []],
|
||||
["Hookshot Cave - Bottom Left", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Hookshot Cave - Bottom Left", False, [], ['Pegasus Boots', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Left", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Left", True, ['Progressive Glove', 'Hammer', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Bottom Left", True, ['Progressive Glove', 'Flute', 'Hookshot']],
|
||||
|
||||
["Hookshot Cave - Top Left", False, []],
|
||||
["Hookshot Cave - Top Left", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Hookshot Cave - Top Left", False, [], ['Pegasus Boots', 'Hookshot']],
|
||||
["Hookshot Cave - Top Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
|
||||
["Hookshot Cave - Top Left", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Top Left", True, ['Progressive Glove', 'Hammer', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Top Left", True, ['Progressive Glove', 'Flute', 'Hookshot']],
|
||||
|
||||
["Hookshot Cave - Top Right", False, []],
|
||||
["Hookshot Cave - Top Right", False, [], ['Progressive Glove', 'Flute']],
|
||||
["Hookshot Cave - Top Right", False, [], ['Pegasus Boots', 'Hookshot']],
|
||||
["Hookshot Cave - Top Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
|
||||
["Hookshot Cave - Top Right", True, ['Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Top Right", True, ['Progressive Glove', 'Hammer', 'Moon Pearl', 'Flute', 'Hookshot']],
|
||||
["Hookshot Cave - Top Right", True, ['Progressive Glove', 'Flute', 'Hookshot']],
|
||||
])
|
||||
|
||||
def testWestDarkWorldDeathMountain(self):
|
||||
|
@ -211,19 +200,18 @@ class TestInvertedDeathMountain(TestInvertedMinor):
|
|||
["Spike Cave", False, [], ['Cane of Byrna', 'AnyBottle', 'Magic Upgrade (1/2)']],
|
||||
["Spike Cave", False, [], ['AnyBottle', 'Magic Upgrade (1/2)', 'Pegasus Boots', 'Boss Heart Container', 'Piece of Heart', 'Sanctuary Heart Container']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']],
|
||||
# Change from base ER - this fork places a blue potion in dark world
|
||||
#["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Cape']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cape']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Flute', 'Cape']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
#["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cape']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Cape']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
|
||||
["Spike Cave", True, ['Pegasus Boots', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Pegasus Boots', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Pegasus Boots', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Boss Heart Container', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Boss Heart Container', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Boss Heart Container', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
])
|
||||
|
||||
|
|
|
@ -6,29 +6,32 @@ class TestEntrances(TestInvertedMinor):
|
|||
def testDungeonEntrances(self):
|
||||
self.run_entrance_tests([
|
||||
["Hyrule Castle Entrance (South)", False, []],
|
||||
["Hyrule Castle Entrance (South)", False, [], ["Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Hyrule Castle Entrance (South)", False, [], ["Beat Agahnim 1", "Progressive Glove"]],
|
||||
["Hyrule Castle Entrance (South)", False, [], ["Flute", "Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Hyrule Castle Entrance (South)", False, [], ["Flute", "Beat Agahnim 1", "Progressive Glove"]],
|
||||
["Hyrule Castle Entrance (South)", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]],
|
||||
["Hyrule Castle Entrance (South)", True, ["Beat Agahnim 1"]],
|
||||
["Hyrule Castle Entrance (South)", True, ["Moon Pearl", "Hammer", "Progressive Glove"]],
|
||||
["Hyrule Castle Entrance (South)", True, ["Moon Pearl", "Progressive Glove", "Progressive Glove"]],
|
||||
["Hyrule Castle Entrance (South)", True, ["Flute", "Progressive Glove", "Progressive Glove"]],
|
||||
|
||||
["Eastern Palace", False, []],
|
||||
["Eastern Palace", False, [], ["Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Eastern Palace", False, [], ["Beat Agahnim 1", "Progressive Glove"]],
|
||||
["Eastern Palace", False, [], ["Flute", "Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Eastern Palace", False, [], ["Flute", "Beat Agahnim 1", "Progressive Glove"]],
|
||||
["Eastern Palace", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]],
|
||||
["Eastern Palace", True, ["Beat Agahnim 1"]],
|
||||
["Eastern Palace", True, ["Moon Pearl", "Hammer", "Progressive Glove"]],
|
||||
["Eastern Palace", True, ["Moon Pearl", "Progressive Glove", "Progressive Glove"]],
|
||||
["Eastern Palace", True, ["Flute", "Progressive Glove", "Progressive Glove"]],
|
||||
|
||||
["Desert Palace Entrance (South)", False, []],
|
||||
["Desert Palace Entrance (South)", False, [], ["Book of Mudora"]],
|
||||
["Desert Palace Entrance (South)", False, [], ["Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Desert Palace Entrance (South)", False, [], ["Flute", "Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Desert Palace Entrance (South)", False, [], ["Beat Agahnim 1", "Progressive Glove"]],
|
||||
["Desert Palace Entrance (South)", False, ["Progressive Glove"], ["Beat Agahnim 1", "Hammer", "Progressive Glove"]],
|
||||
["Desert Palace Entrance (South)", True, ["Book of Mudora", "Beat Agahnim 1"]],
|
||||
["Desert Palace Entrance (South)", True, ["Book of Mudora", "Moon Pearl", "Hammer", "Progressive Glove"]],
|
||||
["Desert Palace Entrance (South)", True, ["Book of Mudora", "Moon Pearl", "Progressive Glove", "Progressive Glove"]],
|
||||
["Desert Palace Entrance (South)", True, ["Book of Mudora", "Flute", "Progressive Glove", "Progressive Glove"]],
|
||||
["Desert Palace Entrance (North)", False, []],
|
||||
["Desert Palace Entrance (North)", False, [], ["Book of Mudora"]],
|
||||
["Desert Palace Entrance (North)", False, [], ["Progressive Glove"]],
|
||||
|
@ -46,18 +49,13 @@ class TestEntrances(TestInvertedMinor):
|
|||
["Tower of Hera", False, [], ["Flute", "Progressive Glove"]],
|
||||
["Tower of Hera", True, ["Moon Pearl", "Hammer", "Progressive Glove", "Progressive Glove", "Lamp"]],
|
||||
["Tower of Hera", True, ["Moon Pearl", "Hammer", "Hookshot", "Progressive Glove", "Lamp"]],
|
||||
["Tower of Hera", True, ["Moon Pearl", "Hammer", "Hookshot", "Progressive Glove", "Flute"]],
|
||||
["Tower of Hera", True, ["Moon Pearl", "Hammer", "Beat Agahnim 1", "Flute", "Hookshot"]],
|
||||
["Tower of Hera", True, ["Moon Pearl", "Hammer", "Hookshot", "Flute"]],
|
||||
|
||||
["Inverted Agahnims Tower", False, []],
|
||||
["Inverted Agahnims Tower", False, [], ["Flute", "Lamp"]],
|
||||
["Inverted Agahnims Tower", False, [], ["Flute", "Progressive Glove"]],
|
||||
["Inverted Agahnims Tower", False, [], ["Moon Pearl", "Lamp"]],
|
||||
["Inverted Agahnims Tower", False, [], ["Moon Pearl", "Progressive Glove"]],
|
||||
["Inverted Agahnims Tower", True, ["Lamp", "Progressive Glove"]],
|
||||
["Inverted Agahnims Tower", True, ["Flute", "Beat Agahnim 1", "Moon Pearl"]],
|
||||
["Inverted Agahnims Tower", True, ["Flute", "Progressive Glove", "Progressive Glove", "Moon Pearl"]],
|
||||
["Inverted Agahnims Tower", True, ["Flute", "Progressive Glove", "Hammer", "Moon Pearl"]],
|
||||
["Inverted Agahnims Tower", True, ["Flute"]],
|
||||
|
||||
["Palace of Darkness", True, []],
|
||||
|
||||
|
@ -75,15 +73,12 @@ class TestEntrances(TestInvertedMinor):
|
|||
|
||||
["Misery Mire", False, []],
|
||||
["Misery Mire", False, [], ["Flute", "Magic Mirror"]],
|
||||
["Misery Mire", False, [], ["Moon Pearl", "Magic Mirror"]],
|
||||
["Misery Mire", False, [], ["Ether"]],
|
||||
["Misery Mire", False, [], ["Progressive Sword"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Beat Agahnim 1", "Magic Mirror"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Beat Agahnim 1", "Moon Pearl", "Flute"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Flute"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Hammer", "Progressive Glove", "Magic Mirror"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Hammer", "Progressive Glove", "Flute"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Progressive Glove", "Progressive Glove", "Magic Mirror"]],
|
||||
["Misery Mire", True, ["Progressive Sword", "Ether", "Moon Pearl", "Progressive Glove", "Progressive Glove", "Flute"]],
|
||||
|
||||
["Turtle Rock", False, []],
|
||||
["Turtle Rock", False, [], ["Quake"]],
|
||||
|
@ -91,9 +86,7 @@ class TestEntrances(TestInvertedMinor):
|
|||
["Turtle Rock", False, [], ["Lamp", "Flute"]],
|
||||
["Turtle Rock", False, [], ["Progressive Glove", "Flute"]],
|
||||
["Turtle Rock", True, ["Quake", "Progressive Sword", "Progressive Glove", "Lamp"]],
|
||||
["Turtle Rock", True, ["Quake", "Progressive Sword", "Progressive Glove", "Progressive Glove", "Moon Pearl", "Flute"]],
|
||||
["Turtle Rock", True, ["Quake", "Progressive Sword", "Progressive Glove", "Hammer", "Moon Pearl", "Flute"]],
|
||||
["Turtle Rock", True, ["Quake", "Progressive Sword", "Beat Agahnim 1", "Moon Pearl", "Flute"]],
|
||||
["Turtle Rock", True, ["Quake", "Progressive Sword", "Flute"]],
|
||||
|
||||
["Inverted Ganons Tower", False, []],
|
||||
["Inverted Ganons Tower", False, [], ["Crystal 1"]],
|
||||
|
|
|
@ -186,7 +186,8 @@ class TestInvertedLightWorld(TestInvertedMinor):
|
|||
["Bombos Tablet", False, []],
|
||||
["Bombos Tablet", False, ['Progressive Sword'], ['Progressive Sword']],
|
||||
["Bombos Tablet", False, [], ['Book of Mudora']],
|
||||
["Bombos Tablet", False, [], ['Moon Pearl', 'Beat Agahnim 1']],
|
||||
# Flute to Mire, take portal
|
||||
["Bombos Tablet", True, ['Flute', 'Book of Mudora', 'Progressive Glove', 'Progressive Glove', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Bombos Tablet", True, ['Beat Agahnim 1', 'Book of Mudora', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Bombos Tablet", True, ['Moon Pearl', 'Book of Mudora', 'Progressive Glove', 'Progressive Glove', 'Progressive Sword', 'Progressive Sword']],
|
||||
["Bombos Tablet", True, ['Moon Pearl', 'Book of Mudora', 'Progressive Glove', 'Hammer', 'Progressive Sword', 'Progressive Sword']],
|
||||
|
|
|
@ -9,70 +9,70 @@ class TestInvertedTurtleRock(TestInvertedMinor):
|
|||
["Turtle Rock - Compass Chest", False, [], ['Cane of Somaria']],
|
||||
["Turtle Rock - Compass Chest", False, [], ['Quake', 'Magic Mirror']],
|
||||
["Turtle Rock - Compass Chest", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Quake', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Compass Chest", True, ['Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Compass Chest", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Compass Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Compass Chest", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
|
||||
["Turtle Rock - Chain Chomps", False, []],
|
||||
["Turtle Rock - Chain Chomps", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
# Item rando only needs 1 key. ER needs to consider the case when the back is accessible, but not the middle (key wasted on Trinexx door)
|
||||
["Turtle Rock - Chain Chomps", False, ['Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', '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)']],
|
||||
["Turtle Rock - Chain Chomps", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', '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, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']],
|
||||
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
|
||||
["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 - Roller Room - Left", False, []],
|
||||
["Turtle Rock - Roller Room - Left", False, [], ['Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Left", False, [], ['Fire Rod']],
|
||||
["Turtle Rock - Roller Room - Left", False, [], ['Quake', 'Magic Mirror']],
|
||||
["Turtle Rock - Roller Room - Left", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Quake', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
|
||||
["Turtle Rock - Roller Room - Left", True, ['Moon Pearl', 'Fire Rod', 'Flute', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Left", True, ['Fire Rod', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
|
||||
["Turtle Rock - Roller Room - Right", False, []],
|
||||
["Turtle Rock - Roller Room - Right", False, [], ['Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Right", False, [], ['Fire Rod']],
|
||||
["Turtle Rock - Roller Room - Right", False, [], ['Quake', 'Magic Mirror']],
|
||||
["Turtle Rock - Roller Room - Right", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Quake', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Moon Pearl', 'Fire Rod', 'Flute', 'Magic Mirror', 'Hookshot', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Roller Room - Right", True, ['Fire Rod', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
|
||||
["Turtle Rock - Big Chest", False, []],
|
||||
["Turtle Rock - Big Chest", False, [], ['Big Key (Turtle Rock)']],
|
||||
["Turtle Rock - Big Chest", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Big Chest", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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)']],
|
||||
["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)']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Hookshot']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Hookshot']],
|
||||
|
||||
["Turtle Rock - Big Key Chest", False, []],
|
||||
["Turtle Rock - Big Key Chest", False, ['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', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', '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)']],
|
||||
["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)']],
|
||||
# Mirror in from ledge, use left side entrance, have enough keys to get to the chest
|
||||
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Big Key Chest", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', '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, ['Moon Pearl', '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, ['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 - Crystaroller Room", False, []],
|
||||
["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
|
@ -80,117 +80,15 @@ class TestInvertedTurtleRock(TestInvertedMinor):
|
|||
["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)', 'Lamp']],
|
||||
["Turtle Rock - Crystaroller Room", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Crystaroller Room", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Crystaroller Room", 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)']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Big Key (Turtle Rock)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Somaria']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Somaria']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Lamp', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Somaria']],
|
||||
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, []],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, ['Progressive Shield', 'Progressive Shield'], ['Progressive Shield', 'Cape', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, [], ['Magic Mirror', 'Lamp']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", 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)', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", 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)', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", 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)', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
|
||||
# Mirroring into Eye Bridge does not require Cane of Somaria
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, []],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, ['Progressive Shield', 'Progressive Shield'], ['Progressive Shield', 'Cape', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, [], ['Magic Mirror', 'Lamp']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", 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)', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", 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)', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", 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)', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Bottom Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, []],
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, ['Progressive Shield', 'Progressive Shield'], ['Progressive Shield', 'Cape', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, [], ['Magic Mirror', 'Lamp']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", 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)', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", 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)', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", 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)', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Left", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, []],
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, ['Progressive Shield', 'Progressive Shield'], ['Progressive Shield', 'Cape', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, [], ['Magic Mirror', 'Lamp']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", 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)', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", 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)', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Big Key (Turtle Rock)', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", 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)', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Byrna']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cape']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Beat Agahnim 1', 'Magic Mirror', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Eye Bridge - Top Right", True, ['Moon Pearl', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
["Turtle Rock - Crystaroller Room", True, ['Lamp', 'Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Cane of Somaria']],
|
||||
|
||||
["Turtle Rock - Boss", False, []],
|
||||
["Turtle Rock - Boss", False, [], ['Cane of Somaria']],
|
||||
|
@ -200,9 +98,43 @@ class TestInvertedTurtleRock(TestInvertedMinor):
|
|||
["Turtle Rock - Boss", False, [], ['Big Key (Turtle Rock)']],
|
||||
["Turtle Rock - Boss", False, [], ['Magic Mirror', 'Lamp']],
|
||||
["Turtle Rock - Boss", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']],
|
||||
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Moon Pearl', 'Flute', 'Beat Agahnim 1', '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)', '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)', '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)', '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)', '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', 'Beat Agahnim 1', '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):
|
||||
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"]:
|
||||
self.run_location_tests([
|
||||
[location, False, []],
|
||||
[location, False, ['Progressive Shield', 'Progressive Shield'], ['Progressive Shield', 'Cape', 'Cane of Byrna']],
|
||||
[location, False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
|
||||
[location, False, [], ['Magic Mirror', 'Cane of Somaria']],
|
||||
[location, False, [], ['Magic Mirror', 'Lamp']],
|
||||
[location, False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
|
||||
[location, True, ['Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cane of Byrna']],
|
||||
[location, 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)', 'Cane of Byrna']],
|
||||
[location, True, ['Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Cape']],
|
||||
[location, 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)', 'Cape']],
|
||||
[location, True, ['Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Lamp', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
[location, 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)', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
|
||||
# Mirroring into Eye Bridge does not require Cane of Somaria
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cane of Byrna']],
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cane of Byrna']],
|
||||
[location, True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Cane of Byrna']],
|
||||
[location, True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cane of Byrna']],
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Cape']],
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Cape']],
|
||||
[location, True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Cape']],
|
||||
[location, True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Cape']],
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
[location, True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
[location, True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
[location, True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Progressive Shield', 'Progressive Shield', 'Progressive Shield']],
|
||||
]
|
||||
)
|
||||
|
|
|
@ -78,14 +78,14 @@ class TestDeathMountain(TestInvertedOWG):
|
|||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']],
|
||||
# Change from base ER - this fork places a blue potion in dark world
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Bottle', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Lamp', 'Cape']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cape']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Cape']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Magic Upgrade (1/2)', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Pegasus Boots', 'Hammer', 'Progressive Glove', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Boss Heart Container', 'Hammer', 'Progressive Glove', 'Lamp', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Boss Heart Container', 'Hammer', 'Progressive Glove', 'Flute', 'Moon Pearl', 'Cane of Byrna']],
|
||||
["Spike Cave", True, ['Boss Heart Container', 'Hammer', 'Progressive Glove', 'Flute', 'Cane of Byrna']],
|
||||
])
|
||||
|
||||
def testEastDarkWorldDeathMountain(self):
|
||||
|
|
Loading…
Reference in New Issue