Merge branch 'main' into instruction_patch_clean

This commit is contained in:
Silvris
2024-02-28 16:41:09 -06:00
committed by GitHub
141 changed files with 4409 additions and 3558 deletions

1
.github/labeler.yml vendored
View File

@@ -27,4 +27,5 @@
- '!WebHostLib/**'
- any-glob-to-any-file: # exceptions to the above rules of "stuff that isn't core"
- 'worlds/generic/**/*.py'
- 'worlds/*.py'
- 'CommonClient.py'

65
.github/workflows/scan-build.yml vendored Normal file
View File

@@ -0,0 +1,65 @@
name: Native Code Static Analysis
on:
push:
paths:
- '**.c'
- '**.cc'
- '**.cpp'
- '**.cxx'
- '**.h'
- '**.hh'
- '**.hpp'
- '**.pyx'
- 'setup.py'
- 'requirements.txt'
- '.github/workflows/scan-build.yml'
pull_request:
paths:
- '**.c'
- '**.cc'
- '**.cpp'
- '**.cxx'
- '**.h'
- '**.hh'
- '**.hpp'
- '**.pyx'
- 'setup.py'
- 'requirements.txt'
- '.github/workflows/scan-build.yml'
jobs:
scan-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install newer Clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x ./llvm.sh
sudo ./llvm.sh 17
- name: Install scan-build command
run: |
sudo apt install clang-tools-17
- name: Get a recent python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip -r requirements.txt
- name: scan-build
run: |
source venv/bin/activate
scan-build-17 --status-bugs -o scan-build-reports -disable-checker deadcode.DeadStores python setup.py build -y
- name: Store report
if: failure()
uses: actions/upload-artifact@v4
with:
name: scan-build-reports
path: scan-build-reports

View File

@@ -110,10 +110,14 @@ class MultiWorld():
return self
def append(self, region: Region):
assert region.name not in self.region_cache[region.player], \
f"{region.name} already exists in region cache."
self.region_cache[region.player][region.name] = region
def extend(self, regions: Iterable[Region]):
for region in regions:
assert region.name not in self.region_cache[region.player], \
f"{region.name} already exists in region cache."
self.region_cache[region.player][region.name] = region
def add_group(self, new_id: int):
@@ -159,11 +163,11 @@ class MultiWorld():
self.fix_trock_doors = self.AttributeProxy(
lambda player: self.shuffle[player] != 'vanilla' or self.mode[player] == 'inverted')
self.fix_skullwoods_exit = self.AttributeProxy(
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'])
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeons_simple'])
self.fix_palaceofdarkness_exit = self.AttributeProxy(
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'])
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeons_simple'])
self.fix_trock_exit = self.AttributeProxy(
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'])
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeons_simple'])
for player in range(1, players + 1):
def set_player_attr(attr, val):
@@ -877,6 +881,8 @@ class Region:
del(self.region_manager.location_cache[location.player][location.name])
def insert(self, index: int, value: Location) -> None:
assert value.name not in self.region_manager.location_cache[value.player], \
f"{value.name} already exists in the location cache."
self._list.insert(index, value)
self.region_manager.location_cache[value.player][value.name] = value
@@ -887,6 +893,8 @@ class Region:
del(self.region_manager.entrance_cache[entrance.player][entrance.name])
def insert(self, index: int, value: Entrance) -> None:
assert value.name not in self.region_manager.entrance_cache[value.player], \
f"{value.name} already exists in the entrance cache."
self._list.insert(index, value)
self.region_manager.entrance_cache[value.player][value.name] = value
@@ -1272,12 +1280,12 @@ class Spoiler:
for location in sphere:
state.collect(location.item, True, location)
required_locations -= sphere
collection_spheres.append(sphere)
logging.debug('Calculated final sphere %i, containing %i of %i progress items.', len(collection_spheres),
len(sphere), len(required_locations))
required_locations -= sphere
if not sphere:
raise RuntimeError(f'Not all required items reachable. Unreachable locations: {required_locations}')

View File

@@ -941,4 +941,5 @@ def run_as_textclient():
if __name__ == '__main__':
logging.getLogger().setLevel(logging.INFO) # force log-level to work around log level resetting to WARNING
run_as_textclient()

View File

@@ -315,20 +315,6 @@ def prefer_int(input_data: str) -> Union[str, int]:
return input_data
goals = {
'ganon': 'ganon',
'crystals': 'crystals',
'bosses': 'bosses',
'pedestal': 'pedestal',
'ganon_pedestal': 'ganonpedestal',
'triforce_hunt': 'triforcehunt',
'local_triforce_hunt': 'localtriforcehunt',
'ganon_triforce_hunt': 'ganontriforcehunt',
'local_ganon_triforce_hunt': 'localganontriforcehunt',
'ice_rod_hunt': 'icerodhunt',
}
def roll_percentage(percentage: Union[int, float]) -> bool:
"""Roll a percentage chance.
percentage is expected to be in range [0, 100]"""
@@ -357,15 +343,6 @@ def roll_meta_option(option_key, game: str, category_dict: Dict) -> Any:
if options[option_key].supports_weighting:
return get_choice(option_key, category_dict)
return category_dict[option_key]
if game == "A Link to the Past": # TODO wow i hate this
if option_key in {"glitches_required", "dark_room_logic", "entrance_shuffle", "goals", "triforce_pieces_mode",
"triforce_pieces_percentage", "triforce_pieces_available", "triforce_pieces_extra",
"triforce_pieces_required", "shop_shuffle", "mode", "item_pool", "item_functionality",
"boss_shuffle", "enemy_damage", "enemy_health", "timer", "countdown_start_time",
"red_clock_time", "blue_clock_time", "green_clock_time", "dungeon_counters", "shuffle_prizes",
"misery_mire_medallion", "turtle_rock_medallion", "sprite_pool", "sprite",
"random_sprite_on_event"}:
return get_choice(option_key, category_dict)
raise Exception(f"Error generating meta option {option_key} for {game}.")
@@ -485,120 +462,23 @@ def roll_settings(weights: dict, plando_options: PlandoOptions = PlandoOptions.b
handle_option(ret, game_weights, option_key, option, plando_options)
if PlandoOptions.items in plando_options:
ret.plando_items = game_weights.get("plando_items", [])
if ret.game == "Minecraft" or ret.game == "Ocarina of Time":
# bad hardcoded behavior to make this work for now
ret.plando_connections = []
if PlandoOptions.connections in plando_options:
options = game_weights.get("plando_connections", [])
for placement in options:
if roll_percentage(get_choice("percentage", placement, 100)):
ret.plando_connections.append(PlandoConnection(
get_choice("entrance", placement),
get_choice("exit", placement),
get_choice("direction", placement)
))
elif ret.game == "A Link to the Past":
if ret.game == "A Link to the Past":
roll_alttp_settings(ret, game_weights, plando_options)
if PlandoOptions.connections in plando_options:
ret.plando_connections = []
options = game_weights.get("plando_connections", [])
for placement in options:
if roll_percentage(get_choice("percentage", placement, 100)):
ret.plando_connections.append(PlandoConnection(
get_choice("entrance", placement),
get_choice("exit", placement),
get_choice("direction", placement, "both")
))
return ret
def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
if "dungeon_items" in weights and get_choice_legacy('dungeon_items', weights, "none") != "none":
raise Exception(f"dungeon_items key in A Link to the Past was removed, but is present in these weights as {get_choice_legacy('dungeon_items', weights, False)}.")
glitches_required = get_choice_legacy('glitches_required', weights)
if glitches_required not in [None, 'none', 'no_logic', 'overworld_glitches', 'hybrid_major_glitches', 'minor_glitches']:
logging.warning("Only NMG, OWG, HMG and No Logic supported")
glitches_required = 'none'
ret.logic = {None: 'noglitches', 'none': 'noglitches', 'no_logic': 'nologic', 'overworld_glitches': 'owglitches',
'minor_glitches': 'minorglitches', 'hybrid_major_glitches': 'hybridglitches'}[
glitches_required]
ret.dark_room_logic = get_choice_legacy("dark_room_logic", weights, "lamp")
if not ret.dark_room_logic: # None/False
ret.dark_room_logic = "none"
if ret.dark_room_logic == "sconces":
ret.dark_room_logic = "torches"
if ret.dark_room_logic not in {"lamp", "torches", "none"}:
raise ValueError(f"Unknown Dark Room Logic: \"{ret.dark_room_logic}\"")
entrance_shuffle = get_choice_legacy('entrance_shuffle', weights, 'vanilla')
if entrance_shuffle.startswith('none-'):
ret.shuffle = 'vanilla'
else:
ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla'
goal = get_choice_legacy('goals', weights, 'ganon')
ret.goal = goals[goal]
extra_pieces = get_choice_legacy('triforce_pieces_mode', weights, 'available')
ret.triforce_pieces_required = LttPOptions.TriforcePieces.from_any(get_choice_legacy('triforce_pieces_required', weights, 20))
# sum a percentage to required
if extra_pieces == 'percentage':
percentage = max(100, float(get_choice_legacy('triforce_pieces_percentage', weights, 150))) / 100
ret.triforce_pieces_available = int(round(ret.triforce_pieces_required * percentage, 0))
# vanilla mode (specify how many pieces are)
elif extra_pieces == 'available':
ret.triforce_pieces_available = LttPOptions.TriforcePieces.from_any(
get_choice_legacy('triforce_pieces_available', weights, 30))
# required pieces + fixed extra
elif extra_pieces == 'extra':
extra_pieces = max(0, int(get_choice_legacy('triforce_pieces_extra', weights, 10)))
ret.triforce_pieces_available = ret.triforce_pieces_required + extra_pieces
# change minimum to required pieces to avoid problems
ret.triforce_pieces_available = min(max(ret.triforce_pieces_required, int(ret.triforce_pieces_available)), 90)
ret.shop_shuffle = get_choice_legacy('shop_shuffle', weights, '')
if not ret.shop_shuffle:
ret.shop_shuffle = ''
ret.mode = get_choice_legacy("mode", weights)
ret.difficulty = get_choice_legacy('item_pool', weights)
ret.item_functionality = get_choice_legacy('item_functionality', weights)
ret.enemy_damage = {None: 'default',
'default': 'default',
'shuffled': 'shuffled',
'random': 'chaos', # to be removed
'chaos': 'chaos',
}[get_choice_legacy('enemy_damage', weights)]
ret.enemy_health = get_choice_legacy('enemy_health', weights)
ret.timer = {'none': False,
None: False,
False: False,
'timed': 'timed',
'timed_ohko': 'timed-ohko',
'ohko': 'ohko',
'timed_countdown': 'timed-countdown',
'display': 'display'}[get_choice_legacy('timer', weights, False)]
ret.countdown_start_time = int(get_choice_legacy('countdown_start_time', weights, 10))
ret.red_clock_time = int(get_choice_legacy('red_clock_time', weights, -2))
ret.blue_clock_time = int(get_choice_legacy('blue_clock_time', weights, 2))
ret.green_clock_time = int(get_choice_legacy('green_clock_time', weights, 4))
ret.dungeon_counters = get_choice_legacy('dungeon_counters', weights, 'default')
ret.shuffle_prizes = get_choice_legacy('shuffle_prizes', weights, "g")
ret.required_medallions = [get_choice_legacy("misery_mire_medallion", weights, "random"),
get_choice_legacy("turtle_rock_medallion", weights, "random")]
for index, medallion in enumerate(ret.required_medallions):
ret.required_medallions[index] = {"ether": "Ether", "quake": "Quake", "bombos": "Bombos", "random": "random"} \
.get(medallion.lower(), None)
if not ret.required_medallions[index]:
raise Exception(f"unknown Medallion {medallion} for {'misery mire' if index == 0 else 'turtle rock'}")
ret.plando_texts = {}
if PlandoOptions.texts in plando_options:
@@ -612,17 +492,6 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
raise Exception(f"No text target \"{at}\" found.")
ret.plando_texts[at] = str(get_choice_legacy("text", placement))
ret.plando_connections = []
if PlandoOptions.connections in plando_options:
options = weights.get("plando_connections", [])
for placement in options:
if roll_percentage(get_choice_legacy("percentage", placement, 100)):
ret.plando_connections.append(PlandoConnection(
get_choice_legacy("entrance", placement),
get_choice_legacy("exit", placement),
get_choice_legacy("direction", placement, "both")
))
ret.sprite_pool = weights.get('sprite_pool', [])
ret.sprite = get_choice_legacy('sprite', weights, "Link")
if 'random_sprite_on_event' in weights:

View File

@@ -19,14 +19,12 @@ import warnings
from argparse import Namespace
from settings import Settings, get_settings
from typing import BinaryIO, Coroutine, Optional, Set, Dict, Any, Union
from yaml import load, load_all, dump, SafeLoader
from yaml import load, load_all, dump
try:
from yaml import CLoader as UnsafeLoader
from yaml import CDumper as Dumper
from yaml import CLoader as UnsafeLoader, CSafeLoader as SafeLoader, CDumper as Dumper
except ImportError:
from yaml import Loader as UnsafeLoader
from yaml import Dumper
from yaml import Loader as UnsafeLoader, SafeLoader, Dumper
if typing.TYPE_CHECKING:
import tkinter

View File

@@ -48,6 +48,7 @@ cdef struct IndexEntry:
size_t count
@cython.auto_pickle(False)
cdef class LocationStore:
"""Compact store for locations and their items in a MultiServer"""
# The original implementation uses Dict[int, Dict[int, Tuple(int, int, int]]
@@ -78,18 +79,6 @@ cdef class LocationStore:
size += sizeof(self._raw_proxies[0]) * self.sender_index_size
return size
def __cinit__(self, locations_dict: Dict[int, Dict[int, Sequence[int]]]) -> None:
self._mem = None
self._keys = None
self._items = None
self._proxies = None
self._len = 0
self.entries = NULL
self.entry_count = 0
self.sender_index = NULL
self.sender_index_size = 0
self._raw_proxies = NULL
def __init__(self, locations_dict: Dict[int, Dict[int, Sequence[int]]]) -> None:
self._mem = Pool()
cdef object key
@@ -281,6 +270,7 @@ cdef class LocationStore:
entry.location not in checked])
@cython.auto_pickle(False)
@cython.internal # unsafe. disable direct import
cdef class PlayerLocationProxy:
cdef LocationStore _store

Binary file not shown.

View File

@@ -22,6 +22,10 @@ SOFTWARE.
local SCRIPT_VERSION = 1
-- Set to log incoming requests
-- Will cause lag due to large console output
local DEBUG = false
--[[
This script expects to receive JSON and will send JSON back. A message should
be a list of 1 or more requests which will be executed in order. Each request
@@ -271,10 +275,6 @@ local base64 = require("base64")
local socket = require("socket")
local json = require("json")
-- Set to log incoming requests
-- Will cause lag due to large console output
local DEBUG = false
local SOCKET_PORT_FIRST = 43055
local SOCKET_PORT_RANGE_SIZE = 5
local SOCKET_PORT_LAST = SOCKET_PORT_FIRST + SOCKET_PORT_RANGE_SIZE
@@ -330,18 +330,28 @@ function unlock ()
client_socket:settimeout(0)
end
function process_request (req)
local res = {}
request_handlers = {
["PING"] = function (req)
local res = {}
if req["type"] == "PING" then
res["type"] = "PONG"
elseif req["type"] == "SYSTEM" then
return res
end,
["SYSTEM"] = function (req)
local res = {}
res["type"] = "SYSTEM_RESPONSE"
res["value"] = emu.getsystemid()
elseif req["type"] == "PREFERRED_CORES" then
return res
end,
["PREFERRED_CORES"] = function (req)
local res = {}
local preferred_cores = client.getconfig().PreferredCores
res["type"] = "PREFERRED_CORES_RESPONSE"
res["value"] = {}
res["value"]["NES"] = preferred_cores.NES
@@ -354,14 +364,21 @@ function process_request (req)
res["value"]["PCECD"] = preferred_cores.PCECD
res["value"]["SGX"] = preferred_cores.SGX
elseif req["type"] == "HASH" then
return res
end,
["HASH"] = function (req)
local res = {}
res["type"] = "HASH_RESPONSE"
res["value"] = rom_hash
elseif req["type"] == "GUARD" then
res["type"] = "GUARD_RESPONSE"
local expected_data = base64.decode(req["expected_data"])
return res
end,
["GUARD"] = function (req)
local res = {}
local expected_data = base64.decode(req["expected_data"])
local actual_data = memory.read_bytes_as_array(req["address"], #expected_data, req["domain"])
local data_is_validated = true
@@ -372,39 +389,83 @@ function process_request (req)
end
end
res["type"] = "GUARD_RESPONSE"
res["value"] = data_is_validated
res["address"] = req["address"]
elseif req["type"] == "LOCK" then
return res
end,
["LOCK"] = function (req)
local res = {}
res["type"] = "LOCKED"
lock()
elseif req["type"] == "UNLOCK" then
return res
end,
["UNLOCK"] = function (req)
local res = {}
res["type"] = "UNLOCKED"
unlock()
elseif req["type"] == "READ" then
return res
end,
["READ"] = function (req)
local res = {}
res["type"] = "READ_RESPONSE"
res["value"] = base64.encode(memory.read_bytes_as_array(req["address"], req["size"], req["domain"]))
elseif req["type"] == "WRITE" then
return res
end,
["WRITE"] = function (req)
local res = {}
res["type"] = "WRITE_RESPONSE"
memory.write_bytes_as_array(req["address"], base64.decode(req["value"]), req["domain"])
elseif req["type"] == "DISPLAY_MESSAGE" then
return res
end,
["DISPLAY_MESSAGE"] = function (req)
local res = {}
res["type"] = "DISPLAY_MESSAGE_RESPONSE"
message_queue:push(req["message"])
elseif req["type"] == "SET_MESSAGE_INTERVAL" then
return res
end,
["SET_MESSAGE_INTERVAL"] = function (req)
local res = {}
res["type"] = "SET_MESSAGE_INTERVAL_RESPONSE"
message_interval = req["value"]
else
return res
end,
["default"] = function (req)
local res = {}
res["type"] = "ERROR"
res["err"] = "Unknown command: "..req["type"]
end
return res
return res
end,
}
function process_request (req)
if request_handlers[req["type"]] then
return request_handlers[req["type"]](req)
else
return request_handlers["default"](req)
end
end
-- Receive data from AP client and send message back

View File

@@ -327,7 +327,11 @@ Sent to server to inform it of locations that the client has checked. Used to in
| locations | list\[int\] | The ids of the locations checked by the client. May contain any number of checks, even ones sent before; duplicates do not cause issues with the Archipelago server. |
### LocationScouts
Sent to the server to inform it of locations the client has seen, but not checked. Useful in cases in which the item may appear in the game world, such as 'ledge items' in A Link to the Past. The server will always respond with a [LocationInfo](#LocationInfo) packet with the items located in the scouted location.
Sent to the server to retrieve the items that are on a specified list of locations. The server will respond with a [LocationInfo](#LocationInfo) packet containing the items located in the scouted locations.
Fully remote clients without a patch file may use this to "place" items onto their in-game locations, most commonly to display their names or item classifications before/upon pickup.
LocationScouts can also be used to inform the server of locations the client has seen, but not checked. This creates a hint as if the player had run `!hint_location` on a location, but without deducting hint points.
This is useful in cases where an item appears in the game world, such as 'ledge items' in _A Link to the Past_. To do this, set the `create_as_hint` parameter to a non-zero value.
#### Arguments
| Name | Type | Notes |

View File

@@ -24,8 +24,11 @@ display as `Value1` on the webhost.
(i.e. `alias_value_1 = option_value1`) which will allow users to use either `value_1` or `value1` in their yaml
files, and both will resolve as `value1`. This should be used when changing options around, i.e. changing a Toggle to a
Choice, and defining `alias_true = option_full`.
- All options support `random` as a generic option. `random` chooses from any of the available values for that option,
and is reserved by AP. You can set this as your default value, but you cannot define your own `option_random`.
- All options with a fixed set of possible values (i.e. those which inherit from `Toggle`, `(Text)Choice` or
`(Named/Special)Range`) support `random` as a generic option. `random` chooses from any of the available values for that
option, and is reserved by AP. You can set this as your default value, but you cannot define your own `option_random`.
However, you can override `from_text` and handle `text == "random"` to customize its behavior or
implement it for additional option types.
As an example, suppose we want an option that lets the user start their game with a sword in their inventory, an option
to let the player choose the difficulty, and an option to choose how much health the final boss has. Let's create our

View File

@@ -170,6 +170,7 @@ could also be progress in a research tree, or even something more abstract like
Each location has a `name` and an `address` (hereafter referred to as an `id`), is placed in a Region, has access rules,
and has a classification. The name needs to be unique within each game and must not be numeric (must contain least 1
letter or symbol). The ID needs to be unique across all games, and is best kept in the same range as the item IDs.
Locations and items can share IDs, so typically a game's locations and items start at the same ID.
World-specific IDs must be in the range 1 to 2<sup>53</sup>-1; IDs ≤ 0 are global and reserved.

View File

@@ -1,13 +1,13 @@
colorama>=0.4.5
colorama>=0.4.6
websockets>=12.0
PyYAML>=6.0.1
jellyfish>=1.0.3
jinja2>=3.1.2
jinja2>=3.1.3
schema>=0.7.5
kivy>=2.3.0
bsdiff4>=1.2.4
platformdirs>=4.0.0
platformdirs>=4.1.0
certifi>=2023.11.17
cython>=3.0.6
cython>=3.0.8
cymem>=2.0.8
orjson>=3.9.10
orjson>=3.9.10

View File

@@ -396,8 +396,6 @@ class BuildExeCommand(cx_Freeze.command.build_exe.BuildEXE):
folders_to_remove.append(file_name)
shutil.rmtree(world_directory)
shutil.copyfile("meta.yaml", self.buildfolder / "Players" / "Templates" / "meta.yaml")
# TODO: fix LttP options one day
shutil.copyfile("playerSettings.yaml", self.buildfolder / "Players" / "Templates" / "A Link to the Past.yaml")
try:
from maseya import z3pr
except ImportError:

View File

@@ -7,7 +7,7 @@ from argparse import Namespace
from Generate import get_seed_name
from test.general import gen_steps
from worlds import AutoWorld
from worlds.AutoWorld import call_all
from worlds.AutoWorld import World, call_all
from BaseClasses import Location, MultiWorld, CollectionState, ItemClassification, Item
from worlds.alttp.Items import ItemFactory
@@ -105,9 +105,15 @@ class TestBase(unittest.TestCase):
class WorldTestBase(unittest.TestCase):
options: typing.Dict[str, typing.Any] = {}
"""Define options that should be used when setting up this TestBase."""
multiworld: MultiWorld
"""The constructed MultiWorld instance after setup."""
world: World
"""The constructed World instance after setup."""
player: typing.ClassVar[int] = 1
game: typing.ClassVar[str] # define game name in subclass, example "Secret of Evermore"
game: typing.ClassVar[str]
"""Define game name in subclass, example "Secret of Evermore"."""
auto_construct: typing.ClassVar[bool] = True
""" automatically set up a world for each test in this class """
memory_leak_tested: typing.ClassVar[bool] = False
@@ -150,8 +156,8 @@ class WorldTestBase(unittest.TestCase):
if not hasattr(self, "game"):
raise NotImplementedError("didn't define game name")
self.multiworld = MultiWorld(1)
self.multiworld.game[1] = self.game
self.multiworld.player_name = {1: "Tester"}
self.multiworld.game[self.player] = self.game
self.multiworld.player_name = {self.player: "Tester"}
self.multiworld.set_seed(seed)
self.multiworld.state = CollectionState(self.multiworld)
random.seed(self.multiworld.seed)
@@ -159,9 +165,10 @@ class WorldTestBase(unittest.TestCase):
args = Namespace()
for name, option in AutoWorld.AutoWorldRegister.world_types[self.game].options_dataclass.type_hints.items():
setattr(args, name, {
1: option.from_any(self.options.get(name, getattr(option, "default")))
1: option.from_any(self.options.get(name, option.default))
})
self.multiworld.set_options(args)
self.world = self.multiworld.worlds[self.player]
for step in gen_steps:
call_all(self.multiworld, step)
@@ -220,19 +227,19 @@ class WorldTestBase(unittest.TestCase):
def can_reach_location(self, location: str) -> bool:
"""Determines if the current state can reach the provided location name"""
return self.multiworld.state.can_reach(location, "Location", 1)
return self.multiworld.state.can_reach(location, "Location", self.player)
def can_reach_entrance(self, entrance: str) -> bool:
"""Determines if the current state can reach the provided entrance name"""
return self.multiworld.state.can_reach(entrance, "Entrance", 1)
return self.multiworld.state.can_reach(entrance, "Entrance", self.player)
def can_reach_region(self, region: str) -> bool:
"""Determines if the current state can reach the provided region name"""
return self.multiworld.state.can_reach(region, "Region", 1)
return self.multiworld.state.can_reach(region, "Region", self.player)
def count(self, item_name: str) -> int:
"""Returns the amount of an item currently in state"""
return self.multiworld.state.count(item_name, 1)
return self.multiworld.state.count(item_name, self.player)
def assertAccessDependency(self,
locations: typing.List[str],
@@ -246,10 +253,11 @@ class WorldTestBase(unittest.TestCase):
self.collect_all_but(all_items, state)
if only_check_listed:
for location in locations:
self.assertFalse(state.can_reach(location, "Location", 1), f"{location} is reachable without {all_items}")
self.assertFalse(state.can_reach(location, "Location", self.player),
f"{location} is reachable without {all_items}")
else:
for location in self.multiworld.get_locations():
loc_reachable = state.can_reach(location, "Location", 1)
loc_reachable = state.can_reach(location, "Location", self.player)
self.assertEqual(loc_reachable, location.name not in locations,
f"{location.name} is reachable without {all_items}" if loc_reachable
else f"{location.name} is not reachable without {all_items}")
@@ -258,7 +266,7 @@ class WorldTestBase(unittest.TestCase):
for item in items:
state.collect(item)
for location in locations:
self.assertTrue(state.can_reach(location, "Location", 1),
self.assertTrue(state.can_reach(location, "Location", self.player),
f"{location} not reachable with {item_names}")
for item in items:
state.remove(item)
@@ -285,7 +293,7 @@ class WorldTestBase(unittest.TestCase):
if not (self.run_default_tests and self.constructed):
return
with self.subTest("Game", game=self.game):
excluded = self.multiworld.worlds[1].options.exclude_locations.value
excluded = self.multiworld.worlds[self.player].options.exclude_locations.value
state = self.multiworld.get_all_state(False)
for location in self.multiworld.get_locations():
if location.name not in excluded:
@@ -302,7 +310,7 @@ class WorldTestBase(unittest.TestCase):
return
with self.subTest("Game", game=self.game):
state = CollectionState(self.multiworld)
locations = self.multiworld.get_reachable_locations(state, 1)
locations = self.multiworld.get_reachable_locations(state, self.player)
self.assertGreater(len(locations), 0,
"Need to be able to reach at least one location to get started.")
@@ -328,7 +336,7 @@ class WorldTestBase(unittest.TestCase):
for location in sphere:
if location.item:
state.collect(location.item, True, location)
return self.multiworld.has_beaten_game(state, 1)
return self.multiworld.has_beaten_game(state, self.player)
with self.subTest("Game", game=self.game, seed=self.multiworld.seed):
distribute_items_restrictive(self.multiworld)

View File

@@ -29,8 +29,8 @@ class TestHelpers(unittest.TestCase):
"event_loc": None,
},
"TestRegion2": {
"loc_1": 321,
"loc_2": 654,
"loc_3": 321,
"loc_4": 654,
}
}

68
test/utils/test_yaml.py Normal file
View File

@@ -0,0 +1,68 @@
# Tests that yaml wrappers in Utils.py do what they should
import unittest
from typing import cast, Any, ClassVar, Dict
from Utils import dump, Dumper # type: ignore[attr-defined]
from Utils import parse_yaml, parse_yamls, unsafe_parse_yaml
class AClass:
def __eq__(self, other: Any) -> bool:
return isinstance(other, self.__class__)
class TestYaml(unittest.TestCase):
safe_data: ClassVar[Dict[str, Any]] = {
"a": [1, 2, 3],
"b": None,
"c": True,
}
unsafe_data: ClassVar[Dict[str, Any]] = {
"a": AClass()
}
@property
def safe_str(self) -> str:
return cast(str, dump(self.safe_data, Dumper=Dumper))
@property
def unsafe_str(self) -> str:
return cast(str, dump(self.unsafe_data, Dumper=Dumper))
def assertIsNonEmptyString(self, string: str) -> None:
self.assertTrue(string)
self.assertIsInstance(string, str)
def test_dump(self) -> None:
self.assertIsNonEmptyString(self.safe_str)
self.assertIsNonEmptyString(self.unsafe_str)
def test_safe_parse(self) -> None:
self.assertEqual(self.safe_data, parse_yaml(self.safe_str))
with self.assertRaises(Exception):
parse_yaml(self.unsafe_str)
with self.assertRaises(Exception):
parse_yaml("1\n---\n2\n")
def test_unsafe_parse(self) -> None:
self.assertEqual(self.safe_data, unsafe_parse_yaml(self.safe_str))
self.assertEqual(self.unsafe_data, unsafe_parse_yaml(self.unsafe_str))
with self.assertRaises(Exception):
unsafe_parse_yaml("1\n---\n2\n")
def test_multi_parse(self) -> None:
self.assertEqual(self.safe_data, next(parse_yamls(self.safe_str)))
with self.assertRaises(Exception):
next(parse_yamls(self.unsafe_str))
self.assertEqual(2, len(list(parse_yamls("1\n---\n2\n"))))
def test_unique_key(self) -> None:
s = """
a: 1
a: 2
"""
with self.assertRaises(Exception):
parse_yaml(s)
with self.assertRaises(Exception):
next(parse_yamls(s))

View File

@@ -15,7 +15,7 @@ from BaseClasses import CollectionState
if TYPE_CHECKING:
import random
from BaseClasses import MultiWorld, Item, Location, Tutorial
from BaseClasses import MultiWorld, Item, Location, Tutorial, Region, Entrance
from . import GamesPackage
from settings import Group
@@ -438,7 +438,7 @@ class World(metaclass=AutoWorldRegister):
def get_pre_fill_items(self) -> List["Item"]:
return []
# following methods should not need to be overridden.
# these two methods can be extended for pseudo-items on state
def collect(self, state: "CollectionState", item: "Item") -> bool:
name = self.collect_item(state, item)
if name:
@@ -458,6 +458,16 @@ class World(metaclass=AutoWorldRegister):
def create_filler(self) -> "Item":
return self.create_item(self.get_filler_item_name())
# convenience methods
def get_location(self, location_name: str) -> "Location":
return self.multiworld.get_location(location_name, self.player)
def get_entrance(self, entrance_name: str) -> "Entrance":
return self.multiworld.get_entrance(entrance_name, self.player)
def get_region(self, region_name: str) -> "Region":
return self.multiworld.get_region(region_name, self.player)
@classmethod
def get_data_package_data(cls) -> "GamesPackage":
sorted_item_name_groups = {

View File

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

View File

@@ -9,7 +9,7 @@ from Fill import fill_restrictive
from .Bosses import BossFactory, Boss
from .Items import ItemFactory
from .Regions import lookup_boss_drops, key_drop_data
from .Options import smallkey_shuffle
from .Options import small_key_shuffle
if typing.TYPE_CHECKING:
from .SubClasses import ALttPLocation, ALttPItem
@@ -66,7 +66,7 @@ def create_dungeons(world: "ALTTPWorld"):
def make_dungeon(name, default_boss, dungeon_regions, big_key, small_keys, dungeon_items):
dungeon = Dungeon(name, dungeon_regions, big_key,
[] if multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal else small_keys,
[] if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal else small_keys,
dungeon_items, player)
for item in dungeon.all_items:
item.dungeon = dungeon

View File

@@ -23,7 +23,7 @@ def parse_arguments(argv, no_defaults=False):
multiargs, _ = parser.parse_known_args(argv)
parser = argparse.ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
parser.add_argument('--logic', default=defval('noglitches'), const='noglitches', nargs='?', choices=['noglitches', 'minorglitches', 'owglitches', 'hybridglitches', 'nologic'],
parser.add_argument('--logic', default=defval('no_glitches'), const='no_glitches', nargs='?', choices=['no_glitches', 'minor_glitches', 'overworld_glitches', 'hybrid_major_glitches', 'no_logic'],
help='''\
Select Enforcement of Item Requirements. (default: %(default)s)
No Glitches:
@@ -49,7 +49,7 @@ def parse_arguments(argv, no_defaults=False):
instead of a bunny.
''')
parser.add_argument('--goal', default=defval('ganon'), const='ganon', nargs='?',
choices=['ganon', 'pedestal', 'bosses', 'triforcehunt', 'localtriforcehunt', 'ganontriforcehunt', 'localganontriforcehunt', 'crystals', 'ganonpedestal'],
choices=['ganon', 'pedestal', 'bosses', 'triforce_hunt', 'local_triforce_hunt', 'ganon_triforce_hunt', 'local_ganon_triforce_hunt', 'crystals', 'ganon_pedestal'],
help='''\
Select completion goal. (default: %(default)s)
Ganon: Collect all crystals, beat Agahnim 2 then
@@ -92,7 +92,7 @@ def parse_arguments(argv, no_defaults=False):
Hard: Reduced functionality.
Expert: Greatly reduced functionality.
''')
parser.add_argument('--timer', default=defval('none'), const='normal', nargs='?', choices=['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'],
parser.add_argument('--timer', default=defval('none'), const='normal', nargs='?', choices=['none', 'display', 'timed', 'timed_ohko', 'ohko', 'timed_countdown'],
help='''\
Select game timer setting. Affects available itempool. (default: %(default)s)
None: No timer.
@@ -151,7 +151,7 @@ def parse_arguments(argv, no_defaults=False):
slightly biased to placing progression items with
less restrictions.
''')
parser.add_argument('--shuffle', default=defval('vanilla'), const='vanilla', nargs='?', choices=['vanilla', 'simple', 'restricted', 'full', 'crossed', 'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy', 'dungeonsfull', 'dungeonssimple', 'dungeonscrossed'],
parser.add_argument('--shuffle', default=defval('vanilla'), const='vanilla', nargs='?', choices=['vanilla', 'simple', 'restricted', 'full', 'crossed', 'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy', 'dungeons_full', 'dungeons_simple', 'dungeons_crossed'],
help='''\
Select Entrance Shuffling Algorithm. (default: %(default)s)
Full: Mix cave and dungeon entrances freely while limiting
@@ -178,9 +178,9 @@ def parse_arguments(argv, no_defaults=False):
parser.add_argument('--open_pyramid', default=defval('auto'), help='''\
Pre-opens the pyramid hole, this removes the Agahnim 2 requirement for it.
Depending on goal, you might still need to beat Agahnim 2 in order to beat ganon.
fast ganon goals are crystals, ganontriforcehunt, localganontriforcehunt, pedestalganon
fast ganon goals are crystals, ganon_triforce_hunt, local_ganon_triforce_hunt, pedestalganon
auto - Only opens pyramid hole if the goal specifies a fast ganon, and entrance shuffle
is vanilla, dungeonssimple or dungeonsfull.
is vanilla, dungeons_simple or dungeons_full.
goal - Opens pyramid hole if the goal specifies a fast ganon.
yes - Always opens the pyramid hole.
no - Never opens the pyramid hole.

View File

@@ -21,17 +21,17 @@ def link_entrances(world, player):
connect_simple(world, exitname, regionname, player)
# if we do not shuffle, set default connections
if world.shuffle[player] == 'vanilla':
if world.entrance_shuffle[player] == 'vanilla':
for exitname, regionname in default_connections:
connect_simple(world, exitname, regionname, player)
for exitname, regionname in default_dungeon_connections:
connect_simple(world, exitname, regionname, player)
elif world.shuffle[player] == 'dungeonssimple':
elif world.entrance_shuffle[player] == 'dungeons_simple':
for exitname, regionname in default_connections:
connect_simple(world, exitname, regionname, player)
simple_shuffle_dungeons(world, player)
elif world.shuffle[player] == 'dungeonsfull':
elif world.entrance_shuffle[player] == 'dungeons_full':
for exitname, regionname in default_connections:
connect_simple(world, exitname, regionname, player)
@@ -63,9 +63,9 @@ def link_entrances(world, player):
connect_mandatory_exits(world, lw_entrances, dungeon_exits, list(LW_Dungeon_Entrances_Must_Exit), player)
connect_mandatory_exits(world, dw_entrances, dungeon_exits, list(DW_Dungeon_Entrances_Must_Exit), player)
connect_caves(world, lw_entrances, dw_entrances, dungeon_exits, player)
elif world.shuffle[player] == 'dungeonscrossed':
elif world.entrance_shuffle[player] == 'dungeons_crossed':
crossed_shuffle_dungeons(world, player)
elif world.shuffle[player] == 'simple':
elif world.entrance_shuffle[player] == 'simple':
simple_shuffle_dungeons(world, player)
old_man_entrances = list(Old_Man_Entrances)
@@ -136,7 +136,7 @@ def link_entrances(world, player):
# place remaining doors
connect_doors(world, single_doors, door_targets, player)
elif world.shuffle[player] == 'restricted':
elif world.entrance_shuffle[player] == 'restricted':
simple_shuffle_dungeons(world, player)
lw_entrances = list(LW_Entrances + LW_Single_Cave_Doors + Old_Man_Entrances)
@@ -207,62 +207,8 @@ def link_entrances(world, player):
# place remaining doors
connect_doors(world, doors, door_targets, player)
elif world.shuffle[player] == 'restricted_legacy':
simple_shuffle_dungeons(world, player)
lw_entrances = list(LW_Entrances)
dw_entrances = list(DW_Entrances)
dw_must_exits = list(DW_Entrances_Must_Exit)
old_man_entrances = list(Old_Man_Entrances)
caves = list(Cave_Exits)
three_exit_caves = list(Cave_Three_Exits)
single_doors = list(Single_Cave_Doors)
bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors)
blacksmith_doors = list(Blacksmith_Single_Cave_Doors)
door_targets = list(Single_Cave_Targets)
# only use two exit caves to do mandatory dw connections
connect_mandatory_exits(world, dw_entrances, caves, dw_must_exits, player)
# add three exit doors to pool for remainder
caves.extend(three_exit_caves)
# place old man, has limited options
# exit has to come from specific set of doors, the entrance is free to move about
world.random.shuffle(old_man_entrances)
old_man_exit = old_man_entrances.pop()
lw_entrances.extend(old_man_entrances)
world.random.shuffle(lw_entrances)
old_man_entrance = lw_entrances.pop()
connect_two_way(world, old_man_entrance, 'Old Man Cave Exit (West)', player)
connect_two_way(world, old_man_exit, 'Old Man Cave Exit (East)', player)
# place Old Man House in Light World
connect_caves(world, lw_entrances, [], Old_Man_House, player)
# connect rest. There's 2 dw entrances remaining, so we will not run into parity issue placing caves
connect_caves(world, lw_entrances, dw_entrances, caves, player)
# scramble holes
scramble_holes(world, player)
# place blacksmith, has limited options
world.random.shuffle(blacksmith_doors)
blacksmith_hut = blacksmith_doors.pop()
connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player)
bomb_shop_doors.extend(blacksmith_doors)
# place dam and pyramid fairy, have limited options
world.random.shuffle(bomb_shop_doors)
bomb_shop = bomb_shop_doors.pop()
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
single_doors.extend(bomb_shop_doors)
# tavern back door cannot be shuffled yet
connect_doors(world, ['Tavern North'], ['Tavern'], player)
# place remaining doors
connect_doors(world, single_doors, door_targets, player)
elif world.shuffle[player] == 'full':
elif world.entrance_shuffle[player] == 'full':
skull_woods_shuffle(world, player)
lw_entrances = list(LW_Entrances + LW_Dungeon_Entrances + LW_Single_Cave_Doors + Old_Man_Entrances)
@@ -368,7 +314,7 @@ def link_entrances(world, player):
# place remaining doors
connect_doors(world, doors, door_targets, player)
elif world.shuffle[player] == 'crossed':
elif world.entrance_shuffle[player] == 'crossed':
skull_woods_shuffle(world, player)
entrances = list(LW_Entrances + LW_Dungeon_Entrances + LW_Single_Cave_Doors + Old_Man_Entrances + DW_Entrances + DW_Dungeon_Entrances + DW_Single_Cave_Doors)
@@ -445,337 +391,8 @@ def link_entrances(world, player):
# place remaining doors
connect_doors(world, entrances, door_targets, player)
elif world.shuffle[player] == 'full_legacy':
skull_woods_shuffle(world, player)
lw_entrances = list(LW_Entrances + LW_Dungeon_Entrances + Old_Man_Entrances)
dw_entrances = list(DW_Entrances + DW_Dungeon_Entrances)
dw_must_exits = list(DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit)
lw_must_exits = list(LW_Dungeon_Entrances_Must_Exit)
old_man_entrances = list(Old_Man_Entrances + ['Tower of Hera'])
caves = list(Cave_Exits + Dungeon_Exits + Cave_Three_Exits) # don't need to consider three exit caves, have one exit caves to avoid parity issues
single_doors = list(Single_Cave_Doors)
bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors)
blacksmith_doors = list(Blacksmith_Single_Cave_Doors)
door_targets = list(Single_Cave_Targets)
if world.mode[player] == 'standard':
# must connect front of hyrule castle to do escape
connect_two_way(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player)
else:
caves.append(tuple(world.random.sample(
['Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'], 3)))
lw_entrances.append('Hyrule Castle Entrance (South)')
if not world.shuffle_ganon:
connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit', player)
else:
dw_entrances.append('Ganons Tower')
caves.append('Ganons Tower Exit')
# we randomize which world requirements we fulfill first so we get better dungeon distribution
if world.random.randint(0, 1) == 0:
connect_mandatory_exits(world, lw_entrances, caves, lw_must_exits, player)
connect_mandatory_exits(world, dw_entrances, caves, dw_must_exits, player)
else:
connect_mandatory_exits(world, dw_entrances, caves, dw_must_exits, player)
connect_mandatory_exits(world, lw_entrances, caves, lw_must_exits, player)
if world.mode[player] == 'standard':
# rest of hyrule castle must be in light world
connect_caves(world, lw_entrances, [], [('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')], player)
# place old man, has limited options
# exit has to come from specific set of doors, the entrance is free to move about
old_man_entrances = [door for door in old_man_entrances if door in lw_entrances]
world.random.shuffle(old_man_entrances)
old_man_exit = old_man_entrances.pop()
lw_entrances.remove(old_man_exit)
world.random.shuffle(lw_entrances)
old_man_entrance = lw_entrances.pop()
connect_two_way(world, old_man_entrance, 'Old Man Cave Exit (West)', player)
connect_two_way(world, old_man_exit, 'Old Man Cave Exit (East)', player)
# place Old Man House in Light World
connect_caves(world, lw_entrances, [], list(Old_Man_House), player) #need this to avoid badness with multiple seeds
# now scramble the rest
connect_caves(world, lw_entrances, dw_entrances, caves, player)
# scramble holes
scramble_holes(world, player)
# place blacksmith, has limited options
world.random.shuffle(blacksmith_doors)
blacksmith_hut = blacksmith_doors.pop()
connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player)
bomb_shop_doors.extend(blacksmith_doors)
# place bomb shop, has limited options
world.random.shuffle(bomb_shop_doors)
bomb_shop = bomb_shop_doors.pop()
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
single_doors.extend(bomb_shop_doors)
# tavern back door cannot be shuffled yet
connect_doors(world, ['Tavern North'], ['Tavern'], player)
# place remaining doors
connect_doors(world, single_doors, door_targets, player)
elif world.shuffle[player] == 'madness_legacy':
# here lie dragons, connections are no longer two way
lw_entrances = list(LW_Entrances + LW_Dungeon_Entrances + Old_Man_Entrances)
dw_entrances = list(DW_Entrances + DW_Dungeon_Entrances)
dw_entrances_must_exits = list(DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit)
lw_doors = list(LW_Entrances + LW_Dungeon_Entrances + LW_Dungeon_Entrances_Must_Exit) + ['Kakariko Well Cave',
'Bat Cave Cave',
'North Fairy Cave',
'Sanctuary',
'Lost Woods Hideout Stump',
'Lumberjack Tree Cave'] + list(
Old_Man_Entrances)
dw_doors = list(
DW_Entrances + DW_Dungeon_Entrances + DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit) + [
'Skull Woods First Section Door', 'Skull Woods Second Section Door (East)',
'Skull Woods Second Section Door (West)']
world.random.shuffle(lw_doors)
world.random.shuffle(dw_doors)
dw_entrances_must_exits.append('Skull Woods Second Section Door (West)')
dw_entrances.append('Skull Woods Second Section Door (East)')
dw_entrances.append('Skull Woods First Section Door')
lw_entrances.extend(
['Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump',
'Lumberjack Tree Cave'])
lw_entrances_must_exits = list(LW_Dungeon_Entrances_Must_Exit)
old_man_entrances = list(Old_Man_Entrances) + ['Tower of Hera']
mandatory_light_world = ['Old Man House Exit (Bottom)', 'Old Man House Exit (Top)']
mandatory_dark_world = []
caves = list(Cave_Exits + Dungeon_Exits + Cave_Three_Exits)
# shuffle up holes
lw_hole_entrances = ['Kakariko Well Drop', 'Bat Cave Drop', 'North Fairy Cave Drop', 'Lost Woods Hideout Drop', 'Lumberjack Tree Tree', 'Sanctuary Grave']
dw_hole_entrances = ['Skull Woods First Section Hole (East)', 'Skull Woods First Section Hole (West)', 'Skull Woods First Section Hole (North)', 'Skull Woods Second Section Hole']
hole_targets = [('Kakariko Well Exit', 'Kakariko Well (top)'),
('Bat Cave Exit', 'Bat Cave (right)'),
('North Fairy Cave Exit', 'North Fairy Cave'),
('Lost Woods Hideout Exit', 'Lost Woods Hideout (top)'),
('Lumberjack Tree Exit', 'Lumberjack Tree (top)'),
(('Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)'), 'Skull Woods Second Section (Drop)')]
if world.mode[player] == 'standard':
# cannot move uncle cave
connect_entrance(world, 'Hyrule Castle Secret Entrance Drop', 'Hyrule Castle Secret Entrance', player)
connect_exit(world, 'Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance Stairs', player)
connect_entrance(world, 'Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Secret Entrance Exit', player)
else:
lw_hole_entrances.append('Hyrule Castle Secret Entrance Drop')
hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance'))
lw_doors.append('Hyrule Castle Secret Entrance Stairs')
lw_entrances.append('Hyrule Castle Secret Entrance Stairs')
if not world.shuffle_ganon:
connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit', player)
connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player)
connect_entrance(world, 'Pyramid Hole', 'Pyramid', player)
else:
dw_entrances.append('Ganons Tower')
caves.append('Ganons Tower Exit')
dw_hole_entrances.append('Pyramid Hole')
hole_targets.append(('Pyramid Exit', 'Pyramid'))
dw_entrances_must_exits.append('Pyramid Entrance')
dw_doors.extend(['Ganons Tower', 'Pyramid Entrance'])
world.random.shuffle(lw_hole_entrances)
world.random.shuffle(dw_hole_entrances)
world.random.shuffle(hole_targets)
# decide if skull woods first section should be in light or dark world
sw_light = world.random.randint(0, 1) == 0
if sw_light:
sw_hole_pool = lw_hole_entrances
mandatory_light_world.append('Skull Woods First Section Exit')
else:
sw_hole_pool = dw_hole_entrances
mandatory_dark_world.append('Skull Woods First Section Exit')
for target in ['Skull Woods First Section (Left)', 'Skull Woods First Section (Right)',
'Skull Woods First Section (Top)']:
connect_entrance(world, sw_hole_pool.pop(), target, player)
# sanctuary has to be in light world
connect_entrance(world, lw_hole_entrances.pop(), 'Sewer Drop', player)
mandatory_light_world.append('Sanctuary Exit')
# fill up remaining holes
for hole in dw_hole_entrances:
exits, target = hole_targets.pop()
mandatory_dark_world.append(exits)
connect_entrance(world, hole, target, player)
for hole in lw_hole_entrances:
exits, target = hole_targets.pop()
mandatory_light_world.append(exits)
connect_entrance(world, hole, target, player)
# hyrule castle handling
if world.mode[player] == 'standard':
# must connect front of hyrule castle to do escape
connect_entrance(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player)
connect_exit(world, 'Hyrule Castle Exit (South)', 'Hyrule Castle Entrance (South)', player)
mandatory_light_world.append(('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
else:
lw_doors.append('Hyrule Castle Entrance (South)')
lw_entrances.append('Hyrule Castle Entrance (South)')
caves.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
# now let's deal with mandatory reachable stuff
def extract_reachable_exit(cavelist):
world.random.shuffle(cavelist)
candidate = None
for cave in cavelist:
if isinstance(cave, tuple) and len(cave) > 1:
# special handling: TRock and Spectracle Rock cave have two entries that we should consider entrance only
# ToDo this should be handled in a more sensible manner
if cave[0] in ['Turtle Rock Exit (Front)', 'Spectacle Rock Cave Exit (Peak)'] and len(cave) == 2:
continue
candidate = cave
break
if candidate is None:
raise KeyError('No suitable cave.')
cavelist.remove(candidate)
return candidate
def connect_reachable_exit(entrance, general, worldspecific, worldoors):
# select which one is the primary option
if world.random.randint(0, 1) == 0:
primary = general
secondary = worldspecific
else:
primary = worldspecific
secondary = general
try:
cave = extract_reachable_exit(primary)
except KeyError:
cave = extract_reachable_exit(secondary)
exit = cave[-1]
cave = cave[:-1]
connect_exit(world, exit, entrance, player)
connect_entrance(world, worldoors.pop(), exit, player)
# rest of cave now is forced to be in this world
worldspecific.append(cave)
# we randomize which world requirements we fulfill first so we get better dungeon distribution
if world.random.randint(0, 1) == 0:
for entrance in lw_entrances_must_exits:
connect_reachable_exit(entrance, caves, mandatory_light_world, lw_doors)
for entrance in dw_entrances_must_exits:
connect_reachable_exit(entrance, caves, mandatory_dark_world, dw_doors)
else:
for entrance in dw_entrances_must_exits:
connect_reachable_exit(entrance, caves, mandatory_dark_world, dw_doors)
for entrance in lw_entrances_must_exits:
connect_reachable_exit(entrance, caves, mandatory_light_world, lw_doors)
# place old man, has limited options
# exit has to come from specific set of doors, the entrance is free to move about
old_man_entrances = [entrance for entrance in old_man_entrances if entrance in lw_entrances]
world.random.shuffle(old_man_entrances)
old_man_exit = old_man_entrances.pop()
lw_entrances.remove(old_man_exit)
connect_exit(world, 'Old Man Cave Exit (East)', old_man_exit, player)
connect_entrance(world, lw_doors.pop(), 'Old Man Cave Exit (East)', player)
mandatory_light_world.append('Old Man Cave Exit (West)')
# we connect up the mandatory associations we have found
for mandatory in mandatory_light_world:
if not isinstance(mandatory, tuple):
mandatory = (mandatory,)
for exit in mandatory:
# point out somewhere
connect_exit(world, exit, lw_entrances.pop(), player)
# point in from somewhere
connect_entrance(world, lw_doors.pop(), exit, player)
for mandatory in mandatory_dark_world:
if not isinstance(mandatory, tuple):
mandatory = (mandatory,)
for exit in mandatory:
# point out somewhere
connect_exit(world, exit, dw_entrances.pop(), player)
# point in from somewhere
connect_entrance(world, dw_doors.pop(), exit, player)
# handle remaining caves
while caves:
# connect highest exit count caves first, prevent issue where we have 2 or 3 exits accross worlds left to fill
cave_candidate = (None, 0)
for i, cave in enumerate(caves):
if isinstance(cave, str):
cave = (cave,)
if len(cave) > cave_candidate[1]:
cave_candidate = (i, len(cave))
cave = caves.pop(cave_candidate[0])
place_lightworld = world.random.randint(0, 1) == 0
if place_lightworld:
target_doors = lw_doors
target_entrances = lw_entrances
else:
target_doors = dw_doors
target_entrances = dw_entrances
if isinstance(cave, str):
cave = (cave,)
# check if we can still fit the cave into our target group
if len(target_doors) < len(cave):
if not place_lightworld:
target_doors = lw_doors
target_entrances = lw_entrances
else:
target_doors = dw_doors
target_entrances = dw_entrances
for exit in cave:
connect_exit(world, exit, target_entrances.pop(), player)
connect_entrance(world, target_doors.pop(), exit, player)
# handle simple doors
single_doors = list(Single_Cave_Doors)
bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors)
blacksmith_doors = list(Blacksmith_Single_Cave_Doors)
door_targets = list(Single_Cave_Targets)
# place blacksmith, has limited options
world.random.shuffle(blacksmith_doors)
blacksmith_hut = blacksmith_doors.pop()
connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player)
bomb_shop_doors.extend(blacksmith_doors)
# place dam and pyramid fairy, have limited options
world.random.shuffle(bomb_shop_doors)
bomb_shop = bomb_shop_doors.pop()
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
single_doors.extend(bomb_shop_doors)
# tavern back door cannot be shuffled yet
connect_doors(world, ['Tavern North'], ['Tavern'], player)
# place remaining doors
connect_doors(world, single_doors, door_targets, player)
elif world.shuffle[player] == 'insanity':
elif world.entrance_shuffle[player] == 'insanity':
# beware ye who enter here
entrances = LW_Entrances + LW_Dungeon_Entrances + DW_Entrances + DW_Dungeon_Entrances + Old_Man_Entrances + ['Skull Woods Second Section Door (East)', 'Skull Woods First Section Door', 'Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave']
@@ -922,157 +539,15 @@ def link_entrances(world, player):
# place remaining doors
connect_doors(world, doors, door_targets, player)
elif world.shuffle[player] == 'insanity_legacy':
world.fix_fake_world[player] = False
# beware ye who enter here
entrances = LW_Entrances + LW_Dungeon_Entrances + DW_Entrances + DW_Dungeon_Entrances + Old_Man_Entrances + ['Skull Woods Second Section Door (East)', 'Skull Woods First Section Door', 'Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave']
entrances_must_exits = DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit + LW_Dungeon_Entrances_Must_Exit + ['Skull Woods Second Section Door (West)']
doors = LW_Entrances + LW_Dungeon_Entrances + LW_Dungeon_Entrances_Must_Exit + ['Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave'] + Old_Man_Entrances +\
DW_Entrances + DW_Dungeon_Entrances + DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit + ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)', 'Skull Woods Second Section Door (West)']
world.random.shuffle(doors)
old_man_entrances = list(Old_Man_Entrances) + ['Tower of Hera']
caves = Cave_Exits + Dungeon_Exits + Cave_Three_Exits + ['Old Man House Exit (Bottom)', 'Old Man House Exit (Top)', 'Skull Woods First Section Exit', 'Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)',
'Kakariko Well Exit', 'Bat Cave Exit', 'North Fairy Cave Exit', 'Lost Woods Hideout Exit', 'Lumberjack Tree Exit', 'Sanctuary Exit']
# shuffle up holes
hole_entrances = ['Kakariko Well Drop', 'Bat Cave Drop', 'North Fairy Cave Drop', 'Lost Woods Hideout Drop', 'Lumberjack Tree Tree', 'Sanctuary Grave',
'Skull Woods First Section Hole (East)', 'Skull Woods First Section Hole (West)', 'Skull Woods First Section Hole (North)', 'Skull Woods Second Section Hole']
hole_targets = ['Kakariko Well (top)', 'Bat Cave (right)', 'North Fairy Cave', 'Lost Woods Hideout (top)', 'Lumberjack Tree (top)', 'Sewer Drop', 'Skull Woods Second Section (Drop)',
'Skull Woods First Section (Left)', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Top)']
if world.mode[player] == 'standard':
# cannot move uncle cave
connect_entrance(world, 'Hyrule Castle Secret Entrance Drop', 'Hyrule Castle Secret Entrance', player)
connect_exit(world, 'Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance Stairs', player)
connect_entrance(world, 'Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Secret Entrance Exit', player)
else:
hole_entrances.append('Hyrule Castle Secret Entrance Drop')
hole_targets.append('Hyrule Castle Secret Entrance')
doors.append('Hyrule Castle Secret Entrance Stairs')
entrances.append('Hyrule Castle Secret Entrance Stairs')
caves.append('Hyrule Castle Secret Entrance Exit')
if not world.shuffle_ganon:
connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit', player)
connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player)
connect_entrance(world, 'Pyramid Hole', 'Pyramid', player)
else:
entrances.append('Ganons Tower')
caves.extend(['Ganons Tower Exit', 'Pyramid Exit'])
hole_entrances.append('Pyramid Hole')
hole_targets.append('Pyramid')
entrances_must_exits.append('Pyramid Entrance')
doors.extend(['Ganons Tower', 'Pyramid Entrance'])
world.random.shuffle(hole_entrances)
world.random.shuffle(hole_targets)
world.random.shuffle(entrances)
# fill up holes
for hole in hole_entrances:
connect_entrance(world, hole, hole_targets.pop(), player)
# hyrule castle handling
if world.mode[player] == 'standard':
# must connect front of hyrule castle to do escape
connect_entrance(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player)
connect_exit(world, 'Hyrule Castle Exit (South)', 'Hyrule Castle Entrance (South)', player)
caves.append(('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
else:
doors.append('Hyrule Castle Entrance (South)')
entrances.append('Hyrule Castle Entrance (South)')
caves.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
# now let's deal with mandatory reachable stuff
def extract_reachable_exit(cavelist):
world.random.shuffle(cavelist)
candidate = None
for cave in cavelist:
if isinstance(cave, tuple) and len(cave) > 1:
# special handling: TRock has two entries that we should consider entrance only
# ToDo this should be handled in a more sensible manner
if cave[0] in ['Turtle Rock Exit (Front)', 'Spectacle Rock Cave Exit (Peak)'] and len(cave) == 2:
continue
candidate = cave
break
if candidate is None:
raise KeyError('No suitable cave.')
cavelist.remove(candidate)
return candidate
def connect_reachable_exit(entrance, caves, doors):
cave = extract_reachable_exit(caves)
exit = cave[-1]
cave = cave[:-1]
connect_exit(world, exit, entrance, player)
connect_entrance(world, doors.pop(), exit, player)
# rest of cave now is forced to be in this world
caves.append(cave)
# connect mandatory exits
for entrance in entrances_must_exits:
connect_reachable_exit(entrance, caves, doors)
# place old man, has limited options
# exit has to come from specific set of doors, the entrance is free to move about
old_man_entrances = [entrance for entrance in old_man_entrances if entrance in entrances]
world.random.shuffle(old_man_entrances)
old_man_exit = old_man_entrances.pop()
entrances.remove(old_man_exit)
connect_exit(world, 'Old Man Cave Exit (East)', old_man_exit, player)
connect_entrance(world, doors.pop(), 'Old Man Cave Exit (East)', player)
caves.append('Old Man Cave Exit (West)')
# handle remaining caves
for cave in caves:
if isinstance(cave, str):
cave = (cave,)
for exit in cave:
connect_exit(world, exit, entrances.pop(), player)
connect_entrance(world, doors.pop(), exit, player)
# handle simple doors
single_doors = list(Single_Cave_Doors)
bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors)
blacksmith_doors = list(Blacksmith_Single_Cave_Doors)
door_targets = list(Single_Cave_Targets)
# place blacksmith, has limited options
world.random.shuffle(blacksmith_doors)
blacksmith_hut = blacksmith_doors.pop()
connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player)
bomb_shop_doors.extend(blacksmith_doors)
# place dam and pyramid fairy, have limited options
world.random.shuffle(bomb_shop_doors)
bomb_shop = bomb_shop_doors.pop()
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
single_doors.extend(bomb_shop_doors)
# tavern back door cannot be shuffled yet
connect_doors(world, ['Tavern North'], ['Tavern'], player)
# place remaining doors
connect_doors(world, single_doors, door_targets, player)
else:
raise NotImplementedError(
f'{world.shuffle[player]} Shuffling not supported yet. Player {world.get_player_name(player)}')
f'{world.entrance_shuffle[player]} Shuffling not supported yet. Player {world.get_player_name(player)}')
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
if world.glitches_required[player] in ['overworld_glitches', 'hybrid_major_glitches', 'no_logic']:
overworld_glitch_connections(world, player)
# mandatory hybrid major glitches connections
if world.logic[player] in ['hybridglitches', 'nologic']:
if world.glitches_required[player] in ['hybrid_major_glitches', 'no_logic']:
underworld_glitch_connections(world, player)
# check for swamp palace fix
@@ -1106,17 +581,17 @@ def link_inverted_entrances(world, player):
connect_simple(world, exitname, regionname, player)
# if we do not shuffle, set default connections
if world.shuffle[player] == 'vanilla':
if world.entrance_shuffle[player] == 'vanilla':
for exitname, regionname in inverted_default_connections:
connect_simple(world, exitname, regionname, player)
for exitname, regionname in inverted_default_dungeon_connections:
connect_simple(world, exitname, regionname, player)
elif world.shuffle[player] == 'dungeonssimple':
elif world.entrance_shuffle[player] == 'dungeons_simple':
for exitname, regionname in inverted_default_connections:
connect_simple(world, exitname, regionname, player)
simple_shuffle_dungeons(world, player)
elif world.shuffle[player] == 'dungeonsfull':
elif world.entrance_shuffle[player] == 'dungeons_full':
for exitname, regionname in inverted_default_connections:
connect_simple(world, exitname, regionname, player)
@@ -1171,9 +646,9 @@ def link_inverted_entrances(world, player):
connect_mandatory_exits(world, lw_entrances, dungeon_exits, lw_dungeon_entrances_must_exit, player)
connect_caves(world, lw_entrances, dw_entrances, dungeon_exits, player)
elif world.shuffle[player] == 'dungeonscrossed':
elif world.entrance_shuffle[player] == 'dungeons_crossed':
inverted_crossed_shuffle_dungeons(world, player)
elif world.shuffle[player] == 'simple':
elif world.entrance_shuffle[player] == 'simple':
simple_shuffle_dungeons(world, player)
old_man_entrances = list(Inverted_Old_Man_Entrances)
@@ -1270,7 +745,7 @@ def link_inverted_entrances(world, player):
# place remaining doors
connect_doors(world, single_doors, door_targets, player)
elif world.shuffle[player] == 'restricted':
elif world.entrance_shuffle[player] == 'restricted':
simple_shuffle_dungeons(world, player)
lw_entrances = list(Inverted_LW_Entrances + Inverted_LW_Single_Cave_Doors)
@@ -1355,7 +830,7 @@ def link_inverted_entrances(world, player):
doors = lw_entrances + dw_entrances
# place remaining doors
connect_doors(world, doors, door_targets, player)
elif world.shuffle[player] == 'full':
elif world.entrance_shuffle[player] == 'full':
skull_woods_shuffle(world, player)
lw_entrances = list(Inverted_LW_Entrances + Inverted_LW_Dungeon_Entrances + Inverted_LW_Single_Cave_Doors)
@@ -1506,7 +981,7 @@ def link_inverted_entrances(world, player):
# place remaining doors
connect_doors(world, doors, door_targets, player)
elif world.shuffle[player] == 'crossed':
elif world.entrance_shuffle[player] == 'crossed':
skull_woods_shuffle(world, player)
entrances = list(Inverted_LW_Entrances + Inverted_LW_Dungeon_Entrances + Inverted_LW_Single_Cave_Doors + Inverted_Old_Man_Entrances + Inverted_DW_Entrances + Inverted_DW_Dungeon_Entrances + Inverted_DW_Single_Cave_Doors)
@@ -1617,7 +1092,7 @@ def link_inverted_entrances(world, player):
# place remaining doors
connect_doors(world, entrances, door_targets, player)
elif world.shuffle[player] == 'insanity':
elif world.entrance_shuffle[player] == 'insanity':
# beware ye who enter here
entrances = Inverted_LW_Entrances + Inverted_LW_Dungeon_Entrances + Inverted_DW_Entrances + Inverted_DW_Dungeon_Entrances + Inverted_Old_Man_Entrances + Old_Man_Entrances + ['Skull Woods Second Section Door (East)', 'Skull Woods Second Section Door (West)', 'Skull Woods First Section Door', 'Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave', 'Hyrule Castle Entrance (South)']
@@ -1776,10 +1251,10 @@ def link_inverted_entrances(world, player):
else:
raise NotImplementedError('Shuffling not supported yet')
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
if world.glitches_required[player] in ['overworld_glitches', 'hybrid_major_glitches', 'no_logic']:
overworld_glitch_connections(world, player)
# mandatory hybrid major glitches connections
if world.logic[player] in ['hybridglitches', 'nologic']:
if world.glitches_required[player] in ['hybrid_major_glitches', 'no_logic']:
underworld_glitch_connections(world, player)
# patch swamp drain
@@ -1880,14 +1355,14 @@ def scramble_holes(world, player):
hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance'))
# do not shuffle sanctuary into pyramid hole unless shuffle is crossed
if world.shuffle[player] == 'crossed':
if world.entrance_shuffle[player] == 'crossed':
hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
if world.shuffle_ganon:
world.random.shuffle(hole_targets)
exit, target = hole_targets.pop()
connect_two_way(world, 'Pyramid Entrance', exit, player)
connect_entrance(world, 'Pyramid Hole', target, player)
if world.shuffle[player] != 'crossed':
if world.entrance_shuffle[player] != 'crossed':
hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
world.random.shuffle(hole_targets)
@@ -1922,14 +1397,14 @@ def scramble_inverted_holes(world, player):
hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance'))
# do not shuffle sanctuary into pyramid hole unless shuffle is crossed
if world.shuffle[player] == 'crossed':
if world.entrance_shuffle[player] == 'crossed':
hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
if world.shuffle_ganon:
world.random.shuffle(hole_targets)
exit, target = hole_targets.pop()
connect_two_way(world, 'Inverted Pyramid Entrance', exit, player)
connect_entrance(world, 'Inverted Pyramid Hole', target, player)
if world.shuffle[player] != 'crossed':
if world.entrance_shuffle[player] != 'crossed':
hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
world.random.shuffle(hole_targets)
@@ -1958,7 +1433,7 @@ def connect_mandatory_exits(world, entrances, caves, must_be_exits, player):
invalid_connections = Must_Exit_Invalid_Connections.copy()
invalid_cave_connections = defaultdict(set)
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
if world.glitches_required[player] in ['overworld_glitches', 'hybrid_major_glitches', 'no_logic']:
from worlds.alttp import OverworldGlitchRules
for entrance in OverworldGlitchRules.get_non_mandatory_exits(world.mode[player] == 'inverted'):
invalid_connections[entrance] = set()
@@ -3038,6 +2513,7 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
('Sanctuary Push Door', 'Sanctuary'),
('Sewer Drop', 'Sewers'),
('Sewers Back Door', 'Sewers (Dark)'),
('Sewers Secret Room', 'Sewers Secret Room'),
('Agahnim 1', 'Agahnim 1'),
('Flute Spot 1', 'Death Mountain'),
('Death Mountain Entrance Rock', 'Death Mountain Entrance'),
@@ -3053,6 +2529,8 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
('Spiral Cave Ledge Access', 'Spiral Cave Ledge'),
('Spiral Cave Ledge Drop', 'East Death Mountain (Bottom)'),
('Spiral Cave (top to bottom)', 'Spiral Cave (Bottom)'),
('Hookshot Cave Bomb Wall (South)', 'Hookshot Cave (Upper)'),
('Hookshot Cave Bomb Wall (North)', 'Hookshot Cave'),
('East Death Mountain (Top)', 'East Death Mountain (Top)'),
('Death Mountain (Top)', 'Death Mountain (Top)'),
('Death Mountain Drop', 'Death Mountain'),
@@ -3227,6 +2705,7 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
('Sanctuary Push Door', 'Sanctuary'),
('Sewer Drop', 'Sewers'),
('Sewers Back Door', 'Sewers (Dark)'),
('Sewers Secret Room', 'Sewers Secret Room'),
('Agahnim 1', 'Agahnim 1'),
('Death Mountain Entrance Rock', 'Death Mountain Entrance'),
('Death Mountain Entrance Drop', 'Light World'),
@@ -3241,6 +2720,8 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
('Spiral Cave Ledge Access', 'Spiral Cave Ledge'),
('Spiral Cave Ledge Drop', 'East Death Mountain (Bottom)'),
('Spiral Cave (top to bottom)', 'Spiral Cave (Bottom)'),
('Hookshot Cave Bomb Wall (South)', 'Hookshot Cave (Upper)'),
('Hookshot Cave Bomb Wall (North)', 'Hookshot Cave'),
('East Death Mountain (Top)', 'East Death Mountain (Top)'),
('Death Mountain (Top)', 'Death Mountain (Top)'),
('Death Mountain Drop', 'Death Mountain'),
@@ -3572,7 +3053,7 @@ default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'),
('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'),
('Hookshot Cave Exit (South)', 'Dark Death Mountain (Top)'),
('Hookshot Cave Exit (North)', 'Death Mountain Floating Island (Dark World)'),
('Hookshot Cave Back Entrance', 'Hookshot Cave'),
('Hookshot Cave Back Entrance', 'Hookshot Cave (Upper)'),
('Mimic Cave', 'Mimic Cave'),
('Pyramid Hole', 'Pyramid'),
@@ -3703,7 +3184,7 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
('Superbunny Cave (Bottom)', 'Superbunny Cave (Bottom)'),
('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'),
('Hookshot Cave Exit (North)', 'Death Mountain Floating Island (Dark World)'),
('Hookshot Cave Back Entrance', 'Hookshot Cave'),
('Hookshot Cave Back Entrance', 'Hookshot Cave (Upper)'),
('Mimic Cave', 'Mimic Cave'),
('Inverted Pyramid Hole', 'Pyramid'),
('Inverted Links House', 'Inverted Links House'),

View File

@@ -133,7 +133,7 @@ def create_inverted_regions(world, player):
create_cave_region(world, player, 'Kakariko Gamble Game', 'a game of chance'),
create_cave_region(world, player, 'Potion Shop', 'the potion shop', ['Potion Shop']),
create_lw_region(world, player, 'Lake Hylia Island', ['Lake Hylia Island']),
create_cave_region(world, player, 'Capacity Upgrade', 'the queen of fairies'),
create_cave_region(world, player, 'Capacity Upgrade', 'the queen of fairies', ['Capacity Upgrade Shop']),
create_cave_region(world, player, 'Two Brothers House', 'a connector', None,
['Two Brothers House Exit (East)', 'Two Brothers House Exit (West)']),
create_lw_region(world, player, 'Maze Race Ledge', ['Maze Race'],
@@ -176,8 +176,9 @@ def create_inverted_regions(world, player):
'Throne Room']),
create_dungeon_region(world, player, 'Sewer Drop', 'a drop\'s exit', None, ['Sewer Drop']), # This exists only to be referenced for access checks
create_dungeon_region(world, player, 'Sewers (Dark)', 'a drop\'s exit', ['Sewers - Dark Cross', 'Sewers - Key Rat Key Drop'], ['Sewers Door']),
create_dungeon_region(world, player, 'Sewers', 'a drop\'s exit', ['Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle',
'Sewers - Secret Room - Right'], ['Sanctuary Push Door', 'Sewers Back Door']),
create_dungeon_region(world, player, 'Sewers', 'a drop\'s exit', None, ['Sanctuary Push Door', 'Sewers Back Door', 'Sewers Secret Room']),
create_dungeon_region(world, player, 'Sewers Secret Room', 'a drop\'s exit', ['Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle',
'Sewers - Secret Room - Right']),
create_dungeon_region(world, player, 'Sanctuary', 'a drop\'s exit', ['Sanctuary'], ['Sanctuary Exit']),
create_dungeon_region(world, player, 'Inverted Agahnims Tower', 'Castle Tower', ['Castle Tower - Room 03', 'Castle Tower - Dark Maze', 'Castle Tower - Dark Archer Key Drop', 'Castle Tower - Circle of Pots Key Drop'], ['Agahnim 1', 'Inverted Agahnims Tower Exit']),
create_dungeon_region(world, player, 'Agahnim 1', 'Castle Tower', ['Agahnim 1'], None),
@@ -346,7 +347,9 @@ def create_inverted_regions(world, player):
create_cave_region(world, player, 'Hookshot Cave', 'a connector',
['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right',
'Hookshot Cave - Bottom Left'],
['Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)']),
['Hookshot Cave Exit (South)', 'Hookshot Cave Bomb Wall (South)']),
create_cave_region(world, player, 'Hookshot Cave (Upper)', 'a connector', None, ['Hookshot Cave Exit (North)',
'Hookshot Cave Bomb Wall (North)']),
create_dw_region(world, player, 'Death Mountain Floating Island (Dark World)', None,
['Floating Island Drop', 'Hookshot Cave Back Entrance']),
create_cave_region(world, player, 'Mimic Cave', 'Mimic Cave', ['Mimic Cave']),
@@ -380,8 +383,8 @@ def create_inverted_regions(world, player):
create_dungeon_region(world, player, 'Skull Woods Second Section', 'Skull Woods', ['Skull Woods - Big Key Chest', 'Skull Woods - West Lobby Pot Key'], ['Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)']),
create_dungeon_region(world, player, 'Skull Woods Final Section (Entrance)', 'Skull Woods', ['Skull Woods - Bridge Room', 'Skull Woods - Spike Corner Key Drop'], ['Skull Woods Torch Room', 'Skull Woods Final Section Exit']),
create_dungeon_region(world, player, 'Skull Woods Final Section (Mothula)', 'Skull Woods', ['Skull Woods - Boss', 'Skull Woods - Prize']),
create_dungeon_region(world, player, 'Ice Palace (Entrance)', 'Ice Palace', ['Ice Palace - Jelly Key Drop'], ['Ice Palace (Second Section)', 'Ice Palace Exit']),
create_dungeon_region(world, player, 'Ice Palace (Second Section)', 'Ice Palace', ['Ice Palace - Conveyor Key Drop', 'Ice Palace - Compass Chest'], ['Ice Palace (Main)']),
create_dungeon_region(world, player, 'Ice Palace (Entrance)', 'Ice Palace', ['Ice Palace - Jelly Key Drop', 'Ice Palace - Compass Chest'], ['Ice Palace (Second Section)', 'Ice Palace Exit']),
create_dungeon_region(world, player, 'Ice Palace (Second Section)', 'Ice Palace', ['Ice Palace - Conveyor Key Drop'], ['Ice Palace (Main)']),
create_dungeon_region(world, player, 'Ice Palace (Main)', 'Ice Palace', ['Ice Palace - Freezor Chest',
'Ice Palace - Many Pots Pot Key',
'Ice Palace - Big Chest', 'Ice Palace - Iced T Room'], ['Ice Palace (East)', 'Ice Palace (Kholdstare)']),

View File

@@ -5,12 +5,12 @@ from BaseClasses import ItemClassification
from Fill import FillError
from .SubClasses import ALttPLocation, LTTPRegion, LTTPRegionType
from .Shops import TakeAny, total_shop_slots, set_up_shops, shuffle_shops, create_dynamic_shop_locations
from .Shops import TakeAny, total_shop_slots, set_up_shops, shop_table_by_location, ShopType
from .Bosses import place_bosses
from .Dungeons import get_dungeon_item_pool_player
from .EntranceShuffle import connect_entrance
from .Items import ItemFactory, GetBeemizerItem
from .Options import smallkey_shuffle, compass_shuffle, bigkey_shuffle, map_shuffle, LTTPBosses
from .Items import ItemFactory, GetBeemizerItem, trap_replaceable, item_name_groups
from .Options import small_key_shuffle, compass_shuffle, big_key_shuffle, map_shuffle, TriforcePiecesMode
from .StateHelpers import has_triforce_pieces, has_melee_weapon
from .Regions import key_drop_data
@@ -189,104 +189,62 @@ difficulties = {
),
}
ice_rod_hunt_difficulties = dict()
for diff in {'easy', 'normal', 'hard', 'expert'}:
ice_rod_hunt_difficulties[diff] = Difficulty(
baseitems=['Nothing'] * 41,
bottles=['Nothing'] * 4,
bottle_count=difficulties[diff].bottle_count,
same_bottle=difficulties[diff].same_bottle,
progressiveshield=['Nothing'] * 3,
basicshield=['Nothing'] * 3,
progressivearmor=['Nothing'] * 2,
basicarmor=['Nothing'] * 2,
swordless=['Nothing'] * 4,
progressivemagic=['Nothing'] * 2,
basicmagic=['Nothing'] * 2,
progressivesword=['Nothing'] * 4,
basicsword=['Nothing'] * 4,
progressivebow=['Nothing'] * 2,
basicbow=['Nothing'] * 2,
timedohko=difficulties[diff].timedohko,
timedother=difficulties[diff].timedother,
progressiveglove=['Nothing'] * 2,
basicglove=['Nothing'] * 2,
alwaysitems=['Ice Rod'] + ['Nothing'] * 19,
legacyinsanity=['Nothing'] * 2,
universal_keys=['Nothing'] * 29,
extras=[['Nothing'] * 15, ['Nothing'] * 15, ['Nothing'] * 10, ['Nothing'] * 5, ['Nothing'] * 25],
progressive_sword_limit=difficulties[diff].progressive_sword_limit,
progressive_shield_limit=difficulties[diff].progressive_shield_limit,
progressive_armor_limit=difficulties[diff].progressive_armor_limit,
progressive_bow_limit=difficulties[diff].progressive_bow_limit,
progressive_bottle_limit=difficulties[diff].progressive_bottle_limit,
boss_heart_container_limit=difficulties[diff].boss_heart_container_limit,
heart_piece_limit=difficulties[diff].heart_piece_limit,
)
items_reduction_table = (
("Piece of Heart", "Boss Heart Container", 4, 1),
# the order of the upgrades is important
("Arrow Upgrade (+5)", "Arrow Upgrade (+10)", 8, 4),
("Arrow Upgrade (+5)", "Arrow Upgrade (+10)", 7, 4),
("Arrow Upgrade (+5)", "Arrow Upgrade (+10)", 6, 3),
("Arrow Upgrade (+10)", "Arrow Upgrade (70)", 4, 1),
("Bomb Upgrade (+5)", "Bomb Upgrade (+10)", 8, 4),
("Bomb Upgrade (+5)", "Bomb Upgrade (+10)", 7, 4),
("Bomb Upgrade (+5)", "Bomb Upgrade (+10)", 6, 3),
("Bomb Upgrade (+10)", "Bomb Upgrade (50)", 5, 1),
("Bomb Upgrade (+10)", "Bomb Upgrade (50)", 4, 1),
("Progressive Sword", 4),
("Fighter Sword", 1),
("Master Sword", 1),
("Tempered Sword", 1),
("Golden Sword", 1),
("Progressive Shield", 3),
("Blue Shield", 1),
("Red Shield", 1),
("Mirror Shield", 1),
("Progressive Mail", 2),
("Blue Mail", 1),
("Red Mail", 1),
("Progressive Bow", 2),
("Bow", 1),
("Silver Bow", 1),
("Lamp", 1),
("Bottles",)
)
def generate_itempool(world):
player = world.player
multiworld = world.multiworld
if multiworld.difficulty[player] not in difficulties:
raise NotImplementedError(f"Diffulty {multiworld.difficulty[player]}")
if multiworld.goal[player] not in {'ganon', 'pedestal', 'bosses', 'triforcehunt', 'localtriforcehunt', 'icerodhunt',
'ganontriforcehunt', 'localganontriforcehunt', 'crystals', 'ganonpedestal'}:
if multiworld.item_pool[player].current_key not in difficulties:
raise NotImplementedError(f"Diffulty {multiworld.item_pool[player]}")
if multiworld.goal[player] not in ('ganon', 'pedestal', 'bosses', 'triforce_hunt', 'local_triforce_hunt',
'ganon_triforce_hunt', 'local_ganon_triforce_hunt', 'crystals',
'ganon_pedestal'):
raise NotImplementedError(f"Goal {multiworld.goal[player]} for player {player}")
if multiworld.mode[player] not in {'open', 'standard', 'inverted'}:
if multiworld.mode[player] not in ('open', 'standard', 'inverted'):
raise NotImplementedError(f"Mode {multiworld.mode[player]} for player {player}")
if multiworld.timer[player] not in {False, 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'}:
if multiworld.timer[player] not in {False, 'display', 'timed', 'timed_ohko', 'ohko', 'timed_countdown'}:
raise NotImplementedError(f"Timer {multiworld.mode[player]} for player {player}")
if multiworld.timer[player] in ['ohko', 'timed-ohko']:
if multiworld.timer[player] in ['ohko', 'timed_ohko']:
multiworld.can_take_damage[player] = False
if multiworld.goal[player] in ['pedestal', 'triforcehunt', 'localtriforcehunt', 'icerodhunt']:
if multiworld.goal[player] in ['pedestal', 'triforce_hunt', 'local_triforce_hunt']:
multiworld.push_item(multiworld.get_location('Ganon', player), ItemFactory('Nothing', player), False)
else:
multiworld.push_item(multiworld.get_location('Ganon', player), ItemFactory('Triforce', player), False)
if multiworld.goal[player] == 'icerodhunt':
multiworld.progression_balancing[player].value = 0
loc = multiworld.get_location('Turtle Rock - Boss', player)
multiworld.push_item(loc, ItemFactory('Triforce Piece', player), False)
multiworld.treasure_hunt_count[player] = 1
if multiworld.boss_shuffle[player] != 'none':
if isinstance(multiworld.boss_shuffle[player].value, str) and 'turtle rock-' not in multiworld.boss_shuffle[player].value:
multiworld.boss_shuffle[player] = LTTPBosses.from_text(f'Turtle Rock-Trinexx;{multiworld.boss_shuffle[player].current_key}')
elif isinstance(multiworld.boss_shuffle[player].value, int):
multiworld.boss_shuffle[player] = LTTPBosses.from_text(f'Turtle Rock-Trinexx;{multiworld.boss_shuffle[player].current_key}')
else:
logging.warning(f'Cannot guarantee that Trinexx is the boss of Turtle Rock for player {player}')
loc.event = True
loc.locked = True
itemdiff = difficulties[multiworld.difficulty[player]]
itempool = []
itempool.extend(itemdiff.alwaysitems)
itempool.remove('Ice Rod')
itempool.extend(['Single Arrow', 'Sanctuary Heart Container'])
itempool.extend(['Boss Heart Container'] * itemdiff.boss_heart_container_limit)
itempool.extend(['Piece of Heart'] * itemdiff.heart_piece_limit)
itempool.extend(itemdiff.bottles)
itempool.extend(itemdiff.basicbow)
itempool.extend(itemdiff.basicarmor)
if not multiworld.swordless[player]:
itempool.extend(itemdiff.basicsword)
itempool.extend(itemdiff.basicmagic)
itempool.extend(itemdiff.basicglove)
itempool.extend(itemdiff.basicshield)
itempool.extend(itemdiff.legacyinsanity)
itempool.extend(['Rupees (300)'] * 34)
itempool.extend(['Bombs (10)'] * 5)
itempool.extend(['Arrows (10)'] * 7)
if multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
itempool.extend(itemdiff.universal_keys)
for item in itempool:
multiworld.push_precollected(ItemFactory(item, player))
if multiworld.goal[player] in ['triforcehunt', 'localtriforcehunt', 'icerodhunt']:
if multiworld.goal[player] in ['triforce_hunt', 'local_triforce_hunt']:
region = multiworld.get_region('Light World', player)
loc = ALttPLocation(player, "Murahdahla", parent=region)
@@ -308,7 +266,8 @@ def generate_itempool(world):
('Missing Smith', 'Return Smith'),
('Floodgate', 'Open Floodgate'),
('Agahnim 1', 'Beat Agahnim 1'),
('Flute Activation Spot', 'Activated Flute')
('Flute Activation Spot', 'Activated Flute'),
('Capacity Upgrade Shop', 'Capacity Upgrade Shop')
]
for location_name, event_name in event_pairs:
location = multiworld.get_location(location_name, player)
@@ -340,17 +299,31 @@ def generate_itempool(world):
if not found_sword:
found_sword = True
possible_weapons.append(item)
if item in ['Progressive Bow', 'Bow'] and not found_bow:
elif item in ['Progressive Bow', 'Bow'] and not found_bow:
found_bow = True
possible_weapons.append(item)
if item in ['Hammer', 'Bombs (10)', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']:
elif item in ['Hammer', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']:
if item not in possible_weapons:
possible_weapons.append(item)
elif (item == 'Bombs (10)' and (not multiworld.bombless_start[player]) and item not in
possible_weapons):
possible_weapons.append(item)
elif (item in ['Bomb Upgrade (+10)', 'Bomb Upgrade (50)'] and multiworld.bombless_start[player] and item
not in possible_weapons):
possible_weapons.append(item)
starting_weapon = multiworld.random.choice(possible_weapons)
placed_items["Link's Uncle"] = starting_weapon
pool.remove(starting_weapon)
if placed_items["Link's Uncle"] in ['Bow', 'Progressive Bow', 'Bombs (10)', 'Cane of Somaria', 'Cane of Byrna'] and multiworld.enemy_health[player] not in ['default', 'easy']:
multiworld.escape_assist[player].append('bombs')
if (placed_items["Link's Uncle"] in ['Bow', 'Progressive Bow', 'Bombs (10)', 'Bomb Upgrade (+10)',
'Bomb Upgrade (50)', 'Cane of Somaria', 'Cane of Byrna'] and multiworld.enemy_health[player] not in ['default', 'easy']):
if multiworld.bombless_start[player] and "Bomb Upgrade" not in placed_items["Link's Uncle"]:
if 'Bow' in placed_items["Link's Uncle"]:
multiworld.escape_assist[player].append('arrows')
elif 'Cane' in placed_items["Link's Uncle"]:
multiworld.escape_assist[player].append('magic')
else:
multiworld.escape_assist[player].append('bombs')
for (location, item) in placed_items.items():
multiworld.get_location(location, player).place_locked_item(ItemFactory(item, player))
@@ -377,7 +350,7 @@ def generate_itempool(world):
for key_loc in key_drop_data:
key_data = key_drop_data[key_loc]
drop_item = ItemFactory(key_data[3], player)
if multiworld.goal[player] == 'icerodhunt' or not multiworld.key_drop_shuffle[player]:
if not multiworld.key_drop_shuffle[player]:
if drop_item in dungeon_items:
dungeon_items.remove(drop_item)
else:
@@ -391,88 +364,151 @@ def generate_itempool(world):
world.dungeons[dungeon].small_keys.remove(drop_item)
elif world.dungeons[dungeon].big_key is not None and world.dungeons[dungeon].big_key == drop_item:
world.dungeons[dungeon].big_key = None
if not multiworld.key_drop_shuffle[player]:
# key drop item was removed from the pool because key drop shuffle is off
# and it will now place the removed key into its original location
loc = multiworld.get_location(key_loc, player)
loc.place_locked_item(drop_item)
loc.address = None
elif multiworld.goal[player] == 'icerodhunt':
# key drop item removed because of icerodhunt
multiworld.itempool.append(ItemFactory(GetBeemizerItem(world, player, 'Nothing'), player))
multiworld.push_precollected(drop_item)
elif "Small" in key_data[3] and multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
elif "Small" in key_data[3] and multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal:
# key drop shuffle and universal keys are on. Add universal keys in place of key drop keys.
multiworld.itempool.append(ItemFactory(GetBeemizerItem(world, player, 'Small Key (Universal)'), player))
multiworld.itempool.append(ItemFactory(GetBeemizerItem(multiworld, player, 'Small Key (Universal)'), player))
dungeon_item_replacements = sum(difficulties[multiworld.difficulty[player]].extras, []) * 2
multiworld.random.shuffle(dungeon_item_replacements)
if multiworld.goal[player] == 'icerodhunt':
for item in dungeon_items:
multiworld.itempool.append(ItemFactory(GetBeemizerItem(multiworld, player, 'Nothing'), player))
for x in range(len(dungeon_items)-1, -1, -1):
item = dungeon_items[x]
if ((multiworld.small_key_shuffle[player] == small_key_shuffle.option_start_with and item.type == 'SmallKey')
or (multiworld.big_key_shuffle[player] == big_key_shuffle.option_start_with and item.type == 'BigKey')
or (multiworld.compass_shuffle[player] == compass_shuffle.option_start_with and item.type == 'Compass')
or (multiworld.map_shuffle[player] == map_shuffle.option_start_with and item.type == 'Map')):
dungeon_items.pop(x)
multiworld.push_precollected(item)
else:
for x in range(len(dungeon_items)-1, -1, -1):
item = dungeon_items[x]
if ((multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_start_with and item.type == 'SmallKey')
or (multiworld.bigkey_shuffle[player] == bigkey_shuffle.option_start_with and item.type == 'BigKey')
or (multiworld.compass_shuffle[player] == compass_shuffle.option_start_with and item.type == 'Compass')
or (multiworld.map_shuffle[player] == map_shuffle.option_start_with and item.type == 'Map')):
dungeon_items.pop(x)
multiworld.push_precollected(item)
multiworld.itempool.append(ItemFactory(dungeon_item_replacements.pop(), player))
multiworld.itempool.extend([item for item in dungeon_items])
# logic has some branches where having 4 hearts is one possible requirement (of several alternatives)
# rather than making all hearts/heart pieces progression items (which slows down generation considerably)
# We mark one random heart container as an advancement item (or 4 heart pieces in expert mode)
if multiworld.goal[player] != 'icerodhunt' and multiworld.difficulty[player] in ['easy', 'normal', 'hard'] and not (multiworld.custom and multiworld.customitemarray[30] == 0):
next(item for item in items if item.name == 'Boss Heart Container').classification = ItemClassification.progression
elif multiworld.goal[player] != 'icerodhunt' and multiworld.difficulty[player] in ['expert'] and not (multiworld.custom and multiworld.customitemarray[29] < 4):
adv_heart_pieces = (item for item in items if item.name == 'Piece of Heart')
for i in range(4):
next(adv_heart_pieces).classification = ItemClassification.progression
multiworld.itempool.append(ItemFactory(dungeon_item_replacements.pop(), player))
multiworld.itempool.extend([item for item in dungeon_items])
progressionitems = []
nonprogressionitems = []
for item in items:
if item.advancement or item.type:
progressionitems.append(item)
else:
nonprogressionitems.append(GetBeemizerItem(multiworld, item.player, item))
multiworld.random.shuffle(nonprogressionitems)
if additional_triforce_pieces:
if additional_triforce_pieces > len(nonprogressionitems):
raise FillError(f"Not enough non-progression items to replace with Triforce pieces found for player "
f"{multiworld.get_player_name(player)}.")
progressionitems += [ItemFactory("Triforce Piece", player) for _ in range(additional_triforce_pieces)]
nonprogressionitems.sort(key=lambda item: int("Heart" in item.name)) # try to keep hearts in the pool
nonprogressionitems = nonprogressionitems[additional_triforce_pieces:]
multiworld.random.shuffle(nonprogressionitems)
# shuffle medallions
if multiworld.required_medallions[player][0] == "random":
mm_medallion = multiworld.random.choice(['Ether', 'Quake', 'Bombos'])
else:
mm_medallion = multiworld.required_medallions[player][0]
if multiworld.required_medallions[player][1] == "random":
tr_medallion = multiworld.random.choice(['Ether', 'Quake', 'Bombos'])
else:
tr_medallion = multiworld.required_medallions[player][1]
multiworld.required_medallions[player] = (mm_medallion, tr_medallion)
place_bosses(world)
set_up_shops(multiworld, player)
if multiworld.shop_shuffle[player]:
shuffle_shops(multiworld, nonprogressionitems, player)
if multiworld.retro_bow[player]:
shop_items = 0
shop_locations = [location for shop_locations in (shop.region.locations for shop in multiworld.shops if
shop.type == ShopType.Shop and shop.region.player == player) for location in shop_locations if
location.shop_slot is not None]
for location in shop_locations:
if location.shop.inventory[location.shop_slot]["item"] == "Single Arrow":
location.place_locked_item(ItemFactory("Single Arrow", player))
else:
shop_items += 1
else:
shop_items = min(multiworld.shop_item_slots[player], 30 if multiworld.include_witch_hut[player] else 27)
multiworld.itempool += progressionitems + nonprogressionitems
if multiworld.shuffle_capacity_upgrades[player]:
shop_items += 2
chance_100 = int(multiworld.retro_bow[player]) * 0.25 + int(
multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal) * 0.5
for _ in range(shop_items):
if multiworld.random.random() < chance_100:
items.append(ItemFactory(GetBeemizerItem(multiworld, player, "Rupees (100)"), player))
else:
items.append(ItemFactory(GetBeemizerItem(multiworld, player, "Rupees (50)"), player))
multiworld.random.shuffle(items)
pool_count = len(items)
new_items = ["Triforce Piece" for _ in range(additional_triforce_pieces)]
if multiworld.shuffle_capacity_upgrades[player] or multiworld.bombless_start[player]:
progressive = multiworld.progressive[player]
progressive = multiworld.random.choice([True, False]) if progressive == 'grouped_random' else progressive == 'on'
if multiworld.shuffle_capacity_upgrades[player] == "on_combined":
new_items.append("Bomb Upgrade (50)")
elif multiworld.shuffle_capacity_upgrades[player] == "on":
new_items += ["Bomb Upgrade (+5)"] * 6
new_items.append("Bomb Upgrade (+5)" if progressive else "Bomb Upgrade (+10)")
if multiworld.shuffle_capacity_upgrades[player] != "on_combined" and multiworld.bombless_start[player]:
new_items.append("Bomb Upgrade (+5)" if progressive else "Bomb Upgrade (+10)")
if multiworld.shuffle_capacity_upgrades[player] and not multiworld.retro_bow[player]:
if multiworld.shuffle_capacity_upgrades[player] == "on_combined":
new_items += ["Arrow Upgrade (70)"]
else:
new_items += ["Arrow Upgrade (+5)"] * 6
new_items.append("Arrow Upgrade (+5)" if progressive else "Arrow Upgrade (+10)")
items += [ItemFactory(item, player) for item in new_items]
removed_filler = []
multiworld.random.shuffle(items) # Decide what gets tossed randomly.
while len(items) > pool_count:
for i, item in enumerate(items):
if item.classification in (ItemClassification.filler, ItemClassification.trap):
removed_filler.append(items.pop(i))
break
else:
# no more junk to remove, condense progressive items
def condense_items(items, small_item, big_item, rem, add):
small_item = ItemFactory(small_item, player)
# while (len(items) >= pool_count + rem - 1 # minus 1 to account for the replacement item
# and items.count(small_item) >= rem):
if items.count(small_item) >= rem:
for _ in range(rem):
items.remove(small_item)
removed_filler.append(ItemFactory(small_item.name, player))
items += [ItemFactory(big_item, player) for _ in range(add)]
return True
return False
def cut_item(items, item_to_cut, minimum_items):
item_to_cut = ItemFactory(item_to_cut, player)
if items.count(item_to_cut) > minimum_items:
items.remove(item_to_cut)
removed_filler.append(ItemFactory(item_to_cut.name, player))
return True
return False
while len(items) > pool_count:
items_were_cut = False
for reduce_item in items_reduction_table:
if len(items) <= pool_count:
break
if len(reduce_item) == 2:
items_were_cut = items_were_cut or cut_item(items, *reduce_item)
elif len(reduce_item) == 4:
items_were_cut = items_were_cut or condense_items(items, *reduce_item)
elif len(reduce_item) == 1: # Bottles
bottles = [item for item in items if item.name in item_name_groups["Bottles"]]
if len(bottles) > 4:
bottle = multiworld.random.choice(bottles)
items.remove(bottle)
removed_filler.append(bottle)
items_were_cut = True
assert items_were_cut, f"Failed to limit item pool size for player {player}"
if len(items) < pool_count:
items += removed_filler[len(items) - pool_count:]
if multiworld.randomize_cost_types[player]:
# Heart and Arrow costs require all Heart Container/Pieces and Arrow Upgrades to be advancement items for logic
for item in items:
if (item.name in ("Boss Heart Container", "Sanctuary Heart Container", "Piece of Heart")
or "Arrow Upgrade" in item.name):
item.classification = ItemClassification.progression
else:
# Otherwise, logic has some branches where having 4 hearts is one possible requirement (of several alternatives)
# rather than making all hearts/heart pieces progression items (which slows down generation considerably)
# We mark one random heart container as an advancement item (or 4 heart pieces in expert mode)
if multiworld.item_pool[player] in ['easy', 'normal', 'hard'] and not (multiworld.custom and multiworld.customitemarray[30] == 0):
next(item for item in items if item.name == 'Boss Heart Container').classification = ItemClassification.progression
elif multiworld.item_pool[player] in ['expert'] and not (multiworld.custom and multiworld.customitemarray[29] < 4):
adv_heart_pieces = (item for item in items if item.name == 'Piece of Heart')
for i in range(4):
next(adv_heart_pieces).classification = ItemClassification.progression
multiworld.required_medallions[player] = (multiworld.misery_mire_medallion[player].current_key.title(),
multiworld.turtle_rock_medallion[player].current_key.title())
place_bosses(world)
multiworld.itempool += items
if multiworld.retro_caves[player]:
set_up_take_anys(multiworld, player) # depends on world.itempool to be set
# set_up_take_anys needs to run first
create_dynamic_shop_locations(multiworld, player)
take_any_locations = {
@@ -516,9 +552,14 @@ def set_up_take_anys(world, player):
sword = world.random.choice(swords)
world.itempool.remove(sword)
world.itempool.append(ItemFactory('Rupees (20)', player))
old_man_take_any.shop.add_inventory(0, sword.name, 0, 0, create_location=True)
old_man_take_any.shop.add_inventory(0, sword.name, 0, 0)
loc_name = "Old Man Sword Cave"
location = ALttPLocation(player, loc_name, shop_table_by_location[loc_name], parent=old_man_take_any)
location.shop_slot = 0
old_man_take_any.locations.append(location)
location.place_locked_item(sword)
else:
old_man_take_any.shop.add_inventory(0, 'Rupees (300)', 0, 0, create_location=True)
old_man_take_any.shop.add_inventory(0, 'Rupees (300)', 0, 0)
for num in range(4):
take_any = LTTPRegion("Take-Any #{}".format(num+1), LTTPRegionType.Cave, 'a cave of choice', player, world)
@@ -532,18 +573,22 @@ def set_up_take_anys(world, player):
take_any.shop = TakeAny(take_any, room_id, 0xE3, True, True, total_shop_slots + num + 1)
world.shops.append(take_any.shop)
take_any.shop.add_inventory(0, 'Blue Potion', 0, 0)
take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 0, create_location=True)
take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 0)
location = ALttPLocation(player, take_any.name, shop_table_by_location[take_any.name], parent=take_any)
location.shop_slot = 1
take_any.locations.append(location)
location.place_locked_item(ItemFactory("Boss Heart Container", player))
def get_pool_core(world, player: int):
shuffle = world.shuffle[player]
difficulty = world.difficulty[player]
timer = world.timer[player]
goal = world.goal[player]
mode = world.mode[player]
shuffle = world.entrance_shuffle[player].current_key
difficulty = world.item_pool[player].current_key
timer = world.timer[player].current_key
goal = world.goal[player].current_key
mode = world.mode[player].current_key
swordless = world.swordless[player]
retro_bow = world.retro_bow[player]
logic = world.logic[player]
logic = world.glitches_required[player]
pool = []
placed_items = {}
@@ -552,7 +597,7 @@ def get_pool_core(world, player: int):
treasure_hunt_count = None
treasure_hunt_icon = None
diff = ice_rod_hunt_difficulties[difficulty] if goal == 'icerodhunt' else difficulties[difficulty]
diff = difficulties[difficulty]
pool.extend(diff.alwaysitems)
def place_item(loc, item):
@@ -560,7 +605,7 @@ def get_pool_core(world, player: int):
placed_items[loc] = item
# provide boots to major glitch dependent seeds
if logic in {'owglitches', 'hybridglitches', 'nologic'} and world.glitch_boots[player] and goal != 'icerodhunt':
if logic in {'overworld_glitches', 'hybrid_major_glitches', 'no_logic'} and world.glitch_boots[player]:
precollected_items.append('Pegasus Boots')
pool.remove('Pegasus Boots')
pool.append('Rupees (20)')
@@ -611,7 +656,7 @@ def get_pool_core(world, player: int):
if want_progressives(world.random):
pool.extend(diff.progressivebow)
world.worlds[player].has_progressive_bows = True
elif (swordless or logic == 'noglitches') and goal != 'icerodhunt':
elif (swordless or logic == 'no_glitches'):
swordless_bows = ['Bow', 'Silver Bow']
if difficulty == "easy":
swordless_bows *= 2
@@ -627,21 +672,32 @@ def get_pool_core(world, player: int):
extraitems = total_items_to_place - len(pool) - len(placed_items)
if timer in ['timed', 'timed-countdown']:
if timer in ['timed', 'timed_countdown']:
pool.extend(diff.timedother)
extraitems -= len(diff.timedother)
clock_mode = 'stopwatch' if timer == 'timed' else 'countdown'
elif timer == 'timed-ohko':
elif timer == 'timed_ohko':
pool.extend(diff.timedohko)
extraitems -= len(diff.timedohko)
clock_mode = 'countdown-ohko'
additional_pieces_to_place = 0
if 'triforcehunt' in goal:
pieces_in_core = min(extraitems, world.triforce_pieces_available[player])
additional_pieces_to_place = world.triforce_pieces_available[player] - pieces_in_core
if 'triforce_hunt' in goal:
if world.triforce_pieces_mode[player].value == TriforcePiecesMode.option_extra:
triforce_pieces = world.triforce_pieces_available[player].value + world.triforce_pieces_extra[player].value
elif world.triforce_pieces_mode[player].value == TriforcePiecesMode.option_percentage:
percentage = float(max(100, world.triforce_pieces_percentage[player].value)) / 100
triforce_pieces = int(round(world.triforce_pieces_required[player].value * percentage, 0))
else: # available
triforce_pieces = world.triforce_pieces_available[player].value
triforce_pieces = max(triforce_pieces, world.triforce_pieces_required[player].value)
pieces_in_core = min(extraitems, triforce_pieces)
additional_pieces_to_place = triforce_pieces - pieces_in_core
pool.extend(["Triforce Piece"] * pieces_in_core)
extraitems -= pieces_in_core
treasure_hunt_count = world.triforce_pieces_required[player]
treasure_hunt_count = world.triforce_pieces_required[player].value
treasure_hunt_icon = 'Triforce Piece'
for extra in diff.extras:
@@ -659,12 +715,12 @@ def get_pool_core(world, player: int):
pool.remove("Rupees (20)")
if retro_bow:
replace = {'Single Arrow', 'Arrows (10)', 'Arrow Upgrade (+5)', 'Arrow Upgrade (+10)'}
replace = {'Single Arrow', 'Arrows (10)', 'Arrow Upgrade (+5)', 'Arrow Upgrade (+10)', 'Arrow Upgrade (50)'}
pool = ['Rupees (5)' if item in replace else item for item in pool]
if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
if world.small_key_shuffle[player] == small_key_shuffle.option_universal:
pool.extend(diff.universal_keys)
if mode == 'standard':
if world.key_drop_shuffle[player] and world.goal[player] != 'icerodhunt':
if world.key_drop_shuffle[player]:
key_locations = ['Secret Passage', 'Hyrule Castle - Map Guard Key Drop']
key_location = world.random.choice(key_locations)
key_locations.remove(key_location)
@@ -688,8 +744,8 @@ def get_pool_core(world, player: int):
def make_custom_item_pool(world, player):
shuffle = world.shuffle[player]
difficulty = world.difficulty[player]
shuffle = world.entrance_shuffle[player]
difficulty = world.item_pool[player]
timer = world.timer[player]
goal = world.goal[player]
mode = world.mode[player]
@@ -798,9 +854,9 @@ def make_custom_item_pool(world, player):
treasure_hunt_count = world.triforce_pieces_required[player]
treasure_hunt_icon = 'Triforce Piece'
if timer in ['display', 'timed', 'timed-countdown']:
clock_mode = 'countdown' if timer == 'timed-countdown' else 'stopwatch'
elif timer == 'timed-ohko':
if timer in ['display', 'timed', 'timed_countdown']:
clock_mode = 'countdown' if timer == 'timed_countdown' else 'stopwatch'
elif timer == 'timed_ohko':
clock_mode = 'countdown-ohko'
elif timer == 'ohko':
clock_mode = 'ohko'
@@ -810,7 +866,7 @@ def make_custom_item_pool(world, player):
itemtotal = itemtotal + 1
if mode == 'standard':
if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
if world.small_key_shuffle[player] == small_key_shuffle.option_universal:
key_location = world.random.choice(
['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest',
'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross'])
@@ -833,7 +889,7 @@ def make_custom_item_pool(world, player):
pool.extend(['Magic Mirror'] * customitemarray[22])
pool.extend(['Moon Pearl'] * customitemarray[28])
if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
if world.small_key_shuffle[player] == small_key_shuffle.option_universal:
itemtotal = itemtotal - 28 # Corrects for small keys not being in item pool in universal Mode
if world.key_drop_shuffle[player]:
itemtotal = itemtotal - (len(key_drop_data) - 1)

View File

@@ -112,13 +112,15 @@ item_table = {'Bow': ItemData(IC.progression, None, 0x0B, 'You have\nchosen the\
'Crystal 7': ItemData(IC.progression, 'Crystal', (0x08, 0x34, 0x64, 0x40, 0x7C, 0x06), None, None, None, None, None, None, "a blue crystal"),
'Single Arrow': ItemData(IC.filler, None, 0x43, 'a lonely arrow\nsits here.', 'and the arrow', 'stick-collecting kid', 'sewing needle for sale', 'fungus for arrow', 'archer boy sews again', 'an arrow'),
'Arrows (10)': ItemData(IC.filler, None, 0x44, 'This will give\nyou ten shots\nwith your bow!', 'and the arrow pack','stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again','ten arrows'),
'Arrow Upgrade (+10)': ItemData(IC.filler, None, 0x54, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
'Arrow Upgrade (+5)': ItemData(IC.filler, None, 0x53, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
'Arrow Upgrade (+10)': ItemData(IC.useful, None, 0x54, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
'Arrow Upgrade (+5)': ItemData(IC.useful, None, 0x53, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
'Arrow Upgrade (70)': ItemData(IC.useful, None, 0x4D, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
'Single Bomb': ItemData(IC.filler, None, 0x27, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'),
'Bombs (3)': ItemData(IC.filler, None, 0x28, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'),
'Bombs (10)': ItemData(IC.filler, None, 0x31, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'),
'Bomb Upgrade (+10)': ItemData(IC.filler, None, 0x52, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
'Bomb Upgrade (+5)': ItemData(IC.filler, None, 0x51, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
'Bomb Upgrade (+10)': ItemData(IC.progression, None, 0x52, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
'Bomb Upgrade (+5)': ItemData(IC.progression, None, 0x51, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
'Bomb Upgrade (50)': ItemData(IC.progression, None, 0x4C, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
'Blue Mail': ItemData(IC.useful, None, 0x22, 'Now you\'re a\nblue elf!', 'and the banana hat', 'the protected kid', 'banana hat for sale', 'the clothing store', 'tailor boy banana hatted again', 'the Blue Mail'),
'Red Mail': ItemData(IC.useful, None, 0x23, 'Now you\'re a\nred elf!', 'and the eggplant hat', 'well-protected kid', 'purple hat for sale', 'the nice clothing store', 'tailor boy fears nothing again', 'the Red Mail'),
'Progressive Mail': ItemData(IC.useful, None, 0x60, 'time for a\nchange of\nclothes?', 'and the unknown hat', 'the protected kid', 'new hat for sale', 'the clothing store', 'tailor boy has threads again', 'some armor'),
@@ -222,6 +224,7 @@ item_table = {'Bow': ItemData(IC.progression, None, 0x0B, 'You have\nchosen the\
'Return Smith': ItemData(IC.progression, 'Event', None, None, None, None, None, None, None, None),
'Pick Up Purple Chest': ItemData(IC.progression, 'Event', None, None, None, None, None, None, None, None),
'Open Floodgate': ItemData(IC.progression, 'Event', None, None, None, None, None, None, None, None),
'Capacity Upgrade Shop': ItemData(IC.progression, 'Event', None, None, None, None, None, None, None, None),
}
item_init_table = {name: data.as_init_dict() for name, data in item_table.items()}
@@ -287,5 +290,5 @@ progression_items = {name for name in everything if
item_table[name].classification in {IC.progression, IC.progression_skip_balancing}}
item_name_groups['Progression Items'] = progression_items
item_name_groups['Non Progression Items'] = everything - progression_items
item_name_groups['Upgrades'] = {name for name in everything if 'Upgrade' in name}
trap_replaceable = item_name_groups['Rupees'] | {'Arrows (10)', 'Single Bomb', 'Bombs (3)', 'Bombs (10)', 'Nothing'}

View File

@@ -1,10 +1,18 @@
import typing
from BaseClasses import MultiWorld
from Options import Choice, Range, Option, Toggle, DefaultOnToggle, DeathLink, StartInventoryPool, PlandoBosses
from Options import Choice, Range, Option, Toggle, DefaultOnToggle, DeathLink, StartInventoryPool, PlandoBosses,\
FreeText
class Logic(Choice):
class GlitchesRequired(Choice):
"""Determine the logic required to complete the seed
None: No glitches required
Minor Glitches: Puts fake flipper, waterwalk, super bunny shenanigans, and etc into logic
Overworld Glitches: Assumes the player has knowledge of both overworld major glitches (boots clips, mirror clips) and minor glitches
Hybrid Major Glitches: In addition to overworld glitches, also requires underworld clips between dungeons.
No Logic: Your own items are placed with no regard to any logic; such as your Fire Rod can be on your Trinexx."""
display_name = "Glitches Required"
option_no_glitches = 0
option_minor_glitches = 1
option_overworld_glitches = 2
@@ -12,20 +20,121 @@ class Logic(Choice):
option_no_logic = 4
alias_owg = 2
alias_hmg = 3
alias_none = 0
class Objective(Choice):
option_crystals = 0
# option_pendants = 1
option_triforce_pieces = 2
option_pedestal = 3
option_bingo = 4
class DarkRoomLogic(Choice):
"""Logic for unlit dark rooms. Lamp: require the Lamp for these rooms to be considered accessible.
Torches: in addition to lamp, allow the fire rod and presence of easily accessible torches for access.
None: all dark rooms are always considered doable, meaning this may force completion of rooms in complete darkness."""
display_name = "Dark Room Logic"
option_lamp = 0
option_torches = 1
option_none = 2
default = 0
class Goal(Choice):
option_kill_ganon = 0
option_kill_ganon_and_gt_agahnim = 1
option_hand_in = 2
"""Ganon: Climb GT, defeat Agahnim 2, and then kill Ganon
Crystals: Only killing Ganon is required. However, items may still be placed in GT
Bosses: Defeat the boss of all dungeons, including Agahnim's tower and GT (Aga 2)
Pedestal: Pull the Triforce from the Master Sword pedestal
Ganon Pedestal: Pull the Master Sword pedestal, then kill Ganon
Triforce Hunt: Collect Triforce pieces spread throughout the worlds, then turn them in to Murahadala in front of Hyrule Castle
Local Triforce Hunt: Collect Triforce pieces spread throughout your world, then turn them in to Murahadala in front of Hyrule Castle
Ganon Triforce Hunt: Collect Triforce pieces spread throughout the worlds, then kill Ganon
Local Ganon Triforce Hunt: Collect Triforce pieces spread throughout your world, then kill Ganon"""
display_name = "Goal"
default = 0
option_ganon = 0
option_crystals = 1
option_bosses = 2
option_pedestal = 3
option_ganon_pedestal = 4
option_triforce_hunt = 5
option_local_triforce_hunt = 6
option_ganon_triforce_hunt = 7
option_local_ganon_triforce_hunt = 8
class EntranceShuffle(Choice):
"""Dungeons Simple: Shuffle just dungeons amongst each other, swapping dungeons entirely, so Hyrule Castle is always 1 dungeon.
Dungeons Full: Shuffle any dungeon entrance with any dungeon interior, so Hyrule Castle can be 4 different dungeons, but keep dungeons to a specific world.
Dungeons Crossed: like dungeons_full, but allow cross-world traversal through a dungeon. Warning: May force repeated dungeon traversal.
Simple: Entrances are grouped together before being randomized. Interiors with two entrances are grouped shuffled together with each other,
and Death Mountain entrances are shuffled only on Death Mountain. Dungeons are swapped entirely.
Restricted: Like Simple, but single entrance interiors, multi entrance interiors, and Death Mountain interior entrances are all shuffled with each other.
Full: Like Restricted, but all Dungeon entrances are shuffled with all non-Dungeon entrances.
Crossed: Like Full, but interiors with multiple entrances are no longer confined to the same world, which may allow crossing worlds.
Insanity: Like Crossed, but entrances and exits may be decoupled from each other, so that leaving through an exit may not return you to the entrance you entered from."""
display_name = "Entrance Shuffle"
default = 0
alias_none = 0
option_vanilla = 0
option_dungeons_simple = 1
option_dungeons_full = 2
option_dungeons_crossed = 3
option_simple = 4
option_restricted = 5
option_full = 6
option_crossed = 7
option_insanity = 8
alias_dungeonssimple = 1
alias_dungeonsfull = 2
alias_dungeonscrossed = 3
class EntranceShuffleSeed(FreeText):
"""You can specify a number to use as an entrance shuffle seed, or a group name. Everyone with the same group name
will get the same entrance shuffle result as long as their Entrance Shuffle, Mode, Retro Caves, and Glitches
Required options are the same."""
default = "random"
display_name = "Entrance Shuffle Seed"
class TriforcePiecesMode(Choice):
"""Determine how to calculate the extra available triforce pieces.
Extra: available = triforce_pieces_extra + triforce_pieces_required
Percentage: available = (triforce_pieces_percentage /100) * triforce_pieces_required
Available: available = triforce_pieces_available"""
display_name = "Triforce Pieces Mode"
default = 2
option_extra = 0
option_percentage = 1
option_available = 2
class TriforcePiecesPercentage(Range):
"""Set to how many triforce pieces according to a percentage of the required ones, are available to collect in the world."""
display_name = "Triforce Pieces Percentage"
range_start = 100
range_end = 1000
default = 150
class TriforcePiecesAvailable(Range):
"""Set to how many triforces pieces are available to collect in the world. Default is 30. Max is 90, Min is 1"""
display_name = "Triforce Pieces Available"
range_start = 1
range_end = 90
default = 30
class TriforcePiecesRequired(Range):
"""Set to how many out of X triforce pieces you need to win the game in a triforce hunt.
Default is 20. Max is 90, Min is 1."""
display_name = "Triforce Pieces Required"
range_start = 1
range_end = 90
default = 20
class TriforcePiecesExtra(Range):
"""Set to how many extra triforces pieces are available to collect in the world."""
display_name = "Triforce Pieces Extra"
range_start = 0
range_end = 89
default = 10
class OpenPyramid(Choice):
@@ -44,10 +153,10 @@ class OpenPyramid(Choice):
def to_bool(self, world: MultiWorld, player: int) -> bool:
if self.value == self.option_goal:
return world.goal[player] in {'crystals', 'ganontriforcehunt', 'localganontriforcehunt', 'ganonpedestal'}
return world.goal[player] in {'crystals', 'ganon_triforce_hunt', 'local_ganon_triforce_hunt', 'ganon_pedestal'}
elif self.value == self.option_auto:
return world.goal[player] in {'crystals', 'ganontriforcehunt', 'localganontriforcehunt', 'ganonpedestal'} \
and (world.shuffle[player] in {'vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed'} or not
return world.goal[player] in {'crystals', 'ganon_triforce_hunt', 'local_ganon_triforce_hunt', 'ganon_pedestal'} \
and (world.entrance_shuffle[player] in {'vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed'} or not
world.shuffle_ganon)
elif self.value == self.option_open:
return True
@@ -76,13 +185,13 @@ class DungeonItem(Choice):
return self.value in {1, 2, 3, 4}
class bigkey_shuffle(DungeonItem):
class big_key_shuffle(DungeonItem):
"""Big Key Placement"""
item_name_group = "Big Keys"
display_name = "Big Key Shuffle"
class smallkey_shuffle(DungeonItem):
class small_key_shuffle(DungeonItem):
"""Small Key Placement"""
option_universal = 5
item_name_group = "Small Keys"
@@ -101,12 +210,154 @@ class map_shuffle(DungeonItem):
display_name = "Map Shuffle"
class key_drop_shuffle(Toggle):
class key_drop_shuffle(DefaultOnToggle):
"""Shuffle keys found in pots and dropped from killed enemies,
respects the small key and big key shuffle options."""
display_name = "Key Drop Shuffle"
class DungeonCounters(Choice):
"""On: Always display amount of items checked in a dungeon. Pickup: Show when compass is picked up.
Default: Show when compass is picked up if the compass itself is shuffled. Off: Never show item count in dungeons."""
display_name = "Dungeon Counters"
default = 1
option_on = 0
option_pickup = 1
option_default = 2
option_off = 4
class Mode(Choice):
"""Standard: Begin the game by rescuing Zelda from her cell and escorting her to the Sanctuary
Open: Begin the game from your choice of Link's House or the Sanctuary
Inverted: Begin in the Dark World. The Moon Pearl is required to avoid bunny-state in Light World, and the Light World game map is altered"""
option_standard = 0
option_open = 1
option_inverted = 2
default = 1
display_name = "Mode"
class ItemPool(Choice):
"""Easy: Doubled upgrades, progressives, and etc. Normal: Item availability remains unchanged from vanilla game.
Hard: Reduced upgrade availability (max: 14 hearts, blue mail, tempered sword, fire shield, no silvers unless swordless).
Expert: Minimum upgrade availability (max: 8 hearts, green mail, master sword, fighter shield, no silvers unless swordless)."""
display_name = "Item Pool"
default = 1
option_easy = 0
option_normal = 1
option_hard = 2
option_expert = 3
class ItemFunctionality(Choice):
"""Easy: Allow Hammer to damage ganon, Allow Hammer tablet collection, Allow swordless medallion use everywhere.
Normal: Vanilla item functionality
Hard: Reduced helpfulness of items (potions less effective, can't catch faeries, cape uses double magic, byrna does not grant invulnerability, boomerangs do not stun, silvers disabled outside ganon)
Expert: Vastly reduces the helpfulness of items (potions barely effective, can't catch faeries, cape uses double magic, byrna does not grant invulnerability, boomerangs and hookshot do not stun, silvers disabled outside ganon)"""
display_name = "Item Functionality"
default = 1
option_easy = 0
option_normal = 1
option_hard = 2
option_expert = 3
class EnemyHealth(Choice):
"""Default: Vanilla enemy HP. Easy: Enemies have reduced health. Hard: Enemies have increased health.
Expert: Enemies have greatly increased health."""
display_name = "Enemy Health"
default = 1
option_easy = 0
option_default = 1
option_hard = 2
option_expert = 3
class EnemyDamage(Choice):
"""Default: Vanilla enemy damage. Shuffled: 0 # Enemies deal 0 to 4 hearts and armor helps.
Chaos: Enemies deal 0 to 8 hearts and armor just reshuffles the damage."""
display_name = "Enemy Damage"
default = 0
option_default = 0
option_shuffled = 2
option_chaos = 3
class ShufflePrizes(Choice):
"""Shuffle "general" prize packs, as in enemy, tree pull, dig etc.; "bonk" prizes; or both."""
display_name = "Shuffle Prizes"
default = 1
option_off = 0
option_general = 1
option_bonk = 2
option_both = 3
class Medallion(Choice):
default = "random"
option_ether = 0
option_bombos = 1
option_quake = 2
class MiseryMireMedallion(Medallion):
"""Required medallion to open Misery Mire front entrance."""
display_name = "Misery Mire Medallion"
class TurtleRockMedallion(Medallion):
"""Required medallion to open Turtle Rock front entrance."""
display_name = "Turtle Rock Medallion"
class Timer(Choice):
"""None: No timer will be displayed. OHKO: Timer always at zero. Permanent OHKO.
Timed: Starts with clock at zero. Green clocks subtract 4 minutes (total 20). Blue clocks subtract 2 minutes (total 10). Red clocks add two minutes (total 10). Winner is the player with the lowest time at the end.
Timed OHKO: Starts the clock at ten minutes. Green clocks add five minutes (total 25). As long as the clock as at zero, Link will die in one hit.
Timed Countdown: Starts the clock with forty minutes. Same clocks as timed mode, but if the clock hits zero you lose. You can still keep playing, though.
Display: Displays a timer, but otherwise does not affect gameplay or the item pool."""
display_name = "Timer"
option_none = 0
option_timed = 1
option_timed_ohko = 2
option_ohko = 3
option_timed_countdown = 4
option_display = 5
default = 0
class CountdownStartTime(Range):
"""For Timed OHKO and Timed Countdown timer modes, the amount of time in minutes to start with."""
display_name = "Countdown Start Time"
range_start = 0
range_end = 480
default = 10
class ClockTime(Range):
range_start = -60
range_end = 60
class RedClockTime(ClockTime):
"""For all timer modes, the amount of time in minutes to gain or lose when picking up a red clock."""
display_name = "Red Clock Time"
default = -2
class BlueClockTime(ClockTime):
"""For all timer modes, the amount of time in minutes to gain or lose when picking up a blue clock."""
display_name = "Blue Clock Time"
default = 2
class GreenClockTime(ClockTime):
"""For all timer modes, the amount of time in minutes to gain or lose when picking up a green clock."""
display_name = "Green Clock Time"
default = 4
class Crystals(Range):
range_start = 0
range_end = 7
@@ -137,18 +388,52 @@ class ShopItemSlots(Range):
range_end = 30
class RandomizeShopInventories(Choice):
"""Generate new default inventories for overworld/underworld shops, and unique shops; or each shop independently"""
display_name = "Randomize Shop Inventories"
default = 0
option_default = 0
option_randomize_by_shop_type = 1
option_randomize_each = 2
class ShuffleShopInventories(Toggle):
"""Shuffle default inventories of the shops around"""
display_name = "Shuffle Shop Inventories"
class RandomizeShopPrices(Toggle):
"""Randomize the prices of the items in shop inventories"""
display_name = "Randomize Shop Prices"
class RandomizeCostTypes(Toggle):
"""Prices of the items in shop inventories may cost hearts, arrow, or bombs instead of rupees"""
display_name = "Randomize Cost Types"
class ShopPriceModifier(Range):
"""Percentage modifier for shuffled item prices in shops"""
display_name = "Shop Price Cost Percent"
display_name = "Shop Price Modifier"
range_start = 0
default = 100
range_end = 400
class WorldState(Choice):
option_standard = 1
option_open = 0
option_inverted = 2
class IncludeWitchHut(Toggle):
"""Consider witch's hut like any other shop and shuffle/randomize it too"""
display_name = "Include Witch's Hut"
class ShuffleCapacityUpgrades(Choice):
"""Shuffle capacity upgrades into the item pool (and allow them to traverse the multiworld).
On Combined will shuffle only a single bomb upgrade and arrow upgrade each which bring you to the maximum capacity."""
display_name = "Shuffle Capacity Upgrades"
option_off = 0
option_on = 1
option_on_combined = 2
alias_false = 0
alias_true = 1
class LTTPBosses(PlandoBosses):
@@ -236,6 +521,11 @@ class Swordless(Toggle):
display_name = "Swordless"
class BomblessStart(Toggle):
"""Start with a max of 0 bombs available, requiring Bomb Upgrade items in order to use bombs"""
display_name = "Bombless Start"
# Might be a decent idea to split "Bow" into its own option with choices of
# Defer to Progressive Option (default), Progressive, Non-Progressive, Bow + Silvers, Retro
class RetroBow(Toggle):
@@ -433,29 +723,66 @@ class AllowCollect(Toggle):
alttp_options: typing.Dict[str, type(Option)] = {
"start_inventory_from_pool": StartInventoryPool,
"goal": Goal,
"mode": Mode,
"glitches_required": GlitchesRequired,
"dark_room_logic": DarkRoomLogic,
"open_pyramid": OpenPyramid,
"crystals_needed_for_gt": CrystalsTower,
"crystals_needed_for_ganon": CrystalsGanon,
"open_pyramid": OpenPyramid,
"bigkey_shuffle": bigkey_shuffle,
"smallkey_shuffle": smallkey_shuffle,
"triforce_pieces_mode": TriforcePiecesMode,
"triforce_pieces_percentage": TriforcePiecesPercentage,
"triforce_pieces_required": TriforcePiecesRequired,
"triforce_pieces_available": TriforcePiecesAvailable,
"triforce_pieces_extra": TriforcePiecesExtra,
"entrance_shuffle": EntranceShuffle,
"entrance_shuffle_seed": EntranceShuffleSeed,
"big_key_shuffle": big_key_shuffle,
"small_key_shuffle": small_key_shuffle,
"key_drop_shuffle": key_drop_shuffle,
"compass_shuffle": compass_shuffle,
"map_shuffle": map_shuffle,
"restrict_dungeon_item_on_boss": RestrictBossItem,
"item_pool": ItemPool,
"item_functionality": ItemFunctionality,
"enemy_health": EnemyHealth,
"enemy_damage": EnemyDamage,
"progressive": Progressive,
"swordless": Swordless,
"dungeon_counters": DungeonCounters,
"retro_bow": RetroBow,
"retro_caves": RetroCaves,
"hints": Hints,
"scams": Scams,
"restrict_dungeon_item_on_boss": RestrictBossItem,
"boss_shuffle": LTTPBosses,
"pot_shuffle": PotShuffle,
"enemy_shuffle": EnemyShuffle,
"killable_thieves": KillableThieves,
"bush_shuffle": BushShuffle,
"shop_item_slots": ShopItemSlots,
"randomize_shop_inventories": RandomizeShopInventories,
"shuffle_shop_inventories": ShuffleShopInventories,
"include_witch_hut": IncludeWitchHut,
"randomize_shop_prices": RandomizeShopPrices,
"randomize_cost_types": RandomizeCostTypes,
"shop_price_modifier": ShopPriceModifier,
"shuffle_capacity_upgrades": ShuffleCapacityUpgrades,
"bombless_start": BomblessStart,
"shuffle_prizes": ShufflePrizes,
"tile_shuffle": TileShuffle,
"misery_mire_medallion": MiseryMireMedallion,
"turtle_rock_medallion": TurtleRockMedallion,
"glitch_boots": GlitchBoots,
"beemizer_total_chance": BeemizerTotalChance,
"beemizer_trap_chance": BeemizerTrapChance,
"timer": Timer,
"countdown_start_time": CountdownStartTime,
"red_clock_time": RedClockTime,
"blue_clock_time": BlueClockTime,
"green_clock_time": GreenClockTime,
"death_link": DeathLink,
"allow_collect": AllowCollect,
"ow_palettes": OWPalette,
"uw_palettes": UWPalette,
"hud_palettes": HUDPalette,
@@ -469,10 +796,4 @@ alttp_options: typing.Dict[str, type(Option)] = {
"music": Music,
"reduceflashing": ReduceFlashing,
"triforcehud": TriforceHud,
"glitch_boots": GlitchBoots,
"beemizer_total_chance": BeemizerTotalChance,
"beemizer_trap_chance": BeemizerTrapChance,
"death_link": DeathLink,
"allow_collect": AllowCollect,
"start_inventory_from_pool": StartInventoryPool,
}

View File

@@ -94,7 +94,7 @@ def create_regions(world, player):
create_cave_region(world, player, 'Kakariko Gamble Game', 'a game of chance'),
create_cave_region(world, player, 'Potion Shop', 'the potion shop', ['Potion Shop']),
create_lw_region(world, player, 'Lake Hylia Island', ['Lake Hylia Island']),
create_cave_region(world, player, 'Capacity Upgrade', 'the queen of fairies'),
create_cave_region(world, player, 'Capacity Upgrade', 'the queen of fairies', ['Capacity Upgrade Shop']),
create_cave_region(world, player, 'Two Brothers House', 'a connector', None, ['Two Brothers House Exit (East)', 'Two Brothers House Exit (West)']),
create_lw_region(world, player, 'Maze Race Ledge', ['Maze Race'], ['Two Brothers House (West)']),
create_cave_region(world, player, '50 Rupee Cave', 'a cave with some cash'),
@@ -121,8 +121,9 @@ def create_regions(world, player):
['Hyrule Castle Exit (East)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (South)', 'Throne Room']),
create_dungeon_region(world, player, 'Sewer Drop', 'a drop\'s exit', None, ['Sewer Drop']), # This exists only to be referenced for access checks
create_dungeon_region(world, player, 'Sewers (Dark)', 'a drop\'s exit', ['Sewers - Dark Cross', 'Sewers - Key Rat Key Drop'], ['Sewers Door']),
create_dungeon_region(world, player, 'Sewers', 'a drop\'s exit', ['Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle',
'Sewers - Secret Room - Right'], ['Sanctuary Push Door', 'Sewers Back Door']),
create_dungeon_region(world, player, 'Sewers', 'a drop\'s exit', None, ['Sanctuary Push Door', 'Sewers Back Door', 'Sewers Secret Room']),
create_dungeon_region(world, player, 'Sewers Secret Room', 'a drop\'s exit', ['Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle',
'Sewers - Secret Room - Right']),
create_dungeon_region(world, player, 'Sanctuary', 'a drop\'s exit', ['Sanctuary'], ['Sanctuary Exit']),
create_dungeon_region(world, player, 'Agahnims Tower', 'Castle Tower', ['Castle Tower - Room 03', 'Castle Tower - Dark Maze', 'Castle Tower - Dark Archer Key Drop', 'Castle Tower - Circle of Pots Key Drop'], ['Agahnim 1', 'Agahnims Tower Exit']),
create_dungeon_region(world, player, 'Agahnim 1', 'Castle Tower', ['Agahnim 1'], None),
@@ -275,7 +276,9 @@ def create_regions(world, player):
create_cave_region(world, player, 'Hookshot Cave', 'a connector',
['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right',
'Hookshot Cave - Bottom Left'],
['Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)']),
['Hookshot Cave Exit (South)', 'Hookshot Cave Bomb Wall (South)']),
create_cave_region(world, player, 'Hookshot Cave (Upper)', 'a connector', None, ['Hookshot Cave Exit (North)',
'Hookshot Cave Bomb Wall (North)']),
create_dw_region(world, player, 'Death Mountain Floating Island (Dark World)', None,
['Floating Island Drop', 'Hookshot Cave Back Entrance', 'Floating Island Mirror Spot']),
create_lw_region(world, player, 'Death Mountain Floating Island (Light World)', ['Floating Island']),
@@ -311,8 +314,8 @@ def create_regions(world, player):
create_dungeon_region(world, player, 'Skull Woods Second Section', 'Skull Woods', ['Skull Woods - Big Key Chest', 'Skull Woods - West Lobby Pot Key'], ['Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)']),
create_dungeon_region(world, player, 'Skull Woods Final Section (Entrance)', 'Skull Woods', ['Skull Woods - Bridge Room'], ['Skull Woods Torch Room', 'Skull Woods Final Section Exit']),
create_dungeon_region(world, player, 'Skull Woods Final Section (Mothula)', 'Skull Woods', ['Skull Woods - Spike Corner Key Drop', 'Skull Woods - Boss', 'Skull Woods - Prize']),
create_dungeon_region(world, player, 'Ice Palace (Entrance)', 'Ice Palace', ['Ice Palace - Jelly Key Drop'], ['Ice Palace (Second Section)', 'Ice Palace Exit']),
create_dungeon_region(world, player, 'Ice Palace (Second Section)', 'Ice Palace', ['Ice Palace - Conveyor Key Drop', 'Ice Palace - Compass Chest'], ['Ice Palace (Main)']),
create_dungeon_region(world, player, 'Ice Palace (Entrance)', 'Ice Palace', ['Ice Palace - Jelly Key Drop', 'Ice Palace - Compass Chest'], ['Ice Palace (Second Section)', 'Ice Palace Exit']),
create_dungeon_region(world, player, 'Ice Palace (Second Section)', 'Ice Palace', ['Ice Palace - Conveyor Key Drop'], ['Ice Palace (Main)']),
create_dungeon_region(world, player, 'Ice Palace (Main)', 'Ice Palace', ['Ice Palace - Freezor Chest',
'Ice Palace - Many Pots Pot Key',
'Ice Palace - Big Chest', 'Ice Palace - Iced T Room'], ['Ice Palace (East)', 'Ice Palace (Kholdstare)']),
@@ -735,6 +738,7 @@ location_table: typing.Dict[str,
'Missing Smith': (None, None, False, None),
'Dark Blacksmith Ruins': (None, None, False, None),
'Flute Activation Spot': (None, None, False, None),
'Capacity Upgrade Shop': (None, None, False, None),
'Eastern Palace - Prize': ([0x1209D, 0x53EF8, 0x53EF9, 0x180052, 0x18007C, 0xC6FE], None, True, 'Eastern Palace'),
'Desert Palace - Prize': ([0x1209E, 0x53F1C, 0x53F1D, 0x180053, 0x180078, 0xC6FF], None, True, 'Desert Palace'),
'Tower of Hera - Prize': (

View File

@@ -4,7 +4,7 @@ import Utils
import worlds.Files
LTTPJPN10HASH: str = "03a63945398191337e896e5771f77173"
RANDOMIZERBASEHASH: str = "9952c2a3ec1b421e408df0d20c8f0c7f"
RANDOMIZERBASEHASH: str = "35d010bc148e0ea0ee68e81e330223f1"
ROM_PLAYER_LIMIT: int = 255
import io
@@ -36,7 +36,7 @@ from .Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmith
SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
from .Items import ItemFactory, item_table, item_name_groups, progression_items
from .EntranceShuffle import door_addresses
from .Options import smallkey_shuffle
from .Options import small_key_shuffle
try:
from maseya import z3pr
@@ -294,7 +294,7 @@ def patch_enemizer(world, rom: LocalRom, enemizercli, output_directory):
'RandomizeBushEnemyChance': multiworld.bush_shuffle[player].value,
'RandomizeEnemyHealthRange': multiworld.enemy_health[player] != 'default',
'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[
multiworld.enemy_health[player]],
multiworld.enemy_health[player].current_key],
'OHKO': False,
'RandomizeEnemyDamage': multiworld.enemy_damage[player] != 'default',
'AllowEnemyZeroDamage': True,
@@ -858,13 +858,13 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
# Thanks to Zarby89 for originally finding these values
# todo fix screen scrolling
if world.shuffle[player] not in {'insanity', 'insanity_legacy', 'madness_legacy'} and \
if world.entrance_shuffle[player] != 'insanity' and \
exit.name in {'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit',
'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit',
'Palace of Darkness Exit', 'Swamp Palace Exit', 'Ganons Tower Exit',
'Desert Palace Exit (North)', 'Agahnims Tower Exit', 'Spiral Cave Exit (Top)',
'Superbunny Cave Exit (Bottom)', 'Turtle Rock Ledge Exit (East)'} and \
(world.logic[player] not in ['hybridglitches', 'nologic'] or
(world.glitches_required[player] not in ['hybrid_major_glitches', 'no_logic'] or
exit.name not in {'Palace of Darkness Exit', 'Tower of Hera Exit', 'Swamp Palace Exit'}):
# For exits that connot be reached from another, no need to apply offset fixes.
rom.write_int16(0x15DB5 + 2 * offset, link_y) # same as final else
@@ -907,7 +907,9 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
if world.retro_caves[player]: # Old man cave and Take any caves will count towards collection rate.
credits_total += 5
if world.shop_item_slots[player]: # Potion shop only counts towards collection rate if included in the shuffle.
credits_total += 30 if 'w' in world.shop_shuffle[player] else 27
credits_total += 30 if world.include_witch_hut[player] else 27
if world.shuffle_capacity_upgrades[player]:
credits_total += 2
rom.write_byte(0x187010, credits_total) # dynamic credits
@@ -1059,7 +1061,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
# Set stun items
rom.write_byte(0x180180, 0x03) # All standard items
# Set overflow items for progressive equipment
if world.timer[player] in ['timed', 'timed-countdown', 'timed-ohko']:
if world.timer[player] in ['timed', 'timed_countdown', 'timed_ohko']:
overflow_replacement = GREEN_CLOCK
else:
overflow_replacement = GREEN_TWENTY_RUPEES
@@ -1079,7 +1081,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
difficulty.progressive_bow_limit, item_table[difficulty.basicbow[-1]].item_code])
if difficulty.progressive_bow_limit < 2 and (
world.swordless[player] or world.logic[player] == 'noglitches'):
world.swordless[player] or world.glitches_required[player] == 'no_glitches'):
rom.write_bytes(0x180098, [2, item_table["Silver Bow"].item_code])
rom.write_byte(0x180181, 0x01) # Make silver arrows work only on ganon
rom.write_byte(0x180182, 0x00) # Don't auto equip silvers on pickup
@@ -1095,7 +1097,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
prize_replacements[0xE1] = 0xDA # 5 Arrows -> Blue Rupee
prize_replacements[0xE2] = 0xDB # 10 Arrows -> Red Rupee
if "g" in world.shuffle_prizes[player]:
if world.shuffle_prizes[player] in ("general", "both"):
# shuffle prize packs
prizes = [0xD8, 0xD8, 0xD8, 0xD8, 0xD9, 0xD8, 0xD8, 0xD9, 0xDA, 0xD9, 0xDA, 0xDB, 0xDA, 0xD9, 0xDA, 0xDA, 0xE0,
0xDF, 0xDF, 0xDA, 0xE0, 0xDF, 0xD8, 0xDF,
@@ -1157,7 +1159,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
byte = int(rom.read_byte(address))
rom.write_byte(address, prize_replacements.get(byte, byte))
if "b" in world.shuffle_prizes[player]:
if world.shuffle_prizes[player] in ("bonk", "both"):
# set bonk prizes
bonk_prizes = [0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xAC, 0xE3, 0xE3, 0xDA, 0xE3, 0xDA, 0xD8, 0xAC,
0xAC, 0xE3, 0xD8, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xDC, 0xDB, 0xE3, 0xDA, 0x79, 0x79,
@@ -1274,7 +1276,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
gametype = 0x04 # item
if world.shuffle[player] != 'vanilla':
if world.entrance_shuffle[player] != 'vanilla':
gametype |= 0x02 # entrance
if enemized:
gametype |= 0x01 # enemizer
@@ -1312,7 +1314,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
equip[0x36C] = 0x18
equip[0x36D] = 0x18
equip[0x379] = 0x68
starting_max_bombs = 10
starting_max_bombs = 0 if world.bombless_start[player] else 10
starting_max_arrows = 30
startingstate = CollectionState(world)
@@ -1430,8 +1432,8 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
'Bottle (Fairy)': 6, 'Bottle (Bee)': 7, 'Bottle (Good Bee)': 8}
rupees = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)': 50, 'Rupees (100)': 100,
'Rupees (300)': 300}
bomb_caps = {'Bomb Upgrade (+5)': 5, 'Bomb Upgrade (+10)': 10}
arrow_caps = {'Arrow Upgrade (+5)': 5, 'Arrow Upgrade (+10)': 10}
bomb_caps = {'Bomb Upgrade (+5)': 5, 'Bomb Upgrade (+10)': 10, 'Bomb Upgrade (50)': 50}
arrow_caps = {'Arrow Upgrade (+5)': 5, 'Arrow Upgrade (+10)': 10, 'Arrow Upgrade (70)': 70}
bombs = {'Single Bomb': 1, 'Bombs (3)': 3, 'Bombs (10)': 10}
arrows = {'Single Arrow': 1, 'Arrows (10)': 10}
@@ -1498,7 +1500,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_byte(0x3A96D, 0xF0 if world.mode[
player] != 'inverted' else 0xD0) # Residual Portal: Normal (F0= Light Side, D0=Dark Side, 42 = both (Darth Vader))
rom.write_byte(0x3A9A7, 0xD0) # Residual Portal: Normal (D0= Light Side, F0=Dark Side, 42 = both (Darth Vader))
if 'u' in world.shop_shuffle[player]:
if world.shuffle_capacity_upgrades[player]:
rom.write_bytes(0x180080,
[5, 10, 5, 10]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10)
else:
@@ -1509,11 +1511,11 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
(0x02 if 'bombs' in world.escape_assist[player] else 0x00) |
(0x04 if 'magic' in world.escape_assist[player] else 0x00))) # Escape assist
if world.goal[player] in ['pedestal', 'triforcehunt', 'localtriforcehunt', 'icerodhunt']:
if world.goal[player] in ['pedestal', 'triforce_hunt', 'local_triforce_hunt']:
rom.write_byte(0x18003E, 0x01) # make ganon invincible
elif world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']:
elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']:
rom.write_byte(0x18003E, 0x05) # make ganon invincible until enough triforce pieces are collected
elif world.goal[player] in ['ganonpedestal']:
elif world.goal[player] in ['ganon_pedestal']:
rom.write_byte(0x18003E, 0x06)
elif world.goal[player] in ['bosses']:
rom.write_byte(0x18003E, 0x02) # make ganon invincible until all bosses are beat
@@ -1534,12 +1536,12 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
# c - enabled for inside compasses
# s - enabled for inside small keys
# block HC upstairs doors in rain state in standard mode
rom.write_byte(0x18008A, 0x01 if world.mode[player] == "standard" and world.shuffle[player] != 'vanilla' else 0x00)
rom.write_byte(0x18008A, 0x01 if world.mode[player] == "standard" and world.entrance_shuffle[player] != 'vanilla' else 0x00)
rom.write_byte(0x18016A, 0x10 | ((0x01 if world.smallkey_shuffle[player] else 0x00)
rom.write_byte(0x18016A, 0x10 | ((0x01 if world.small_key_shuffle[player] else 0x00)
| (0x02 if world.compass_shuffle[player] else 0x00)
| (0x04 if world.map_shuffle[player] else 0x00)
| (0x08 if world.bigkey_shuffle[
| (0x08 if world.big_key_shuffle[
player] else 0x00))) # free roaming item text boxes
rom.write_byte(0x18003B, 0x01 if world.map_shuffle[player] else 0x00) # maps showing crystals on overworld
@@ -1561,9 +1563,9 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
# b - Big Key
# a - Small Key
#
rom.write_byte(0x180045, ((0x00 if (world.smallkey_shuffle[player] == smallkey_shuffle.option_original_dungeon or
world.smallkey_shuffle[player] == smallkey_shuffle.option_universal) else 0x01)
| (0x02 if world.bigkey_shuffle[player] else 0x00)
rom.write_byte(0x180045, ((0x00 if (world.small_key_shuffle[player] == small_key_shuffle.option_original_dungeon or
world.small_key_shuffle[player] == small_key_shuffle.option_universal) else 0x01)
| (0x02 if world.big_key_shuffle[player] else 0x00)
| (0x04 if world.map_shuffle[player] else 0x00)
| (0x08 if world.compass_shuffle[player] else 0x00))) # free roaming items in menu
@@ -1595,8 +1597,8 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_int16(0x18017C, get_reveal_bytes('Crystal 5') | get_reveal_bytes('Crystal 6') if world.map_shuffle[
player] else 0x0000) # Bomb Shop Reveal
rom.write_byte(0x180172, 0x01 if world.smallkey_shuffle[
player] == smallkey_shuffle.option_universal else 0x00) # universal keys
rom.write_byte(0x180172, 0x01 if world.small_key_shuffle[
player] == small_key_shuffle.option_universal else 0x00) # universal keys
rom.write_byte(0x18637E, 0x01 if world.retro_bow[player] else 0x00) # Skip quiver in item shops once bought
rom.write_byte(0x180175, 0x01 if world.retro_bow[player] else 0x00) # rupee bow
rom.write_byte(0x180176, 0x0A if world.retro_bow[player] else 0x00) # wood arrow cost
@@ -1613,9 +1615,9 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_byte(0x180020, digging_game_rng)
rom.write_byte(0xEFD95, digging_game_rng)
rom.write_byte(0x1800A3, 0x01) # enable correct world setting behaviour after agahnim kills
rom.write_byte(0x1800A4, 0x01 if world.logic[player] != 'nologic' else 0x00) # enable POD EG fix
rom.write_byte(0x186383, 0x01 if world.glitch_triforce or world.logic[
player] == 'nologic' else 0x00) # disable glitching to Triforce from Ganons Room
rom.write_byte(0x1800A4, 0x01 if world.glitches_required[player] != 'no_logic' else 0x00) # enable POD EG fix
rom.write_byte(0x186383, 0x01 if world.glitch_triforce or world.glitches_required[
player] == 'no_logic' else 0x00) # disable glitching to Triforce from Ganons Room
rom.write_byte(0x180042, 0x01 if world.save_and_quit_from_boss else 0x00) # Allow Save and Quit after boss kill
# remove shield from uncle
@@ -1660,8 +1662,8 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
0x4F])
# allow smith into multi-entrance caves in appropriate shuffles
if world.shuffle[player] in ['restricted', 'full', 'crossed', 'insanity', 'madness'] or (
world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'):
if world.entrance_shuffle[player] in ['restricted', 'full', 'crossed', 'insanity'] or (
world.entrance_shuffle[player] == 'simple' and world.mode[player] == 'inverted'):
rom.write_byte(0x18004C, 0x01)
# set correct flag for hera basement item
@@ -1758,8 +1760,8 @@ def write_custom_shops(rom, world, player):
if item is None:
break
if world.shop_item_slots[player] or shop.type == ShopType.TakeAny:
count_shop = (shop.region.name != 'Potion Shop' or 'w' in world.shop_shuffle[player]) and \
shop.region.name != 'Capacity Upgrade'
count_shop = (shop.region.name != 'Potion Shop' or world.include_witch_hut[player]) and \
(shop.region.name != 'Capacity Upgrade' or world.shuffle_capacity_upgrades[player])
rom.write_byte(0x186560 + shop.sram_offset + slot, 1 if count_shop else 0)
if item['item'] == 'Single Arrow' and item['player'] == 0:
arrow_mask |= 1 << index
@@ -2201,7 +2203,7 @@ def write_strings(rom, world, player):
tt.removeUnwantedText()
# Let's keep this guy's text accurate to the shuffle setting.
if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple', 'dungeonscrossed']:
if world.entrance_shuffle[player] in ['vanilla', 'dungeons_full', 'dungeons_simple', 'dungeons_crossed']:
tt['kakariko_flophouse_man_no_flippers'] = 'I really hate mowing my yard.\n{PAGEBREAK}\nI should move.'
tt['kakariko_flophouse_man'] = 'I really hate mowing my yard.\n{PAGEBREAK}\nI should move.'
@@ -2255,7 +2257,7 @@ def write_strings(rom, world, player):
entrances_to_hint.update({'Inverted Ganons Tower': 'The sealed castle door'})
else:
entrances_to_hint.update({'Ganons Tower': 'Ganon\'s Tower'})
if world.shuffle[player] in ['simple', 'restricted', 'restricted_legacy']:
if world.entrance_shuffle[player] in ['simple', 'restricted']:
for entrance in all_entrances:
if entrance.name in entrances_to_hint:
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(
@@ -2265,9 +2267,9 @@ def write_strings(rom, world, player):
break
# Now we write inconvenient locations for most shuffles and finish taking care of the less chaotic ones.
entrances_to_hint.update(InconvenientOtherEntrances)
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']:
if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']:
hint_count = 0
elif world.shuffle[player] in ['simple', 'restricted', 'restricted_legacy']:
elif world.entrance_shuffle[player] in ['simple', 'restricted']:
hint_count = 2
else:
hint_count = 4
@@ -2284,14 +2286,14 @@ def write_strings(rom, world, player):
# Next we handle hints for randomly selected other entrances,
# curating the selection intelligently based on shuffle.
if world.shuffle[player] not in ['simple', 'restricted', 'restricted_legacy']:
if world.entrance_shuffle[player] not in ['simple', 'restricted']:
entrances_to_hint.update(ConnectorEntrances)
entrances_to_hint.update(DungeonEntrances)
if world.mode[player] == 'inverted':
entrances_to_hint.update({'Inverted Agahnims Tower': 'The dark mountain tower'})
else:
entrances_to_hint.update({'Agahnims Tower': 'The sealed castle door'})
elif world.shuffle[player] == 'restricted':
elif world.entrance_shuffle[player] == 'restricted':
entrances_to_hint.update(ConnectorEntrances)
entrances_to_hint.update(OtherEntrances)
if world.mode[player] == 'inverted':
@@ -2301,15 +2303,15 @@ def write_strings(rom, world, player):
else:
entrances_to_hint.update({'Dark Sanctuary Hint': 'The dark sanctuary cave'})
entrances_to_hint.update({'Big Bomb Shop': 'The old bomb shop'})
if world.shuffle[player] in ['insanity', 'madness_legacy', 'insanity_legacy']:
if world.entrance_shuffle[player] != 'insanity':
entrances_to_hint.update(InsanityEntrances)
if world.shuffle_ganon:
if world.mode[player] == 'inverted':
entrances_to_hint.update({'Inverted Pyramid Entrance': 'The extra castle passage'})
else:
entrances_to_hint.update({'Pyramid Ledge': 'The pyramid ledge'})
hint_count = 4 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull',
'dungeonscrossed'] else 0
hint_count = 4 if world.entrance_shuffle[player] not in ['vanilla', 'dungeons_simple', 'dungeons_full',
'dungeons_crossed'] else 0
for entrance in all_entrances:
if entrance.name in entrances_to_hint:
if hint_count:
@@ -2323,11 +2325,11 @@ def write_strings(rom, world, player):
# Next we write a few hints for specific inconvenient locations. We don't make many because in entrance this is highly unpredictable.
locations_to_hint = InconvenientLocations.copy()
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']:
if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']:
locations_to_hint.extend(InconvenientVanillaLocations)
local_random.shuffle(locations_to_hint)
hint_count = 3 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull',
'dungeonscrossed'] else 5
hint_count = 3 if world.entrance_shuffle[player] not in ['vanilla', 'dungeons_simple', 'dungeons_full',
'dungeons_crossed'] else 5
for location in locations_to_hint[:hint_count]:
if location == 'Swamp Left':
if local_random.randint(0, 1):
@@ -2381,16 +2383,16 @@ def write_strings(rom, world, player):
# Lastly we write hints to show where certain interesting items are.
items_to_hint = RelevantItems.copy()
if world.smallkey_shuffle[player].hints_useful:
if world.small_key_shuffle[player].hints_useful:
items_to_hint |= item_name_groups["Small Keys"]
if world.bigkey_shuffle[player].hints_useful:
if world.big_key_shuffle[player].hints_useful:
items_to_hint |= item_name_groups["Big Keys"]
if world.hints[player] == "full":
hint_count = len(hint_locations) # fill all remaining hint locations with Item hints.
else:
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull',
'dungeonscrossed'] else 8
hint_count = 5 if world.entrance_shuffle[player] not in ['vanilla', 'dungeons_simple', 'dungeons_full',
'dungeons_crossed'] else 8
hint_count = min(hint_count, len(items_to_hint), len(hint_locations))
if hint_count:
locations = world.find_items_in_locations(items_to_hint, player, True)
@@ -2417,7 +2419,7 @@ def write_strings(rom, world, player):
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
if world.worlds[player].has_progressive_bows and (world.difficulty_requirements[player].progressive_bow_limit >= 2 or (
world.swordless[player] or world.logic[player] == 'noglitches')):
world.swordless[player] or world.glitches_required[player] == 'no_glitches')):
prog_bow_locs = world.find_item_locations('Progressive Bow', player, True)
world.per_slot_randoms[player].shuffle(prog_bow_locs)
found_bow = False
@@ -2448,7 +2450,7 @@ def write_strings(rom, world, player):
if world.goal[player] == 'bosses':
tt['sign_ganon'] = 'You need to kill all bosses, Ganon last.'
elif world.goal[player] == 'ganonpedestal':
elif world.goal[player] == 'ganon_pedestal':
tt['sign_ganon'] = 'You need to pull the pedestal to defeat Ganon.'
elif world.goal[player] == "ganon":
if world.crystals_needed_for_ganon[player] == 1:
@@ -2456,14 +2458,6 @@ def write_strings(rom, world, player):
else:
tt['sign_ganon'] = f'You need {world.crystals_needed_for_ganon[player]} crystals to beat Ganon and ' \
f'have beaten Agahnim atop Ganons Tower'
elif world.goal[player] == "icerodhunt":
tt['sign_ganon'] = 'Go find the Ice Rod and Kill Trinexx, then talk to Murahdahla... Ganon is invincible!'
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Go kill Trinexx instead.'
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\n" \
"invisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\n" \
"hidden in a hollow tree. " \
"If you bring me the Triforce piece from Turtle Rock, I can reassemble it."
else:
if world.crystals_needed_for_ganon[player] == 1:
tt['sign_ganon'] = 'You need a crystal to beat Ganon.'
@@ -2478,10 +2472,10 @@ def write_strings(rom, world, player):
tt['sahasrahla_quest_have_master_sword'] = Sahasrahla2_texts[local_random.randint(0, len(Sahasrahla2_texts) - 1)]
tt['blind_by_the_light'] = Blind_texts[local_random.randint(0, len(Blind_texts) - 1)]
if world.goal[player] in ['triforcehunt', 'localtriforcehunt', 'icerodhunt']:
if world.goal[player] in ['triforce_hunt', 'local_triforce_hunt']:
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.'
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
if world.goal[player] == 'triforcehunt' and world.players > 1:
if world.goal[player] == 'triforce_hunt' and world.players > 1:
tt['sign_ganon'] = 'Go find the Triforce pieces with your friends... Ganon is invincible!'
else:
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!'
@@ -2504,17 +2498,17 @@ def write_strings(rom, world, player):
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
if world.treasure_hunt_count[player] > 1:
if world.goal[player] == 'ganontriforcehunt' and world.players > 1:
if world.goal[player] == 'ganon_triforce_hunt' and world.players > 1:
tt['sign_ganon'] = 'You need to find %d Triforce pieces out of %d with your friends to defeat Ganon.' % \
(world.treasure_hunt_count[player], world.triforce_pieces_available[player])
elif world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']:
elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']:
tt['sign_ganon'] = 'You need to find %d Triforce pieces out of %d to defeat Ganon.' % \
(world.treasure_hunt_count[player], world.triforce_pieces_available[player])
else:
if world.goal[player] == 'ganontriforcehunt' and world.players > 1:
if world.goal[player] == 'ganon_triforce_hunt' and world.players > 1:
tt['sign_ganon'] = 'You need to find %d Triforce piece out of %d with your friends to defeat Ganon.' % \
(world.treasure_hunt_count[player], world.triforce_pieces_available[player])
elif world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']:
elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']:
tt['sign_ganon'] = 'You need to find %d Triforce piece out of %d to defeat Ganon.' % \
(world.treasure_hunt_count[player], world.triforce_pieces_available[player])
@@ -2614,12 +2608,12 @@ def set_inverted_mode(world, player, rom):
rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph proof
# the following bytes should only be written in vanilla
# or they'll overwrite the randomizer's shuffles
if world.shuffle[player] == 'vanilla':
if world.entrance_shuffle[player] == 'vanilla':
rom.write_byte(0xDBB73 + 0x23, 0x37) # switch AT and GT
rom.write_byte(0xDBB73 + 0x36, 0x24)
rom.write_int16(0x15AEE + 2 * 0x38, 0x00E0)
rom.write_int16(0x15AEE + 2 * 0x25, 0x000C)
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']:
if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']:
rom.write_byte(0x15B8C, 0x6C)
rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house
rom.write_byte(0xDBB73 + 0x52, 0x01)
@@ -2677,7 +2671,7 @@ def set_inverted_mode(world, player, rom):
rom.write_int16(snes_to_pc(0x02D9A6), 0x005A)
rom.write_byte(snes_to_pc(0x02D9B3), 0x12)
# keep the old man spawn point at old man house unless shuffle is vanilla
if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple', 'dungeonscrossed']:
if world.entrance_shuffle[player] in ['vanilla', 'dungeons_full', 'dungeons_simple', 'dungeons_crossed']:
rom.write_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01])
rom.write_int16(snes_to_pc(0x02D8DE), 0x00F1)
rom.write_bytes(snes_to_pc(0x02D910), [0x1F, 0x1E, 0x1F, 0x1F, 0x03, 0x02, 0x03, 0x03])
@@ -2740,7 +2734,7 @@ def set_inverted_mode(world, player, rom):
rom.write_int16s(snes_to_pc(0x1bb836), [0x001B, 0x001B, 0x001B])
rom.write_int16(snes_to_pc(0x308300), 0x0140) # new pyramid hole entrance
rom.write_int16(snes_to_pc(0x308320), 0x001B)
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']:
if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']:
rom.write_byte(snes_to_pc(0x308340), 0x7B)
rom.write_int16(snes_to_pc(0x1af504), 0x148B)
rom.write_int16(snes_to_pc(0x1af50c), 0x149B)
@@ -2777,10 +2771,10 @@ def set_inverted_mode(world, player, rom):
rom.write_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82])
rom.write_int16(0xDB96F + 2 * 0x35, 0x001B) # move pyramid exit door
rom.write_int16(0xDBA71 + 2 * 0x35, 0x06A4)
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']:
if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']:
rom.write_byte(0xDBB73 + 0x35, 0x36)
rom.write_byte(snes_to_pc(0x09D436), 0xF3) # remove castle gate warp
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']:
if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']:
rom.write_int16(0x15AEE + 2 * 0x37, 0x0010) # pyramid exit to new hc area
rom.write_byte(0x15B8C + 0x37, 0x1B)
rom.write_int16(0x15BDB + 2 * 0x37, 0x0418)

View File

@@ -9,25 +9,25 @@ from worlds.generic.Rules import (add_item_rule, add_rule, forbid_item,
from . import OverworldGlitchRules
from .Bosses import GanonDefeatRule
from .Items import ItemFactory, item_name_groups, item_table, progression_items
from .Options import smallkey_shuffle
from .Options import small_key_shuffle
from .OverworldGlitchRules import no_logic_rules, overworld_glitches_rules
from .Regions import LTTPRegionType, location_table
from .StateHelpers import (can_extend_magic, can_kill_most_things,
can_lift_heavy_rocks, can_lift_rocks,
can_melt_things, can_retrieve_tablet,
can_shoot_arrows, has_beam_sword, has_crystals,
has_fire_source, has_hearts,
has_fire_source, has_hearts, has_melee_weapon,
has_misery_mire_medallion, has_sword, has_turtle_rock_medallion,
has_triforce_pieces)
has_triforce_pieces, can_use_bombs, can_bomb_or_bonk)
from .UnderworldGlitchRules import underworld_glitches_rules
def set_rules(world):
player = world.player
world = world.multiworld
if world.logic[player] == 'nologic':
if world.glitches_required[player] == 'no_logic':
if player == next(player_id for player_id in world.get_game_players("A Link to the Past")
if world.logic[player_id] == 'nologic'): # only warn one time
if world.glitches_required[player_id] == 'no_logic'): # only warn one time
logging.info(
'WARNING! Seeds generated under this logic often require major glitches and may be impossible!')
@@ -45,8 +45,8 @@ def set_rules(world):
else:
world.completion_condition[player] = lambda state: state.has('Triforce', player)
global_rules(world, player)
dungeon_boss_rules(world, player)
global_rules(world, player)
if world.mode[player] != 'inverted':
default_rules(world, player)
@@ -61,24 +61,24 @@ def set_rules(world):
else:
raise NotImplementedError(f'World state {world.mode[player]} is not implemented yet')
if world.logic[player] == 'noglitches':
if world.glitches_required[player] == 'no_glitches':
no_glitches_rules(world, player)
elif world.logic[player] == 'owglitches':
elif world.glitches_required[player] == 'overworld_glitches':
# Initially setting no_glitches_rules to set the baseline rules for some
# entrances. The overworld_glitches_rules set is primarily additive.
no_glitches_rules(world, player)
fake_flipper_rules(world, player)
overworld_glitches_rules(world, player)
elif world.logic[player] in ['hybridglitches', 'nologic']:
elif world.glitches_required[player] in ['hybrid_major_glitches', 'no_logic']:
no_glitches_rules(world, player)
fake_flipper_rules(world, player)
overworld_glitches_rules(world, player)
underworld_glitches_rules(world, player)
elif world.logic[player] == 'minorglitches':
elif world.glitches_required[player] == 'minor_glitches':
no_glitches_rules(world, player)
fake_flipper_rules(world, player)
else:
raise NotImplementedError(f'Not implemented yet: Logic - {world.logic[player]}')
raise NotImplementedError(f'Not implemented yet: Logic - {world.glitches_required[player]}')
if world.goal[player] == 'bosses':
# require all bosses to beat ganon
@@ -89,7 +89,7 @@ def set_rules(world):
if world.mode[player] != 'inverted':
set_big_bomb_rules(world, player)
if world.logic[player] in {'owglitches', 'hybridglitches', 'nologic'} and world.shuffle[player] not in {'insanity', 'insanity_legacy', 'madness'}:
if world.glitches_required[player] in {'overworld_glitches', 'hybrid_major_glitches', 'no_logic'} and world.entrance_shuffle[player] not in {'insanity', 'insanity_legacy', 'madness'}:
path_to_courtyard = mirrorless_path_to_castle_courtyard(world, player)
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.multiworld.get_entrance('Dark Death Mountain Offset Mirror', player).can_reach(state) and all(rule(state) for rule in path_to_courtyard), 'or')
else:
@@ -97,18 +97,18 @@ def set_rules(world):
# if swamp and dam have not been moved we require mirror for swamp palace
# however there is mirrorless swamp in hybrid MG, so we don't necessarily want this. HMG handles this requirement itself.
if not world.swamp_patch_required[player] and world.logic[player] not in ['hybridglitches', 'nologic']:
if not world.swamp_patch_required[player] and world.glitches_required[player] not in ['hybrid_major_glitches', 'no_logic']:
add_rule(world.get_entrance('Swamp Palace Moat', player), lambda state: state.has('Magic Mirror', player))
# GT Entrance may be required for Turtle Rock for OWG and < 7 required
ganons_tower = world.get_entrance('Inverted Ganons Tower' if world.mode[player] == 'inverted' else 'Ganons Tower', player)
if world.crystals_needed_for_gt[player] == 7 and not (world.logic[player] in ['owglitches', 'hybridglitches', 'nologic'] and world.mode[player] != 'inverted'):
if world.crystals_needed_for_gt[player] == 7 and not (world.glitches_required[player] in ['overworld_glitches', 'hybrid_major_glitches', 'no_logic'] and world.mode[player] != 'inverted'):
set_rule(ganons_tower, lambda state: False)
set_trock_key_rules(world, player)
set_rule(ganons_tower, lambda state: has_crystals(state, state.multiworld.crystals_needed_for_gt[player], player))
if world.mode[player] != 'inverted' and world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
if world.mode[player] != 'inverted' and world.glitches_required[player] in ['overworld_glitches', 'hybrid_major_glitches', 'no_logic']:
add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.multiworld.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or')
set_bunny_rules(world, player, world.mode[player] == 'inverted')
@@ -139,6 +139,7 @@ def set_defeat_dungeon_boss_rule(location):
add_rule(location, lambda state: location.parent_region.dungeon.boss.can_defeat(state))
def set_always_allow(spot, rule):
spot.always_allow = rule
@@ -184,6 +185,7 @@ def dungeon_boss_rules(world, player):
for location in boss_locations:
set_defeat_dungeon_boss_rule(world.get_location(location, player))
def global_rules(world, player):
# ganon can only carry triforce
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)
@@ -213,14 +215,61 @@ def global_rules(world, player):
set_rule(world.get_location('Ether Tablet', player), lambda state: can_retrieve_tablet(state, player))
set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player))
set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith
set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith
set_rule(world.get_location('Blacksmith', player), lambda state: state.has('Return Smith', player))
set_rule(world.get_location('Magic Bat', player), lambda state: state.has('Magic Powder', player))
set_rule(world.get_location('Sick Kid', player), lambda state: state.has_group("Bottles", player))
set_rule(world.get_location('Library', player), lambda state: state.has('Pegasus Boots', player))
set_rule(world.get_location('Mimic Cave', player), lambda state: state.has('Hammer', player))
if world.enemy_shuffle[player]:
set_rule(world.get_location('Mimic Cave', player), lambda state: state.has('Hammer', player) and
can_kill_most_things(state, player, 4))
else:
set_rule(world.get_location('Mimic Cave', player), lambda state: state.has('Hammer', player)
and ((state.multiworld.enemy_health[player] in ("easy", "default") and can_use_bombs(state, player, 4))
or can_shoot_arrows(state, player) or state.has("Cane of Somaria", player)
or has_beam_sword(state, player)))
set_rule(world.get_location('Sahasrahla', player), lambda state: state.has('Green Pendant', player))
set_rule(world.get_location('Aginah\'s Cave', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Blind\'s Hideout - Top', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Chicken House', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Kakariko Well - Top', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Graveyard Cave', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Sahasrahla\'s Hut - Left', player), lambda state: can_bomb_or_bonk(state, player))
set_rule(world.get_location('Sahasrahla\'s Hut - Middle', player), lambda state: can_bomb_or_bonk(state, player))
set_rule(world.get_location('Sahasrahla\'s Hut - Right', player), lambda state: can_bomb_or_bonk(state, player))
set_rule(world.get_location('Paradox Cave Lower - Left', player), lambda state: can_use_bombs(state, player)
or has_beam_sword(state, player) or can_shoot_arrows(state, player)
or state.has_any(["Fire Rod", "Cane of Somaria"], player))
set_rule(world.get_location('Paradox Cave Lower - Right', player), lambda state: can_use_bombs(state, player)
or has_beam_sword(state, player) or can_shoot_arrows(state, player)
or state.has_any(["Fire Rod", "Cane of Somaria"], player))
set_rule(world.get_location('Paradox Cave Lower - Far Right', player), lambda state: can_use_bombs(state, player)
or has_beam_sword(state, player) or can_shoot_arrows(state, player)
or state.has_any(["Fire Rod", "Cane of Somaria"], player))
set_rule(world.get_location('Paradox Cave Lower - Middle', player), lambda state: can_use_bombs(state, player)
or has_beam_sword(state, player) or can_shoot_arrows(state, player)
or state.has_any(["Fire Rod", "Cane of Somaria"], player))
set_rule(world.get_location('Paradox Cave Lower - Far Left', player), lambda state: can_use_bombs(state, player)
or has_beam_sword(state, player) or can_shoot_arrows(state, player)
or state.has_any(["Fire Rod", "Cane of Somaria"], player))
set_rule(world.get_location('Paradox Cave Upper - Left', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Paradox Cave Upper - Right', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Mini Moldorm Cave - Far Left', player), lambda state: can_kill_most_things(state, player, 4))
set_rule(world.get_location('Mini Moldorm Cave - Left', player), lambda state: can_kill_most_things(state, player, 4))
set_rule(world.get_location('Mini Moldorm Cave - Far Right', player), lambda state: can_kill_most_things(state, player, 4))
set_rule(world.get_location('Mini Moldorm Cave - Right', player), lambda state: can_kill_most_things(state, player, 4))
set_rule(world.get_location('Mini Moldorm Cave - Generous Guy', player), lambda state: can_kill_most_things(state, player, 4))
set_rule(world.get_location('Hype Cave - Bottom', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Hype Cave - Middle Left', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Hype Cave - Middle Right', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Hype Cave - Top', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Light World Death Mountain Shop', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Two Brothers House Exit (West)', player), lambda state: can_bomb_or_bonk(state, player))
set_rule(world.get_entrance('Two Brothers House Exit (East)', player), lambda state: can_bomb_or_bonk(state, player))
set_rule(world.get_location('Spike Cave', player), lambda state:
state.has('Hammer', player) and can_lift_rocks(state, player) and
@@ -238,61 +287,81 @@ def global_rules(world, player):
set_rule(world.get_entrance('Sewers Door', player),
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4) or (
world.smallkey_shuffle[player] == smallkey_shuffle.option_universal and world.mode[
world.small_key_shuffle[player] == small_key_shuffle.option_universal and world.mode[
player] == 'standard')) # standard universal small keys cannot access the shop
set_rule(world.get_entrance('Sewers Back Door', player),
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4))
set_rule(world.get_entrance('Sewers Secret Room', player), lambda state: can_bomb_or_bonk(state, player))
set_rule(world.get_entrance('Agahnim 1', player),
lambda state: has_sword(state, player) and state._lttp_has_key('Small Key (Agahnims Tower)', player, 4))
set_rule(world.get_location('Castle Tower - Room 03', player), lambda state: can_kill_most_things(state, player, 8))
set_rule(world.get_location('Castle Tower - Room 03', player), lambda state: can_kill_most_things(state, player, 4))
set_rule(world.get_location('Castle Tower - Dark Maze', player),
lambda state: can_kill_most_things(state, player, 8) and state._lttp_has_key('Small Key (Agahnims Tower)',
lambda state: can_kill_most_things(state, player, 4) and state._lttp_has_key('Small Key (Agahnims Tower)',
player))
set_rule(world.get_location('Castle Tower - Dark Archer Key Drop', player),
lambda state: can_kill_most_things(state, player, 8) and state._lttp_has_key('Small Key (Agahnims Tower)',
lambda state: can_kill_most_things(state, player, 4) and state._lttp_has_key('Small Key (Agahnims Tower)',
player, 2))
set_rule(world.get_location('Castle Tower - Circle of Pots Key Drop', player),
lambda state: can_kill_most_things(state, player, 8) and state._lttp_has_key('Small Key (Agahnims Tower)',
lambda state: can_kill_most_things(state, player, 4) and state._lttp_has_key('Small Key (Agahnims Tower)',
player, 3))
set_always_allow(world.get_location('Eastern Palace - Big Key Chest', player),
lambda state, item: item.name == 'Big Key (Eastern Palace)' and item.player == player)
set_rule(world.get_location('Eastern Palace - Big Key Chest', player),
lambda state: state._lttp_has_key('Small Key (Eastern Palace)', player, 2) or
((location_item_name(state, 'Eastern Palace - Big Key Chest', player) == ('Big Key (Eastern Palace)', player)
and state.has('Small Key (Eastern Palace)', player))))
lambda state: can_kill_most_things(state, player, 5) and (state._lttp_has_key('Small Key (Eastern Palace)',
player, 2) or ((location_item_name(state, 'Eastern Palace - Big Key Chest', player)
== ('Big Key (Eastern Palace)', player) and state.has('Small Key (Eastern Palace)',
player)))))
set_rule(world.get_location('Eastern Palace - Dark Eyegore Key Drop', player),
lambda state: state.has('Big Key (Eastern Palace)', player))
lambda state: state.has('Big Key (Eastern Palace)', player) and can_kill_most_things(state, player, 1))
set_rule(world.get_location('Eastern Palace - Big Chest', player),
lambda state: state.has('Big Key (Eastern Palace)', player))
# not bothering to check for can_kill_most_things in the rooms leading to boss, as if you can kill a boss you should
# be able to get through these rooms
ep_boss = world.get_location('Eastern Palace - Boss', player)
set_rule(ep_boss, lambda state: state.has('Big Key (Eastern Palace)', player) and
add_rule(ep_boss, lambda state: state.has('Big Key (Eastern Palace)', player) and
state._lttp_has_key('Small Key (Eastern Palace)', player, 2) and
ep_boss.parent_region.dungeon.boss.can_defeat(state))
ep_prize = world.get_location('Eastern Palace - Prize', player)
set_rule(ep_prize, lambda state: state.has('Big Key (Eastern Palace)', player) and
add_rule(ep_prize, lambda state: state.has('Big Key (Eastern Palace)', player) and
state._lttp_has_key('Small Key (Eastern Palace)', player, 2) and
ep_prize.parent_region.dungeon.boss.can_defeat(state))
if not world.enemy_shuffle[player]:
add_rule(ep_boss, lambda state: can_shoot_arrows(state, player))
add_rule(ep_prize, lambda state: can_shoot_arrows(state, player))
# You can always kill the Stalfos' with the pots on easy/normal
if world.enemy_health[player] in ("hard", "expert") or world.enemy_shuffle[player]:
stalfos_rule = lambda state: can_kill_most_things(state, player, 4)
for location in ['Eastern Palace - Compass Chest', 'Eastern Palace - Big Chest',
'Eastern Palace - Dark Square Pot Key', 'Eastern Palace - Dark Eyegore Key Drop',
'Eastern Palace - Big Key Chest', 'Eastern Palace - Boss', 'Eastern Palace - Prize']:
add_rule(world.get_location(location, player), stalfos_rule)
set_rule(world.get_location('Desert Palace - Big Chest', player), lambda state: state.has('Big Key (Desert Palace)', player))
set_rule(world.get_location('Desert Palace - Torch', player), lambda state: state.has('Pegasus Boots', player))
set_rule(world.get_entrance('Desert Palace East Wing', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 4))
set_rule(world.get_location('Desert Palace - Big Key Chest', player), lambda state: can_kill_most_things(state, player))
set_rule(world.get_location('Desert Palace - Beamos Hall Pot Key', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 2) and can_kill_most_things(state, player))
set_rule(world.get_location('Desert Palace - Desert Tiles 2 Pot Key', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 3) and can_kill_most_things(state, player))
set_rule(world.get_location('Desert Palace - Prize', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 4) and state.has('Big Key (Desert Palace)', player) and has_fire_source(state, player) and state.multiworld.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state))
set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 4) and state.has('Big Key (Desert Palace)', player) and has_fire_source(state, player) and state.multiworld.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state))
set_rule(world.get_location('Desert Palace - Big Key Chest', player), lambda state: can_kill_most_things(state, player, 3))
set_rule(world.get_location('Desert Palace - Beamos Hall Pot Key', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 2) and can_kill_most_things(state, player, 4))
set_rule(world.get_location('Desert Palace - Desert Tiles 2 Pot Key', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 3) and can_kill_most_things(state, player, 4))
add_rule(world.get_location('Desert Palace - Prize', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 4) and state.has('Big Key (Desert Palace)', player) and has_fire_source(state, player) and state.multiworld.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state))
add_rule(world.get_location('Desert Palace - Boss', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player, 4) and state.has('Big Key (Desert Palace)', player) and has_fire_source(state, player) and state.multiworld.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state))
# logic patch to prevent placing a crystal in Desert that's required to reach the required keys
if not (world.smallkey_shuffle[player] and world.bigkey_shuffle[player]):
if not (world.small_key_shuffle[player] and world.big_key_shuffle[player]):
add_rule(world.get_location('Desert Palace - Prize', player), lambda state: state.multiworld.get_region('Desert Palace Main (Outer)', player).can_reach(state))
set_rule(world.get_entrance('Tower of Hera Small Key Door', player), lambda state: state._lttp_has_key('Small Key (Tower of Hera)', player) or location_item_name(state, 'Tower of Hera - Big Key Chest', player) == ('Small Key (Tower of Hera)', player))
set_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: state.has('Big Key (Tower of Hera)', player))
if world.enemy_shuffle[player]:
add_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: can_kill_most_things(state, player, 3))
else:
add_rule(world.get_entrance('Tower of Hera Big Key Door', player),
lambda state: (has_melee_weapon(state, player) or (state.has('Silver Bow', player)
and can_shoot_arrows(state, player)) or state.has("Cane of Byrna", player)
or state.has("Cane of Somaria", player)))
set_rule(world.get_location('Tower of Hera - Big Chest', player), lambda state: state.has('Big Key (Tower of Hera)', player))
set_rule(world.get_location('Tower of Hera - Big Key Chest', player), lambda state: has_fire_source(state, player))
if world.accessibility[player] != 'locations':
@@ -300,9 +369,13 @@ def global_rules(world, player):
set_rule(world.get_entrance('Swamp Palace Moat', player), lambda state: state.has('Flippers', player) and state.has('Open Floodgate', player))
set_rule(world.get_entrance('Swamp Palace Small Key Door', player), lambda state: state._lttp_has_key('Small Key (Swamp Palace)', player))
set_rule(world.get_location('Swamp Palace - Map Chest', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_location('Swamp Palace - Trench 1 Pot Key', player), lambda state: state._lttp_has_key('Small Key (Swamp Palace)', player, 2))
set_rule(world.get_entrance('Swamp Palace (Center)', player), lambda state: state.has('Hammer', player) and state._lttp_has_key('Small Key (Swamp Palace)', player, 3))
set_rule(world.get_location('Swamp Palace - Hookshot Pot Key', player), lambda state: state.has('Hookshot', player))
if world.pot_shuffle[player]:
# it could move the key to the top right platform which can only be reached with bombs
add_rule(world.get_location('Swamp Palace - Hookshot Pot Key', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Swamp Palace (West)', player), lambda state: state._lttp_has_key('Small Key (Swamp Palace)', player, 6)
if state.has('Hookshot', player)
else state._lttp_has_key('Small Key (Swamp Palace)', player, 4))
@@ -310,20 +383,23 @@ def global_rules(world, player):
if world.accessibility[player] != 'locations':
allow_self_locking_items(world.get_location('Swamp Palace - Big Chest', player), 'Big Key (Swamp Palace)')
set_rule(world.get_entrance('Swamp Palace (North)', player), lambda state: state.has('Hookshot', player) and state._lttp_has_key('Small Key (Swamp Palace)', player, 5))
if not world.smallkey_shuffle[player] and world.logic[player] not in ['hybridglitches', 'nologic']:
if not world.small_key_shuffle[player] and world.glitches_required[player] not in ['hybrid_major_glitches', 'no_logic']:
forbid_item(world.get_location('Swamp Palace - Entrance', player), 'Big Key (Swamp Palace)', player)
set_rule(world.get_location('Swamp Palace - Prize', player), lambda state: state._lttp_has_key('Small Key (Swamp Palace)', player, 6))
set_rule(world.get_location('Swamp Palace - Boss', player), lambda state: state._lttp_has_key('Small Key (Swamp Palace)', player, 6))
if world.pot_shuffle[player]:
# key can (and probably will) be moved behind bombable wall
set_rule(world.get_location('Swamp Palace - Waterway Pot Key', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Thieves Town Big Key Door', player), lambda state: state.has('Big Key (Thieves Town)', player))
if world.worlds[player].dungeons["Thieves Town"].boss.enemizer_name == "Blind":
set_rule(world.get_entrance('Blind Fight', player), lambda state: state._lttp_has_key('Small Key (Thieves Town)', player, 3))
set_rule(world.get_entrance('Blind Fight', player), lambda state: state._lttp_has_key('Small Key (Thieves Town)', player, 3) and can_use_bombs(state, player))
set_rule(world.get_location('Thieves\' Town - Big Chest', player),
lambda state: (state._lttp_has_key('Small Key (Thieves Town)', player, 3)) and state.has('Hammer', player))
lambda state: ((state._lttp_has_key('Small Key (Thieves Town)', player, 3)) or (location_item_name(state, 'Thieves\' Town - Big Chest', player) == ("Small Key (Thieves Town)", player)) and state._lttp_has_key('Small Key (Thieves Town)', player, 2)) and state.has('Hammer', player))
if world.accessibility[player] != 'locations':
allow_self_locking_items(world.get_location('Thieves\' Town - Big Chest', player), 'Small Key (Thieves Town)')
set_always_allow(world.get_location('Thieves\' Town - Big Chest', player), lambda state, item: item.name == 'Small Key (Thieves Town)' and item.player == player)
set_rule(world.get_location('Thieves\' Town - Attic', player), lambda state: state._lttp_has_key('Small Key (Thieves Town)', player, 3))
set_rule(world.get_location('Thieves\' Town - Spike Switch Pot Key', player),
@@ -334,7 +410,7 @@ def global_rules(world, player):
set_rule(world.get_entrance('Skull Woods First Section (Right) North Door', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 5))
set_rule(world.get_entrance('Skull Woods First Section West Door', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 5))
set_rule(world.get_entrance('Skull Woods First Section (Left) Door to Exit', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 5))
set_rule(world.get_location('Skull Woods - Big Chest', player), lambda state: state.has('Big Key (Skull Woods)', player))
set_rule(world.get_location('Skull Woods - Big Chest', player), lambda state: state.has('Big Key (Skull Woods)', player) and can_use_bombs(state, player))
if world.accessibility[player] != 'locations':
allow_self_locking_items(world.get_location('Skull Woods - Big Chest', player), 'Big Key (Skull Woods)')
set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 4) and state.has('Fire Rod', player) and has_sword(state, player)) # sword required for curtain
@@ -342,7 +418,9 @@ def global_rules(world, player):
add_rule(world.get_location('Skull Woods - Boss', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 5))
set_rule(world.get_location('Ice Palace - Jelly Key Drop', player), lambda state: can_melt_things(state, player))
set_rule(world.get_entrance('Ice Palace (Second Section)', player), lambda state: can_melt_things(state, player) and state._lttp_has_key('Small Key (Ice Palace)', player))
set_rule(world.get_location('Ice Palace - Compass Chest', player), lambda state: can_melt_things(state, player) and state._lttp_has_key('Small Key (Ice Palace)', player))
set_rule(world.get_entrance('Ice Palace (Second Section)', player), lambda state: can_melt_things(state, player) and state._lttp_has_key('Small Key (Ice Palace)', player) and can_use_bombs(state, player))
set_rule(world.get_entrance('Ice Palace (Main)', player), lambda state: state._lttp_has_key('Small Key (Ice Palace)', player, 2))
set_rule(world.get_location('Ice Palace - Big Chest', player), lambda state: state.has('Big Key (Ice Palace)', player))
set_rule(world.get_entrance('Ice Palace (Kholdstare)', player), lambda state: can_lift_rocks(state, player) and state.has('Hammer', player) and state.has('Big Key (Ice Palace)', player) and (state._lttp_has_key('Small Key (Ice Palace)', player, 6) or (state.has('Cane of Somaria', player) and state._lttp_has_key('Small Key (Ice Palace)', player, 5))))
@@ -387,16 +465,21 @@ def global_rules(world, player):
else state._lttp_has_key('Small Key (Misery Mire)', player, 6))
set_rule(world.get_location('Misery Mire - Compass Chest', player), lambda state: has_fire_source(state, player))
set_rule(world.get_location('Misery Mire - Big Key Chest', player), lambda state: has_fire_source(state, player))
set_rule(world.get_entrance('Misery Mire (Vitreous)', player), lambda state: state.has('Cane of Somaria', player))
set_rule(world.get_entrance('Misery Mire (Vitreous)', player), lambda state: state.has('Cane of Somaria', player) and can_use_bombs(state, player))
set_rule(world.get_entrance('Turtle Rock Entrance Gap', player), lambda state: state.has('Cane of Somaria', player))
set_rule(world.get_entrance('Turtle Rock Entrance Gap Reverse', player), lambda state: state.has('Cane of Somaria', player))
set_rule(world.get_location('Turtle Rock - Pokey 1 Key Drop', player), lambda state: can_kill_most_things(state, player, 5))
set_rule(world.get_location('Turtle Rock - Pokey 2 Key Drop', player), lambda state: can_kill_most_things(state, player, 5))
set_rule(world.get_location('Turtle Rock - Compass Chest', player), lambda state: state.has('Cane of Somaria', player))
set_rule(world.get_location('Turtle Rock - Roller Room - Left', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player))
set_rule(world.get_location('Turtle Rock - Roller Room - Right', player), lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player))
set_rule(world.get_location('Turtle Rock - Big Chest', player), lambda state: state.has('Big Key (Turtle Rock)', player) and (state.has('Cane of Somaria', player) or state.has('Hookshot', player)))
set_rule(world.get_entrance('Turtle Rock (Big Chest) (North)', player), lambda state: state.has('Cane of Somaria', player) or state.has('Hookshot', player))
set_rule(world.get_entrance('Turtle Rock Big Key Door', player), lambda state: state.has('Big Key (Turtle Rock)', player))
set_rule(world.get_entrance('Turtle Rock Big Key Door', player), lambda state: state.has('Big Key (Turtle Rock)', player) and can_kill_most_things(state, player, 10))
set_rule(world.get_entrance('Turtle Rock Ledge Exit (West)', player), lambda state: can_use_bombs(state, player) and can_kill_most_things(state, player, 10))
set_rule(world.get_location('Turtle Rock - Chain Chomps', player), lambda state: can_use_bombs(state, player) or can_shoot_arrows(state, player)
or has_beam_sword(state, player) or state.has_any(["Blue Boomerang", "Red Boomerang", "Hookshot", "Cane of Somaria", "Fire Rod", "Ice Rod"], player))
set_rule(world.get_entrance('Turtle Rock (Dark Room) (North)', player), lambda state: state.has('Cane of Somaria', player))
set_rule(world.get_entrance('Turtle Rock (Dark Room) (South)', player), lambda state: state.has('Cane of Somaria', player))
set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
@@ -405,16 +488,22 @@ def global_rules(world, player):
set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
set_rule(world.get_entrance('Turtle Rock (Trinexx)', player), lambda state: state._lttp_has_key('Small Key (Turtle Rock)', player, 6) and state.has('Big Key (Turtle Rock)', player) and state.has('Cane of Somaria', player))
if not world.enemy_shuffle[player]:
set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: can_shoot_arrows(state, player))
if world.enemy_shuffle[player]:
set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: can_bomb_or_bonk(state, player) and can_kill_most_things(state, player, 3))
else:
set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: can_bomb_or_bonk(state, player) and can_shoot_arrows(state, player))
set_rule(world.get_entrance('Palace of Darkness Hammer Peg Drop', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Palace of Darkness Bridge Room', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 1)) # If we can reach any other small key door, we already have back door access to this area
set_rule(world.get_entrance('Palace of Darkness Big Key Door', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 6) and state.has('Big Key (Palace of Darkness)', player) and can_shoot_arrows(state, player) and state.has('Hammer', player))
set_rule(world.get_entrance('Palace of Darkness (North)', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 4))
set_rule(world.get_location('Palace of Darkness - Big Chest', player), lambda state: state.has('Big Key (Palace of Darkness)', player))
set_rule(world.get_location('Palace of Darkness - Big Chest', player), lambda state: can_use_bombs(state, player) and state.has('Big Key (Palace of Darkness)', player))
set_rule(world.get_location('Palace of Darkness - The Arena - Ledge', player), lambda state: can_use_bombs(state, player))
if world.pot_shuffle[player]:
# chest switch may be up on ledge where bombs are required
set_rule(world.get_location('Palace of Darkness - Stalfos Basement', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 6) or (
location_item_name(state, 'Palace of Darkness - Big Key Chest', player) in [('Small Key (Palace of Darkness)', player)] and state._lttp_has_key('Small Key (Palace of Darkness)', player, 3)))
set_rule(world.get_entrance('Palace of Darkness Big Key Chest Staircase', player), lambda state: can_use_bombs(state, player) and (state._lttp_has_key('Small Key (Palace of Darkness)', player, 6) or (
location_item_name(state, 'Palace of Darkness - Big Key Chest', player) in [('Small Key (Palace of Darkness)', player)] and state._lttp_has_key('Small Key (Palace of Darkness)', player, 3))))
if world.accessibility[player] != 'locations':
set_always_allow(world.get_location('Palace of Darkness - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Palace of Darkness)' and item.player == player and state._lttp_has_key('Small Key (Palace of Darkness)', player, 5))
@@ -430,13 +519,9 @@ def global_rules(world, player):
compass_room_chests = ['Ganons Tower - Compass Room - Top Left', 'Ganons Tower - Compass Room - Top Right', 'Ganons Tower - Compass Room - Bottom Left', 'Ganons Tower - Compass Room - Bottom Right', 'Ganons Tower - Conveyor Star Pits Pot Key']
back_chests = ['Ganons Tower - Bob\'s Chest', 'Ganons Tower - Big Chest', 'Ganons Tower - Big Key Room - Left', 'Ganons Tower - Big Key Room - Right', 'Ganons Tower - Big Key Chest']
set_rule(world.get_location('Ganons Tower - Bob\'s Torch', player), lambda state: state.has('Pegasus Boots', player))
set_rule(world.get_entrance('Ganons Tower (Tile Room)', player), lambda state: state.has('Cane of Somaria', player))
set_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hammer', player) and (state.has('Hookshot', player) or state.has('Pegasus Boots', player)))
if world.pot_shuffle[player]:
# Pot Shuffle can move this check into the hookshot room
set_rule(world.get_location('Ganons Tower - Conveyor Cross Pot Key', player), lambda state: state.has('Hammer', player) and (state.has('Hookshot', player) or state.has('Pegasus Boots', player)))
set_rule(world.get_entrance('Ganons Tower (Map Room)', player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 8) or (
location_item_name(state, 'Ganons Tower - Map Chest', player) in [('Big Key (Ganons Tower)', player)] and state._lttp_has_key('Small Key (Ganons Tower)', player, 6)))
@@ -465,17 +550,17 @@ def global_rules(world, player):
item_name_in_location_names(state, 'Big Key (Ganons Tower)', player, zip(back_chests, [player] * len(back_chests))) and state._lttp_has_key('Small Key (Ganons Tower)', player, 5)))
# Actual requirements
for location in compass_room_chests:
set_rule(world.get_location(location, player), lambda state: state.has('Fire Rod', player) and (state._lttp_has_key('Small Key (Ganons Tower)', player, 7) or (
set_rule(world.get_location(location, player), lambda state: (can_use_bombs(state, player) or state.has("Cane of Somaria", player)) and state.has('Fire Rod', player) and (state._lttp_has_key('Small Key (Ganons Tower)', player, 7) or (
item_name_in_location_names(state, 'Big Key (Ganons Tower)', player, zip(compass_room_chests, [player] * len(compass_room_chests))) and state._lttp_has_key('Small Key (Ganons Tower)', player, 5))))
set_rule(world.get_location('Ganons Tower - Big Chest', player), lambda state: state.has('Big Key (Ganons Tower)', player))
set_rule(world.get_location('Ganons Tower - Big Key Room - Left', player),
lambda state: state.multiworld.get_location('Ganons Tower - Big Key Room - Left', player).parent_region.dungeon.bosses['bottom'].can_defeat(state))
lambda state: can_use_bombs(state, player) and state.multiworld.get_location('Ganons Tower - Big Key Room - Left', player).parent_region.dungeon.bosses['bottom'].can_defeat(state))
set_rule(world.get_location('Ganons Tower - Big Key Chest', player),
lambda state: state.multiworld.get_location('Ganons Tower - Big Key Chest', player).parent_region.dungeon.bosses['bottom'].can_defeat(state))
lambda state: can_use_bombs(state, player) and state.multiworld.get_location('Ganons Tower - Big Key Chest', player).parent_region.dungeon.bosses['bottom'].can_defeat(state))
set_rule(world.get_location('Ganons Tower - Big Key Room - Right', player),
lambda state: state.multiworld.get_location('Ganons Tower - Big Key Room - Right', player).parent_region.dungeon.bosses['bottom'].can_defeat(state))
lambda state: can_use_bombs(state, player) and state.multiworld.get_location('Ganons Tower - Big Key Room - Right', player).parent_region.dungeon.bosses['bottom'].can_defeat(state))
if world.enemy_shuffle[player]:
set_rule(world.get_entrance('Ganons Tower Big Key Door', player),
lambda state: state.has('Big Key (Ganons Tower)', player))
@@ -483,7 +568,8 @@ def global_rules(world, player):
set_rule(world.get_entrance('Ganons Tower Big Key Door', player),
lambda state: state.has('Big Key (Ganons Tower)', player) and can_shoot_arrows(state, player))
set_rule(world.get_entrance('Ganons Tower Torch Rooms', player),
lambda state: has_fire_source(state, player) and state.multiworld.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state))
lambda state: can_kill_most_things(state, player, 8) and has_fire_source(state, player) and state.multiworld.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state))
set_rule(world.get_location('Ganons Tower - Mini Helmasaur Key Drop', player), lambda state: can_kill_most_things(state, player, 1))
set_rule(world.get_location('Ganons Tower - Pre-Moldorm Chest', player),
lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 7))
set_rule(world.get_entrance('Ganons Tower Moldorm Door', player),
@@ -493,9 +579,9 @@ def global_rules(world, player):
set_defeat_dungeon_boss_rule(world.get_location('Agahnim 2', player))
ganon = world.get_location('Ganon', player)
set_rule(ganon, lambda state: GanonDefeatRule(state, player))
if world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']:
if world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']:
add_rule(ganon, lambda state: has_triforce_pieces(state, player))
elif world.goal[player] == 'ganonpedestal':
elif world.goal[player] == 'ganon_pedestal':
add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player))
else:
add_rule(ganon, lambda state: has_crystals(state, state.multiworld.crystals_needed_for_ganon[player], player))
@@ -507,6 +593,12 @@ def global_rules(world, player):
def default_rules(world, player):
"""Default world rules when world state is not inverted."""
# overworld requirements
set_rule(world.get_entrance('Light World Bomb Hut', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Ice Rod Cave', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has('Pegasus Boots', player))
set_rule(world.get_entrance('Kings Grave Outer Rocks', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Kings Grave Inner Rocks', player), lambda state: can_lift_heavy_rocks(state, player))
@@ -562,12 +654,12 @@ def default_rules(world, player):
set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: (state.has('Moon Pearl', player) and state.has('Flippers', player) or state.has('Magic Mirror', player))) # Overworld Bunny Revival
set_rule(world.get_location('Bombos Tablet', player), lambda state: can_retrieve_tablet(state, player))
set_rule(world.get_entrance('Dark Lake Hylia Drop (South)', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) # ToDo any fake flipper set up?
set_rule(world.get_entrance('Dark Lake Hylia Ledge Fairy', player), lambda state: state.has('Moon Pearl', player)) # bomb required
set_rule(world.get_entrance('Dark Lake Hylia Ledge Fairy', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player))
set_rule(world.get_entrance('Dark Lake Hylia Ledge Spike Cave', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Village of Outcasts Heavy Rock', player), lambda state: state.has('Moon Pearl', player) and can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Hype Cave', player), lambda state: state.has('Moon Pearl', player)) # bomb required
set_rule(world.get_entrance('Brewery', player), lambda state: state.has('Moon Pearl', player)) # bomb required
set_rule(world.get_entrance('Hype Cave', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player))
set_rule(world.get_entrance('Brewery', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player))
set_rule(world.get_entrance('Thieves Town', player), lambda state: state.has('Moon Pearl', player)) # bunny cannot pull
set_rule(world.get_entrance('Skull Woods First Section Hole (North)', player), lambda state: state.has('Moon Pearl', player)) # bunny cannot lift bush
set_rule(world.get_entrance('Skull Woods Second Section Hole', player), lambda state: state.has('Moon Pearl', player)) # bunny cannot lift bush
@@ -621,9 +713,9 @@ def inverted_rules(world, player):
# overworld requirements
set_rule(world.get_location('Maze Race', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Ice Rod Cave', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player))
set_rule(world.get_entrance('Ice Rod Cave', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player))
set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player))
set_rule(world.get_entrance('Potion Shop Pier', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Light World Pier', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has('Pegasus Boots', player) and state.has('Moon Pearl', player))
@@ -669,7 +761,7 @@ def inverted_rules(world, player):
set_rule(world.get_entrance('Bush Covered Lawn Outer Bushes', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Bomb Hut Inner Bushes', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Bomb Hut Outer Bushes', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Light World Bomb Hut', player), lambda state: state.has('Moon Pearl', player)) # need bomb
set_rule(world.get_entrance('Light World Bomb Hut', player), lambda state: state.has('Moon Pearl', player) and can_use_bombs(state, player))
set_rule(world.get_entrance('North Fairy Cave Drop', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Lost Woods Hideout Drop', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_location('Potion Shop', player), lambda state: state.has('Mushroom', player) and (state.can_reach('Potion Shop Area', 'Region', player))) # new inverted region, need pearl for bushes or access to potion shop door/waterfall fairy
@@ -715,6 +807,11 @@ def inverted_rules(world, player):
set_rule(world.get_entrance('Bumper Cave Exit (Top)', player), lambda state: state.has('Cape', player))
set_rule(world.get_entrance('Bumper Cave Exit (Bottom)', player), lambda state: state.has('Cape', player) or state.has('Hookshot', player))
set_rule(world.get_entrance('Hype Cave', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Brewery', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Dark Lake Hylia Ledge Fairy', player), lambda state: can_use_bombs(state, player))
set_rule(world.get_entrance('Skull Woods Final Section', player), lambda state: state.has('Fire Rod', player))
set_rule(world.get_entrance('Misery Mire', player), lambda state: has_sword(state, player) and has_misery_mire_medallion(state, player)) # sword required to cast magic (!)
@@ -900,20 +997,25 @@ def add_conditional_lamps(world, player):
def open_rules(world, player):
set_rule(world.get_location('Hyrule Castle - Map Guard Key Drop', player),
lambda state: can_kill_most_things(state, player, 1))
def basement_key_rule(state):
if location_item_name(state, 'Sewers - Key Rat Key Drop', player) == ("Small Key (Hyrule Castle)", player):
return state._lttp_has_key("Small Key (Hyrule Castle)", player, 2)
else:
return state._lttp_has_key("Small Key (Hyrule Castle)", player, 3)
set_rule(world.get_location('Hyrule Castle - Boomerang Guard Key Drop', player), basement_key_rule)
set_rule(world.get_location('Hyrule Castle - Boomerang Guard Key Drop', player),
lambda state: basement_key_rule(state) and can_kill_most_things(state, player, 2))
set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), basement_key_rule)
set_rule(world.get_location('Sewers - Key Rat Key Drop', player),
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 3))
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 3) and can_kill_most_things(state, player, 1))
set_rule(world.get_location('Hyrule Castle - Big Key Drop', player),
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4))
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4) and can_kill_most_things(state, player, 1))
set_rule(world.get_location('Hyrule Castle - Zelda\'s Chest', player),
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 4) and
state.has('Big Key (Hyrule Castle)', player))
@@ -924,6 +1026,7 @@ def swordless_rules(world, player):
set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 3) and state.has('Fire Rod', player)) # no curtain
set_rule(world.get_location('Ice Palace - Jelly Key Drop', player), lambda state: state.has('Fire Rod', player) or state.has('Bombos', player))
set_rule(world.get_location('Ice Palace - Compass Chest', player), lambda state: (state.has('Fire Rod', player) or state.has('Bombos', player)) and state._lttp_has_key('Small Key (Ice Palace)', player))
set_rule(world.get_entrance('Ice Palace (Second Section)', player), lambda state: (state.has('Fire Rod', player) or state.has('Bombos', player)) and state._lttp_has_key('Small Key (Ice Palace)', player))
set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has('Hammer', player)) # need to damage ganon to get tiles to drop
@@ -954,7 +1057,7 @@ def standard_rules(world, player):
set_rule(world.get_entrance('Links House S&Q', player), lambda state: state.can_reach('Sanctuary', 'Region', player))
set_rule(world.get_entrance('Sanctuary S&Q', player), lambda state: state.can_reach('Sanctuary', 'Region', player))
if world.smallkey_shuffle[player] != smallkey_shuffle.option_universal:
if world.small_key_shuffle[player] != small_key_shuffle.option_universal:
set_rule(world.get_location('Hyrule Castle - Boomerang Guard Key Drop', player),
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player, 1))
set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player),
@@ -1062,15 +1165,15 @@ def set_trock_key_rules(world, player):
return 6
# If TR is only accessible from the middle, the big key must be further restricted to prevent softlock potential
if not can_reach_front and not world.smallkey_shuffle[player]:
if not can_reach_front and not world.small_key_shuffle[player]:
# Must not go in the Big Key Chest - only 1 other chest available and 2+ keys required for all other chests
forbid_item(world.get_location('Turtle Rock - Big Key Chest', player), 'Big Key (Turtle Rock)', player)
if not can_reach_big_chest:
# Must not go in the Chain Chomps chest - only 2 other chests available and 3+ keys required for all other chests
forbid_item(world.get_location('Turtle Rock - Chain Chomps', player), 'Big Key (Turtle Rock)', player)
forbid_item(world.get_location('Turtle Rock - Pokey 2 Key Drop', player), 'Big Key (Turtle Rock)', player)
if world.accessibility[player] == 'locations' and world.goal[player] != 'icerodhunt':
if world.bigkey_shuffle[player] and can_reach_big_chest:
if world.accessibility[player] == 'locations':
if world.big_key_shuffle[player] and can_reach_big_chest:
# Must not go in the dungeon - all 3 available chests (Chomps, Big Chest, Crystaroller) must be keys to access laser bridge, and the big key is required first
for location in ['Turtle Rock - Chain Chomps', 'Turtle Rock - Compass Chest',
'Turtle Rock - Pokey 1 Key Drop', 'Turtle Rock - Pokey 2 Key Drop',
@@ -1515,8 +1618,10 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool):
# regions for the exits of multi-entrance caves/drops that bunny cannot pass
# Note spiral cave and two brothers house are passable in superbunny state for glitch logic with extra requirements.
bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)',
'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)']
bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)',
'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)',
'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid',
'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)']
bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree',
'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid',
@@ -1549,7 +1654,7 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool):
def get_rule_to_add(region, location = None, connecting_entrance = None):
# In OWG, a location can potentially be superbunny-mirror accessible or
# bunny revival accessible.
if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic']:
if world.glitches_required[player] in ['minor_glitches', 'overworld_glitches', 'hybrid_major_glitches', 'no_logic']:
if region.name == 'Swamp Palace (Entrance)': # Need to 0hp revive - not in logic
return lambda state: state.has('Moon Pearl', player)
if region.name == 'Tower of Hera (Bottom)': # Need to hit the crystal switch
@@ -1589,7 +1694,7 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool):
seen.add(new_region)
if not is_link(new_region):
# For glitch rulesets, establish superbunny and revival rules.
if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic'] and entrance.name not in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
if world.glitches_required[player] in ['minor_glitches', 'overworld_glitches', 'hybrid_major_glitches', 'no_logic'] and entrance.name not in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions():
possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has('Magic Mirror', player) and has_sword(state, player))
elif (region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions()
@@ -1626,7 +1731,7 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool):
# Add requirements for all locations that are actually in the dark world, except those available to the bunny, including dungeon revival
for entrance in world.get_entrances(player):
if is_bunny(entrance.connected_region):
if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic'] :
if world.glitches_required[player] in ['minor_glitches', 'overworld_glitches', 'hybrid_major_glitches', 'no_logic'] :
if entrance.connected_region.type == LTTPRegionType.Dungeon:
if entrance.parent_region.type != LTTPRegionType.Dungeon and entrance.connected_region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
add_rule(entrance, get_rule_to_add(entrance.connected_region, None, entrance))
@@ -1634,7 +1739,7 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool):
if entrance.connected_region.name == 'Turtle Rock (Entrance)':
add_rule(world.get_entrance('Turtle Rock Entrance Gap', player), get_rule_to_add(entrance.connected_region, None, entrance))
for location in entrance.connected_region.locations:
if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic'] and entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances():
if world.glitches_required[player] in ['minor_glitches', 'overworld_glitches', 'hybrid_major_glitches', 'no_logic'] and entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances():
continue
if location.name in bunny_accessible_locations:
continue

View File

@@ -5,11 +5,14 @@ import logging
from Utils import int16_as_bytes
from worlds.generic.Rules import add_rule
from BaseClasses import CollectionState
from .SubClasses import ALttPLocation
from .EntranceShuffle import door_addresses
from .Items import item_name_groups, item_table, ItemFactory, trap_replaceable, GetBeemizerItem
from .Options import smallkey_shuffle
from .Items import item_name_groups
from .Options import small_key_shuffle, RandomizeShopInventories
from .StateHelpers import has_hearts, can_use_bombs, can_hold_arrows
logger = logging.getLogger("Shops")
@@ -36,9 +39,9 @@ class ShopPriceType(IntEnum):
Item = 10
class Shop():
class Shop:
slots: int = 3 # slot count is not dynamic in asm, however inventory can have None as empty slots
blacklist: Set[str] = set() # items that don't work, todo: actually check against this
blacklist: Set[str] = set() # items that don't work
type = ShopType.Shop
slot_names: Dict[int, str] = {
0: " Left",
@@ -103,7 +106,7 @@ class Shop():
self.inventory = [None] * self.slots
def add_inventory(self, slot: int, item: str, price: int, max: int = 0,
replacement: Optional[str] = None, replacement_price: int = 0, create_location: bool = False,
replacement: Optional[str] = None, replacement_price: int = 0,
player: int = 0, price_type: int = ShopPriceType.Rupees,
replacement_price_type: int = ShopPriceType.Rupees):
self.inventory[slot] = {
@@ -114,33 +117,23 @@ class Shop():
'replacement': replacement,
'replacement_price': replacement_price,
'replacement_price_type': replacement_price_type,
'create_location': create_location,
'player': player
}
def push_inventory(self, slot: int, item: str, price: int, max: int = 1, player: int = 0,
price_type: int = ShopPriceType.Rupees):
if not self.inventory[slot]:
raise ValueError("Inventory can't be pushed back if it doesn't exist")
if not self.can_push_inventory(slot):
logging.warning(f'Warning, there is already an item pushed into this slot.')
self.inventory[slot] = {
'item': item,
'price': price,
'price_type': price_type,
'max': max,
'replacement': self.inventory[slot]["item"],
'replacement_price': self.inventory[slot]["price"],
'replacement_price_type': self.inventory[slot]["price_type"],
'create_location': self.inventory[slot]["create_location"],
'replacement': self.inventory[slot]["item"] if self.inventory[slot] else None,
'replacement_price': self.inventory[slot]["price"] if self.inventory[slot] else 0,
'replacement_price_type': self.inventory[slot]["price_type"] if self.inventory[slot] else ShopPriceType.Rupees,
'player': player
}
def can_push_inventory(self, slot: int):
return self.inventory[slot] and not self.inventory[slot]["replacement"]
class TakeAny(Shop):
type = ShopType.TakeAny
@@ -156,6 +149,10 @@ class UpgradeShop(Shop):
# Potions break due to VRAM flags set in UpgradeShop.
# Didn't check for more things breaking as not much else can be shuffled here currently
blacklist = item_name_groups["Potions"]
slot_names: Dict[int, str] = {
0: " Left",
1: " Right"
}
shop_class_mapping = {ShopType.UpgradeShop: UpgradeShop,
@@ -163,191 +160,84 @@ shop_class_mapping = {ShopType.UpgradeShop: UpgradeShop,
ShopType.TakeAny: TakeAny}
def FillDisabledShopSlots(world):
shop_slots: Set[ALttPLocation] = {location for shop_locations in (shop.region.locations for shop in world.shops)
for location in shop_locations
if location.shop_slot is not None and location.shop_slot_disabled}
def push_shop_inventories(multiworld):
shop_slots = [location for shop_locations in (shop.region.locations for shop in multiworld.shops if shop.type
!= ShopType.TakeAny) for location in shop_locations if location.shop_slot is not None]
for location in shop_slots:
location.shop_slot_disabled = True
shop: Shop = location.parent_region.shop
location.item = ItemFactory(shop.inventory[location.shop_slot]['item'], location.player)
location.item_rule = lambda item: item.name == location.item.name and item.player == location.player
location.locked = True
item_name = location.item.name
# Retro Bow arrows will already have been pushed
if (not multiworld.retro_bow[location.player]) or ((item_name, location.item.player)
!= ("Single Arrow", location.player)):
location.shop.push_inventory(location.shop_slot, item_name, location.shop_price,
1, location.item.player if location.item.player != location.player else 0,
location.shop_price_type)
location.shop_price = location.shop.inventory[location.shop_slot]["price"] = min(location.shop_price,
get_price(multiworld, location.shop.inventory[location.shop_slot], location.player,
location.shop_price_type)[1])
def ShopSlotFill(multiworld):
shop_slots: Set[ALttPLocation] = {location for shop_locations in
(shop.region.locations for shop in multiworld.shops if shop.type != ShopType.TakeAny)
for location in shop_locations if location.shop_slot is not None}
removed = set()
for location in shop_slots:
shop: Shop = location.parent_region.shop
if not shop.can_push_inventory(location.shop_slot) or location.shop_slot_disabled:
location.shop_slot_disabled = True
removed.add(location)
if removed:
shop_slots -= removed
if shop_slots:
logger.info("Filling LttP Shop Slots")
del shop_slots
from Fill import swap_location_item
# TODO: allow each game to register a blacklist to be used here?
blacklist_words = {"Rupee"}
blacklist_words = {item_name for item_name in item_table if any(
blacklist_word in item_name for blacklist_word in blacklist_words)}
blacklist_words.add("Bee")
locations_per_sphere = [sorted(sphere, key=lambda location: (location.name, location.player))
for sphere in multiworld.get_spheres()]
# currently special care needs to be taken so that Shop.region.locations.item is identical to Shop.inventory
# Potentially create Locations as needed and make inventory the only source, to prevent divergence
cumu_weights = []
shops_per_sphere = []
candidates_per_sphere = []
# sort spheres into piles of valid candidates and shops
for sphere in locations_per_sphere:
current_shops_slots = []
current_candidates = []
shops_per_sphere.append(current_shops_slots)
candidates_per_sphere.append(current_candidates)
for location in sphere:
if isinstance(location, ALttPLocation) and location.shop_slot is not None:
if not location.shop_slot_disabled:
current_shops_slots.append(location)
elif not location.locked and location.item.name not in blacklist_words:
current_candidates.append(location)
if cumu_weights:
x = cumu_weights[-1]
else:
x = 0
cumu_weights.append(len(current_candidates) + x)
multiworld.random.shuffle(current_candidates)
del locations_per_sphere
for i, current_shop_slots in enumerate(shops_per_sphere):
if current_shop_slots:
# getting all candidates and shuffling them feels cpu expensive, there may be a better method
candidates = [(location, i) for i, candidates in enumerate(candidates_per_sphere[i:], start=i)
for location in candidates]
multiworld.random.shuffle(candidates)
for location in current_shop_slots:
shop: Shop = location.parent_region.shop
for index, (c, swapping_sphere_id) in enumerate(candidates): # chosen item locations
if c.item_rule(location.item) and location.item_rule(c.item):
swap_location_item(c, location, check_locked=False)
logger.debug(f"Swapping {c} into {location}:: {location.item}")
# remove candidate
candidates_per_sphere[swapping_sphere_id].remove(c)
candidates.pop(index)
break
else:
# This *should* never happen. But let's fail safely just in case.
logger.warning("Ran out of ShopShuffle Item candidate locations.")
location.shop_slot_disabled = True
continue
item_name = location.item.name
if location.item.game != "A Link to the Past":
if location.item.advancement:
price = multiworld.random.randrange(8, 56)
elif location.item.useful:
price = multiworld.random.randrange(4, 28)
else:
price = multiworld.random.randrange(2, 14)
elif any(x in item_name for x in
['Compass', 'Map', 'Single Bomb', 'Single Arrow', 'Piece of Heart']):
price = multiworld.random.randrange(1, 7)
elif any(x in item_name for x in ['Arrow', 'Bomb', 'Clock']):
price = multiworld.random.randrange(2, 14)
elif any(x in item_name for x in ['Small Key', 'Heart']):
price = multiworld.random.randrange(4, 28)
else:
price = multiworld.random.randrange(8, 56)
shop.push_inventory(location.shop_slot, item_name,
min(int(price * multiworld.shop_price_modifier[location.player] / 100) * 5, 9999), 1,
location.item.player if location.item.player != location.player else 0)
if 'P' in multiworld.shop_shuffle[location.player]:
price_to_funny_price(multiworld, shop.inventory[location.shop_slot], location.player)
FillDisabledShopSlots(multiworld)
def create_shops(world, player: int):
option = world.shop_shuffle[player]
def create_shops(multiworld, player: int):
player_shop_table = shop_table.copy()
if "w" in option:
if multiworld.include_witch_hut[player]:
player_shop_table["Potion Shop"] = player_shop_table["Potion Shop"]._replace(locked=False)
dynamic_shop_slots = total_dynamic_shop_slots + 3
else:
dynamic_shop_slots = total_dynamic_shop_slots
if multiworld.shuffle_capacity_upgrades[player]:
player_shop_table["Capacity Upgrade"] = player_shop_table["Capacity Upgrade"]._replace(locked=False)
num_slots = min(dynamic_shop_slots, world.shop_item_slots[player])
num_slots = min(dynamic_shop_slots, multiworld.shop_item_slots[player])
single_purchase_slots: List[bool] = [True] * num_slots + [False] * (dynamic_shop_slots - num_slots)
world.random.shuffle(single_purchase_slots)
multiworld.random.shuffle(single_purchase_slots)
if 'g' in option or 'f' in option:
if multiworld.randomize_shop_inventories[player]:
default_shop_table = [i for l in
[shop_generation_types[x] for x in ['arrows', 'bombs', 'potions', 'shields', 'bottle'] if
not world.retro_bow[player] or x != 'arrows'] for i in l]
new_basic_shop = world.random.sample(default_shop_table, k=3)
new_dark_shop = world.random.sample(default_shop_table, k=3)
not multiworld.retro_bow[player] or x != 'arrows'] for i in l]
new_basic_shop = multiworld.random.sample(default_shop_table, k=3)
new_dark_shop = multiworld.random.sample(default_shop_table, k=3)
for name, shop in player_shop_table.items():
typ, shop_id, keeper, custom, locked, items, sram_offset = shop
if not locked:
new_items = world.random.sample(default_shop_table, k=3)
if 'f' not in option:
new_items = multiworld.random.sample(default_shop_table, k=len(items))
if multiworld.randomize_shop_inventories[player] == RandomizeShopInventories.option_randomize_by_shop_type:
if items == _basic_shop_defaults:
new_items = new_basic_shop
elif items == _dark_world_shop_defaults:
new_items = new_dark_shop
keeper = world.random.choice([0xA0, 0xC1, 0xFF])
keeper = multiworld.random.choice([0xA0, 0xC1, 0xFF])
player_shop_table[name] = ShopData(typ, shop_id, keeper, custom, locked, new_items, sram_offset)
if world.mode[player] == "inverted":
if multiworld.mode[player] == "inverted":
# make sure that blue potion is available in inverted, special case locked = None; lock when done.
player_shop_table["Dark Lake Hylia Shop"] = \
player_shop_table["Dark Lake Hylia Shop"]._replace(items=_inverted_hylia_shop_defaults, locked=None)
chance_100 = int(world.retro_bow[player]) * 0.25 + int(
world.smallkey_shuffle[player] == smallkey_shuffle.option_universal) * 0.5
for region_name, (room_id, type, shopkeeper, custom, locked, inventory, sram_offset) in player_shop_table.items():
region = world.get_region(region_name, player)
region = multiworld.get_region(region_name, player)
shop: Shop = shop_class_mapping[type](region, room_id, shopkeeper, custom, locked, sram_offset)
# special case: allow shop slots, but do not allow overwriting of base inventory behind them
if locked is None:
shop.locked = True
region.shop = shop
world.shops.append(shop)
multiworld.shops.append(shop)
for index, item in enumerate(inventory):
shop.add_inventory(index, *item)
if not locked and num_slots:
if not locked and (num_slots or type == ShopType.UpgradeShop):
slot_name = f"{region.name}{shop.slot_names[index]}"
loc = ALttPLocation(player, slot_name, address=shop_table_by_location[slot_name],
parent=region, hint_text="for sale")
loc.shop_price_type, loc.shop_price = get_price(multiworld, None, player)
loc.item_rule = lambda item, spot=loc: not any(i for i in price_blacklist[spot.shop_price_type] if i in item.name)
add_rule(loc, lambda state, spot=loc: shop_price_rules(state, player, spot))
loc.shop = shop
loc.shop_slot = index
loc.locked = True
if single_purchase_slots.pop():
if world.goal[player] != 'icerodhunt':
if world.random.random() < chance_100:
additional_item = 'Rupees (100)'
else:
additional_item = 'Rupees (50)'
else:
additional_item = GetBeemizerItem(world, player, 'Nothing')
loc.item = ItemFactory(additional_item, player)
else:
loc.item = ItemFactory(GetBeemizerItem(world, player, 'Nothing'), player)
if ((not (multiworld.shuffle_capacity_upgrades[player] and type == ShopType.UpgradeShop))
and not single_purchase_slots.pop()):
loc.shop_slot_disabled = True
shop.region.locations.append(loc)
loc.locked = True
else:
shop.region.locations.append(loc)
class ShopData(NamedTuple):
@@ -387,9 +277,10 @@ total_dynamic_shop_slots = sum(3 for shopname, data in shop_table.items() if not
SHOP_ID_START = 0x400000
shop_table_by_location_id = dict(enumerate(
(f"{name}{Shop.slot_names[num]}" for name, shop_data in
sorted(shop_table.items(), key=lambda item: item[1].sram_offset)
for num in range(3)), start=SHOP_ID_START))
(f"{name}{UpgradeShop.slot_names[num]}" if shop_data.type == ShopType.UpgradeShop else
f"{name}{Shop.slot_names[num]}" for name, shop_data in sorted(shop_table.items(),
key=lambda item: item[1].sram_offset)
for num in range(2 if shop_data.type == ShopType.UpgradeShop else 3)), start=SHOP_ID_START))
shop_table_by_location_id[(SHOP_ID_START + total_shop_slots)] = "Old Man Sword Cave"
shop_table_by_location_id[(SHOP_ID_START + total_shop_slots + 1)] = "Take-Any #1"
@@ -409,114 +300,54 @@ shop_generation_types = {
}
def set_up_shops(world, player: int):
def set_up_shops(multiworld, player: int):
# TODO: move hard+ mode changes for shields here, utilizing the new shops
if world.retro_bow[player]:
rss = world.get_region('Red Shield Shop', player).shop
if multiworld.retro_bow[player]:
rss = multiworld.get_region('Red Shield Shop', player).shop
replacement_items = [['Red Potion', 150], ['Green Potion', 75], ['Blue Potion', 200], ['Bombs (10)', 50],
['Blue Shield', 50], ['Small Heart',
10]] # Can't just replace the single arrow with 10 arrows as retro doesn't need them.
if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal:
replacement_items.append(['Small Key (Universal)', 100])
replacement_item = world.random.choice(replacement_items)
replacement_item = multiworld.random.choice(replacement_items)
rss.add_inventory(2, 'Single Arrow', 80, 1, replacement_item[0], replacement_item[1])
rss.locked = True
if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal or world.retro_bow[player]:
for shop in world.random.sample([s for s in world.shops if
s.custom and not s.locked and s.type == ShopType.Shop and s.region.player == player],
5):
if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal or multiworld.retro_bow[player]:
for shop in multiworld.random.sample([s for s in multiworld.shops if
s.custom and not s.locked and s.type == ShopType.Shop
and s.region.player == player], 5):
shop.locked = True
slots = [0, 1, 2]
world.random.shuffle(slots)
multiworld.random.shuffle(slots)
slots = iter(slots)
if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal:
shop.add_inventory(next(slots), 'Small Key (Universal)', 100)
if world.retro_bow[player]:
if multiworld.retro_bow[player]:
shop.push_inventory(next(slots), 'Single Arrow', 80)
def shuffle_shops(world, items, player: int):
option = world.shop_shuffle[player]
if 'u' in option:
progressive = world.progressive[player]
progressive = world.random.choice([True, False]) if progressive == 'grouped_random' else progressive == 'on'
progressive &= world.goal == 'icerodhunt'
new_items = ["Bomb Upgrade (+5)"] * 6
new_items.append("Bomb Upgrade (+5)" if progressive else "Bomb Upgrade (+10)")
if not world.retro_bow[player]:
new_items += ["Arrow Upgrade (+5)"] * 6
new_items.append("Arrow Upgrade (+5)" if progressive else "Arrow Upgrade (+10)")
world.random.shuffle(new_items) # Decide what gets tossed randomly if it can't insert everything.
capacityshop: Optional[Shop] = None
for shop in world.shops:
if multiworld.shuffle_capacity_upgrades[player]:
for shop in multiworld.shops:
if shop.type == ShopType.UpgradeShop and shop.region.player == player and \
shop.region.name == "Capacity Upgrade":
shop.clear_inventory()
capacityshop = shop
if world.goal[player] != 'icerodhunt':
for i, item in enumerate(items):
if item.name in trap_replaceable:
items[i] = ItemFactory(new_items.pop(), player)
if not new_items:
break
else:
logging.warning(
f"Not all upgrades put into Player{player}' item pool. Putting remaining items in Capacity Upgrade shop instead.")
bombupgrades = sum(1 for item in new_items if 'Bomb Upgrade' in item)
arrowupgrades = sum(1 for item in new_items if 'Arrow Upgrade' in item)
slots = iter(range(2))
if bombupgrades:
capacityshop.add_inventory(next(slots), 'Bomb Upgrade (+5)', 100, bombupgrades)
if arrowupgrades:
capacityshop.add_inventory(next(slots), 'Arrow Upgrade (+5)', 100, arrowupgrades)
else:
for item in new_items:
world.push_precollected(ItemFactory(item, player))
if any(setting in option for setting in 'ipP'):
if (multiworld.shuffle_shop_inventories[player] or multiworld.randomize_shop_prices[player]
or multiworld.randomize_cost_types[player]):
shops = []
upgrade_shops = []
total_inventory = []
for shop in world.shops:
for shop in multiworld.shops:
if shop.region.player == player:
if shop.type == ShopType.UpgradeShop:
upgrade_shops.append(shop)
elif shop.type == ShopType.Shop and not shop.locked:
if shop.type == ShopType.Shop and not shop.locked:
shops.append(shop)
total_inventory.extend(shop.inventory)
if 'p' in option:
def price_adjust(price: int) -> int:
# it is important that a base price of 0 always returns 0 as new price!
adjust = 2 if price < 100 else 5
return int((price / adjust) * (0.5 + world.random.random() * 1.5)) * adjust
for item in total_inventory:
item["price_type"], item["price"] = get_price(multiworld, item, player)
def adjust_item(item):
if item:
item["price"] = price_adjust(item["price"])
item['replacement_price'] = price_adjust(item["price"])
for item in total_inventory:
adjust_item(item)
for shop in upgrade_shops:
for item in shop.inventory:
adjust_item(item)
if 'P' in option:
for item in total_inventory:
price_to_funny_price(world, item, player)
# Don't apply to upgrade shops
# Upgrade shop is only one place, and will generally be too easy to
# replenish hearts and bombs
if 'i' in option:
world.random.shuffle(total_inventory)
if multiworld.shuffle_shop_inventories[player]:
multiworld.random.shuffle(total_inventory)
i = 0
for shop in shops:
@@ -539,16 +370,18 @@ price_blacklist = {
}
price_chart = {
ShopPriceType.Rupees: lambda p: p,
ShopPriceType.Hearts: lambda p: min(5, p // 5) * 8, # Each heart is 0x8 in memory, Max of 5 hearts (20 total??)
ShopPriceType.Magic: lambda p: min(15, p // 5) * 8, # Each pip is 0x8 in memory, Max of 15 pips (16 total...)
ShopPriceType.Bombs: lambda p: max(1, min(10, p // 5)), # 10 Bombs max
ShopPriceType.Arrows: lambda p: max(1, min(30, p // 5)), # 30 Arrows Max
ShopPriceType.HeartContainer: lambda p: 0x8,
ShopPriceType.BombUpgrade: lambda p: 0x1,
ShopPriceType.ArrowUpgrade: lambda p: 0x1,
ShopPriceType.Keys: lambda p: min(3, (p // 100) + 1), # Max of 3 keys for a price
ShopPriceType.Potion: lambda p: (p // 5) % 5,
ShopPriceType.Rupees: lambda p, d: p,
# Each heart is 0x8 in memory, Max of 19 hearts on easy/normal, 9 on hard, 7 on expert
ShopPriceType.Hearts: lambda p, d: max(8, min([19, 19, 9, 7][d], p // 14) * 8),
# Each pip is 0x8 in memory, Max of 15 pips (16 total)
ShopPriceType.Magic: lambda p, d: max(8, min(15, p // 18) * 8),
ShopPriceType.Bombs: lambda p, d: max(1, min(50, p // 5)), # 50 Bombs max
ShopPriceType.Arrows: lambda p, d: max(1, min(70, p // 4)), # 70 Arrows Max
ShopPriceType.HeartContainer: lambda p, d: 0x8,
ShopPriceType.BombUpgrade: lambda p, d: 0x1,
ShopPriceType.ArrowUpgrade: lambda p, d: 0x1,
ShopPriceType.Keys: lambda p, d: max(1, min(3, (p // 90) + 1)), # Max of 3 keys for a price
ShopPriceType.Potion: lambda p, d: (p // 5) % 5,
}
price_type_display_name = {
@@ -557,6 +390,8 @@ price_type_display_name = {
ShopPriceType.Bombs: "Bombs",
ShopPriceType.Arrows: "Arrows",
ShopPriceType.Keys: "Keys",
ShopPriceType.Item: "Item",
ShopPriceType.Magic: "Magic"
}
# price division
@@ -565,57 +400,74 @@ price_rate_display = {
ShopPriceType.Magic: 8,
}
# prices with no? logic requirements
simple_price_types = [
ShopPriceType.Rupees,
ShopPriceType.Hearts,
ShopPriceType.Bombs,
ShopPriceType.Arrows,
ShopPriceType.Keys
]
def get_price_modifier(item):
if item.game == "A Link to the Past":
if any(x in item.name for x in
['Compass', 'Map', 'Single Bomb', 'Single Arrow', 'Piece of Heart']):
return 0.125
elif any(x in item.name for x in
['Arrow', 'Bomb', 'Clock']) and item.name != "Bombos" and "(50)" not in item.name:
return 0.25
elif any(x in item.name for x in ['Small Key', 'Heart']):
return 0.5
else:
return 1
if item.advancement:
return 1
elif item.useful:
return 0.5
else:
return 0.25
def price_to_funny_price(world, item: dict, player: int):
"""
Converts a raw Rupee price into a special price type
"""
def get_price(multiworld, item, player: int, price_type=None):
"""Converts a raw Rupee price into a special price type"""
if price_type:
price_types = [price_type]
else:
price_types = [ShopPriceType.Rupees] # included as a chance to not change price
if multiworld.randomize_cost_types[player]:
price_types += [
ShopPriceType.Hearts,
ShopPriceType.Bombs,
ShopPriceType.Magic,
]
if multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal:
if item and item["item"] == "Small Key (Universal)":
price_types = [ShopPriceType.Rupees, ShopPriceType.Magic] # no logical requirements for repeatable keys
else:
price_types.append(ShopPriceType.Keys)
if multiworld.retro_bow[player]:
if item and item["item"] == "Single Arrow":
price_types = [ShopPriceType.Rupees, ShopPriceType.Magic] # no logical requirements for arrows
else:
price_types.append(ShopPriceType.Arrows)
diff = multiworld.item_pool[player].value
if item:
price_types = [
ShopPriceType.Rupees, # included as a chance to not change price type
ShopPriceType.Hearts,
ShopPriceType.Bombs,
]
# don't pay in universal keys to get access to universal keys
if world.smallkey_shuffle[player] == smallkey_shuffle.option_universal \
and not "Small Key (Universal)" == item['replacement']:
price_types.append(ShopPriceType.Keys)
if not world.retro_bow[player]:
price_types.append(ShopPriceType.Arrows)
world.random.shuffle(price_types)
# This is for a shop's regular inventory, the item is already determined, and we will decide the price here
price = item["price"]
if multiworld.randomize_shop_prices[player]:
adjust = 2 if price < 100 else 5
price = int((price / adjust) * (0.5 + multiworld.random.random() * 1.5)) * adjust
multiworld.random.shuffle(price_types)
for p_type in price_types:
# Ignore rupee prices
if p_type == ShopPriceType.Rupees:
return
if any(x in item['item'] for x in price_blacklist[p_type]):
continue
else:
item['price'] = min(price_chart[p_type](item['price']), 255)
item['price_type'] = p_type
break
return p_type, price_chart[p_type](price, diff)
else:
# This is an AP location and the price will be adjusted after an item is shuffled into it
p_type = multiworld.random.choice(price_types)
return p_type, price_chart[p_type](min(int(multiworld.random.randint(8, 56)
* multiworld.shop_price_modifier[player] / 100) * 5, 9999), diff)
def create_dynamic_shop_locations(world, player):
for shop in world.shops:
if shop.region.player == player:
for i, item in enumerate(shop.inventory):
if item is None:
continue
if item['create_location']:
slot_name = f"{shop.region.name}{shop.slot_names[i]}"
loc = ALttPLocation(player, slot_name,
address=shop_table_by_location[slot_name], parent=shop.region)
loc.place_locked_item(ItemFactory(item['item'], player))
if shop.type == ShopType.TakeAny:
loc.shop_slot_disabled = True
shop.region.locations.append(loc)
loc.shop_slot = i
def shop_price_rules(state: CollectionState, player: int, location: ALttPLocation):
if location.shop_price_type == ShopPriceType.Hearts:
return has_hearts(state, player, (location.shop_price / 8) + 1)
elif location.shop_price_type == ShopPriceType.Bombs:
return can_use_bombs(state, player, location.shop_price)
elif location.shop_price_type == ShopPriceType.Arrows:
return can_hold_arrows(state, player, location.shop_price)
return True

View File

@@ -10,7 +10,7 @@ def is_not_bunny(state: CollectionState, region: LTTPRegion, player: int) -> boo
def can_bomb_clip(state: CollectionState, region: LTTPRegion, player: int) -> bool:
return is_not_bunny(state, region, player) and state.has('Pegasus Boots', player)
return can_use_bombs(state, player) and is_not_bunny(state, region, player) and state.has('Pegasus Boots', player)
def can_buy_unlimited(state: CollectionState, item: str, player: int) -> bool:
@@ -83,13 +83,47 @@ def can_extend_magic(state: CollectionState, player: int, smallmagic: int = 16,
return basemagic >= smallmagic
def can_hold_arrows(state: CollectionState, player: int, quantity: int):
arrows = 30 + ((state.count("Arrow Upgrade (+5)", player) * 5) + (state.count("Arrow Upgrade (+10)", player) * 10)
+ (state.count("Bomb Upgrade (50)", player) * 50))
# Arrow Upgrade (+5) beyond the 6th gives +10
arrows += max(0, ((state.count("Arrow Upgrade (+5)", player) - 6) * 10))
return min(70, arrows) >= quantity
def can_use_bombs(state: CollectionState, player: int, quantity: int = 1) -> bool:
bombs = 0 if state.multiworld.bombless_start[player] else 10
bombs += ((state.count("Bomb Upgrade (+5)", player) * 5) + (state.count("Bomb Upgrade (+10)", player) * 10)
+ (state.count("Bomb Upgrade (50)", player) * 50))
# Bomb Upgrade (+5) beyond the 6th gives +10
bombs += max(0, ((state.count("Bomb Upgrade (+5)", player) - 6) * 10))
if (not state.multiworld.shuffle_capacity_upgrades[player]) and state.has("Capacity Upgrade Shop", player):
bombs += 40
return bombs >= min(quantity, 50)
def can_bomb_or_bonk(state: CollectionState, player: int) -> bool:
return state.has("Pegasus Boots", player) or can_use_bombs(state, player)
def can_kill_most_things(state: CollectionState, player: int, enemies: int = 5) -> bool:
return (has_melee_weapon(state, player)
or state.has('Cane of Somaria', player)
or (state.has('Cane of Byrna', player) and (enemies < 6 or can_extend_magic(state, player)))
or can_shoot_arrows(state, player)
or state.has('Fire Rod', player)
or (state.has('Bombs (10)', player) and enemies < 6))
if state.multiworld.enemy_shuffle[player]:
# I don't fully understand Enemizer's logic for placing enemies in spots where they need to be killable, if any.
# Just go with maximal requirements for now.
return (has_melee_weapon(state, player)
and state.has('Cane of Somaria', player)
and state.has('Cane of Byrna', player) and can_extend_magic(state, player)
and can_shoot_arrows(state, player)
and state.has('Fire Rod', player)
and can_use_bombs(state, player, enemies * 4))
else:
return (has_melee_weapon(state, player)
or state.has('Cane of Somaria', player)
or (state.has('Cane of Byrna', player) and (enemies < 6 or can_extend_magic(state, player)))
or can_shoot_arrows(state, player)
or state.has('Fire Rod', player)
or (state.multiworld.enemy_health[player] in ("easy", "default")
and can_use_bombs(state, player, enemies * 4)))
def can_get_good_bee(state: CollectionState, player: int) -> bool:
@@ -159,4 +193,4 @@ def can_get_glitched_speed_dw(state: CollectionState, player: int) -> bool:
rules = [state.has('Pegasus Boots', player), any([state.has('Hookshot', player), has_sword(state, player)])]
if state.multiworld.mode[player] != 'inverted':
rules.append(state.has('Moon Pearl', player))
return all(rules)
return all(rules)

View File

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

View File

@@ -42,7 +42,7 @@ def dungeon_reentry_rules(world, player, clip: Entrance, dungeon_region: str, du
fix_fake_worlds = world.fix_fake_world[player]
dungeon_entrance = [r for r in world.get_region(dungeon_region, player).entrances if r.name != clip.name][0]
if not fix_dungeon_exits: # vanilla, simple, restricted, dungeonssimple; should never have fake worlds fix
if not fix_dungeon_exits: # vanilla, simple, restricted, dungeons_simple; should never have fake worlds fix
# Dungeons are only shuffled among themselves. We need to check SW, MM, and AT because they can't be reentered trivially.
if dungeon_entrance.name == 'Skull Woods Final Section':
set_rule(clip, lambda state: False) # entrance doesn't exist until you fire rod it from the other side
@@ -52,12 +52,12 @@ def dungeon_reentry_rules(world, player, clip: Entrance, dungeon_region: str, du
add_rule(clip, lambda state: state.has('Cape', player) or has_beam_sword(state, player) or state.has('Beat Agahnim 1', player)) # kill/bypass barrier
# Then we set a restriction on exiting the dungeon, so you can't leave unless you got in normally.
add_rule(world.get_entrance(dungeon_exit, player), lambda state: dungeon_entrance.can_reach(state))
elif not fix_fake_worlds: # full, dungeonsfull; fixed dungeon exits, but no fake worlds fix
elif not fix_fake_worlds: # full, dungeons_full; fixed dungeon exits, but no fake worlds fix
# Entry requires the entrance's requirements plus a fake pearl, but you don't gain logical access to the surrounding region.
add_rule(clip, lambda state: dungeon_entrance.access_rule(fake_pearl_state(state, player)))
# exiting restriction
add_rule(world.get_entrance(dungeon_exit, player), lambda state: dungeon_entrance.can_reach(state))
# Otherwise, the shuffle type is crossed, dungeonscrossed, or insanity; all of these do not need additional rules on where we can go,
# Otherwise, the shuffle type is crossed, dungeons_crossed, or insanity; all of these do not need additional rules on where we can go,
# since the clip links directly to the exterior region.
@@ -93,7 +93,7 @@ def underworld_glitches_rules(world, player):
# We need to be able to s+q to old man, then go to either Mire or Hera at either Hera or GT.
# First we require a certain type of entrance shuffle, then build the rule from its pieces.
if not world.swamp_patch_required[player]:
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed']:
if world.entrance_shuffle[player] in ['vanilla', 'dungeons_simple', 'dungeons_full', 'dungeons_crossed']:
rule_map = {
'Misery Mire (Entrance)': (lambda state: True),
'Tower of Hera (Bottom)': (lambda state: state.can_reach('Tower of Hera Big Key Door', 'Entrance', player))

View File

@@ -13,14 +13,14 @@ from .EntranceShuffle import link_entrances, link_inverted_entrances, plando_con
from .InvertedRegions import create_inverted_regions, mark_dark_world_regions
from .ItemPool import generate_itempool, difficulties
from .Items import item_init_table, item_name_groups, item_table, GetBeemizerItem
from .Options import alttp_options, smallkey_shuffle
from .Options import alttp_options, small_key_shuffle
from .Regions import lookup_name_to_id, create_regions, mark_light_world_regions, lookup_vanilla_location_to_entrance, \
is_main_entrance, key_drop_data
from .Client import ALTTPSNIClient
from .Rom import LocalRom, patch_rom, patch_race_rom, check_enemizer, patch_enemizer, apply_rom_settings, \
get_hash_string, get_base_rom_path, LttPDeltaPatch
from .Rules import set_rules
from .Shops import create_shops, Shop, ShopSlotFill, ShopType, price_rate_display, price_type_display_name
from .Shops import create_shops, Shop, push_shop_inventories, ShopType, price_rate_display, price_type_display_name
from .SubClasses import ALttPItem, LTTPRegionType
from worlds.AutoWorld import World, WebWorld, LogicMixin
from .StateHelpers import can_buy_unlimited
@@ -42,7 +42,7 @@ class ALTTPSettings(settings.Group):
class ALTTPWeb(WebWorld):
setup_en = Tutorial(
"Multiworld Setup Tutorial",
"Multiworld Setup Guide",
"A guide to setting up the Archipelago ALttP Software on your computer. This guide covers single-player, multiworld, and related software.",
"English",
"multiworld_en.md",
@@ -78,7 +78,7 @@ class ALTTPWeb(WebWorld):
)
msu = Tutorial(
"MSU-1 Setup Tutorial",
"MSU-1 Setup Guide",
"A guide to setting up MSU-1, which allows for custom in-game music.",
"English",
"msu1_en.md",
@@ -105,7 +105,7 @@ class ALTTPWeb(WebWorld):
)
plando = Tutorial(
"Plando Tutorial",
"Plando Guide",
"A guide to creating Multiworld Plandos with LTTP",
"English",
"plando_en.md",
@@ -213,7 +213,7 @@ class ALTTPWorld(World):
item_name_to_id = {name: data.item_code for name, data in item_table.items() if type(data.item_code) == int}
location_name_to_id = lookup_name_to_id
data_version = 8
data_version = 9
required_client_version = (0, 4, 1)
web = ALTTPWeb()
@@ -290,33 +290,34 @@ class ALTTPWorld(World):
self.pyramid_fairy_bottle_fill = self.random.choice(bottle_options)
if multiworld.mode[player] == 'standard':
if multiworld.smallkey_shuffle[player]:
if (multiworld.smallkey_shuffle[player] not in
(smallkey_shuffle.option_universal, smallkey_shuffle.option_own_dungeons,
smallkey_shuffle.option_start_with)):
if multiworld.small_key_shuffle[player]:
if (multiworld.small_key_shuffle[player] not in
(small_key_shuffle.option_universal, small_key_shuffle.option_own_dungeons,
small_key_shuffle.option_start_with)):
self.multiworld.local_early_items[self.player]["Small Key (Hyrule Castle)"] = 1
self.multiworld.local_items[self.player].value.add("Small Key (Hyrule Castle)")
self.multiworld.non_local_items[self.player].value.discard("Small Key (Hyrule Castle)")
if multiworld.bigkey_shuffle[player]:
if multiworld.big_key_shuffle[player]:
self.multiworld.local_items[self.player].value.add("Big Key (Hyrule Castle)")
self.multiworld.non_local_items[self.player].value.discard("Big Key (Hyrule Castle)")
# system for sharing ER layouts
self.er_seed = str(multiworld.random.randint(0, 2 ** 64))
if "-" in multiworld.shuffle[player]:
shuffle, seed = multiworld.shuffle[player].split("-", 1)
multiworld.shuffle[player] = shuffle
if multiworld.entrance_shuffle[player] != "vanilla" and multiworld.entrance_shuffle_seed[player] != "random":
shuffle = multiworld.entrance_shuffle[player].current_key
if shuffle == "vanilla":
self.er_seed = "vanilla"
elif seed.startswith("group-") or multiworld.is_race:
elif (not multiworld.entrance_shuffle_seed[player].value.isdigit()) or multiworld.is_race:
self.er_seed = get_same_seed(multiworld, (
shuffle, seed, multiworld.retro_caves[player], multiworld.mode[player], multiworld.logic[player]))
shuffle, multiworld.entrance_shuffle_seed[player].value, multiworld.retro_caves[player], multiworld.mode[player],
multiworld.glitches_required[player]))
else: # not a race or group seed, use set seed as is.
self.er_seed = seed
elif multiworld.shuffle[player] == "vanilla":
self.er_seed = int(multiworld.entrance_shuffle_seed[player].value)
elif multiworld.entrance_shuffle[player] == "vanilla":
self.er_seed = "vanilla"
for dungeon_item in ["smallkey_shuffle", "bigkey_shuffle", "compass_shuffle", "map_shuffle"]:
for dungeon_item in ["small_key_shuffle", "big_key_shuffle", "compass_shuffle", "map_shuffle"]:
option = getattr(multiworld, dungeon_item)[player]
if option == "own_world":
multiworld.local_items[player].value |= self.item_name_groups[option.item_name_group]
@@ -329,10 +330,10 @@ class ALTTPWorld(World):
if option == "original_dungeon":
self.dungeon_specific_item_names |= self.item_name_groups[option.item_name_group]
multiworld.difficulty_requirements[player] = difficulties[multiworld.difficulty[player]]
multiworld.difficulty_requirements[player] = difficulties[multiworld.item_pool[player].current_key]
# enforce pre-defined local items.
if multiworld.goal[player] in ["localtriforcehunt", "localganontriforcehunt"]:
if multiworld.goal[player] in ["local_triforce_hunt", "local_ganon_triforce_hunt"]:
multiworld.local_items[player].value.add('Triforce Piece')
# Not possible to place crystals outside boss prizes yet (might as well make it consistent with pendants too).
@@ -345,9 +346,6 @@ class ALTTPWorld(World):
player = self.player
world = self.multiworld
world.triforce_pieces_available[player] = max(world.triforce_pieces_available[player],
world.triforce_pieces_required[player])
if world.mode[player] != 'inverted':
create_regions(world, player)
else:
@@ -355,8 +353,8 @@ class ALTTPWorld(World):
create_shops(world, player)
self.create_dungeons()
if world.logic[player] not in ["noglitches", "minorglitches"] and world.shuffle[player] in \
{"vanilla", "dungeonssimple", "dungeonsfull", "simple", "restricted", "full"}:
if world.glitches_required[player] not in ["no_glitches", "minor_glitches"] and world.entrance_shuffle[player] in \
{"vanilla", "dungeons_simple", "dungeons_full", "simple", "restricted", "full"}:
world.fix_fake_world[player] = False
# seeded entrance shuffle
@@ -455,7 +453,7 @@ class ALTTPWorld(World):
if state.has('Silver Bow', item.player):
return
elif state.has('Bow', item.player) and (self.multiworld.difficulty_requirements[item.player].progressive_bow_limit >= 2
or self.multiworld.logic[item.player] == 'noglitches'
or self.multiworld.glitches_required[item.player] == 'no_glitches'
or self.multiworld.swordless[item.player]): # modes where silver bow is always required for ganon
return 'Silver Bow'
elif self.multiworld.difficulty_requirements[item.player].progressive_bow_limit >= 1:
@@ -499,9 +497,9 @@ class ALTTPWorld(World):
break
else:
raise FillError('Unable to place dungeon prizes')
if world.mode[player] == 'standard' and world.smallkey_shuffle[player] \
and world.smallkey_shuffle[player] != smallkey_shuffle.option_universal and \
world.smallkey_shuffle[player] != smallkey_shuffle.option_own_dungeons:
if world.mode[player] == 'standard' and world.small_key_shuffle[player] \
and world.small_key_shuffle[player] != small_key_shuffle.option_universal and \
world.small_key_shuffle[player] != small_key_shuffle.option_own_dungeons:
world.local_early_items[player]["Small Key (Hyrule Castle)"] = 1
@classmethod
@@ -509,10 +507,9 @@ class ALTTPWorld(World):
from .Dungeons import fill_dungeons_restrictive
fill_dungeons_restrictive(world)
@classmethod
def stage_post_fill(cls, world):
ShopSlotFill(world)
push_shop_inventories(world)
@property
def use_enemizer(self) -> bool:
@@ -579,7 +576,7 @@ class ALTTPWorld(World):
@classmethod
def stage_extend_hint_information(cls, world, hint_data: typing.Dict[int, typing.Dict[int, str]]):
er_hint_data = {player: {} for player in world.get_game_players("A Link to the Past") if
world.shuffle[player] != "vanilla" or world.retro_caves[player]}
world.entrance_shuffle[player] != "vanilla" or world.retro_caves[player]}
for region in world.regions:
if region.player in er_hint_data and region.locations:
@@ -645,9 +642,9 @@ class ALTTPWorld(World):
trash_counts = {}
for player in world.get_game_players("A Link to the Past"):
if not world.ganonstower_vanilla[player] or \
world.logic[player] in {'owglitches', 'hybridglitches', "nologic"}:
world.glitches_required[player] in {'overworld_glitches', 'hybrid_major_glitches', "no_logic"}:
pass
elif 'triforcehunt' in world.goal[player] and ('local' in world.goal[player] or world.players == 1):
elif 'triforce_hunt' in world.goal[player].current_key and ('local' in world.goal[player].current_key or world.players == 1):
trash_counts[player] = world.random.randint(world.crystals_needed_for_gt[player] * 2,
world.crystals_needed_for_gt[player] * 4)
else:
@@ -681,35 +678,6 @@ class ALTTPWorld(World):
return variable
return "Yes" if variable else "No"
spoiler_handle.write('Logic: %s\n' % self.multiworld.logic[self.player])
spoiler_handle.write('Dark Room Logic: %s\n' % self.multiworld.dark_room_logic[self.player])
spoiler_handle.write('Mode: %s\n' % self.multiworld.mode[self.player])
spoiler_handle.write('Goal: %s\n' % self.multiworld.goal[self.player])
if "triforce" in self.multiworld.goal[self.player]: # triforce hunt
spoiler_handle.write("Pieces available for Triforce: %s\n" %
self.multiworld.triforce_pieces_available[self.player])
spoiler_handle.write("Pieces required for Triforce: %s\n" %
self.multiworld.triforce_pieces_required[self.player])
spoiler_handle.write('Difficulty: %s\n' % self.multiworld.difficulty[self.player])
spoiler_handle.write('Item Functionality: %s\n' % self.multiworld.item_functionality[self.player])
spoiler_handle.write('Entrance Shuffle: %s\n' % self.multiworld.shuffle[self.player])
if self.multiworld.shuffle[self.player] != "vanilla":
spoiler_handle.write('Entrance Shuffle Seed %s\n' % self.er_seed)
spoiler_handle.write('Shop inventory shuffle: %s\n' %
bool_to_text("i" in self.multiworld.shop_shuffle[self.player]))
spoiler_handle.write('Shop price shuffle: %s\n' %
bool_to_text("p" in self.multiworld.shop_shuffle[self.player]))
spoiler_handle.write('Shop upgrade shuffle: %s\n' %
bool_to_text("u" in self.multiworld.shop_shuffle[self.player]))
spoiler_handle.write('New Shop inventory: %s\n' %
bool_to_text("g" in self.multiworld.shop_shuffle[self.player] or
"f" in self.multiworld.shop_shuffle[self.player]))
spoiler_handle.write('Custom Potion Shop: %s\n' %
bool_to_text("w" in self.multiworld.shop_shuffle[self.player]))
spoiler_handle.write('Enemy health: %s\n' % self.multiworld.enemy_health[self.player])
spoiler_handle.write('Enemy damage: %s\n' % self.multiworld.enemy_damage[self.player])
spoiler_handle.write('Prize shuffle %s\n' % self.multiworld.shuffle_prizes[self.player])
def write_spoiler(self, spoiler_handle: typing.TextIO) -> None:
player_name = self.multiworld.get_player_name(self.player)
spoiler_handle.write("\n\nMedallions:\n")
@@ -783,7 +751,7 @@ class ALTTPWorld(World):
if item["replacement"] is None:
continue
shop_data["item_{}".format(index)] +=\
f", {item['replacement']} - {item['replacement_price']}" \
f", {item['replacement']} - {item['replacement_price'] // price_rate_display.get(item['replacement_price_type'], 1)}" \
f" {price_type_display_name[item['replacement_price_type']]}"
return shop_data
@@ -796,10 +764,7 @@ class ALTTPWorld(World):
item)))
def get_filler_item_name(self) -> str:
if self.multiworld.goal[self.player] == "icerodhunt":
item = "Nothing"
else:
item = self.multiworld.random.choice(extras_list)
item = self.multiworld.random.choice(extras_list)
return GetBeemizerItem(self.multiworld, self.player, item)
def get_pre_fill_items(self):
@@ -819,20 +784,20 @@ class ALTTPWorld(World):
# for convenient auto-tracking of the generated settings and adjusting the tracker accordingly
slot_options = ["crystals_needed_for_gt", "crystals_needed_for_ganon", "open_pyramid",
"bigkey_shuffle", "smallkey_shuffle", "compass_shuffle", "map_shuffle",
"big_key_shuffle", "small_key_shuffle", "compass_shuffle", "map_shuffle",
"progressive", "swordless", "retro_bow", "retro_caves", "shop_item_slots",
"boss_shuffle", "pot_shuffle", "enemy_shuffle", "key_drop_shuffle"]
"boss_shuffle", "pot_shuffle", "enemy_shuffle", "key_drop_shuffle", "bombless_start",
"randomize_shop_inventories", "shuffle_shop_inventories", "shuffle_capacity_upgrades",
"entrance_shuffle", "dark_room_logic", "goal", "mode",
"triforce_pieces_mode", "triforce_pieces_percentage", "triforce_pieces_required",
"triforce_pieces_available", "triforce_pieces_extra",
]
slot_data = {option_name: getattr(self.multiworld, option_name)[self.player].value for option_name in slot_options}
slot_data.update({
'mode': self.multiworld.mode[self.player],
'goal': self.multiworld.goal[self.player],
'dark_room_logic': self.multiworld.dark_room_logic[self.player],
'mm_medalion': self.multiworld.required_medallions[self.player][0],
'tr_medalion': self.multiworld.required_medallions[self.player][1],
'shop_shuffle': self.multiworld.shop_shuffle[self.player],
'entrance_shuffle': self.multiworld.shuffle[self.player],
}
)
return slot_data
@@ -849,8 +814,8 @@ def get_same_seed(world, seed_def: tuple) -> str:
class ALttPLogic(LogicMixin):
def _lttp_has_key(self, item, player, count: int = 1):
if self.multiworld.logic[player] == 'nologic':
if self.multiworld.glitches_required[player] == 'no_logic':
return True
if self.multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
if self.multiworld.small_key_shuffle[player] == small_key_shuffle.option_universal:
return can_buy_unlimited(self, 'Small Key (Universal)', player)
return self.prog_items[player][item] >= count

View File

@@ -7,30 +7,30 @@ class TestAgahnimsTower(TestDungeon):
self.starting_regions = ['Agahnims Tower']
self.run_tests([
["Castle Tower - Room 03", False, []],
["Castle Tower - Room 03", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Room 03", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Room 03", True, ['Progressive Sword']],
["Castle Tower - Dark Maze", False, []],
["Castle Tower - Dark Maze", False, [], ['Small Key (Agahnims Tower)']],
["Castle Tower - Dark Maze", False, [], ['Lamp']],
["Castle Tower - Dark Maze", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Dark Maze", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Dark Maze", True, ['Progressive Sword', 'Small Key (Agahnims Tower)', 'Lamp']],
["Castle Tower - Dark Archer Key Drop", False, []],
["Castle Tower - Dark Archer Key Drop", False, ['Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)']],
["Castle Tower - Dark Archer Key Drop", False, [], ['Lamp']],
["Castle Tower - Dark Archer Key Drop", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Dark Archer Key Drop", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Dark Archer Key Drop", True, ['Progressive Sword', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Lamp']],
["Castle Tower - Circle of Pots Key Drop", False, []],
["Castle Tower - Circle of Pots Key Drop", False, ['Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)']],
["Castle Tower - Circle of Pots Key Drop", False, ['Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)']],
["Castle Tower - Circle of Pots Key Drop", False, [], ['Lamp']],
["Castle Tower - Circle of Pots Key Drop", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Circle of Pots Key Drop", True, ['Progressive Sword', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Lamp']],
["Castle Tower - Circle of Pots Key Drop", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Circle of Pots Key Drop", True, ['Progressive Sword', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Lamp']],
["Agahnim 1", False, []],
["Agahnim 1", False, ['Small Key (Agahnims Tower)'], ['Small Key (Agahnims Tower)']],
["Agahnim 1", False, ['Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)']],
["Agahnim 1", False, [], ['Progressive Sword']],
["Agahnim 1", False, [], ['Lamp']],
["Agahnim 1", True, ['Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Lamp', 'Progressive Sword']],
["Agahnim 1", True, ['Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)', 'Lamp', 'Progressive Sword']],
])

View File

@@ -11,29 +11,37 @@ class TestDarkPalace(TestDungeon):
["Palace of Darkness - The Arena - Ledge", False, []],
["Palace of Darkness - The Arena - Ledge", False, [], ['Progressive Bow']],
["Palace of Darkness - The Arena - Ledge", True, ['Progressive Bow']],
["Palace of Darkness - The Arena - Ledge", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Palace of Darkness - The Arena - Ledge", True, ['Progressive Bow', 'Bomb Upgrade (+5)']],
["Palace of Darkness - Map Chest", False, []],
["Palace of Darkness - Map Chest", False, [], ['Progressive Bow']],
["Palace of Darkness - Map Chest", True, ['Progressive Bow']],
["Palace of Darkness - Map Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Palace of Darkness - Map Chest", True, ['Progressive Bow', 'Bomb Upgrade (+5)']],
["Palace of Darkness - Map Chest", True, ['Progressive Bow', 'Pegasus Boots']],
#Lower requirement for self-locking key
#No lower requirement when bow/hammer is out of logic
["Palace of Darkness - Big Key Chest", False, []],
["Palace of Darkness - Big Key Chest", False, [key]*5, [key]],
["Palace of Darkness - Big Key Chest", True, [key]*6],
["Palace of Darkness - Big Key Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Palace of Darkness - Big Key Chest", True, [key]*6 + ['Bomb Upgrade (+5)']],
["Palace of Darkness - The Arena - Bridge", False, []],
["Palace of Darkness - The Arena - Bridge", False, [], [key, 'Progressive Bow']],
["Palace of Darkness - The Arena - Bridge", False, [], [key, 'Hammer']],
["Palace of Darkness - The Arena - Bridge", False, [], [key, 'Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Palace of Darkness - The Arena - Bridge", True, [key]],
["Palace of Darkness - The Arena - Bridge", True, ['Progressive Bow', 'Hammer']],
["Palace of Darkness - The Arena - Bridge", True, ['Progressive Bow', 'Hammer', 'Bomb Upgrade (+5)']],
["Palace of Darkness - The Arena - Bridge", True, ['Progressive Bow', 'Hammer', 'Pegasus Boots']],
["Palace of Darkness - Stalfos Basement", False, []],
["Palace of Darkness - Stalfos Basement", False, [], [key, 'Progressive Bow']],
["Palace of Darkness - Stalfos Basement", False, [], [key, 'Hammer']],
["Palace of Darkness - Stalfos Basement", False, [], [key, 'Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Palace of Darkness - Stalfos Basement", True, [key]],
["Palace of Darkness - Stalfos Basement", True, ['Progressive Bow', 'Hammer']],
["Palace of Darkness - Stalfos Basement", True, ['Progressive Bow', 'Hammer', 'Bomb Upgrade (+5)']],
["Palace of Darkness - Stalfos Basement", True, ['Progressive Bow', 'Hammer', 'Pegasus Boots']],
["Palace of Darkness - Compass Chest", False, []],
["Palace of Darkness - Compass Chest", False, [key]*3, [key]],
@@ -67,8 +75,9 @@ class TestDarkPalace(TestDungeon):
["Palace of Darkness - Big Chest", False, []],
["Palace of Darkness - Big Chest", False, [], ['Lamp']],
["Palace of Darkness - Big Chest", False, [], ['Big Key (Palace of Darkness)']],
["Palace of Darkness - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Palace of Darkness - Big Chest", False, [key]*5, [key]],
["Palace of Darkness - Big Chest", True, ['Lamp', 'Big Key (Palace of Darkness)'] + [key]*6],
["Palace of Darkness - Big Chest", True, ['Bomb Upgrade (+5)', 'Lamp', 'Big Key (Palace of Darkness)'] + [key]*6],
["Palace of Darkness - Boss", False, []],
["Palace of Darkness - Boss", False, [], ['Lamp']],

View File

@@ -19,35 +19,35 @@ class TestDesertPalace(TestDungeon):
["Desert Palace - Compass Chest", False, []],
["Desert Palace - Compass Chest", False, [], ['Small Key (Desert Palace)']],
["Desert Palace - Compass Chest", False, ['Progressive Sword', 'Hammer', 'Fire Rod', 'Ice Rod', 'Progressive Bow', 'Cane of Somaria', 'Cane of Byrna']],
["Desert Palace - Compass Chest", False, ['Small Key (Desert Palace)']],
["Desert Palace - Compass Chest", True, ['Progressive Sword', 'Small Key (Desert Palace)']],
["Desert Palace - Compass Chest", True, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)']],
["Desert Palace - Compass Chest", True, ['Progressive Sword', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)']],
["Desert Palace - Big Key Chest", False, []],
["Desert Palace - Big Key Chest", False, [], ['Small Key (Desert Palace)']],
["Desert Palace - Big Key Chest", False, ['Progressive Sword', 'Hammer', 'Fire Rod', 'Ice Rod', 'Progressive Bow', 'Cane of Somaria', 'Cane of Byrna']],
["Desert Palace - Big Key Chest", False, ['Small Key (Desert Palace)']],
["Desert Palace - Big Key Chest", True, ['Progressive Sword', 'Small Key (Desert Palace)']],
["Desert Palace - Big Key Chest", False, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)']],
["Desert Palace - Big Key Chest", True, ['Progressive Sword', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)']],
["Desert Palace - Desert Tiles 1 Pot Key", True, []],
["Desert Palace - Beamos Hall Pot Key", False, []],
["Desert Palace - Beamos Hall Pot Key", False, [], ['Small Key (Desert Palace)']],
["Desert Palace - Beamos Hall Pot Key", False, ['Small Key (Desert Palace)']],
["Desert Palace - Beamos Hall Pot Key", False, ['Progressive Sword', 'Hammer', 'Fire Rod', 'Ice Rod', 'Progressive Bow', 'Cane of Somaria', 'Cane of Byrna']],
["Desert Palace - Beamos Hall Pot Key", True, ['Small Key (Desert Palace)', 'Progressive Sword']],
["Desert Palace - Beamos Hall Pot Key", True, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Progressive Sword']],
["Desert Palace - Desert Tiles 2 Pot Key", False, []],
["Desert Palace - Desert Tiles 2 Pot Key", False, ['Small Key (Desert Palace)']],
["Desert Palace - Desert Tiles 2 Pot Key", False, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)']],
["Desert Palace - Desert Tiles 2 Pot Key", False, ['Progressive Sword', 'Hammer', 'Fire Rod', 'Ice Rod', 'Progressive Bow', 'Cane of Somaria', 'Cane of Byrna']],
["Desert Palace - Desert Tiles 2 Pot Key", True, ['Small Key (Desert Palace)', 'Progressive Sword']],
["Desert Palace - Desert Tiles 2 Pot Key", True, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Progressive Sword']],
["Desert Palace - Boss", False, []],
["Desert Palace - Boss", False, [], ['Small Key (Desert Palace)']],
["Desert Palace - Boss", False, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)']],
["Desert Palace - Boss", False, [], ['Big Key (Desert Palace)']],
["Desert Palace - Boss", False, [], ['Lamp', 'Fire Rod']],
["Desert Palace - Boss", False, [], ['Progressive Sword', 'Hammer', 'Fire Rod', 'Ice Rod', 'Progressive Bow', 'Cane of Somaria', 'Cane of Byrna']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Fire Rod']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Lamp', 'Progressive Sword']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Lamp', 'Hammer']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Lamp', 'Cane of Somaria']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Lamp', 'Cane of Byrna']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Fire Rod']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Lamp', 'Progressive Sword']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Lamp', 'Hammer']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Lamp', 'Cane of Somaria']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Lamp', 'Cane of Byrna']],
])

View File

@@ -14,6 +14,8 @@ class TestDungeon(LTTPTestBase):
self.starting_regions = [] # Where to start exploring
self.remove_exits = [] # Block dungeon exits
self.multiworld.difficulty_requirements[1] = difficulties['normal']
self.multiworld.bombless_start[1].value = True
self.multiworld.shuffle_capacity_upgrades[1].value = True
create_regions(self.multiworld, 1)
self.multiworld.worlds[1].create_dungeons()
create_shops(self.multiworld, 1)

View File

@@ -18,13 +18,13 @@ class TestEasternPalace(TestDungeon):
["Eastern Palace - Big Key Chest", False, []],
["Eastern Palace - Big Key Chest", False, [], ['Lamp']],
["Eastern Palace - Big Key Chest", True, ['Lamp', 'Small Key (Eastern Palace)', 'Small Key (Eastern Palace)']],
["Eastern Palace - Big Key Chest", True, ['Lamp', 'Big Key (Eastern Palace)']],
["Eastern Palace - Big Key Chest", True, ['Lamp', 'Small Key (Eastern Palace)', 'Small Key (Eastern Palace)', 'Progressive Sword']],
#@todo: Advanced?
["Eastern Palace - Boss", False, []],
["Eastern Palace - Boss", False, [], ['Lamp']],
["Eastern Palace - Boss", False, [], ['Progressive Bow']],
["Eastern Palace - Boss", False, [], ['Big Key (Eastern Palace)']],
["Eastern Palace - Boss", True, ['Lamp', 'Progressive Bow', 'Big Key (Eastern Palace)']]
["Eastern Palace - Boss", False, ['Small Key (Eastern Palace)', 'Small Key (Eastern Palace)']],
["Eastern Palace - Boss", True, ['Lamp', 'Small Key (Eastern Palace)', 'Small Key (Eastern Palace)', 'Progressive Bow', 'Big Key (Eastern Palace)']]
])

View File

@@ -33,50 +33,46 @@ class TestGanonsTower(TestDungeon):
["Ganons Tower - Randomizer Room - Top Left", False, []],
["Ganons Tower - Randomizer Room - Top Left", False, [], ['Hammer']],
["Ganons Tower - Randomizer Room - Top Left", False, [], ['Hookshot']],
["Ganons Tower - Randomizer Room - Top Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Randomizer Room - Top Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Randomizer Room - Top Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Randomizer Room - Top Right", False, []],
["Ganons Tower - Randomizer Room - Top Right", False, [], ['Hammer']],
["Ganons Tower - Randomizer Room - Top Right", False, [], ['Hookshot']],
["Ganons Tower - Randomizer Room - Top Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Randomizer Room - Top Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Randomizer Room - Top Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Randomizer Room - Bottom Left", False, []],
["Ganons Tower - Randomizer Room - Bottom Left", False, [], ['Hammer']],
["Ganons Tower - Randomizer Room - Bottom Left", False, [], ['Hookshot']],
["Ganons Tower - Randomizer Room - Bottom Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Randomizer Room - Bottom Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Randomizer Room - Bottom Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Randomizer Room - Bottom Right", False, []],
["Ganons Tower - Randomizer Room - Bottom Right", False, [], ['Hammer']],
["Ganons Tower - Randomizer Room - Bottom Right", False, [], ['Hookshot']],
["Ganons Tower - Randomizer Room - Bottom Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Randomizer Room - Bottom Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Randomizer Room - Bottom Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Firesnake Room", False, []],
["Ganons Tower - Firesnake Room", False, [], ['Hammer']],
["Ganons Tower - Firesnake Room", False, [], ['Hookshot']],
["Ganons Tower - Firesnake Room", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Firesnake Room", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Map Chest", False, []],
["Ganons Tower - Map Chest", False, [], ['Hammer']],
["Ganons Tower - Map Chest", False, [], ['Hookshot', 'Pegasus Boots']],
["Ganons Tower - Map Chest", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Map Chest", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hammer', 'Pegasus Boots']],
["Ganons Tower - Map Chest", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Map Chest", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hammer', 'Pegasus Boots']],
["Ganons Tower - Big Chest", False, []],
["Ganons Tower - Big Chest", False, [], ['Big Key (Ganons Tower)']],
["Ganons Tower - Big Chest", True, ['Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']],
["Ganons Tower - Big Chest", True, ['Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Big Chest", True, ['Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']],
["Ganons Tower - Big Chest", True, ['Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Hope Room - Left", True, []],
["Ganons Tower - Hope Room - Right", True, []],
["Ganons Tower - Bob's Chest", False, []],
["Ganons Tower - Bob's Chest", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']],
["Ganons Tower - Bob's Chest", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Bob's Chest", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']],
["Ganons Tower - Bob's Chest", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Tile Room", False, []],
["Ganons Tower - Tile Room", False, [], ['Cane of Somaria']],
@@ -85,34 +81,34 @@ class TestGanonsTower(TestDungeon):
["Ganons Tower - Compass Room - Top Left", False, []],
["Ganons Tower - Compass Room - Top Left", False, [], ['Cane of Somaria']],
["Ganons Tower - Compass Room - Top Left", False, [], ['Fire Rod']],
["Ganons Tower - Compass Room - Top Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Compass Room - Top Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Compass Room - Top Right", False, []],
["Ganons Tower - Compass Room - Top Right", False, [], ['Cane of Somaria']],
["Ganons Tower - Compass Room - Top Right", False, [], ['Fire Rod']],
["Ganons Tower - Compass Room - Top Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Compass Room - Top Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Compass Room - Bottom Left", False, []],
["Ganons Tower - Compass Room - Bottom Left", False, [], ['Cane of Somaria']],
["Ganons Tower - Compass Room - Bottom Left", False, [], ['Fire Rod']],
["Ganons Tower - Compass Room - Bottom Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Compass Room - Bottom Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Compass Room - Bottom Right", False, []],
["Ganons Tower - Compass Room - Bottom Right", False, [], ['Cane of Somaria']],
["Ganons Tower - Compass Room - Bottom Right", False, [], ['Fire Rod']],
["Ganons Tower - Compass Room - Bottom Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Compass Room - Bottom Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Cane of Somaria']],
["Ganons Tower - Big Key Chest", False, []],
["Ganons Tower - Big Key Chest", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']],
["Ganons Tower - Big Key Chest", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Big Key Chest", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']],
["Ganons Tower - Big Key Chest", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Big Key Room - Left", False, []],
["Ganons Tower - Big Key Room - Left", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']],
["Ganons Tower - Big Key Room - Left", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Big Key Room - Left", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']],
["Ganons Tower - Big Key Room - Left", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Big Key Room - Right", False, []],
["Ganons Tower - Big Key Room - Right", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']],
["Ganons Tower - Big Key Room - Right", True, ['Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Big Key Room - Right", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Cane of Somaria', 'Fire Rod']],
["Ganons Tower - Big Key Room - Right", True, ['Bomb Upgrade (+5)', 'Progressive Bow', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']],
["Ganons Tower - Mini Helmasaur Room - Left", False, []],
["Ganons Tower - Mini Helmasaur Room - Left", False, [], ['Progressive Bow']],
@@ -132,8 +128,8 @@ class TestGanonsTower(TestDungeon):
["Ganons Tower - Pre-Moldorm Chest", False, [], ['Progressive Bow']],
["Ganons Tower - Pre-Moldorm Chest", False, [], ['Big Key (Ganons Tower)']],
["Ganons Tower - Pre-Moldorm Chest", False, [], ['Lamp', 'Fire Rod']],
["Ganons Tower - Pre-Moldorm Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Lamp']],
["Ganons Tower - Pre-Moldorm Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod']],
["Ganons Tower - Pre-Moldorm Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Lamp']],
["Ganons Tower - Pre-Moldorm Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod']],
["Ganons Tower - Validation Chest", False, []],
["Ganons Tower - Validation Chest", False, [], ['Hookshot']],
@@ -141,8 +137,8 @@ class TestGanonsTower(TestDungeon):
["Ganons Tower - Validation Chest", False, [], ['Big Key (Ganons Tower)']],
["Ganons Tower - Validation Chest", False, [], ['Lamp', 'Fire Rod']],
["Ganons Tower - Validation Chest", False, [], ['Progressive Sword', 'Hammer']],
["Ganons Tower - Validation Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Lamp', 'Hookshot', 'Progressive Sword']],
["Ganons Tower - Validation Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Hookshot', 'Progressive Sword']],
["Ganons Tower - Validation Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Lamp', 'Hookshot', 'Hammer']],
["Ganons Tower - Validation Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Hookshot', 'Hammer']],
["Ganons Tower - Validation Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Lamp', 'Hookshot', 'Progressive Sword']],
["Ganons Tower - Validation Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Hookshot', 'Progressive Sword']],
["Ganons Tower - Validation Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Lamp', 'Hookshot', 'Hammer']],
["Ganons Tower - Validation Chest", True, ['Progressive Bow', 'Big Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Fire Rod', 'Hookshot', 'Hammer']],
])

View File

@@ -11,8 +11,9 @@ class TestIcePalace(TestDungeon):
["Ice Palace - Big Key Chest", False, [], ['Progressive Glove']],
["Ice Palace - Big Key Chest", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Big Key Chest", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Big Key Chest", True, ['Progressive Glove', 'Fire Rod', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']],
["Ice Palace - Big Key Chest", True, ['Progressive Glove', 'Bombos', 'Progressive Sword', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']],
["Ice Palace - Big Key Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Big Key Chest", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Fire Rod', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
["Ice Palace - Big Key Chest", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Bombos', 'Progressive Sword', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
#@todo: Change from item randomizer - Right side key door is only in logic if big key is in there
#["Ice Palace - Big Key Chest", True, ['Progressive Glove', 'Cane of Byrna', 'Fire Rod', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
#["Ice Palace - Big Key Chest", True, ['Progressive Glove', 'Cane of Byrna', 'Bombos', 'Progressive Sword', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
@@ -22,16 +23,17 @@ class TestIcePalace(TestDungeon):
["Ice Palace - Compass Chest", False, []],
["Ice Palace - Compass Chest", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Compass Chest", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Compass Chest", True, ['Fire Rod']],
["Ice Palace - Compass Chest", True, ['Bombos', 'Progressive Sword']],
["Ice Palace - Compass Chest", True, ['Small Key (Ice Palace)', 'Fire Rod']],
["Ice Palace - Compass Chest", True, ['Small Key (Ice Palace)', 'Bombos', 'Progressive Sword']],
["Ice Palace - Map Chest", False, []],
["Ice Palace - Map Chest", False, [], ['Hammer']],
["Ice Palace - Map Chest", False, [], ['Progressive Glove']],
["Ice Palace - Map Chest", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Map Chest", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Map Chest", True, ['Progressive Glove', 'Fire Rod', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']],
["Ice Palace - Map Chest", True, ['Progressive Glove', 'Bombos', 'Progressive Sword', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']],
["Ice Palace - Map Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Map Chest", True, ['Small Key (Ice Palace)', 'Bomb Upgrade (+5)', 'Progressive Glove', 'Fire Rod', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']],
["Ice Palace - Map Chest", True, ['Small Key (Ice Palace)', 'Bomb Upgrade (+5)', 'Progressive Glove', 'Bombos', 'Progressive Sword', 'Hammer', 'Hookshot', 'Small Key (Ice Palace)']],
#["Ice Palace - Map Chest", True, ['Progressive Glove', 'Cane of Byrna', 'Fire Rod', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
#["Ice Palace - Map Chest", True, ['Progressive Glove', 'Cane of Byrna', 'Bombos', 'Progressive Sword', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
#["Ice Palace - Map Chest", True, ['Progressive Glove', 'Cape', 'Fire Rod', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
@@ -40,8 +42,9 @@ class TestIcePalace(TestDungeon):
["Ice Palace - Spike Room", False, []],
["Ice Palace - Spike Room", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Spike Room", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Spike Room", True, ['Fire Rod', 'Hookshot', 'Small Key (Ice Palace)']],
["Ice Palace - Spike Room", True, ['Bombos', 'Progressive Sword', 'Hookshot', 'Small Key (Ice Palace)']],
["Ice Palace - Spike Room", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Spike Room", True, ['Bomb Upgrade (+5)', 'Fire Rod', 'Hookshot', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
["Ice Palace - Spike Room", True, ['Bomb Upgrade (+5)', 'Bombos', 'Progressive Sword', 'Hookshot', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
#["Ice Palace - Spike Room", True, ['Cape', 'Fire Rod', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
#["Ice Palace - Spike Room", True, ['Cape', 'Bombos', 'Progressive Sword', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
#["Ice Palace - Spike Room", True, ['Cane of Byrna', 'Fire Rod', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
@@ -50,21 +53,24 @@ class TestIcePalace(TestDungeon):
["Ice Palace - Freezor Chest", False, []],
["Ice Palace - Freezor Chest", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Freezor Chest", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Freezor Chest", True, ['Fire Rod']],
["Ice Palace - Freezor Chest", True, ['Bombos', 'Progressive Sword']],
["Ice Palace - Freezor Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Freezor Chest", True, ['Bomb Upgrade (+5)', 'Fire Rod', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
["Ice Palace - Freezor Chest", True, ['Bomb Upgrade (+5)', 'Bombos', 'Progressive Sword', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
["Ice Palace - Iced T Room", False, []],
["Ice Palace - Iced T Room", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Iced T Room", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Iced T Room", True, ['Fire Rod']],
["Ice Palace - Iced T Room", True, ['Bombos', 'Progressive Sword']],
["Ice Palace - Iced T Room", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Iced T Room", True, ['Bomb Upgrade (+5)', 'Fire Rod', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
["Ice Palace - Iced T Room", True, ['Bomb Upgrade (+5)', 'Bombos', 'Progressive Sword', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)']],
["Ice Palace - Big Chest", False, []],
["Ice Palace - Big Chest", False, [], ['Big Key (Ice Palace)']],
["Ice Palace - Big Chest", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Big Chest", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Big Chest", True, ['Big Key (Ice Palace)', 'Fire Rod']],
["Ice Palace - Big Chest", True, ['Big Key (Ice Palace)', 'Bombos', 'Progressive Sword']],
["Ice Palace - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Palace - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Fire Rod']],
["Ice Palace - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Bombos', 'Progressive Sword']],
["Ice Palace - Boss", False, []],
["Ice Palace - Boss", False, [], ['Hammer']],
@@ -72,9 +78,10 @@ class TestIcePalace(TestDungeon):
["Ice Palace - Boss", False, [], ['Big Key (Ice Palace)']],
["Ice Palace - Boss", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Boss", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Boss", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
# need hookshot now to reach the right side for the 6th key
["Ice Palace - Boss", True, ['Progressive Glove', 'Big Key (Ice Palace)', 'Fire Rod', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Hookshot']],
["Ice Palace - Boss", True, ['Progressive Glove', 'Big Key (Ice Palace)', 'Fire Rod', 'Hammer', 'Cane of Somaria', 'Small Key (Ice Palace)', 'Hookshot']],
["Ice Palace - Boss", True, ['Progressive Glove', 'Big Key (Ice Palace)', 'Bombos', 'Progressive Sword', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Hookshot']],
["Ice Palace - Boss", True, ['Progressive Glove', 'Big Key (Ice Palace)', 'Bombos', 'Progressive Sword', 'Hammer', 'Cane of Somaria', 'Small Key (Ice Palace)', 'Hookshot']],
["Ice Palace - Boss", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Big Key (Ice Palace)', 'Fire Rod', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Hookshot']],
["Ice Palace - Boss", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Big Key (Ice Palace)', 'Fire Rod', 'Hammer', 'Cane of Somaria', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Hookshot']],
["Ice Palace - Boss", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Big Key (Ice Palace)', 'Bombos', 'Progressive Sword', 'Hammer', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Hookshot']],
["Ice Palace - Boss", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Big Key (Ice Palace)', 'Bombos', 'Progressive Sword', 'Hammer', 'Cane of Somaria', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Small Key (Ice Palace)', 'Hookshot']],
])

View File

@@ -32,36 +32,32 @@ class TestMiseryMire(TestDungeon):
["Misery Mire - Main Lobby", False, []],
["Misery Mire - Main Lobby", False, [], ['Pegasus Boots', 'Hookshot']],
["Misery Mire - Main Lobby", False, [], ['Small Key (Misery Mire)', 'Big Key (Misery Mire)']],
["Misery Mire - Main Lobby", True, ['Small Key (Misery Mire)', 'Hookshot', 'Progressive Sword']],
["Misery Mire - Main Lobby", True, ['Small Key (Misery Mire)', 'Pegasus Boots', 'Progressive Sword']],
["Misery Mire - Main Lobby", True, ['Big Key (Misery Mire)', 'Hookshot', 'Progressive Sword']],
["Misery Mire - Main Lobby", True, ['Big Key (Misery Mire)', 'Pegasus Boots', 'Progressive Sword']],
["Misery Mire - Main Lobby", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Hookshot', 'Progressive Sword']],
["Misery Mire - Main Lobby", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Pegasus Boots', 'Progressive Sword']],
["Misery Mire - Big Key Chest", False, []],
["Misery Mire - Big Key Chest", False, [], ['Fire Rod', 'Lamp']],
["Misery Mire - Big Key Chest", False, [], ['Pegasus Boots', 'Hookshot']],
["Misery Mire - Big Key Chest", False, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)'], ['Small Key (Misery Mire)']],
["Misery Mire - Big Key Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Lamp', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Big Key Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Lamp', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Big Key Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Fire Rod', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Big Key Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Fire Rod', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Big Key Chest", False, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)']],
["Misery Mire - Big Key Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Lamp', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Big Key Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Lamp', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Big Key Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Fire Rod', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Big Key Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Fire Rod', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Compass Chest", False, []],
["Misery Mire - Compass Chest", False, [], ['Fire Rod', 'Lamp']],
["Misery Mire - Compass Chest", False, [], ['Pegasus Boots', 'Hookshot']],
["Misery Mire - Compass Chest", False, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)'], ['Small Key (Misery Mire)']],
["Misery Mire - Compass Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Lamp', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Compass Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Lamp', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Compass Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Fire Rod', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Compass Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Fire Rod', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Compass Chest", False, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)']],
["Misery Mire - Compass Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Lamp', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Compass Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Lamp', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Compass Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Fire Rod', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Compass Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Fire Rod', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Map Chest", False, []],
["Misery Mire - Map Chest", False, [], ['Small Key (Misery Mire)', 'Big Key (Misery Mire)']],
["Misery Mire - Map Chest", False, [], ['Small Key (Misery Mire)']],
["Misery Mire - Map Chest", False, [], ['Pegasus Boots', 'Hookshot']],
["Misery Mire - Map Chest", True, ['Small Key (Misery Mire)', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Map Chest", True, ['Small Key (Misery Mire)', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Map Chest", True, ['Big Key (Misery Mire)', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Map Chest", True, ['Big Key (Misery Mire)', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Map Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Map Chest", True, ['Small Key (Misery Mire)', 'Small Key (Misery Mire)', 'Progressive Sword', 'Hookshot']],
["Misery Mire - Spike Chest", False, []],
["Misery Mire - Spike Chest", False, [], ['Pegasus Boots', 'Hookshot']],
@@ -78,7 +74,8 @@ class TestMiseryMire(TestDungeon):
["Misery Mire - Boss", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow']],
["Misery Mire - Boss", False, [], ['Big Key (Misery Mire)']],
["Misery Mire - Boss", False, [], ['Pegasus Boots', 'Hookshot']],
["Misery Mire - Boss", True, ['Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Boss", True, ['Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Hammer', 'Pegasus Boots']],
["Misery Mire - Boss", True, ['Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Progressive Bow', 'Pegasus Boots']],
["Misery Mire - Boss", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Misery Mire - Boss", True, ['Bomb Upgrade (+5)', 'Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Progressive Sword', 'Pegasus Boots']],
["Misery Mire - Boss", True, ['Bomb Upgrade (+5)', 'Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Hammer', 'Pegasus Boots']],
["Misery Mire - Boss", True, ['Bomb Upgrade (+5)', 'Big Key (Misery Mire)', 'Lamp', 'Cane of Somaria', 'Progressive Bow', 'Pegasus Boots']],
])

View File

@@ -8,7 +8,8 @@ class TestSkullWoods(TestDungeon):
self.run_tests([
["Skull Woods - Big Chest", False, []],
["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']],
["Skull Woods - Big Chest", True, ['Big Key (Skull Woods)']],
["Skull Woods - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Skull Woods - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Skull Woods)']],
["Skull Woods - Compass Chest", True, []],
@@ -64,7 +65,8 @@ class TestSkullWoods(TestDungeon):
self.run_tests([
["Skull Woods - Big Chest", False, []],
["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']],
["Skull Woods - Big Chest", True, ['Big Key (Skull Woods)']],
["Skull Woods - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Skull Woods - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Skull Woods)']],
["Skull Woods - Compass Chest", False, []],
["Skull Woods - Compass Chest", False, ['Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)'], ['Small Key (Skull Woods)']],
@@ -94,6 +96,6 @@ class TestSkullWoods(TestDungeon):
["Skull Woods - Boss", False, []],
["Skull Woods - Boss", False, [], ['Fire Rod']],
["Skull Woods - Boss", False, [], ['Progressive Sword']],
["Skull Woods - Boss", False, ['Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)'], ['Small Key (Skull Woods)']],
["Skull Woods - Boss", True, ['Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Fire Rod', 'Progressive Sword']],
["Skull Woods - Boss", False, ['Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)'], ['Small Key (Skull Woods)']],
["Skull Woods - Boss", True, ['Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Small Key (Skull Woods)', 'Fire Rod', 'Progressive Sword']],
])

View File

@@ -16,35 +16,36 @@ class TestSwampPalace(TestDungeon):
["Swamp Palace - Big Chest", False, [], ['Open Floodgate']],
["Swamp Palace - Big Chest", False, [], ['Hammer']],
["Swamp Palace - Big Chest", False, [], ['Big Key (Swamp Palace)']],
["Swamp Palace - Big Chest", False, [], ['Small Key (Swamp Palace)']],
["Swamp Palace - Big Chest", True, ['Open Floodgate', 'Big Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer']],
["Swamp Palace - Big Chest", False, [], ['Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)']],
["Swamp Palace - Big Chest", True, ['Open Floodgate', 'Big Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer']],
["Swamp Palace - Big Key Chest", False, []],
["Swamp Palace - Big Key Chest", False, [], ['Flippers']],
["Swamp Palace - Big Key Chest", False, [], ['Open Floodgate']],
["Swamp Palace - Big Key Chest", False, [], ['Hammer']],
["Swamp Palace - Big Key Chest", False, [], ['Small Key (Swamp Palace)']],
["Swamp Palace - Big Key Chest", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer']],
["Swamp Palace - Big Key Chest", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer']],
["Swamp Palace - Map Chest", False, []],
["Swamp Palace - Map Chest", False, [], ['Flippers']],
["Swamp Palace - Map Chest", False, [], ['Open Floodgate']],
["Swamp Palace - Map Chest", False, [], ['Small Key (Swamp Palace)']],
["Swamp Palace - Map Chest", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers']],
["Swamp Palace - Map Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Swamp Palace - Map Chest", True, ['Bomb Upgrade (+5)', 'Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers']],
["Swamp Palace - West Chest", False, []],
["Swamp Palace - West Chest", False, [], ['Flippers']],
["Swamp Palace - West Chest", False, [], ['Open Floodgate']],
["Swamp Palace - West Chest", False, [], ['Hammer']],
["Swamp Palace - West Chest", False, [], ['Small Key (Swamp Palace)']],
["Swamp Palace - West Chest", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer']],
["Swamp Palace - West Chest", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer']],
["Swamp Palace - Compass Chest", False, []],
["Swamp Palace - Compass Chest", False, [], ['Flippers']],
["Swamp Palace - Compass Chest", False, [], ['Open Floodgate']],
["Swamp Palace - Compass Chest", False, [], ['Hammer']],
["Swamp Palace - Compass Chest", False, [], ['Small Key (Swamp Palace)']],
["Swamp Palace - Compass Chest", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer']],
["Swamp Palace - Compass Chest", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer']],
["Swamp Palace - Flooded Room - Left", False, []],
["Swamp Palace - Flooded Room - Left", False, [], ['Flippers']],
@@ -52,7 +53,7 @@ class TestSwampPalace(TestDungeon):
["Swamp Palace - Flooded Room - Left", False, [], ['Hammer']],
["Swamp Palace - Flooded Room - Left", False, [], ['Hookshot']],
["Swamp Palace - Flooded Room - Left", False, [], ['Small Key (Swamp Palace)']],
["Swamp Palace - Flooded Room - Left", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer', 'Hookshot']],
["Swamp Palace - Flooded Room - Left", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer', 'Hookshot']],
["Swamp Palace - Flooded Room - Right", False, []],
["Swamp Palace - Flooded Room - Right", False, [], ['Flippers']],
@@ -60,7 +61,7 @@ class TestSwampPalace(TestDungeon):
["Swamp Palace - Flooded Room - Right", False, [], ['Hammer']],
["Swamp Palace - Flooded Room - Right", False, [], ['Hookshot']],
["Swamp Palace - Flooded Room - Right", False, [], ['Small Key (Swamp Palace)']],
["Swamp Palace - Flooded Room - Right", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer', 'Hookshot']],
["Swamp Palace - Flooded Room - Right", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer', 'Hookshot']],
["Swamp Palace - Waterfall Room", False, []],
["Swamp Palace - Waterfall Room", False, [], ['Flippers']],
@@ -68,7 +69,7 @@ class TestSwampPalace(TestDungeon):
["Swamp Palace - Waterfall Room", False, [], ['Hammer']],
["Swamp Palace - Waterfall Room", False, [], ['Hookshot']],
["Swamp Palace - Waterfall Room", False, [], ['Small Key (Swamp Palace)']],
["Swamp Palace - Waterfall Room", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer', 'Hookshot']],
["Swamp Palace - Waterfall Room", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer', 'Hookshot']],
["Swamp Palace - Boss", False, []],
["Swamp Palace - Boss", False, [], ['Flippers']],
@@ -76,5 +77,5 @@ class TestSwampPalace(TestDungeon):
["Swamp Palace - Boss", False, [], ['Hammer']],
["Swamp Palace - Boss", False, [], ['Hookshot']],
["Swamp Palace - Boss", False, [], ['Small Key (Swamp Palace)']],
["Swamp Palace - Boss", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer', 'Hookshot']],
["Swamp Palace - Boss", True, ['Open Floodgate', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Small Key (Swamp Palace)', 'Flippers', 'Hammer', 'Hookshot']],
])

View File

@@ -21,18 +21,19 @@ class TestThievesTown(TestDungeon):
["Thieves' Town - Spike Switch Pot Key", False, []],
["Thieves' Town - Spike Switch Pot Key", False, [], ['Big Key (Thieves Town)']],
["Thieves' Town - Spike Switch Pot Key", True, ['Big Key (Thieves Town)']],
["Thieves' Town - Spike Switch Pot Key", False, [], ['Small Key (Thieves Town)']],
["Thieves' Town - Spike Switch Pot Key", True, ['Big Key (Thieves Town)', 'Small Key (Thieves Town)']],
["Thieves' Town - Attic", False, []],
["Thieves' Town - Attic", False, [], ['Big Key (Thieves Town)']],
["Thieves' Town - Attic", False, [], ['Small Key (Thieves Town)']],
["Thieves' Town - Attic", True, ['Big Key (Thieves Town)', 'Small Key (Thieves Town)']],
["Thieves' Town - Attic", True, ['Big Key (Thieves Town)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)']],
["Thieves' Town - Big Chest", False, []],
["Thieves' Town - Big Chest", False, [], ['Big Key (Thieves Town)']],
["Thieves' Town - Big Chest", False, [], ['Small Key (Thieves Town)']],
["Thieves' Town - Big Chest", False, [], ['Hammer']],
["Thieves' Town - Big Chest", True, ['Hammer', 'Small Key (Thieves Town)', 'Big Key (Thieves Town)']],
["Thieves' Town - Big Chest", True, ['Hammer', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Big Key (Thieves Town)']],
["Thieves' Town - Blind's Cell", False, []],
["Thieves' Town - Blind's Cell", False, [], ['Big Key (Thieves Town)']],
@@ -41,8 +42,9 @@ class TestThievesTown(TestDungeon):
["Thieves' Town - Boss", False, []],
["Thieves' Town - Boss", False, [], ['Big Key (Thieves Town)']],
["Thieves' Town - Boss", False, [], ['Hammer', 'Progressive Sword', 'Cane of Somaria', 'Cane of Byrna']],
["Thieves' Town - Boss", True, ['Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Hammer']],
["Thieves' Town - Boss", True, ['Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Progressive Sword']],
["Thieves' Town - Boss", True, ['Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Cane of Somaria']],
["Thieves' Town - Boss", True, ['Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Cane of Byrna']],
["Thieves' Town - Boss", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Thieves' Town - Boss", True, ['Bomb Upgrade (+5)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Hammer']],
["Thieves' Town - Boss", True, ['Bomb Upgrade (+5)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Progressive Sword']],
["Thieves' Town - Boss", True, ['Bomb Upgrade (+5)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Cane of Somaria']],
["Thieves' Town - Boss", True, ['Bomb Upgrade (+5)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Small Key (Thieves Town)', 'Big Key (Thieves Town)', 'Cane of Byrna']],
])

View File

@@ -18,11 +18,11 @@ class TestTowerOfHera(TestDungeon):
["Tower of Hera - Compass Chest", False, []],
["Tower of Hera - Compass Chest", False, [], ['Big Key (Tower of Hera)']],
["Tower of Hera - Compass Chest", True, ['Big Key (Tower of Hera)']],
["Tower of Hera - Compass Chest", True, ['Big Key (Tower of Hera)', 'Progressive Sword']],
["Tower of Hera - Big Chest", False, []],
["Tower of Hera - Big Chest", False, [], ['Big Key (Tower of Hera)']],
["Tower of Hera - Big Chest", True, ['Big Key (Tower of Hera)']],
["Tower of Hera - Big Chest", True, ['Big Key (Tower of Hera)', 'Progressive Sword']],
["Tower of Hera - Boss", False, []],
["Tower of Hera - Boss", False, [], ['Big Key (Tower of Hera)']],

View File

@@ -14,7 +14,9 @@ class TestInverted(TestBase, LTTPTestBase):
def setUp(self):
self.world_setup()
self.multiworld.difficulty_requirements[1] = difficulties['normal']
self.multiworld.mode[1] = "inverted"
self.multiworld.mode[1].value = 2
self.multiworld.bombless_start[1].value = True
self.multiworld.shuffle_capacity_upgrades[1].value = True
create_inverted_regions(self.multiworld, 1)
self.multiworld.worlds[1].create_dungeons()
create_shops(self.multiworld, 1)

View File

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

View File

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

View File

@@ -40,10 +40,12 @@ class TestInvertedDeathMountain(TestInverted):
["Paradox Cave Lower - Far Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Cane of Somaria', 'Fire Rod']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Fire Rod']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Progressive Bow']],
["Paradox Cave Lower - Left", False, []],
["Paradox Cave Lower - Left", False, [], ['Moon Pearl']],
@@ -52,10 +54,12 @@ class TestInvertedDeathMountain(TestInverted):
["Paradox Cave Lower - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Cane of Somaria', 'Fire Rod']],
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Fire Rod']],
["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Progressive Bow']],
["Paradox Cave Lower - Middle", False, []],
["Paradox Cave Lower - Middle", False, [], ['Moon Pearl']],
@@ -64,10 +68,12 @@ class TestInvertedDeathMountain(TestInverted):
["Paradox Cave Lower - Middle", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Middle", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Middle", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Cane of Somaria', 'Fire Rod']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Fire Rod']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Progressive Bow']],
["Paradox Cave Lower - Right", False, []],
["Paradox Cave Lower - Right", False, [], ['Moon Pearl']],
@@ -76,10 +82,12 @@ class TestInvertedDeathMountain(TestInverted):
["Paradox Cave Lower - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Cane of Somaria', 'Fire Rod']],
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Fire Rod']],
["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Progressive Bow']],
["Paradox Cave Lower - Far Right", False, []],
["Paradox Cave Lower - Far Right", False, [], ['Moon Pearl']],
@@ -88,10 +96,12 @@ class TestInvertedDeathMountain(TestInverted):
["Paradox Cave Lower - Far Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Cane of Somaria', 'Fire Rod']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Moon Pearl', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl', 'Cane of Somaria']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Fire Rod']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl', 'Progressive Bow']],
["Paradox Cave Upper - Left", False, []],
["Paradox Cave Upper - Left", False, [], ['Moon Pearl']],
@@ -100,10 +110,11 @@ class TestInvertedDeathMountain(TestInverted):
["Paradox Cave Upper - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Upper - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Upper - Right", False, []],
["Paradox Cave Upper - Right", False, [], ['Moon Pearl']],
@@ -112,20 +123,22 @@ class TestInvertedDeathMountain(TestInverted):
["Paradox Cave Upper - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Upper - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Mimic Cave", False, []],
["Mimic Cave", False, [], ['Moon Pearl']],
["Mimic Cave", False, [], ['Hammer']],
["Mimic Cave", False, [], ['Progressive Glove', 'Flute']],
["Mimic Cave", False, [], ['Lamp', 'Flute']],
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
["Mimic Cave", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']],
["Mimic Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Bow', 'Cane of Somaria', 'Progressive Sword']],
["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Flute', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Progressive Bow', 'Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
["Mimic Cave", True, ['Cane of Somaria', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']],
["Ether Tablet", False, []],
["Ether Tablet", False, [], ['Moon Pearl']],

View File

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

View File

@@ -11,20 +11,20 @@ class TestInvertedTurtleRock(TestInverted):
["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, ['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', '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 - 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)', '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)', '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)', '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)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Chain Chomps", False, []],
["Turtle Rock - Chain Chomps", False, [], ['Magic Mirror', 'Cane of Somaria']],
["Turtle Rock - Chain Chomps", False, ['Small Key (Turtle Rock)'], ['Magic Mirror', 'Small Key (Turtle Rock)']],
["Turtle Rock - Chain Chomps", True, ['Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Chain Chomps", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Chain Chomps", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
["Turtle Rock - Chain Chomps", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Chain Chomps", True, ['Bomb Upgrade (+5)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
["Turtle Rock - Chain Chomps", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']],
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot']],
["Turtle Rock - Chain Chomps", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
["Turtle Rock - Chain Chomps", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Fire Rod']],
["Turtle Rock - Roller Room - Left", False, []],
["Turtle Rock - Roller Room - Left", False, [], ['Cane of Somaria']],
@@ -33,10 +33,10 @@ class TestInvertedTurtleRock(TestInverted):
["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', '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, ['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 - 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)', '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)', '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)', '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)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Roller Room - Right", False, []],
["Turtle Rock - Roller Room - Right", False, [], ['Cane of Somaria']],
@@ -45,17 +45,17 @@ class TestInvertedTurtleRock(TestInverted):
["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', '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, ['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 - 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)', '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)', '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)', '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)', '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)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Turtle Rock)', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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']],
@@ -66,12 +66,12 @@ class TestInvertedTurtleRock(TestInverted):
["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, ['Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
# Mirror in from ledge, use left side entrance, have enough keys to get to the chest
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Crystaroller Room", False, []],
["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
@@ -80,7 +80,7 @@ class TestInvertedTurtleRock(TestInverted):
["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)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - 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)', '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)', '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', 'Magic Mirror', 'Hookshot']],
@@ -98,12 +98,15 @@ class TestInvertedTurtleRock(TestInverted):
["Turtle Rock - Boss", False, [], ['Magic Mirror', 'Lamp']],
["Turtle Rock - Boss", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Flute', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Bottle', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Bottle', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Magic Upgrade (1/2)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)','Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Flute', 'Magic Mirror', 'Moon Pearl', 'Hookshot', 'Hammer', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']]
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Bottle', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Magic Upgrade (1/2)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)','Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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)', '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)', '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"]:
@@ -115,11 +118,11 @@ class TestInvertedTurtleRock(TestInverted):
[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)', '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)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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)', '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)', '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)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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)', '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)', '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)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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)', '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']],

View File

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

View File

@@ -40,10 +40,11 @@ class TestInvertedDeathMountain(TestInvertedMinor):
["Paradox Cave Lower - Far Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod']],
["Paradox Cave Lower - Far Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Progressive Bow', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Cane of Somaria', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Left", False, []],
["Paradox Cave Lower - Left", False, [], ['Moon Pearl']],
@@ -52,10 +53,11 @@ class TestInvertedDeathMountain(TestInvertedMinor):
["Paradox Cave Lower - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod']],
["Paradox Cave Lower - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Progressive Bow', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Cane of Somaria', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Middle", False, []],
["Paradox Cave Lower - Middle", False, [], ['Moon Pearl']],
@@ -64,10 +66,11 @@ class TestInvertedDeathMountain(TestInvertedMinor):
["Paradox Cave Lower - Middle", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Middle", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Middle", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod']],
["Paradox Cave Lower - Middle", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Progressive Bow', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Cane of Somaria', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Right", False, []],
["Paradox Cave Lower - Right", False, [], ['Moon Pearl']],
@@ -76,10 +79,11 @@ class TestInvertedDeathMountain(TestInvertedMinor):
["Paradox Cave Lower - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod']],
["Paradox Cave Lower - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Progressive Bow', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Cane of Somaria', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", False, []],
["Paradox Cave Lower - Far Right", False, [], ['Moon Pearl']],
@@ -88,10 +92,11 @@ class TestInvertedDeathMountain(TestInvertedMinor):
["Paradox Cave Lower - Far Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod']],
["Paradox Cave Lower - Far Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Progressive Bow', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Cane of Somaria', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Upper - Left", False, []],
["Paradox Cave Upper - Left", False, [], ['Moon Pearl']],
@@ -100,10 +105,11 @@ class TestInvertedDeathMountain(TestInvertedMinor):
["Paradox Cave Upper - Left", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Upper - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Upper - Right", False, []],
["Paradox Cave Upper - Right", False, [], ['Moon Pearl']],
@@ -112,20 +118,21 @@ class TestInvertedDeathMountain(TestInvertedMinor):
["Paradox Cave Upper - Right", False, ['Progressive Glove'], ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", False, ['Flute', 'Progressive Glove', 'Hammer', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Paradox Cave Upper - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)','Bomb Upgrade (50)']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Moon Pearl']],
["Mimic Cave", False, []],
["Mimic Cave", False, [], ['Moon Pearl']],
["Mimic Cave", False, [], ['Hammer']],
["Mimic Cave", False, [], ['Progressive Glove', 'Flute']],
["Mimic Cave", False, [], ['Lamp', 'Flute']],
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
["Mimic Cave", True, ['Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']],
["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Flute', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Progressive Sword', 'Progressive Sword', 'Flute', 'Moon Pearl', 'Progressive Glove', 'Progressive Glove', 'Hammer']],
["Mimic Cave", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer', 'Hookshot']],
["Mimic Cave", True, ['Cane of Somaria', 'Progressive Glove', 'Progressive Glove', 'Lamp', 'Moon Pearl', 'Hammer']],
["Ether Tablet", False, []],
["Ether Tablet", False, [], ['Moon Pearl']],

View File

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

View File

@@ -13,8 +13,10 @@ from worlds.alttp.test import LTTPTestBase
class TestInvertedMinor(TestBase, LTTPTestBase):
def setUp(self):
self.world_setup()
self.multiworld.mode[1] = "inverted"
self.multiworld.logic[1] = "minorglitches"
self.multiworld.mode[1].value = 2
self.multiworld.glitches_required[1] = "minor_glitches"
self.multiworld.bombless_start[1].value = True
self.multiworld.shuffle_capacity_upgrades[1].value = True
self.multiworld.difficulty_requirements[1] = difficulties['normal']
create_inverted_regions(self.multiworld, 1)
self.multiworld.worlds[1].create_dungeons()

View File

@@ -11,21 +11,21 @@ class TestInvertedTurtleRock(TestInvertedMinor):
["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, ['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', '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 - 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)', '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)', '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)', '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)', '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, ['Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Chain Chomps", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Chain Chomps", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
["Turtle Rock - Chain Chomps", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Chain Chomps", True, ['Bomb Upgrade (+5)', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove']],
["Turtle Rock - Chain Chomps", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot']],
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot']],
["Turtle Rock - Chain Chomps", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
["Turtle Rock - Chain Chomps", True, ['Fire Rod', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror']],
["Turtle Rock - Roller Room - Left", False, []],
["Turtle Rock - Roller Room - Left", False, [], ['Cane of Somaria']],
@@ -34,10 +34,10 @@ class TestInvertedTurtleRock(TestInvertedMinor):
["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', '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, ['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 - 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)', '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)', '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)', '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)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Roller Room - Right", False, []],
["Turtle Rock - Roller Room - Right", False, [], ['Cane of Somaria']],
@@ -46,17 +46,17 @@ class TestInvertedTurtleRock(TestInvertedMinor):
["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', '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, ['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 - 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)', '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)', '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)', '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)', '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)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Chest", True, ['Big Key (Turtle Rock)', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Turtle Rock)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Turtle Rock)', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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']],
@@ -67,12 +67,12 @@ class TestInvertedTurtleRock(TestInvertedMinor):
["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, ['Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
# Mirror in from ledge, use left side entrance, have enough keys to get to the chest
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Lamp', 'Magic Mirror', 'Progressive Glove', 'Moon Pearl', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Moon Pearl', 'Flute', 'Magic Mirror', 'Hookshot', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Big Key Chest", True, ['Flute', 'Progressive Glove', 'Progressive Glove', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Crystaroller Room", False, []],
["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)', 'Magic Mirror']],
@@ -81,7 +81,7 @@ class TestInvertedTurtleRock(TestInvertedMinor):
["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)', 'Flute', 'Quake', 'Progressive Sword', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - 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)', '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)', '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', 'Magic Mirror', 'Hookshot']],
@@ -98,11 +98,11 @@ class TestInvertedTurtleRock(TestInvertedMinor):
["Turtle Rock - Boss", False, [], ['Big Key (Turtle Rock)']],
["Turtle Rock - Boss", False, [], ['Magic Mirror', 'Lamp']],
["Turtle Rock - Boss", False, ['Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Flute', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Bottle', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Bottle', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Magic Upgrade (1/2)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)','Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Magic Mirror', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Flute', 'Magic Mirror', 'Moon Pearl', 'Hookshot', 'Hammer', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']]
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Flute', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Bottle', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Bottle', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']],
["Turtle Rock - Boss", True, ['Ice Rod', 'Fire Rod', 'Lamp', 'Progressive Glove', 'Quake', 'Progressive Sword', 'Progressive Sword', 'Cane of Somaria', 'Magic Upgrade (1/2)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)','Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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)', '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)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Big Key (Turtle Rock)']]
])
@@ -117,11 +117,11 @@ class TestInvertedTurtleRock(TestInvertedMinor):
[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)', '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)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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)', '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)', '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)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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)', '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)', '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)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', '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)', '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']],

View File

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

View File

@@ -24,36 +24,38 @@ class TestDeathMountain(TestInvertedOWG):
["Paradox Cave Lower - Far Left", False, []],
["Paradox Cave Lower - Far Left", False, [], ['Moon Pearl']],
["Paradox Cave Lower - Far Left", True, ['Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Lower - Far Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Lower - Left", False, []],
["Paradox Cave Lower - Left", False, [], ['Moon Pearl']],
["Paradox Cave Lower - Left", True, ['Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Lower - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Lower - Middle", False, []],
["Paradox Cave Lower - Middle", False, [], ['Moon Pearl']],
["Paradox Cave Lower - Middle", True, ['Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Lower - Middle", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Lower - Right", False, []],
["Paradox Cave Lower - Right", False, [], ['Moon Pearl']],
["Paradox Cave Lower - Right", True, ['Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Lower - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Lower - Far Right", False, []],
["Paradox Cave Lower - Far Right", False, [], ['Moon Pearl']],
["Paradox Cave Lower - Far Right", True, ['Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Lower - Far Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Upper - Left", False, []],
["Paradox Cave Upper - Left", False, [], ['Moon Pearl']],
["Paradox Cave Upper - Left", True, ['Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Upper - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Upper - Right", False, []],
["Paradox Cave Upper - Right", False, [], ['Moon Pearl']],
["Paradox Cave Upper - Right", True, ['Moon Pearl', 'Pegasus Boots']],
["Paradox Cave Upper - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Mimic Cave", False, []],
["Mimic Cave", False, [], ['Moon Pearl']],
["Mimic Cave", False, [], ['Hammer']],
["Mimic Cave", True, ['Moon Pearl', 'Hammer', 'Pegasus Boots']],
["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Hammer', 'Pegasus Boots']],
["Ether Tablet", False, []],
["Ether Tablet", False, ['Progressive Sword'], ['Progressive Sword']],

View File

@@ -13,16 +13,15 @@ class TestDungeons(TestInvertedOWG):
["Sanctuary", False, []],
["Sanctuary", False, ['Beat Agahnim 1']],
["Sanctuary", True, ['Magic Mirror', 'Beat Agahnim 1']],
["Sanctuary", True, ['Lamp', 'Beat Agahnim 1', 'Small Key (Hyrule Castle)']],
["Sanctuary", True, ['Lamp', 'Beat Agahnim 1', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)']],
["Sanctuary", True, ['Moon Pearl', 'Pegasus Boots']],
["Sanctuary", True, ['Magic Mirror', 'Pegasus Boots']],
["Sewers - Secret Room - Left", False, []],
["Sewers - Secret Room - Left", True, ['Moon Pearl', 'Progressive Glove', 'Pegasus Boots']],
["Sewers - Secret Room - Left", True, ['Moon Pearl', 'Pegasus Boots', 'Lamp', 'Small Key (Hyrule Castle)']],
["Sewers - Secret Room - Left", True,
['Magic Mirror', 'Pegasus Boots', 'Lamp', 'Small Key (Hyrule Castle)']],
["Sewers - Secret Room - Left", True, ['Beat Agahnim 1', 'Lamp', 'Small Key (Hyrule Castle)']],
["Sewers - Secret Room - Left", True, ['Moon Pearl', 'Pegasus Boots', 'Lamp', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)']],
["Sewers - Secret Room - Left", True, ['Magic Mirror', 'Pegasus Boots', 'Lamp', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)']],
["Sewers - Secret Room - Left", True, ['Bomb Upgrade (+5)', 'Beat Agahnim 1', 'Lamp', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)']],
["Eastern Palace - Compass Chest", False, []],
["Eastern Palace - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots']],
@@ -37,15 +36,15 @@ class TestDungeons(TestInvertedOWG):
["Desert Palace - Boss", False, [], ['Small Key (Desert Palace)']],
["Desert Palace - Boss", False, [], ['Big Key (Desert Palace)']],
["Desert Palace - Boss", False, [], ['Lamp', 'Fire Rod']],
["Desert Palace - Boss", True, ['Progressive Sword', 'Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Moon Pearl', 'Pegasus Boots', 'Lamp']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Moon Pearl', 'Pegasus Boots', 'Fire Rod']],
["Desert Palace - Boss", True, ['Progressive Sword', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Moon Pearl', 'Pegasus Boots', 'Lamp']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Big Key (Desert Palace)', 'Moon Pearl', 'Pegasus Boots', 'Fire Rod']],
["Tower of Hera - Basement Cage", False, []],
["Tower of Hera - Basement Cage", False, [], ['Moon Pearl']],
["Tower of Hera - Basement Cage", True, ['Pegasus Boots', 'Moon Pearl']],
["Castle Tower - Room 03", False, []],
["Castle Tower - Room 03", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Room 03", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Room 03", True, ['Pegasus Boots', 'Progressive Sword']],
["Castle Tower - Room 03", True, ['Pegasus Boots', 'Progressive Bow']],
@@ -62,7 +61,8 @@ class TestDungeons(TestInvertedOWG):
["Skull Woods - Big Chest", False, []],
["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']],
["Skull Woods - Big Chest", True, ['Big Key (Skull Woods)']],
["Skull Woods - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Skull Woods - Big Chest", True, ['Bomb Upgrade (+5)', 'Big Key (Skull Woods)']],
["Skull Woods - Big Key Chest", True, []],
@@ -75,8 +75,8 @@ class TestDungeons(TestInvertedOWG):
["Ice Palace - Compass Chest", False, []],
["Ice Palace - Compass Chest", False, [], ['Fire Rod', 'Bombos', 'Progressive Sword']],
# Qirn Jump
["Ice Palace - Compass Chest", True, ['Fire Rod']],
["Ice Palace - Compass Chest", True, ['Bombos', 'Progressive Sword']],
["Ice Palace - Compass Chest", True, ['Fire Rod', 'Small Key (Ice Palace)']],
["Ice Palace - Compass Chest", True, ['Bombos', 'Progressive Sword', 'Small Key (Ice Palace)']],
["Misery Mire - Bridge Chest", False, []],
["Misery Mire - Bridge Chest", False, [], ['Ether']],
@@ -85,11 +85,20 @@ class TestDungeons(TestInvertedOWG):
["Turtle Rock - Compass Chest", False, []],
["Turtle Rock - Compass Chest", False, [], ['Cane of Somaria']],
["Turtle Rock - Compass Chest", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Compass Chest", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Compass Chest", True, ['Pegasus Boots', 'Quake', 'Progressive Sword', 'Cane of Somaria']],
["Turtle Rock - Chain Chomps", False, []],
["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl']],
["Turtle Rock - Chain Chomps", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Hookshot', 'Progressive Sword', 'Progressive Bow', 'Blue Boomerang', 'Red Boomerang', 'Cane of Somaria', 'Fire Rod', 'Ice Rod']],
["Turtle Rock - Chain Chomps", True, ['Bomb Upgrade (+5)', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']],
["Turtle Rock - Chain Chomps", True, ['Hookshot', 'Pegasus Boots']],
["Turtle Rock - Chain Chomps", True, ['Progressive Bow', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']],
["Turtle Rock - Chain Chomps", True, ['Blue Boomerang', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']],
["Turtle Rock - Chain Chomps", True, ['Red Boomerang', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']],
["Turtle Rock - Chain Chomps", True, ['Cane of Somaria', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']],
["Turtle Rock - Chain Chomps", True, ['Fire Rod', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']],
["Turtle Rock - Chain Chomps", True, ['Ice Rod', 'Pegasus Boots', 'Magic Mirror', 'Moon Pearl']],
["Turtle Rock - Chain Chomps", True, ['Progressive Sword', 'Progressive Sword', 'Pegasus Boots']],
["Turtle Rock - Crystaroller Room", False, []],
["Turtle Rock - Crystaroller Room", True, ['Pegasus Boots', 'Magic Mirror', 'Moon Pearl', 'Big Key (Turtle Rock)']],

View File

@@ -13,8 +13,10 @@ from worlds.alttp.test import LTTPTestBase
class TestInvertedOWG(TestBase, LTTPTestBase):
def setUp(self):
self.world_setup()
self.multiworld.logic[1] = "owglitches"
self.multiworld.mode[1] = "inverted"
self.multiworld.glitches_required[1] = "overworld_glitches"
self.multiworld.mode[1].value = 2
self.multiworld.bombless_start[1].value = True
self.multiworld.shuffle_capacity_upgrades[1].value = True
self.multiworld.difficulty_requirements[1] = difficulties['normal']
create_inverted_regions(self.multiworld, 1)
self.multiworld.worlds[1].create_dungeons()

View File

@@ -40,40 +40,46 @@ class TestLightWorld(TestInvertedOWG):
["Chicken House", False, []],
["Chicken House", False, [], ['Moon Pearl']],
["Chicken House", True, ['Moon Pearl', 'Pegasus Boots']],
["Chicken House", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Chicken House", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Aginah's Cave", False, []],
["Aginah's Cave", False, [], ['Moon Pearl']],
["Aginah's Cave", True, ['Moon Pearl', 'Pegasus Boots']],
["Aginah's Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Aginah's Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Sahasrahla's Hut - Left", False, []],
["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Magic Mirror']],
["Sahasrahla's Hut - Left", False, [], ['Moon Pearl', 'Pegasus Boots']],
["Sahasrahla's Hut - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Pegasus Boots']],
["Sahasrahla's Hut - Left", True, ['Magic Mirror', 'Pegasus Boots']],
##todo: Damage boost superbunny not in logic
#["Sahasrahla's Hut - Left", True, ['Beat Agahnim 1', 'Pegasus Boots']],
["Sahasrahla's Hut - Left", True, ['Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Left", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Middle", False, []],
["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Magic Mirror']],
["Sahasrahla's Hut - Middle", False, [], ['Moon Pearl', 'Pegasus Boots']],
["Sahasrahla's Hut - Middle", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Pegasus Boots']],
["Sahasrahla's Hut - Middle", True, ['Magic Mirror', 'Pegasus Boots']],
#["Sahasrahla's Hut - Middle", True, ['Beat Agahnim 1', 'Pegasus Boots']],
["Sahasrahla's Hut - Middle", True, ['Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Middle", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Right", False, []],
["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Magic Mirror']],
["Sahasrahla's Hut - Right", False, [], ['Moon Pearl', 'Pegasus Boots']],
["Sahasrahla's Hut - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Pegasus Boots']],
["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Pegasus Boots']],
["Sahasrahla's Hut - Right", True, ['Magic Mirror', 'Pegasus Boots']],
#["Sahasrahla's Hut - Right", True, ['Beat Agahnim 1', 'Pegasus Boots']],
["Sahasrahla's Hut - Right", True, ['Moon Pearl', 'Beat Agahnim 1']],
["Sahasrahla's Hut - Right", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Beat Agahnim 1']],
["Kakariko Well - Top", False, []],
["Kakariko Well - Top", False, [], ['Moon Pearl']],
["Kakariko Well - Top", True, ['Moon Pearl', 'Pegasus Boots']],
["Kakariko Well - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Kakariko Well - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Kakariko Well - Left", False, []],
["Kakariko Well - Left", True, ['Moon Pearl', 'Pegasus Boots']],
@@ -101,7 +107,8 @@ class TestLightWorld(TestInvertedOWG):
["Blind's Hideout - Top", False, []],
["Blind's Hideout - Top", False, [], ['Moon Pearl']],
["Blind's Hideout - Top", True, ['Moon Pearl', 'Pegasus Boots']],
["Blind's Hideout - Top", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Blind's Hideout - Top", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Blind's Hideout - Left", False, []],
["Blind's Hideout - Left", False, [], ['Moon Pearl', 'Magic Mirror']],
@@ -134,27 +141,33 @@ class TestLightWorld(TestInvertedOWG):
["Mini Moldorm Cave - Far Left", False, []],
["Mini Moldorm Cave - Far Left", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Far Left", True, ['Moon Pearl', 'Pegasus Boots']],
["Mini Moldorm Cave - Far Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Far Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Pegasus Boots']],
["Mini Moldorm Cave - Left", False, []],
["Mini Moldorm Cave - Left", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Left", True, ['Moon Pearl', 'Pegasus Boots']],
["Mini Moldorm Cave - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Left", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Pegasus Boots']],
["Mini Moldorm Cave - Right", False, []],
["Mini Moldorm Cave - Right", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Right", True, ['Moon Pearl', 'Pegasus Boots']],
["Mini Moldorm Cave - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Pegasus Boots']],
["Mini Moldorm Cave - Far Right", False, []],
["Mini Moldorm Cave - Far Right", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Far Right", True, ['Moon Pearl', 'Pegasus Boots']],
["Mini Moldorm Cave - Far Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Far Right", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Pegasus Boots']],
["Mini Moldorm Cave - Generous Guy", False, []],
["Mini Moldorm Cave - Generous Guy", False, [], ['Moon Pearl']],
["Mini Moldorm Cave - Generous Guy", True, ['Moon Pearl', 'Pegasus Boots']],
["Mini Moldorm Cave - Generous Guy", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mini Moldorm Cave - Generous Guy", True, ['Bomb Upgrade (+5)', 'Progressive Sword', 'Moon Pearl', 'Pegasus Boots']],
["Ice Rod Cave", False, []],
["Ice Rod Cave", False, [], ['Moon Pearl']],
["Ice Rod Cave", True, ['Moon Pearl', 'Pegasus Boots']],
["Ice Rod Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Ice Rod Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
#I don't think so
#["Ice Rod Cave", True, ['Magic Mirror', 'Pegasus Boots', 'BigRedBomb']],
#["Ice Rod Cave", True, ['Magic Mirror', 'Beat Agahnim 1', 'BigRedBomb']],
@@ -236,7 +249,8 @@ class TestLightWorld(TestInvertedOWG):
["Graveyard Cave", False, []],
["Graveyard Cave", False, [], ['Moon Pearl']],
["Graveyard Cave", True, ['Moon Pearl', 'Pegasus Boots']],
["Graveyard Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Graveyard Cave", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots']],
["Checkerboard Cave", False, []],
["Checkerboard Cave", False, [], ['Progressive Glove']],

View File

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

View File

@@ -48,7 +48,8 @@ class TestDeathMountain(TestMinor):
["Mimic Cave", False, [], ['Moon Pearl']],
["Mimic Cave", False, [], ['Cane of Somaria']],
["Mimic Cave", False, ['Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']],
["Mimic Cave", True, ['Quake', 'Progressive Sword', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Moon Pearl', 'Cane of Somaria', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Mimic Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Quake', 'Progressive Sword', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Moon Pearl', 'Cane of Somaria', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Spiral Cave", False, []],
["Spiral Cave", False, [], ['Progressive Glove', 'Flute']],
@@ -73,10 +74,11 @@ class TestDeathMountain(TestMinor):
["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Far Left", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']],
["Paradox Cave Lower - Far Left", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Left", False, []],
["Paradox Cave Lower - Left", False, [], ['Progressive Glove', 'Flute']],
@@ -87,10 +89,11 @@ class TestDeathMountain(TestMinor):
["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Left", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']],
["Paradox Cave Lower - Left", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Middle", False, []],
["Paradox Cave Lower - Middle", False, [], ['Progressive Glove', 'Flute']],
@@ -101,10 +104,11 @@ class TestDeathMountain(TestMinor):
["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Middle", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Middle", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Middle", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']],
["Paradox Cave Lower - Middle", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Middle", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Right", False, []],
["Paradox Cave Lower - Right", False, [], ['Progressive Glove', 'Flute']],
@@ -115,10 +119,11 @@ class TestDeathMountain(TestMinor):
["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Right", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']],
["Paradox Cave Lower - Right", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Right", False, []],
["Paradox Cave Lower - Far Right", False, [], ['Progressive Glove', 'Flute']],
@@ -129,10 +134,11 @@ class TestDeathMountain(TestMinor):
["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Far Right", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)', 'Progressive Sword', 'Progressive Bow', 'Fire Rod', 'Cane of Somaria']],
["Paradox Cave Lower - Far Right", True, ['Cane of Somaria', 'Flute', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Progressive Sword', 'Progressive Sword', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Progressive Bow', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Left", False, []],
["Paradox Cave Upper - Left", False, [], ['Progressive Glove', 'Flute']],
@@ -143,10 +149,11 @@ class TestDeathMountain(TestMinor):
["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Upper - Left", False, ['Flute', 'Hammer']],
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Left", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Left", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Right", False, []],
["Paradox Cave Upper - Right", False, [], ['Progressive Glove', 'Flute']],
@@ -157,10 +164,11 @@ class TestDeathMountain(TestMinor):
["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Upper - Right", False, ['Flute', 'Hammer']],
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Right", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Right", False, ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']],
])
def testWestDarkWorldDeathMountain(self):

View File

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

View File

@@ -10,7 +10,9 @@ from worlds.alttp.test import LTTPTestBase
class TestMinor(TestBase, LTTPTestBase):
def setUp(self):
self.world_setup()
self.multiworld.logic[1] = "minorglitches"
self.multiworld.glitches_required[1] = "minor_glitches"
self.multiworld.bombless_start[1].value = True
self.multiworld.shuffle_capacity_upgrades[1].value = True
self.multiworld.difficulty_requirements[1] = difficulties['normal']
self.multiworld.worlds[1].er_seed = 0
self.multiworld.worlds[1].create_regions()

View File

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

View File

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

View File

@@ -6,13 +6,14 @@ class TestDungeons(TestVanillaOWG):
def testFirstDungeonChests(self):
self.run_location_tests([
["Hyrule Castle - Map Chest", True, []],
["Hyrule Castle - Map Guard Key Drop", True, []],
["Hyrule Castle - Map Guard Key Drop", False, []],
["Hyrule Castle - Map Guard Key Drop", True, ['Progressive Sword']],
["Sanctuary", True, []],
["Sewers - Secret Room - Left", False, []],
["Sewers - Secret Room - Left", True, ['Progressive Glove']],
["Sewers - Secret Room - Left", True, ['Lamp', 'Small Key (Hyrule Castle)']],
["Sewers - Secret Room - Left", True, ['Pegasus Boots', 'Progressive Glove']],
["Sewers - Secret Room - Left", True, ['Bomb Upgrade (+5)', 'Lamp', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)', 'Small Key (Hyrule Castle)']],
["Eastern Palace - Compass Chest", True, []],
@@ -25,8 +26,8 @@ class TestDungeons(TestVanillaOWG):
["Desert Palace - Boss", False, [], ['Small Key (Desert Palace)']],
["Desert Palace - Boss", False, [], ['Big Key (Desert Palace)']],
["Desert Palace - Boss", False, [], ['Lamp', 'Fire Rod']],
["Desert Palace - Boss", True, ['Progressive Sword', 'Small Key (Desert Palace)', 'Pegasus Boots', 'Lamp', 'Big Key (Desert Palace)']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Pegasus Boots', 'Fire Rod', 'Big Key (Desert Palace)']],
["Desert Palace - Boss", True, ['Progressive Sword', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Pegasus Boots', 'Lamp', 'Big Key (Desert Palace)']],
["Desert Palace - Boss", True, ['Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Small Key (Desert Palace)', 'Pegasus Boots', 'Fire Rod', 'Big Key (Desert Palace)']],
["Tower of Hera - Basement Cage", False, []],
["Tower of Hera - Basement Cage", False, [], ['Pegasus Boots', "Flute", "Progressive Glove"]],
@@ -41,10 +42,9 @@ class TestDungeons(TestVanillaOWG):
["Castle Tower - Room 03", False, []],
["Castle Tower - Room 03", False, ['Progressive Sword'], ['Progressive Sword', 'Cape', 'Beat Agahnim 1']],
["Castle Tower - Room 03", False, [], ['Progressive Sword', 'Hammer', 'Progressive Bow', 'Fire Rod', 'Ice Rod', 'Cane of Somaria', 'Cane of Byrna']],
["Castle Tower - Room 03", True, ['Progressive Sword', 'Progressive Sword']],
["Castle Tower - Room 03", True, ['Cape', 'Progressive Bow']],
["Castle Tower - Room 03", True, ['Beat Agahnim 1', 'Fire Rod']],
["Castle Tower - Room 03", True, ['Progressive Sword', 'Cape']],
["Castle Tower - Room 03", True, ['Progressive Sword', 'Beat Agahnim 1']],
["Palace of Darkness - Shooter Room", False, []],
["Palace of Darkness - Shooter Room", False, [], ['Moon Pearl']],
@@ -69,9 +69,10 @@ class TestDungeons(TestVanillaOWG):
["Skull Woods - Big Chest", False, []],
["Skull Woods - Big Chest", False, [], ['Big Key (Skull Woods)']],
["Skull Woods - Big Chest", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
#todo: Bomb Jump in logic?
#["Skull Woods - Big Chest", True, ['Magic Mirror', 'Pegasus Boots', 'Big Key (Skull Woods)']],
["Skull Woods - Big Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Big Key (Skull Woods)']],
["Skull Woods - Big Chest", True, ['Bomb Upgrade (+5)', 'Moon Pearl', 'Pegasus Boots', 'Big Key (Skull Woods)']],
["Skull Woods - Big Key Chest", False, []],
["Skull Woods - Big Key Chest", True, ['Magic Mirror', 'Pegasus Boots']],
@@ -89,10 +90,10 @@ class TestDungeons(TestVanillaOWG):
["Ice Palace - Compass Chest", False, []],
["Ice Palace - Compass Chest", False, [], ['Fire Rod', 'Bombos']],
["Ice Palace - Compass Chest", False, [], ['Fire Rod', 'Progressive Sword']],
["Ice Palace - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Flippers', 'Fire Rod']],
["Ice Palace - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Flippers', 'Bombos', 'Progressive Sword']],
["Ice Palace - Compass Chest", True, ['Progressive Glove', 'Progressive Glove', 'Fire Rod']],
["Ice Palace - Compass Chest", True, ['Progressive Glove', 'Progressive Glove', 'Bombos', 'Progressive Sword']],
["Ice Palace - Compass Chest", True, ['Small Key (Ice Palace)', 'Moon Pearl', 'Pegasus Boots', 'Flippers', 'Fire Rod']],
["Ice Palace - Compass Chest", True, ['Small Key (Ice Palace)', 'Moon Pearl', 'Pegasus Boots', 'Flippers', 'Bombos', 'Progressive Sword']],
["Ice Palace - Compass Chest", True, ['Small Key (Ice Palace)', 'Progressive Glove', 'Progressive Glove', 'Fire Rod']],
["Ice Palace - Compass Chest", True, ['Small Key (Ice Palace)', 'Progressive Glove', 'Progressive Glove', 'Bombos', 'Progressive Sword']],
["Misery Mire - Bridge Chest", False, []],
["Misery Mire - Bridge Chest", False, [], ['Moon Pearl']],
@@ -104,15 +105,15 @@ class TestDungeons(TestVanillaOWG):
["Turtle Rock - Compass Chest", False, [], ['Cane of Somaria']],
#todo: does clip require sword?
#["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', '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', 'Pegasus Boots', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Progressive Sword']],
["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Progressive Sword']],
["Turtle Rock - Compass Chest", True, ['Moon Pearl', 'Pegasus Boots', 'Cane of Somaria', 'Progressive Sword', 'Quake']],
["Turtle Rock - Compass Chest", True, ['Pegasus Boots', '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, ['Pegasus Boots', 'Magic Mirror', 'Cane of Somaria', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Turtle Rock - Chain Chomps", False, []],
#todo: does clip require sword?
#["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Pegasus Boots']],
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Pegasus Boots', 'Progressive Sword']],
["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror']],
["Turtle Rock - Chain Chomps", True, ['Moon Pearl', 'Pegasus Boots', 'Progressive Sword', 'Progressive Sword']],
["Turtle Rock - Chain Chomps", True, ['Pegasus Boots', 'Magic Mirror', 'Progressive Bow']],
["Turtle Rock - Crystaroller Room", False, []],
["Turtle Rock - Crystaroller Room", False, [], ['Big Key (Turtle Rock)']],

View File

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

View File

@@ -11,7 +11,9 @@ class TestVanillaOWG(TestBase, LTTPTestBase):
def setUp(self):
self.world_setup()
self.multiworld.difficulty_requirements[1] = difficulties['normal']
self.multiworld.logic[1] = "owglitches"
self.multiworld.glitches_required[1] = "overworld_glitches"
self.multiworld.bombless_start[1].value = True
self.multiworld.shuffle_capacity_upgrades[1].value = True
self.multiworld.worlds[1].er_seed = 0
self.multiworld.worlds[1].create_regions()
self.multiworld.worlds[1].create_items()

View File

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

View File

@@ -48,7 +48,8 @@ class TestDeathMountain(TestVanilla):
["Mimic Cave", False, [], ['Moon Pearl']],
["Mimic Cave", False, [], ['Cane of Somaria']],
["Mimic Cave", False, ['Small Key (Turtle Rock)'], ['Small Key (Turtle Rock)']],
["Mimic Cave", True, ['Quake', 'Progressive Sword', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Moon Pearl', 'Cane of Somaria', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Mimic Cave", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Mimic Cave", True, ['Bomb Upgrade (+5)', 'Quake', 'Progressive Sword', 'Flute', 'Progressive Glove', 'Progressive Glove', 'Hammer', 'Moon Pearl', 'Cane of Somaria', 'Magic Mirror', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)', 'Small Key (Turtle Rock)']],
["Spiral Cave", False, []],
["Spiral Cave", False, [], ['Progressive Glove', 'Flute']],
@@ -73,10 +74,10 @@ class TestDeathMountain(TestVanilla):
["Paradox Cave Lower - Far Left", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Far Left", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Hookshot', 'Cane of Somaria']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Far Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Far Left", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']],
["Paradox Cave Lower - Left", False, []],
["Paradox Cave Lower - Left", False, [], ['Progressive Glove', 'Flute']],
@@ -87,10 +88,10 @@ class TestDeathMountain(TestVanilla):
["Paradox Cave Lower - Left", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Left", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Left", True, ['Flute', 'Hookshot', 'Cane of Somaria']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Left", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']],
["Paradox Cave Lower - Middle", False, []],
["Paradox Cave Lower - Middle", False, [], ['Progressive Glove', 'Flute']],
@@ -101,10 +102,10 @@ class TestDeathMountain(TestVanilla):
["Paradox Cave Lower - Middle", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Middle", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Middle", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Hookshot', 'Cane of Somaria']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Middle", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Middle", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']],
["Paradox Cave Lower - Right", False, []],
["Paradox Cave Lower - Right", False, [], ['Progressive Glove', 'Flute']],
@@ -115,10 +116,10 @@ class TestDeathMountain(TestVanilla):
["Paradox Cave Lower - Right", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Right", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Right", True, ['Flute', 'Hookshot', 'Cane of Somaria']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Right", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']],
["Paradox Cave Lower - Far Right", False, []],
["Paradox Cave Lower - Far Right", False, [], ['Progressive Glove', 'Flute']],
@@ -129,10 +130,10 @@ class TestDeathMountain(TestVanilla):
["Paradox Cave Lower - Far Right", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Lower - Far Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Lower - Far Right", False, ['Flute', 'Hammer']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Hookshot', 'Cane of Somaria']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Hookshot', 'Bomb Upgrade (+5)']],
["Paradox Cave Lower - Far Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer', 'Progressive Sword', 'Progressive Sword']],
["Paradox Cave Lower - Far Right", True, ['Flute', 'Magic Mirror', 'Hammer', 'Fire Rod']],
["Paradox Cave Upper - Left", False, []],
["Paradox Cave Upper - Left", False, [], ['Progressive Glove', 'Flute']],
@@ -143,10 +144,11 @@ class TestDeathMountain(TestVanilla):
["Paradox Cave Upper - Left", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Left", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Upper - Left", False, ['Flute', 'Hammer']],
["Paradox Cave Upper - Left", True, ['Flute', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Left", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Left", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Left", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Right", False, []],
["Paradox Cave Upper - Right", False, [], ['Progressive Glove', 'Flute']],
@@ -157,10 +159,11 @@ class TestDeathMountain(TestVanilla):
["Paradox Cave Upper - Right", False, ['Progressive Glove', 'Hookshot']],
["Paradox Cave Upper - Right", False, ['Flute', 'Magic Mirror']],
["Paradox Cave Upper - Right", False, ['Flute', 'Hammer']],
["Paradox Cave Upper - Right", True, ['Flute', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Right", True, ['Flute', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Right", False, [], ['Bomb Upgrade (+5)', 'Bomb Upgrade (+10)', 'Bomb Upgrade (50)']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Hookshot']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Progressive Glove', 'Lamp', 'Magic Mirror', 'Hammer']],
["Paradox Cave Upper - Right", True, ['Bomb Upgrade (+5)', 'Flute', 'Magic Mirror', 'Hammer']],
])
def testWestDarkWorldDeathMountain(self):

View File

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

View File

@@ -9,8 +9,10 @@ from worlds.alttp.test import LTTPTestBase
class TestVanilla(TestBase, LTTPTestBase):
def setUp(self):
self.world_setup()
self.multiworld.logic[1] = "noglitches"
self.multiworld.glitches_required[1] = "no_glitches"
self.multiworld.difficulty_requirements[1] = difficulties['normal']
self.multiworld.bombless_start[1].value = True
self.multiworld.shuffle_capacity_upgrades[1].value = True
self.multiworld.worlds[1].er_seed = 0
self.multiworld.worlds[1].create_regions()
self.multiworld.worlds[1].create_items()

View File

@@ -14,7 +14,7 @@ from worlds.generic.Rules import forbid_item
class BumpStikWeb(WebWorld):
tutorials = [Tutorial(
"Bumper Stickers Setup Tutorial",
"Bumper Stickers Setup Guide",
"A guide to setting up the Archipelago Bumper Stickers software on your computer.",
"English",
"setup_en.md",

View File

@@ -10,7 +10,7 @@ client_version = 7
class ChecksFinderWeb(WebWorld):
tutorials = [Tutorial(
"Multiworld Setup Tutorial",
"Multiworld Setup Guide",
"A guide to setting up the Archipelago ChecksFinder software on your computer. This guide covers "
"single-player, multiworld, and related software.",
"English",

View File

@@ -15,7 +15,7 @@ from .Options import RandomizeWeaponLevelOption, PoolTypeOption, EarlySmallLothr
class DarkSouls3Web(WebWorld):
bug_report_page = "https://github.com/Marechal-L/Dark-Souls-III-Archipelago-client/issues"
setup_en = Tutorial(
"Multiworld Setup Tutorial",
"Multiworld Setup Guide",
"A guide to setting up the Archipelago Dark Souls III randomizer on your computer.",
"English",
"setup_en.md",

View File

@@ -2,6 +2,7 @@ import typing
from BaseClasses import Location
from .Names import LocationName
from worlds.AutoWorld import World
class DKC3Location(Location):
@@ -321,13 +322,13 @@ all_locations = {
location_table = {}
def setup_locations(world, player: int):
def setup_locations(world: World):
location_table = {**level_location_table, **boss_location_table, **secret_cave_location_table}
if False:#world.include_trade_sequence[player].value:
if False:#world.options.include_trade_sequence:
location_table.update({**brothers_bear_location_table})
if world.kongsanity[player].value:
if world.options.kongsanity:
location_table.update({**kong_location_table})
return location_table

View File

@@ -1,6 +1,7 @@
from dataclasses import dataclass
import typing
from Options import Choice, Range, Option, Toggle, DeathLink, DefaultOnToggle, OptionList
from Options import Choice, Range, Option, Toggle, DeathLink, DefaultOnToggle, OptionList, PerGameCommonOptions
class Goal(Choice):
@@ -158,21 +159,21 @@ class StartingLifeCount(Range):
default = 5
dkc3_options: typing.Dict[str, type(Option)] = {
#"death_link": DeathLink, # Disabled
"goal": Goal,
#"include_trade_sequence": IncludeTradeSequence, # Disabled
"dk_coins_for_gyrocopter": DKCoinsForGyrocopter,
"krematoa_bonus_coin_cost": KrematoaBonusCoinCost,
"percentage_of_extra_bonus_coins": PercentageOfExtraBonusCoins,
"number_of_banana_birds": NumberOfBananaBirds,
"percentage_of_banana_birds": PercentageOfBananaBirds,
"kongsanity": KONGsanity,
"level_shuffle": LevelShuffle,
"difficulty": Difficulty,
"autosave": Autosave,
"merry": MERRY,
"music_shuffle": MusicShuffle,
"kong_palette_swap": KongPaletteSwap,
"starting_life_count": StartingLifeCount,
}
@dataclass
class DKC3Options(PerGameCommonOptions):
#death_link: DeathLink # Disabled
goal: Goal
#include_trade_sequence: IncludeTradeSequence # Disabled
dk_coins_for_gyrocopter: DKCoinsForGyrocopter
krematoa_bonus_coin_cost: KrematoaBonusCoinCost
percentage_of_extra_bonus_coins: PercentageOfExtraBonusCoins
number_of_banana_birds: NumberOfBananaBirds
percentage_of_banana_birds: PercentageOfBananaBirds
kongsanity: KONGsanity
level_shuffle: LevelShuffle
difficulty: Difficulty
autosave: Autosave
merry: MERRY
music_shuffle: MusicShuffle
kong_palette_swap: KongPaletteSwap
starting_life_count: StartingLifeCount

View File

@@ -4,38 +4,39 @@ from BaseClasses import MultiWorld, Region, Entrance
from .Items import DKC3Item
from .Locations import DKC3Location
from .Names import LocationName, ItemName
from worlds.AutoWorld import World
def create_regions(world, player: int, active_locations):
menu_region = create_region(world, player, active_locations, 'Menu', None)
def create_regions(world: World, active_locations):
menu_region = create_region(world, active_locations, 'Menu', None)
overworld_1_region_locations = {}
if world.goal[player] != "knautilus":
if world.options.goal != "knautilus":
overworld_1_region_locations.update({LocationName.banana_bird_mother: []})
overworld_1_region = create_region(world, player, active_locations, LocationName.overworld_1_region,
overworld_1_region = create_region(world, active_locations, LocationName.overworld_1_region,
overworld_1_region_locations)
overworld_2_region_locations = {}
overworld_2_region = create_region(world, player, active_locations, LocationName.overworld_2_region,
overworld_2_region = create_region(world, active_locations, LocationName.overworld_2_region,
overworld_2_region_locations)
overworld_3_region_locations = {}
overworld_3_region = create_region(world, player, active_locations, LocationName.overworld_3_region,
overworld_3_region = create_region(world, active_locations, LocationName.overworld_3_region,
overworld_3_region_locations)
overworld_4_region_locations = {}
overworld_4_region = create_region(world, player, active_locations, LocationName.overworld_4_region,
overworld_4_region = create_region(world, active_locations, LocationName.overworld_4_region,
overworld_4_region_locations)
lake_orangatanga_region = create_region(world, player, active_locations, LocationName.lake_orangatanga_region, None)
kremwood_forest_region = create_region(world, player, active_locations, LocationName.kremwood_forest_region, None)
cotton_top_cove_region = create_region(world, player, active_locations, LocationName.cotton_top_cove_region, None)
mekanos_region = create_region(world, player, active_locations, LocationName.mekanos_region, None)
k3_region = create_region(world, player, active_locations, LocationName.k3_region, None)
razor_ridge_region = create_region(world, player, active_locations, LocationName.razor_ridge_region, None)
kaos_kore_region = create_region(world, player, active_locations, LocationName.kaos_kore_region, None)
krematoa_region = create_region(world, player, active_locations, LocationName.krematoa_region, None)
lake_orangatanga_region = create_region(world, active_locations, LocationName.lake_orangatanga_region, None)
kremwood_forest_region = create_region(world, active_locations, LocationName.kremwood_forest_region, None)
cotton_top_cove_region = create_region(world, active_locations, LocationName.cotton_top_cove_region, None)
mekanos_region = create_region(world, active_locations, LocationName.mekanos_region, None)
k3_region = create_region(world, active_locations, LocationName.k3_region, None)
razor_ridge_region = create_region(world, active_locations, LocationName.razor_ridge_region, None)
kaos_kore_region = create_region(world, active_locations, LocationName.kaos_kore_region, None)
krematoa_region = create_region(world, active_locations, LocationName.krematoa_region, None)
lakeside_limbo_region_locations = {
@@ -44,9 +45,9 @@ def create_regions(world, player: int, active_locations):
LocationName.lakeside_limbo_bonus_2 : [0x657, 3],
LocationName.lakeside_limbo_dk : [0x657, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
lakeside_limbo_region_locations[LocationName.lakeside_limbo_kong] = []
lakeside_limbo_region = create_region(world, player, active_locations, LocationName.lakeside_limbo_region,
lakeside_limbo_region = create_region(world, active_locations, LocationName.lakeside_limbo_region,
lakeside_limbo_region_locations)
doorstop_dash_region_locations = {
@@ -55,9 +56,9 @@ def create_regions(world, player: int, active_locations):
LocationName.doorstop_dash_bonus_2 : [0x65A, 3],
LocationName.doorstop_dash_dk : [0x65A, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
doorstop_dash_region_locations[LocationName.doorstop_dash_kong] = []
doorstop_dash_region = create_region(world, player, active_locations, LocationName.doorstop_dash_region,
doorstop_dash_region = create_region(world, active_locations, LocationName.doorstop_dash_region,
doorstop_dash_region_locations)
tidal_trouble_region_locations = {
@@ -66,9 +67,9 @@ def create_regions(world, player: int, active_locations):
LocationName.tidal_trouble_bonus_2 : [0x659, 3],
LocationName.tidal_trouble_dk : [0x659, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
tidal_trouble_region_locations[LocationName.tidal_trouble_kong] = []
tidal_trouble_region = create_region(world, player, active_locations, LocationName.tidal_trouble_region,
tidal_trouble_region = create_region(world, active_locations, LocationName.tidal_trouble_region,
tidal_trouble_region_locations)
skiddas_row_region_locations = {
@@ -77,9 +78,9 @@ def create_regions(world, player: int, active_locations):
LocationName.skiddas_row_bonus_2 : [0x65D, 3],
LocationName.skiddas_row_dk : [0x65D, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
skiddas_row_region_locations[LocationName.skiddas_row_kong] = []
skiddas_row_region = create_region(world, player, active_locations, LocationName.skiddas_row_region,
skiddas_row_region = create_region(world, active_locations, LocationName.skiddas_row_region,
skiddas_row_region_locations)
murky_mill_region_locations = {
@@ -88,9 +89,9 @@ def create_regions(world, player: int, active_locations):
LocationName.murky_mill_bonus_2 : [0x65C, 3],
LocationName.murky_mill_dk : [0x65C, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
murky_mill_region_locations[LocationName.murky_mill_kong] = []
murky_mill_region = create_region(world, player, active_locations, LocationName.murky_mill_region,
murky_mill_region = create_region(world, active_locations, LocationName.murky_mill_region,
murky_mill_region_locations)
barrel_shield_bust_up_region_locations = {
@@ -99,9 +100,9 @@ def create_regions(world, player: int, active_locations):
LocationName.barrel_shield_bust_up_bonus_2 : [0x662, 3],
LocationName.barrel_shield_bust_up_dk : [0x662, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
barrel_shield_bust_up_region_locations[LocationName.barrel_shield_bust_up_kong] = []
barrel_shield_bust_up_region = create_region(world, player, active_locations,
barrel_shield_bust_up_region = create_region(world, active_locations,
LocationName.barrel_shield_bust_up_region,
barrel_shield_bust_up_region_locations)
@@ -111,9 +112,9 @@ def create_regions(world, player: int, active_locations):
LocationName.riverside_race_bonus_2 : [0x664, 3],
LocationName.riverside_race_dk : [0x664, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
riverside_race_region_locations[LocationName.riverside_race_kong] = []
riverside_race_region = create_region(world, player, active_locations, LocationName.riverside_race_region,
riverside_race_region = create_region(world, active_locations, LocationName.riverside_race_region,
riverside_race_region_locations)
squeals_on_wheels_region_locations = {
@@ -122,9 +123,9 @@ def create_regions(world, player: int, active_locations):
LocationName.squeals_on_wheels_bonus_2 : [0x65B, 3],
LocationName.squeals_on_wheels_dk : [0x65B, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
squeals_on_wheels_region_locations[LocationName.squeals_on_wheels_kong] = []
squeals_on_wheels_region = create_region(world, player, active_locations, LocationName.squeals_on_wheels_region,
squeals_on_wheels_region = create_region(world, active_locations, LocationName.squeals_on_wheels_region,
squeals_on_wheels_region_locations)
springin_spiders_region_locations = {
@@ -133,9 +134,9 @@ def create_regions(world, player: int, active_locations):
LocationName.springin_spiders_bonus_2 : [0x661, 3],
LocationName.springin_spiders_dk : [0x661, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
springin_spiders_region_locations[LocationName.springin_spiders_kong] = []
springin_spiders_region = create_region(world, player, active_locations, LocationName.springin_spiders_region,
springin_spiders_region = create_region(world, active_locations, LocationName.springin_spiders_region,
springin_spiders_region_locations)
bobbing_barrel_brawl_region_locations = {
@@ -144,9 +145,9 @@ def create_regions(world, player: int, active_locations):
LocationName.bobbing_barrel_brawl_bonus_2 : [0x666, 3],
LocationName.bobbing_barrel_brawl_dk : [0x666, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
bobbing_barrel_brawl_region_locations[LocationName.bobbing_barrel_brawl_kong] = []
bobbing_barrel_brawl_region = create_region(world, player, active_locations,
bobbing_barrel_brawl_region = create_region(world, active_locations,
LocationName.bobbing_barrel_brawl_region,
bobbing_barrel_brawl_region_locations)
@@ -156,9 +157,9 @@ def create_regions(world, player: int, active_locations):
LocationName.bazzas_blockade_bonus_2 : [0x667, 3],
LocationName.bazzas_blockade_dk : [0x667, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
bazzas_blockade_region_locations[LocationName.bazzas_blockade_kong] = []
bazzas_blockade_region = create_region(world, player, active_locations, LocationName.bazzas_blockade_region,
bazzas_blockade_region = create_region(world, active_locations, LocationName.bazzas_blockade_region,
bazzas_blockade_region_locations)
rocket_barrel_ride_region_locations = {
@@ -167,9 +168,9 @@ def create_regions(world, player: int, active_locations):
LocationName.rocket_barrel_ride_bonus_2 : [0x66A, 3],
LocationName.rocket_barrel_ride_dk : [0x66A, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
rocket_barrel_ride_region_locations[LocationName.rocket_barrel_ride_kong] = []
rocket_barrel_ride_region = create_region(world, player, active_locations, LocationName.rocket_barrel_ride_region,
rocket_barrel_ride_region = create_region(world, active_locations, LocationName.rocket_barrel_ride_region,
rocket_barrel_ride_region_locations)
kreeping_klasps_region_locations = {
@@ -178,9 +179,9 @@ def create_regions(world, player: int, active_locations):
LocationName.kreeping_klasps_bonus_2 : [0x658, 3],
LocationName.kreeping_klasps_dk : [0x658, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
kreeping_klasps_region_locations[LocationName.kreeping_klasps_kong] = []
kreeping_klasps_region = create_region(world, player, active_locations, LocationName.kreeping_klasps_region,
kreeping_klasps_region = create_region(world, active_locations, LocationName.kreeping_klasps_region,
kreeping_klasps_region_locations)
tracker_barrel_trek_region_locations = {
@@ -189,9 +190,9 @@ def create_regions(world, player: int, active_locations):
LocationName.tracker_barrel_trek_bonus_2 : [0x66B, 3],
LocationName.tracker_barrel_trek_dk : [0x66B, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
tracker_barrel_trek_region_locations[LocationName.tracker_barrel_trek_kong] = []
tracker_barrel_trek_region = create_region(world, player, active_locations, LocationName.tracker_barrel_trek_region,
tracker_barrel_trek_region = create_region(world, active_locations, LocationName.tracker_barrel_trek_region,
tracker_barrel_trek_region_locations)
fish_food_frenzy_region_locations = {
@@ -200,9 +201,9 @@ def create_regions(world, player: int, active_locations):
LocationName.fish_food_frenzy_bonus_2 : [0x668, 3],
LocationName.fish_food_frenzy_dk : [0x668, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
fish_food_frenzy_region_locations[LocationName.fish_food_frenzy_kong] = []
fish_food_frenzy_region = create_region(world, player, active_locations, LocationName.fish_food_frenzy_region,
fish_food_frenzy_region = create_region(world, active_locations, LocationName.fish_food_frenzy_region,
fish_food_frenzy_region_locations)
fire_ball_frenzy_region_locations = {
@@ -211,9 +212,9 @@ def create_regions(world, player: int, active_locations):
LocationName.fire_ball_frenzy_bonus_2 : [0x66D, 3],
LocationName.fire_ball_frenzy_dk : [0x66D, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
fire_ball_frenzy_region_locations[LocationName.fire_ball_frenzy_kong] = []
fire_ball_frenzy_region = create_region(world, player, active_locations, LocationName.fire_ball_frenzy_region,
fire_ball_frenzy_region = create_region(world, active_locations, LocationName.fire_ball_frenzy_region,
fire_ball_frenzy_region_locations)
demolition_drain_pipe_region_locations = {
@@ -222,9 +223,9 @@ def create_regions(world, player: int, active_locations):
LocationName.demolition_drain_pipe_bonus_2 : [0x672, 3],
LocationName.demolition_drain_pipe_dk : [0x672, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
demolition_drain_pipe_region_locations[LocationName.demolition_drain_pipe_kong] = []
demolition_drain_pipe_region = create_region(world, player, active_locations,
demolition_drain_pipe_region = create_region(world, active_locations,
LocationName.demolition_drain_pipe_region,
demolition_drain_pipe_region_locations)
@@ -234,9 +235,9 @@ def create_regions(world, player: int, active_locations):
LocationName.ripsaw_rage_bonus_2 : [0x660, 3],
LocationName.ripsaw_rage_dk : [0x660, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
ripsaw_rage_region_locations[LocationName.ripsaw_rage_kong] = []
ripsaw_rage_region = create_region(world, player, active_locations, LocationName.ripsaw_rage_region,
ripsaw_rage_region = create_region(world, active_locations, LocationName.ripsaw_rage_region,
ripsaw_rage_region_locations)
blazing_bazookas_region_locations = {
@@ -245,9 +246,9 @@ def create_regions(world, player: int, active_locations):
LocationName.blazing_bazookas_bonus_2 : [0x66E, 3],
LocationName.blazing_bazookas_dk : [0x66E, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
blazing_bazookas_region_locations[LocationName.blazing_bazookas_kong] = []
blazing_bazookas_region = create_region(world, player, active_locations, LocationName.blazing_bazookas_region,
blazing_bazookas_region = create_region(world, active_locations, LocationName.blazing_bazookas_region,
blazing_bazookas_region_locations)
low_g_labyrinth_region_locations = {
@@ -256,9 +257,9 @@ def create_regions(world, player: int, active_locations):
LocationName.low_g_labyrinth_bonus_2 : [0x670, 3],
LocationName.low_g_labyrinth_dk : [0x670, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
low_g_labyrinth_region_locations[LocationName.low_g_labyrinth_kong] = []
low_g_labyrinth_region = create_region(world, player, active_locations, LocationName.low_g_labyrinth_region,
low_g_labyrinth_region = create_region(world, active_locations, LocationName.low_g_labyrinth_region,
low_g_labyrinth_region_locations)
krevice_kreepers_region_locations = {
@@ -267,9 +268,9 @@ def create_regions(world, player: int, active_locations):
LocationName.krevice_kreepers_bonus_2 : [0x673, 3],
LocationName.krevice_kreepers_dk : [0x673, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
krevice_kreepers_region_locations[LocationName.krevice_kreepers_kong] = []
krevice_kreepers_region = create_region(world, player, active_locations, LocationName.krevice_kreepers_region,
krevice_kreepers_region = create_region(world, active_locations, LocationName.krevice_kreepers_region,
krevice_kreepers_region_locations)
tearaway_toboggan_region_locations = {
@@ -278,9 +279,9 @@ def create_regions(world, player: int, active_locations):
LocationName.tearaway_toboggan_bonus_2 : [0x65F, 3],
LocationName.tearaway_toboggan_dk : [0x65F, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
tearaway_toboggan_region_locations[LocationName.tearaway_toboggan_kong] = []
tearaway_toboggan_region = create_region(world, player, active_locations, LocationName.tearaway_toboggan_region,
tearaway_toboggan_region = create_region(world, active_locations, LocationName.tearaway_toboggan_region,
tearaway_toboggan_region_locations)
barrel_drop_bounce_region_locations = {
@@ -289,9 +290,9 @@ def create_regions(world, player: int, active_locations):
LocationName.barrel_drop_bounce_bonus_2 : [0x66C, 3],
LocationName.barrel_drop_bounce_dk : [0x66C, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
barrel_drop_bounce_region_locations[LocationName.barrel_drop_bounce_kong] = []
barrel_drop_bounce_region = create_region(world, player, active_locations, LocationName.barrel_drop_bounce_region,
barrel_drop_bounce_region = create_region(world, active_locations, LocationName.barrel_drop_bounce_region,
barrel_drop_bounce_region_locations)
krack_shot_kroc_region_locations = {
@@ -300,9 +301,9 @@ def create_regions(world, player: int, active_locations):
LocationName.krack_shot_kroc_bonus_2 : [0x66F, 3],
LocationName.krack_shot_kroc_dk : [0x66F, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
krack_shot_kroc_region_locations[LocationName.krack_shot_kroc_kong] = []
krack_shot_kroc_region = create_region(world, player, active_locations, LocationName.krack_shot_kroc_region,
krack_shot_kroc_region = create_region(world, active_locations, LocationName.krack_shot_kroc_region,
krack_shot_kroc_region_locations)
lemguin_lunge_region_locations = {
@@ -311,9 +312,9 @@ def create_regions(world, player: int, active_locations):
LocationName.lemguin_lunge_bonus_2 : [0x65E, 3],
LocationName.lemguin_lunge_dk : [0x65E, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
lemguin_lunge_region_locations[LocationName.lemguin_lunge_kong] = []
lemguin_lunge_region = create_region(world, player, active_locations, LocationName.lemguin_lunge_region,
lemguin_lunge_region = create_region(world, active_locations, LocationName.lemguin_lunge_region,
lemguin_lunge_region_locations)
buzzer_barrage_region_locations = {
@@ -322,9 +323,9 @@ def create_regions(world, player: int, active_locations):
LocationName.buzzer_barrage_bonus_2 : [0x676, 3],
LocationName.buzzer_barrage_dk : [0x676, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
buzzer_barrage_region_locations[LocationName.buzzer_barrage_kong] = []
buzzer_barrage_region = create_region(world, player, active_locations, LocationName.buzzer_barrage_region,
buzzer_barrage_region = create_region(world, active_locations, LocationName.buzzer_barrage_region,
buzzer_barrage_region_locations)
kong_fused_cliffs_region_locations = {
@@ -333,9 +334,9 @@ def create_regions(world, player: int, active_locations):
LocationName.kong_fused_cliffs_bonus_2 : [0x674, 3],
LocationName.kong_fused_cliffs_dk : [0x674, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
kong_fused_cliffs_region_locations[LocationName.kong_fused_cliffs_kong] = []
kong_fused_cliffs_region = create_region(world, player, active_locations, LocationName.kong_fused_cliffs_region,
kong_fused_cliffs_region = create_region(world, active_locations, LocationName.kong_fused_cliffs_region,
kong_fused_cliffs_region_locations)
floodlit_fish_region_locations = {
@@ -344,9 +345,9 @@ def create_regions(world, player: int, active_locations):
LocationName.floodlit_fish_bonus_2 : [0x669, 3],
LocationName.floodlit_fish_dk : [0x669, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
floodlit_fish_region_locations[LocationName.floodlit_fish_kong] = []
floodlit_fish_region = create_region(world, player, active_locations, LocationName.floodlit_fish_region,
floodlit_fish_region = create_region(world, active_locations, LocationName.floodlit_fish_region,
floodlit_fish_region_locations)
pothole_panic_region_locations = {
@@ -355,9 +356,9 @@ def create_regions(world, player: int, active_locations):
LocationName.pothole_panic_bonus_2 : [0x677, 3],
LocationName.pothole_panic_dk : [0x677, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
pothole_panic_region_locations[LocationName.pothole_panic_kong] = []
pothole_panic_region = create_region(world, player, active_locations, LocationName.pothole_panic_region,
pothole_panic_region = create_region(world, active_locations, LocationName.pothole_panic_region,
pothole_panic_region_locations)
ropey_rumpus_region_locations = {
@@ -366,9 +367,9 @@ def create_regions(world, player: int, active_locations):
LocationName.ropey_rumpus_bonus_2 : [0x675, 3],
LocationName.ropey_rumpus_dk : [0x675, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
ropey_rumpus_region_locations[LocationName.ropey_rumpus_kong] = []
ropey_rumpus_region = create_region(world, player, active_locations, LocationName.ropey_rumpus_region,
ropey_rumpus_region = create_region(world, active_locations, LocationName.ropey_rumpus_region,
ropey_rumpus_region_locations)
konveyor_rope_clash_region_locations = {
@@ -377,9 +378,9 @@ def create_regions(world, player: int, active_locations):
LocationName.konveyor_rope_clash_bonus_2 : [0x657, 3],
LocationName.konveyor_rope_clash_dk : [0x657, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
konveyor_rope_clash_region_locations[LocationName.konveyor_rope_clash_kong] = []
konveyor_rope_clash_region = create_region(world, player, active_locations, LocationName.konveyor_rope_clash_region,
konveyor_rope_clash_region = create_region(world, active_locations, LocationName.konveyor_rope_clash_region,
konveyor_rope_clash_region_locations)
creepy_caverns_region_locations = {
@@ -388,9 +389,9 @@ def create_regions(world, player: int, active_locations):
LocationName.creepy_caverns_bonus_2 : [0x678, 3],
LocationName.creepy_caverns_dk : [0x678, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
creepy_caverns_region_locations[LocationName.creepy_caverns_kong] = []
creepy_caverns_region = create_region(world, player, active_locations, LocationName.creepy_caverns_region,
creepy_caverns_region = create_region(world, active_locations, LocationName.creepy_caverns_region,
creepy_caverns_region_locations)
lightning_lookout_region_locations = {
@@ -399,9 +400,9 @@ def create_regions(world, player: int, active_locations):
LocationName.lightning_lookout_bonus_2 : [0x665, 3],
LocationName.lightning_lookout_dk : [0x665, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
lightning_lookout_region_locations[LocationName.lightning_lookout_kong] = []
lightning_lookout_region = create_region(world, player, active_locations, LocationName.lightning_lookout_region,
lightning_lookout_region = create_region(world, active_locations, LocationName.lightning_lookout_region,
lightning_lookout_region_locations)
koindozer_klamber_region_locations = {
@@ -410,9 +411,9 @@ def create_regions(world, player: int, active_locations):
LocationName.koindozer_klamber_bonus_2 : [0x679, 3],
LocationName.koindozer_klamber_dk : [0x679, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
koindozer_klamber_region_locations[LocationName.koindozer_klamber_kong] = []
koindozer_klamber_region = create_region(world, player, active_locations, LocationName.koindozer_klamber_region,
koindozer_klamber_region = create_region(world, active_locations, LocationName.koindozer_klamber_region,
koindozer_klamber_region_locations)
poisonous_pipeline_region_locations = {
@@ -421,9 +422,9 @@ def create_regions(world, player: int, active_locations):
LocationName.poisonous_pipeline_bonus_2 : [0x671, 3],
LocationName.poisonous_pipeline_dk : [0x671, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
poisonous_pipeline_region_locations[LocationName.poisonous_pipeline_kong] = []
poisonous_pipeline_region = create_region(world, player, active_locations, LocationName.poisonous_pipeline_region,
poisonous_pipeline_region = create_region(world, active_locations, LocationName.poisonous_pipeline_region,
poisonous_pipeline_region_locations)
stampede_sprint_region_locations = {
@@ -433,9 +434,9 @@ def create_regions(world, player: int, active_locations):
LocationName.stampede_sprint_bonus_3 : [0x67B, 4],
LocationName.stampede_sprint_dk : [0x67B, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
stampede_sprint_region_locations[LocationName.stampede_sprint_kong] = []
stampede_sprint_region = create_region(world, player, active_locations, LocationName.stampede_sprint_region,
stampede_sprint_region = create_region(world, active_locations, LocationName.stampede_sprint_region,
stampede_sprint_region_locations)
criss_cross_cliffs_region_locations = {
@@ -444,9 +445,9 @@ def create_regions(world, player: int, active_locations):
LocationName.criss_cross_cliffs_bonus_2 : [0x67C, 3],
LocationName.criss_cross_cliffs_dk : [0x67C, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
criss_cross_cliffs_region_locations[LocationName.criss_cross_cliffs_kong] = []
criss_cross_cliffs_region = create_region(world, player, active_locations, LocationName.criss_cross_cliffs_region,
criss_cross_cliffs_region = create_region(world, active_locations, LocationName.criss_cross_cliffs_region,
criss_cross_cliffs_region_locations)
tyrant_twin_tussle_region_locations = {
@@ -456,9 +457,9 @@ def create_regions(world, player: int, active_locations):
LocationName.tyrant_twin_tussle_bonus_3 : [0x67D, 4],
LocationName.tyrant_twin_tussle_dk : [0x67D, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
tyrant_twin_tussle_region_locations[LocationName.tyrant_twin_tussle_kong] = []
tyrant_twin_tussle_region = create_region(world, player, active_locations, LocationName.tyrant_twin_tussle_region,
tyrant_twin_tussle_region = create_region(world, active_locations, LocationName.tyrant_twin_tussle_region,
tyrant_twin_tussle_region_locations)
swoopy_salvo_region_locations = {
@@ -468,147 +469,147 @@ def create_regions(world, player: int, active_locations):
LocationName.swoopy_salvo_bonus_3 : [0x663, 4],
LocationName.swoopy_salvo_dk : [0x663, 5],
}
if world.kongsanity[player]:
if world.options.kongsanity:
swoopy_salvo_region_locations[LocationName.swoopy_salvo_kong] = []
swoopy_salvo_region = create_region(world, player, active_locations, LocationName.swoopy_salvo_region,
swoopy_salvo_region = create_region(world, active_locations, LocationName.swoopy_salvo_region,
swoopy_salvo_region_locations)
rocket_rush_region_locations = {
LocationName.rocket_rush_flag : [0x67E, 1],
LocationName.rocket_rush_dk : [0x67E, 5],
}
rocket_rush_region = create_region(world, player, active_locations, LocationName.rocket_rush_region,
rocket_rush_region = create_region(world, active_locations, LocationName.rocket_rush_region,
rocket_rush_region_locations)
belchas_barn_region_locations = {
LocationName.belchas_barn: [0x64F, 1],
}
belchas_barn_region = create_region(world, player, active_locations, LocationName.belchas_barn_region,
belchas_barn_region = create_region(world, active_locations, LocationName.belchas_barn_region,
belchas_barn_region_locations)
arichs_ambush_region_locations = {
LocationName.arichs_ambush: [0x650, 1],
}
arichs_ambush_region = create_region(world, player, active_locations, LocationName.arichs_ambush_region,
arichs_ambush_region = create_region(world, active_locations, LocationName.arichs_ambush_region,
arichs_ambush_region_locations)
squirts_showdown_region_locations = {
LocationName.squirts_showdown: [0x651, 1],
}
squirts_showdown_region = create_region(world, player, active_locations, LocationName.squirts_showdown_region,
squirts_showdown_region = create_region(world, active_locations, LocationName.squirts_showdown_region,
squirts_showdown_region_locations)
kaos_karnage_region_locations = {
LocationName.kaos_karnage: [0x652, 1],
}
kaos_karnage_region = create_region(world, player, active_locations, LocationName.kaos_karnage_region,
kaos_karnage_region = create_region(world, active_locations, LocationName.kaos_karnage_region,
kaos_karnage_region_locations)
bleaks_house_region_locations = {
LocationName.bleaks_house: [0x653, 1],
}
bleaks_house_region = create_region(world, player, active_locations, LocationName.bleaks_house_region,
bleaks_house_region = create_region(world, active_locations, LocationName.bleaks_house_region,
bleaks_house_region_locations)
barboss_barrier_region_locations = {
LocationName.barboss_barrier: [0x654, 1],
}
barboss_barrier_region = create_region(world, player, active_locations, LocationName.barboss_barrier_region,
barboss_barrier_region = create_region(world, active_locations, LocationName.barboss_barrier_region,
barboss_barrier_region_locations)
kastle_kaos_region_locations = {
LocationName.kastle_kaos: [0x655, 1],
}
kastle_kaos_region = create_region(world, player, active_locations, LocationName.kastle_kaos_region,
kastle_kaos_region = create_region(world, active_locations, LocationName.kastle_kaos_region,
kastle_kaos_region_locations)
knautilus_region_locations = {
LocationName.knautilus: [0x656, 1],
}
knautilus_region = create_region(world, player, active_locations, LocationName.knautilus_region,
knautilus_region = create_region(world, active_locations, LocationName.knautilus_region,
knautilus_region_locations)
belchas_burrow_region_locations = {
LocationName.belchas_burrow: [0x647, 1],
}
belchas_burrow_region = create_region(world, player, active_locations, LocationName.belchas_burrow_region,
belchas_burrow_region = create_region(world, active_locations, LocationName.belchas_burrow_region,
belchas_burrow_region_locations)
kong_cave_region_locations = {
LocationName.kong_cave: [0x645, 1],
}
kong_cave_region = create_region(world, player, active_locations, LocationName.kong_cave_region,
kong_cave_region = create_region(world, active_locations, LocationName.kong_cave_region,
kong_cave_region_locations)
undercover_cove_region_locations = {
LocationName.undercover_cove: [0x644, 1],
}
undercover_cove_region = create_region(world, player, active_locations, LocationName.undercover_cove_region,
undercover_cove_region = create_region(world, active_locations, LocationName.undercover_cove_region,
undercover_cove_region_locations)
ks_cache_region_locations = {
LocationName.ks_cache: [0x642, 1],
}
ks_cache_region = create_region(world, player, active_locations, LocationName.ks_cache_region,
ks_cache_region = create_region(world, active_locations, LocationName.ks_cache_region,
ks_cache_region_locations)
hill_top_hoard_region_locations = {
LocationName.hill_top_hoard: [0x643, 1],
}
hill_top_hoard_region = create_region(world, player, active_locations, LocationName.hill_top_hoard_region,
hill_top_hoard_region = create_region(world, active_locations, LocationName.hill_top_hoard_region,
hill_top_hoard_region_locations)
bounty_beach_region_locations = {
LocationName.bounty_beach: [0x646, 1],
}
bounty_beach_region = create_region(world, player, active_locations, LocationName.bounty_beach_region,
bounty_beach_region = create_region(world, active_locations, LocationName.bounty_beach_region,
bounty_beach_region_locations)
smugglers_cove_region_locations = {
LocationName.smugglers_cove: [0x648, 1],
}
smugglers_cove_region = create_region(world, player, active_locations, LocationName.smugglers_cove_region,
smugglers_cove_region = create_region(world, active_locations, LocationName.smugglers_cove_region,
smugglers_cove_region_locations)
arichs_hoard_region_locations = {
LocationName.arichs_hoard: [0x649, 1],
}
arichs_hoard_region = create_region(world, player, active_locations, LocationName.arichs_hoard_region,
arichs_hoard_region = create_region(world, active_locations, LocationName.arichs_hoard_region,
arichs_hoard_region_locations)
bounty_bay_region_locations = {
LocationName.bounty_bay: [0x64A, 1],
}
bounty_bay_region = create_region(world, player, active_locations, LocationName.bounty_bay_region,
bounty_bay_region = create_region(world, active_locations, LocationName.bounty_bay_region,
bounty_bay_region_locations)
sky_high_secret_region_locations = {}
if False:#world.include_trade_sequence[player]:
if False:#world.options.include_trade_sequence:
sky_high_secret_region_locations[LocationName.sky_high_secret] = [0x64B, 1]
sky_high_secret_region = create_region(world, player, active_locations, LocationName.sky_high_secret_region,
sky_high_secret_region = create_region(world, active_locations, LocationName.sky_high_secret_region,
sky_high_secret_region_locations)
glacial_grotto_region_locations = {
LocationName.glacial_grotto: [0x64C, 1],
}
glacial_grotto_region = create_region(world, player, active_locations, LocationName.glacial_grotto_region,
glacial_grotto_region = create_region(world, active_locations, LocationName.glacial_grotto_region,
glacial_grotto_region_locations)
cifftop_cache_region_locations = {}
if False:#world.include_trade_sequence[player]:
if False:#world.options.include_trade_sequence:
cifftop_cache_region_locations[LocationName.cifftop_cache] = [0x64D, 1]
cifftop_cache_region = create_region(world, player, active_locations, LocationName.cifftop_cache_region,
cifftop_cache_region = create_region(world, active_locations, LocationName.cifftop_cache_region,
cifftop_cache_region_locations)
sewer_stockpile_region_locations = {
LocationName.sewer_stockpile: [0x64E, 1],
}
sewer_stockpile_region = create_region(world, player, active_locations, LocationName.sewer_stockpile_region,
sewer_stockpile_region = create_region(world, active_locations, LocationName.sewer_stockpile_region,
sewer_stockpile_region_locations)
# Set up the regions correctly.
world.regions += [
world.multiworld.regions += [
menu_region,
overworld_1_region,
overworld_2_region,
@@ -693,7 +694,7 @@ def create_regions(world, player: int, active_locations):
blue_region_locations = {}
blizzard_region_locations = {}
if False:#world.include_trade_sequence[player]:
if False:#world.options.include_trade_sequence:
bazaar_region_locations.update({
LocationName.bazaars_general_store_1: [0x615, 2, True],
LocationName.bazaars_general_store_2: [0x615, 3, True],
@@ -713,19 +714,19 @@ def create_regions(world, player: int, active_locations):
blizzard_region_locations[LocationName.blizzards_basecamp] = [0x625, 4, True]
bazaar_region = create_region(world, player, active_locations, LocationName.bazaar_region, bazaar_region_locations)
bramble_region = create_region(world, player, active_locations, LocationName.bramble_region,
bazaar_region = create_region(world, active_locations, LocationName.bazaar_region, bazaar_region_locations)
bramble_region = create_region(world, active_locations, LocationName.bramble_region,
bramble_region_locations)
flower_spot_region = create_region(world, player, active_locations, LocationName.flower_spot_region,
flower_spot_region = create_region(world, active_locations, LocationName.flower_spot_region,
flower_spot_region_locations)
barter_region = create_region(world, player, active_locations, LocationName.barter_region, barter_region_locations)
barnacle_region = create_region(world, player, active_locations, LocationName.barnacle_region,
barter_region = create_region(world, active_locations, LocationName.barter_region, barter_region_locations)
barnacle_region = create_region(world, active_locations, LocationName.barnacle_region,
barnacle_region_locations)
blue_region = create_region(world, player, active_locations, LocationName.blue_region, blue_region_locations)
blizzard_region = create_region(world, player, active_locations, LocationName.blizzard_region,
blue_region = create_region(world, active_locations, LocationName.blue_region, blue_region_locations)
blizzard_region = create_region(world, active_locations, LocationName.blizzard_region,
blizzard_region_locations)
world.regions += [
world.multiworld.regions += [
bazaar_region,
bramble_region,
flower_spot_region,
@@ -736,41 +737,41 @@ def create_regions(world, player: int, active_locations):
]
def connect_regions(world, player, level_list):
def connect_regions(world: World, level_list):
names: typing.Dict[str, int] = {}
# Overworld
connect(world, player, names, 'Menu', LocationName.overworld_1_region)
connect(world, player, names, LocationName.overworld_1_region, LocationName.overworld_2_region,
lambda state: (state.has(ItemName.progressive_boat, player, 1)))
connect(world, player, names, LocationName.overworld_2_region, LocationName.overworld_3_region,
lambda state: (state.has(ItemName.progressive_boat, player, 3)))
connect(world, player, names, LocationName.overworld_1_region, LocationName.overworld_4_region,
lambda state: (state.has(ItemName.dk_coin, player, world.dk_coins_for_gyrocopter[player].value) and
state.has(ItemName.progressive_boat, player, 3)))
connect(world, world.player, names, 'Menu', LocationName.overworld_1_region)
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.overworld_2_region,
lambda state: (state.has(ItemName.progressive_boat, world.player, 1)))
connect(world, world.player, names, LocationName.overworld_2_region, LocationName.overworld_3_region,
lambda state: (state.has(ItemName.progressive_boat, world.player, 3)))
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.overworld_4_region,
lambda state: (state.has(ItemName.dk_coin, world.player, world.options.dk_coins_for_gyrocopter.value) and
state.has(ItemName.progressive_boat, world.player, 3)))
# World Connections
connect(world, player, names, LocationName.overworld_1_region, LocationName.lake_orangatanga_region)
connect(world, player, names, LocationName.overworld_1_region, LocationName.kremwood_forest_region)
connect(world, player, names, LocationName.overworld_1_region, LocationName.bounty_beach_region)
connect(world, player, names, LocationName.overworld_1_region, LocationName.bazaar_region)
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.lake_orangatanga_region)
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.kremwood_forest_region)
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.bounty_beach_region)
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.bazaar_region)
connect(world, player, names, LocationName.overworld_2_region, LocationName.cotton_top_cove_region)
connect(world, player, names, LocationName.overworld_2_region, LocationName.mekanos_region)
connect(world, player, names, LocationName.overworld_2_region, LocationName.kong_cave_region)
connect(world, player, names, LocationName.overworld_2_region, LocationName.bramble_region)
connect(world, world.player, names, LocationName.overworld_2_region, LocationName.cotton_top_cove_region)
connect(world, world.player, names, LocationName.overworld_2_region, LocationName.mekanos_region)
connect(world, world.player, names, LocationName.overworld_2_region, LocationName.kong_cave_region)
connect(world, world.player, names, LocationName.overworld_2_region, LocationName.bramble_region)
connect(world, player, names, LocationName.overworld_3_region, LocationName.k3_region)
connect(world, player, names, LocationName.overworld_3_region, LocationName.razor_ridge_region)
connect(world, player, names, LocationName.overworld_3_region, LocationName.kaos_kore_region)
connect(world, player, names, LocationName.overworld_3_region, LocationName.krematoa_region)
connect(world, player, names, LocationName.overworld_3_region, LocationName.undercover_cove_region)
connect(world, player, names, LocationName.overworld_3_region, LocationName.flower_spot_region)
connect(world, player, names, LocationName.overworld_3_region, LocationName.barter_region)
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.k3_region)
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.razor_ridge_region)
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.kaos_kore_region)
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.krematoa_region)
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.undercover_cove_region)
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.flower_spot_region)
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.barter_region)
connect(world, player, names, LocationName.overworld_4_region, LocationName.belchas_burrow_region)
connect(world, player, names, LocationName.overworld_4_region, LocationName.ks_cache_region)
connect(world, player, names, LocationName.overworld_4_region, LocationName.hill_top_hoard_region)
connect(world, world.player, names, LocationName.overworld_4_region, LocationName.belchas_burrow_region)
connect(world, world.player, names, LocationName.overworld_4_region, LocationName.ks_cache_region)
connect(world, world.player, names, LocationName.overworld_4_region, LocationName.hill_top_hoard_region)
# Lake Orangatanga Connections
@@ -786,7 +787,7 @@ def connect_regions(world, player, level_list):
]
for i in range(0, len(lake_orangatanga_levels)):
connect(world, player, names, LocationName.lake_orangatanga_region, lake_orangatanga_levels[i])
connect(world, world.player, names, LocationName.lake_orangatanga_region, lake_orangatanga_levels[i])
# Kremwood Forest Connections
kremwood_forest_levels = [
@@ -800,10 +801,10 @@ def connect_regions(world, player, level_list):
]
for i in range(0, len(kremwood_forest_levels) - 1):
connect(world, player, names, LocationName.kremwood_forest_region, kremwood_forest_levels[i])
connect(world, world.player, names, LocationName.kremwood_forest_region, kremwood_forest_levels[i])
connect(world, player, names, LocationName.kremwood_forest_region, kremwood_forest_levels[-1],
lambda state: (state.can_reach(LocationName.riverside_race_flag, "Location", player)))
connect(world, world.player, names, LocationName.kremwood_forest_region, kremwood_forest_levels[-1],
lambda state: (state.can_reach(LocationName.riverside_race_flag, "Location", world.player)))
# Cotton-Top Cove Connections
cotton_top_cove_levels = [
@@ -818,7 +819,7 @@ def connect_regions(world, player, level_list):
]
for i in range(0, len(cotton_top_cove_levels)):
connect(world, player, names, LocationName.cotton_top_cove_region, cotton_top_cove_levels[i])
connect(world, world.player, names, LocationName.cotton_top_cove_region, cotton_top_cove_levels[i])
# Mekanos Connections
mekanos_levels = [
@@ -831,14 +832,14 @@ def connect_regions(world, player, level_list):
]
for i in range(0, len(mekanos_levels)):
connect(world, player, names, LocationName.mekanos_region, mekanos_levels[i])
connect(world, world.player, names, LocationName.mekanos_region, mekanos_levels[i])
if False:#world.include_trade_sequence[player]:
connect(world, player, names, LocationName.mekanos_region, LocationName.sky_high_secret_region,
lambda state: (state.has(ItemName.bowling_ball, player, 1)))
if False:#world.options.include_trade_sequence:
connect(world, world.player, names, LocationName.mekanos_region, LocationName.sky_high_secret_region,
lambda state: (state.has(ItemName.bowling_ball, world.player, 1)))
else:
connect(world, player, names, LocationName.mekanos_region, LocationName.sky_high_secret_region,
lambda state: (state.can_reach(LocationName.bleaks_house, "Location", player)))
connect(world, world.player, names, LocationName.mekanos_region, LocationName.sky_high_secret_region,
lambda state: (state.can_reach(LocationName.bleaks_house, "Location", world.player)))
# K3 Connections
k3_levels = [
@@ -853,7 +854,7 @@ def connect_regions(world, player, level_list):
]
for i in range(0, len(k3_levels)):
connect(world, player, names, LocationName.k3_region, k3_levels[i])
connect(world, world.player, names, LocationName.k3_region, k3_levels[i])
# Razor Ridge Connections
razor_ridge_levels = [
@@ -866,13 +867,13 @@ def connect_regions(world, player, level_list):
]
for i in range(0, len(razor_ridge_levels)):
connect(world, player, names, LocationName.razor_ridge_region, razor_ridge_levels[i])
connect(world, world.player, names, LocationName.razor_ridge_region, razor_ridge_levels[i])
if False:#world.include_trade_sequence[player]:
connect(world, player, names, LocationName.razor_ridge_region, LocationName.cifftop_cache_region,
lambda state: (state.has(ItemName.wrench, player, 1)))
if False:#world.options.include_trade_sequence:
connect(world, world.player, names, LocationName.razor_ridge_region, LocationName.cifftop_cache_region,
lambda state: (state.has(ItemName.wrench, world.player, 1)))
else:
connect(world, player, names, LocationName.razor_ridge_region, LocationName.cifftop_cache_region)
connect(world, world.player, names, LocationName.razor_ridge_region, LocationName.cifftop_cache_region)
# KAOS Kore Connections
kaos_kore_levels = [
@@ -885,7 +886,7 @@ def connect_regions(world, player, level_list):
]
for i in range(0, len(kaos_kore_levels)):
connect(world, player, names, LocationName.kaos_kore_region, kaos_kore_levels[i])
connect(world, world.player, names, LocationName.kaos_kore_region, kaos_kore_levels[i])
# Krematoa Connections
krematoa_levels = [
@@ -897,22 +898,22 @@ def connect_regions(world, player, level_list):
]
for i in range(0, len(krematoa_levels)):
connect(world, player, names, LocationName.krematoa_region, krematoa_levels[i],
lambda state, i=i: (state.has(ItemName.bonus_coin, player, world.krematoa_bonus_coin_cost[player].value * (i+1))))
connect(world, world.player, names, LocationName.krematoa_region, krematoa_levels[i],
lambda state, i=i: (state.has(ItemName.bonus_coin, world.player, world.options.krematoa_bonus_coin_cost.value * (i+1))))
if world.goal[player] == "knautilus":
connect(world, player, names, LocationName.kaos_kore_region, LocationName.knautilus_region)
connect(world, player, names, LocationName.krematoa_region, LocationName.kastle_kaos_region,
lambda state: (state.has(ItemName.krematoa_cog, player, 5)))
if world.options.goal == "knautilus":
connect(world, world.player, names, LocationName.kaos_kore_region, LocationName.knautilus_region)
connect(world, world.player, names, LocationName.krematoa_region, LocationName.kastle_kaos_region,
lambda state: (state.has(ItemName.krematoa_cog, world.player, 5)))
else:
connect(world, player, names, LocationName.kaos_kore_region, LocationName.kastle_kaos_region)
connect(world, player, names, LocationName.krematoa_region, LocationName.knautilus_region,
lambda state: (state.has(ItemName.krematoa_cog, player, 5)))
connect(world, world.player, names, LocationName.kaos_kore_region, LocationName.kastle_kaos_region)
connect(world, world.player, names, LocationName.krematoa_region, LocationName.knautilus_region,
lambda state: (state.has(ItemName.krematoa_cog, world.player, 5)))
def create_region(world: MultiWorld, player: int, active_locations, name: str, locations=None):
def create_region(world: World, active_locations, name: str, locations=None):
# Shamelessly stolen from the ROR2 definition
ret = Region(name, player, world)
ret = Region(name, world.player, world.multiworld)
if locations:
for locationName, locationData in locations.items():
loc_id = active_locations.get(locationName, 0)
@@ -921,16 +922,16 @@ def create_region(world: MultiWorld, player: int, active_locations, name: str, l
loc_bit = locationData[1] if (len(locationData) > 1) else 0
loc_invert = locationData[2] if (len(locationData) > 2) else False
location = DKC3Location(player, locationName, loc_id, ret, loc_byte, loc_bit, loc_invert)
location = DKC3Location(world.player, locationName, loc_id, ret, loc_byte, loc_bit, loc_invert)
ret.locations.append(location)
return ret
def connect(world: MultiWorld, player: int, used_names: typing.Dict[str, int], source: str, target: str,
def connect(world: World, player: int, used_names: typing.Dict[str, int], source: str, target: str,
rule: typing.Optional[typing.Callable] = None):
source_region = world.get_region(source, player)
target_region = world.get_region(target, player)
source_region = world.multiworld.get_region(source, player)
target_region = world.multiworld.get_region(target, player)
if target not in used_names:
used_names[target] = 1

View File

@@ -1,5 +1,6 @@
import Utils
from Utils import read_snes_rom
from worlds.AutoWorld import World
from worlds.Files import APDeltaPatch
from .Locations import lookup_id_to_name, all_locations
from .Levels import level_list, level_dict
@@ -475,11 +476,10 @@ class LocalRom(object):
def patch_rom(world, rom, player, active_level_list):
local_random = world.per_slot_randoms[player]
def patch_rom(world: World, rom: LocalRom, active_level_list):
# Boomer Costs
bonus_coin_cost = world.krematoa_bonus_coin_cost[player]
bonus_coin_cost = world.options.krematoa_bonus_coin_cost
inverted_bonus_coin_cost = 0x100 - bonus_coin_cost
rom.write_byte(0x3498B9, inverted_bonus_coin_cost)
rom.write_byte(0x3498BA, inverted_bonus_coin_cost)
@@ -491,7 +491,7 @@ def patch_rom(world, rom, player, active_level_list):
rom.write_byte(0x349862, bonus_coin_cost)
# Gyrocopter Costs
dk_coin_cost = world.dk_coins_for_gyrocopter[player]
dk_coin_cost = world.options.dk_coins_for_gyrocopter
rom.write_byte(0x3484A6, dk_coin_cost)
rom.write_byte(0x3484D5, dk_coin_cost)
rom.write_byte(0x3484D7, 0x90)
@@ -508,8 +508,8 @@ def patch_rom(world, rom, player, active_level_list):
rom.write_bytes(0x34ACD0, bytearray([0xEA, 0xEA]))
# Banana Bird Costs
if world.goal[player] == "banana_bird_hunt":
banana_bird_cost = math.floor(world.number_of_banana_birds[player] * world.percentage_of_banana_birds[player] / 100.0)
if world.options.goal == "banana_bird_hunt":
banana_bird_cost = math.floor(world.options.number_of_banana_birds * world.options.percentage_of_banana_birds / 100.0)
rom.write_byte(0x34AB85, banana_bird_cost)
rom.write_byte(0x329FD8, banana_bird_cost)
rom.write_byte(0x32A025, banana_bird_cost)
@@ -528,65 +528,65 @@ def patch_rom(world, rom, player, active_level_list):
# Palette Swap
rom.write_byte(0x3B96A5, 0xD0)
if world.kong_palette_swap[player] == "default":
if world.options.kong_palette_swap == "default":
rom.write_byte(0x3B96A9, 0x00)
rom.write_byte(0x3B96A8, 0x00)
elif world.kong_palette_swap[player] == "purple":
elif world.options.kong_palette_swap == "purple":
rom.write_byte(0x3B96A9, 0x00)
rom.write_byte(0x3B96A8, 0x3C)
elif world.kong_palette_swap[player] == "spooky":
elif world.options.kong_palette_swap == "spooky":
rom.write_byte(0x3B96A9, 0x00)
rom.write_byte(0x3B96A8, 0xA0)
elif world.kong_palette_swap[player] == "dark":
elif world.options.kong_palette_swap == "dark":
rom.write_byte(0x3B96A9, 0x05)
rom.write_byte(0x3B96A8, 0xA0)
elif world.kong_palette_swap[player] == "chocolate":
elif world.options.kong_palette_swap == "chocolate":
rom.write_byte(0x3B96A9, 0x1D)
rom.write_byte(0x3B96A8, 0xA0)
elif world.kong_palette_swap[player] == "shadow":
elif world.options.kong_palette_swap == "shadow":
rom.write_byte(0x3B96A9, 0x45)
rom.write_byte(0x3B96A8, 0xA0)
elif world.kong_palette_swap[player] == "red_gold":
elif world.options.kong_palette_swap == "red_gold":
rom.write_byte(0x3B96A9, 0x5D)
rom.write_byte(0x3B96A8, 0xA0)
elif world.kong_palette_swap[player] == "gbc":
elif world.options.kong_palette_swap == "gbc":
rom.write_byte(0x3B96A9, 0x20)
rom.write_byte(0x3B96A8, 0x3C)
elif world.kong_palette_swap[player] == "halloween":
elif world.options.kong_palette_swap == "halloween":
rom.write_byte(0x3B96A9, 0x70)
rom.write_byte(0x3B96A8, 0x3C)
if world.music_shuffle[player]:
if world.options.music_shuffle:
for address in music_rom_data:
rand_song = local_random.choice(level_music_ids)
rand_song = world.random.choice(level_music_ids)
rom.write_byte(address, rand_song)
# Starting Lives
rom.write_byte(0x9130, world.starting_life_count[player].value)
rom.write_byte(0x913B, world.starting_life_count[player].value)
rom.write_byte(0x9130, world.options.starting_life_count.value)
rom.write_byte(0x913B, world.options.starting_life_count.value)
# Cheat options
cheat_bytes = [0x00, 0x00]
if world.merry[player]:
if world.options.merry:
cheat_bytes[0] |= 0x01
if world.autosave[player]:
if world.options.autosave:
cheat_bytes[0] |= 0x02
if world.difficulty[player] == "tufst":
if world.options.difficulty == "tufst":
cheat_bytes[0] |= 0x80
cheat_bytes[1] |= 0x80
elif world.difficulty[player] == "hardr":
elif world.options.difficulty == "hardr":
cheat_bytes[0] |= 0x00
cheat_bytes[1] |= 0x00
elif world.difficulty[player] == "norml":
elif world.options.difficulty == "norml":
cheat_bytes[1] |= 0x40
rom.write_bytes(0x8303, bytearray(cheat_bytes))
# Handle Level Shuffle Here
if world.level_shuffle[player]:
if world.options.level_shuffle:
for i in range(len(active_level_list)):
rom.write_byte(level_dict[level_list[i]].nameIDAddress, level_dict[active_level_list[i]].nameID)
rom.write_byte(level_dict[level_list[i]].levelIDAddress, level_dict[active_level_list[i]].levelID)
@@ -611,7 +611,7 @@ def patch_rom(world, rom, player, active_level_list):
rom.write_byte(0x34C213, (0x32 + level_dict[active_level_list[25]].levelID))
rom.write_byte(0x34C21B, (0x32 + level_dict[active_level_list[26]].levelID))
if world.goal[player] == "knautilus":
if world.options.goal == "knautilus":
# Swap Kastle KAOS and Knautilus
rom.write_byte(0x34D4E1, 0xC2)
rom.write_byte(0x34D4E2, 0x24)
@@ -621,7 +621,7 @@ def patch_rom(world, rom, player, active_level_list):
rom.write_byte(0x32F339, 0x55)
# Handle KONGsanity Here
if world.kongsanity[player]:
if world.options.kongsanity:
# Arich's Hoard KONGsanity fix
rom.write_bytes(0x34BA8C, bytearray([0xEA, 0xEA]))
@@ -668,7 +668,7 @@ def patch_rom(world, rom, player, active_level_list):
rom.write_bytes(0x32A5EE, bytearray([0x00, 0x03, 0x50, 0x4F, 0x52, 0x59, 0x47, 0x4F, 0x4E, 0xC5])) # "PORYGONE"
from Utils import __version__
rom.name = bytearray(f'D3{__version__.replace(".", "")[0:3]}_{player}_{world.seed:11}\0', 'utf8')[:21]
rom.name = bytearray(f'D3{__version__.replace(".", "")[0:3]}_{world.player}_{world.multiworld.seed:11}\0', 'utf8')[:21]
rom.name.extend([0] * (21 - len(rom.name)))
rom.write_bytes(0x7FC0, rom.name)

View File

@@ -1,32 +1,31 @@
import math
from BaseClasses import MultiWorld
from .Names import LocationName, ItemName
from worlds.AutoWorld import LogicMixin
from worlds.AutoWorld import LogicMixin, World
from worlds.generic.Rules import add_rule, set_rule
def set_rules(world: MultiWorld, player: int):
def set_rules(world: World):
if False:#world.include_trade_sequence[player]:
add_rule(world.get_location(LocationName.barnacles_island, player),
lambda state: state.has(ItemName.shell, player))
if False:#world.options.include_trade_sequence:
add_rule(world.multiworld.get_location(LocationName.barnacles_island, world.player),
lambda state: state.has(ItemName.shell, world.player))
add_rule(world.get_location(LocationName.blues_beach_hut, player),
lambda state: state.has(ItemName.present, player))
add_rule(world.multiworld.get_location(LocationName.blues_beach_hut, world.player),
lambda state: state.has(ItemName.present, world.player))
add_rule(world.get_location(LocationName.brambles_bungalow, player),
lambda state: state.has(ItemName.flower, player))
add_rule(world.multiworld.get_location(LocationName.brambles_bungalow, world.player),
lambda state: state.has(ItemName.flower, world.player))
add_rule(world.get_location(LocationName.barters_swap_shop, player),
lambda state: state.has(ItemName.mirror, player))
add_rule(world.multiworld.get_location(LocationName.barters_swap_shop, world.player),
lambda state: state.has(ItemName.mirror, world.player))
if world.goal[player] != "knautilus":
if world.options.goal != "knautilus":
required_banana_birds = math.floor(
world.number_of_banana_birds[player].value * (world.percentage_of_banana_birds[player].value / 100.0))
world.options.number_of_banana_birds.value * (world.options.percentage_of_banana_birds.value / 100.0))
add_rule(world.get_location(LocationName.banana_bird_mother, player),
lambda state: state.has(ItemName.banana_bird, player, required_banana_birds))
add_rule(world.multiworld.get_location(LocationName.banana_bird_mother, world.player),
lambda state: state.has(ItemName.banana_bird, world.player, required_banana_birds))
world.completion_condition[player] = lambda state: state.has(ItemName.victory, player)
world.multiworld.completion_condition[world.player] = lambda state: state.has(ItemName.victory, world.player)

View File

@@ -1,3 +1,4 @@
import dataclasses
import os
import typing
import math
@@ -5,9 +6,10 @@ import threading
import settings
from BaseClasses import Item, MultiWorld, Tutorial, ItemClassification
from Options import PerGameCommonOptions
from .Items import DKC3Item, ItemData, item_table, inventory_table, junk_table
from .Locations import DKC3Location, all_locations, setup_locations
from .Options import dkc3_options
from .Options import DKC3Options
from .Regions import create_regions, connect_regions
from .Levels import level_list
from .Rules import set_rules
@@ -50,8 +52,11 @@ class DKC3World(World):
mystery of why Donkey Kong and Diddy disappeared while on vacation.
"""
game: str = "Donkey Kong Country 3"
option_definitions = dkc3_options
settings: typing.ClassVar[DK3Settings]
options_dataclass = DKC3Options
options: DKC3Options
topology_present = False
data_version = 2
#hint_blacklist = {LocationName.rocket_rush_flag}
@@ -74,24 +79,25 @@ class DKC3World(World):
def _get_slot_data(self):
return {
#"death_link": self.world.death_link[self.player].value,
#"death_link": self.options.death_link.value,
"active_levels": self.active_level_list,
}
def fill_slot_data(self) -> dict:
slot_data = self._get_slot_data()
for option_name in dkc3_options:
option = getattr(self.multiworld, option_name)[self.player]
for option_name in (attr.name for attr in dataclasses.fields(DKC3Options)
if attr not in dataclasses.fields(PerGameCommonOptions)):
option = getattr(self.options, option_name)
slot_data[option_name] = option.value
return slot_data
def create_regions(self):
location_table = setup_locations(self.multiworld, self.player)
create_regions(self.multiworld, self.player, location_table)
location_table = setup_locations(self)
create_regions(self, location_table)
# Not generate basic
self.topology_present = self.multiworld.level_shuffle[self.player].value
self.topology_present = self.options.level_shuffle.value
itempool: typing.List[DKC3Item] = []
# Levels
@@ -103,12 +109,12 @@ class DKC3World(World):
number_of_cogs = 4
self.multiworld.get_location(LocationName.rocket_rush_flag, self.player).place_locked_item(self.create_item(ItemName.krematoa_cog))
number_of_bosses = 8
if self.multiworld.goal[self.player] == "knautilus":
if self.options.goal == "knautilus":
self.multiworld.get_location(LocationName.kastle_kaos, self.player).place_locked_item(self.create_item(ItemName.victory))
number_of_bosses = 7
else:
self.multiworld.get_location(LocationName.banana_bird_mother, self.player).place_locked_item(self.create_item(ItemName.victory))
number_of_banana_birds = self.multiworld.number_of_banana_birds[self.player]
number_of_banana_birds = self.options.number_of_banana_birds
# Bosses
total_required_locations += number_of_bosses
@@ -116,15 +122,15 @@ class DKC3World(World):
# Secret Caves
total_required_locations += 13
if self.multiworld.kongsanity[self.player]:
if self.options.kongsanity:
total_required_locations += 39
## Brothers Bear
if False:#self.world.include_trade_sequence[self.player]:
if False:#self.options.include_trade_sequence:
total_required_locations += 10
number_of_bonus_coins = (self.multiworld.krematoa_bonus_coin_cost[self.player] * 5)
number_of_bonus_coins += math.ceil((85 - number_of_bonus_coins) * self.multiworld.percentage_of_extra_bonus_coins[self.player] / 100)
number_of_bonus_coins = (self.options.krematoa_bonus_coin_cost * 5)
number_of_bonus_coins += math.ceil((85 - number_of_bonus_coins) * self.options.percentage_of_extra_bonus_coins / 100)
itempool += [self.create_item(ItemName.bonus_coin) for _ in range(number_of_bonus_coins)]
itempool += [self.create_item(ItemName.dk_coin) for _ in range(41)]
@@ -142,20 +148,17 @@ class DKC3World(World):
self.active_level_list = level_list.copy()
if self.multiworld.level_shuffle[self.player]:
self.multiworld.random.shuffle(self.active_level_list)
if self.options.level_shuffle:
self.random.shuffle(self.active_level_list)
connect_regions(self.multiworld, self.player, self.active_level_list)
connect_regions(self, self.active_level_list)
self.multiworld.itempool += itempool
def generate_output(self, output_directory: str):
try:
world = self.multiworld
player = self.player
rom = LocalRom(get_base_rom_path())
patch_rom(self.multiworld, rom, self.player, self.active_level_list)
patch_rom(self, rom, self.active_level_list)
self.active_level_list.append(LocationName.rocket_rush_region)
@@ -163,15 +166,15 @@ class DKC3World(World):
rom.write_to_file(rompath)
self.rom_name = rom.name
patch = DKC3DeltaPatch(os.path.splitext(rompath)[0]+DKC3DeltaPatch.patch_file_ending, player=player,
player_name=world.player_name[player], patched_path=rompath)
patch = DKC3DeltaPatch(os.path.splitext(rompath)[0]+DKC3DeltaPatch.patch_file_ending, player=self.player,
player_name=self.multiworld.player_name[self.player], patched_path=rompath)
patch.write()
except:
raise
finally:
self.rom_name_available_event.set() # make sure threading continues and errors are collected
if os.path.exists(rompath):
os.unlink(rompath)
self.rom_name_available_event.set() # make sure threading continues and errors are collected
def modify_multidata(self, multidata: dict):
import base64
@@ -183,6 +186,7 @@ class DKC3World(World):
new_name = base64.b64encode(bytes(self.rom_name)).decode()
multidata["connect_names"][new_name] = multidata["connect_names"][self.multiworld.player_name[self.player]]
def extend_hint_information(self, hint_data: typing.Dict[int, typing.Dict[int, str]]):
if self.topology_present:
world_names = [
LocationName.lake_orangatanga_region,
@@ -200,7 +204,8 @@ class DKC3World(World):
level_region = self.multiworld.get_region(self.active_level_list[world_index * 5 + level_index], self.player)
for location in level_region.locations:
er_hint_data[location.address] = world_names[world_index]
multidata['er_hint_data'][self.player] = er_hint_data
hint_data[self.player] = er_hint_data
def create_item(self, name: str, force_non_progression=False) -> Item:
data = item_table[name]
@@ -220,4 +225,4 @@ class DKC3World(World):
return self.multiworld.random.choice(list(junk_table.keys()))
def set_rules(self):
set_rules(self.multiworld, self.player)
set_rules(self)

View File

@@ -14,7 +14,7 @@ client_version = 0
class DLCqwebworld(WebWorld):
setup_en = Tutorial(
"Multiworld Setup Tutorial",
"Multiworld Setup Guide",
"A guide to setting up the Archipelago DLCQuest game on your computer.",
"English",
"setup_en.md",

View File

@@ -53,7 +53,7 @@ If this file does exist, then it will be used.
class FactorioWeb(WebWorld):
tutorials = [Tutorial(
"Multiworld Setup Tutorial",
"Multiworld Setup Guide",
"A guide to setting up the Archipelago Factorio software on your computer.",
"English",
"setup_en.md",

View File

@@ -171,16 +171,16 @@ relevant guide: [A Link to the Past Plando Guide](/tutorial/A%20Link%20to%20the%
## Connections Plando
This is currently only supported by Minecraft and A Link to the Past. As the way that these games interact with their
connections is different, I will only explain the basics here, while more specifics for A Link to the Past connection
plando can be found in its plando guide.
This is currently only supported by a few games, including A Link to the Past, Minecraft, and Ocarina of Time. As the way that these games interact with their
connections is different, only the basics are explained here. More specific information for connection plando in A Link to the Past can be found in
its [plando guide](/tutorial/A%20Link%20to%20the%20Past/plando/en#connections).
* The options for connections are `percentage`, `entrance`, `exit`, and `direction`. Each of these options supports
subweights.
* `percentage` is the percentage chance for this connection from 0 to 100 and defaults to 100.
* Every connection has an `entrance` and an `exit`. These can be unlinked like in A Link to the Past insanity entrance
shuffle.
* `direction` can be `both`, `entrance`, or `exit` and determines in which direction this connection will operate.
* `direction` can be `both`, `entrance`, or `exit` and determines in which direction this connection will operate. `direction` defaults to `both`.
[A Link to the Past connections](https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/alttp/EntranceShuffle.py#L3852)

View File

@@ -278,10 +278,10 @@
tag: forbid
check: True
achievement: The Seeker
BEAR:
BEAR (1):
id: Heteronym Room/Panel_bear_bear
tag: midwhite
MINE:
MINE (1):
id: Heteronym Room/Panel_mine_mine
tag: double midwhite
subtag: left
@@ -297,7 +297,7 @@
DOES:
id: Heteronym Room/Panel_does_does
tag: midwhite
MOBILE:
MOBILE (1):
id: Heteronym Room/Panel_mobile_mobile
tag: double midwhite
subtag: left
@@ -399,8 +399,7 @@
door: Crossroads Entrance
The Tenacious:
door: Tenacious Entrance
Warts Straw Area:
door: Symmetry Door
Near Far Area: True
Hedge Maze:
door: Shortcut to Hedge Maze
Orange Tower First Floor:
@@ -427,14 +426,6 @@
id: Palindrome Room/Panel_slaughter_laughter
colors: red
tag: midred
NEAR:
id: Symmetry Room/Panel_near_far
colors: black
tag: botblack
FAR:
id: Symmetry Room/Panel_far_near
colors: black
tag: botblack
TRACE:
id: Maze Room/Panel_trace_trace
tag: midwhite
@@ -477,14 +468,6 @@
group: Entrances to The Tenacious
panels:
- SLAUGHTER
Symmetry Door:
id:
- Symmetry Room Area Doors/Door_near_far
- Symmetry Room Area Doors/Door_far_near
group: Symmetry Doors
panels:
- NEAR
- FAR
Shortcut to Hedge Maze:
id: Maze Area Doors/Door_trace_trace
group: Hedge Maze Doors
@@ -548,7 +531,7 @@
id: Lingo Room/Panel_shortcut
colors: yellow
tag: midyellow
PILGRIMAGE:
PILGRIM:
id: Lingo Room/Panel_pilgrim
colors: blue
tag: midblue
@@ -569,7 +552,7 @@
Exit:
event: True
panels:
- PILGRIMAGE
- PILGRIM
Pilgrim Room:
entrances:
The Seeker:
@@ -755,7 +738,7 @@
panels:
- TURN
- room: Orange Tower Fourth Floor
panel: RUNT
panel: RUNT (1)
Words Sword Door:
id:
- Shuffle Room Area Doors/Door_words_shuffle_3
@@ -962,11 +945,36 @@
- LEVEL (White)
- RACECAR (White)
- SOLOS (White)
Near Far Area:
entrances:
Hub Room: True
Warts Straw Area:
door: Door
panels:
NEAR:
id: Symmetry Room/Panel_near_far
colors: black
tag: botblack
FAR:
id: Symmetry Room/Panel_far_near
colors: black
tag: botblack
doors:
Door:
id:
- Symmetry Room Area Doors/Door_near_far
- Symmetry Room Area Doors/Door_far_near
group: Symmetry Doors
item_name: Symmetry Room - Near Far Door
location_name: Symmetry Room - NEAR, FAR
panels:
- NEAR
- FAR
Warts Straw Area:
entrances:
Hub Room:
room: Hub Room
door: Symmetry Door
Near Far Area:
room: Near Far Area
door: Door
Leaf Feel Area:
door: Door
panels:
@@ -984,6 +992,8 @@
- Symmetry Room Area Doors/Door_warts_straw
- Symmetry Room Area Doors/Door_straw_warts
group: Symmetry Doors
item_name: Symmetry Room - Warts Straw Door
location_name: Symmetry Room - WARTS, STRAW
panels:
- WARTS
- STRAW
@@ -1009,6 +1019,8 @@
- Symmetry Room Area Doors/Door_leaf_feel
- Symmetry Room Area Doors/Door_feel_leaf
group: Symmetry Doors
item_name: Symmetry Room - Leaf Feel Door
location_name: Symmetry Room - LEAF, FEEL
panels:
- LEAF
- FEEL
@@ -1120,7 +1132,7 @@
tag: forbid
required_panel:
- room: Outside The Bold
panel: MOUTH
panel: SOUND
- room: Outside The Bold
panel: YEAST
- room: Outside The Bold
@@ -1436,7 +1448,7 @@
entrances:
The Perceptive: True
panels:
NAPS:
SPAN:
id: Naps Room/Panel_naps_span
colors: black
tag: midblack
@@ -1462,7 +1474,7 @@
location_name: The Fearless - First Floor Puzzles
group: Fearless Doors
panels:
- NAPS
- SPAN
- TEAM
- TEEM
- IMPATIENT
@@ -1564,11 +1576,11 @@
required_door:
door: Stairs
achievement: The Observant
BACK:
FOUR (1):
id: Look Room/Panel_four_back
colors: green
tag: forbid
SIDE:
FOUR (2):
id: Look Room/Panel_four_side
colors: green
tag: forbid
@@ -1578,87 +1590,87 @@
hunt: True
required_door:
door: Backside Door
STAIRS:
SIX:
id: Look Room/Panel_six_stairs
colors: green
tag: forbid
WAYS:
FOUR (3):
id: Look Room/Panel_four_ways
colors: green
tag: forbid
"ON":
TWO (1):
id: Look Room/Panel_two_on
colors: green
tag: forbid
UP:
TWO (2):
id: Look Room/Panel_two_up
colors: green
tag: forbid
SWIMS:
FIVE:
id: Look Room/Panel_five_swims
colors: green
tag: forbid
UPSTAIRS:
BELOW (1):
id: Look Room/Panel_eight_upstairs
colors: green
tag: forbid
required_door:
door: Stairs
TOIL:
BLUE:
id: Look Room/Panel_blue_toil
colors: green
tag: forbid
required_door:
door: Stairs
STOP:
BELOW (2):
id: Look Room/Panel_four_stop
colors: green
tag: forbid
required_door:
door: Stairs
TOP:
MINT (1):
id: Look Room/Panel_aqua_top
colors: green
tag: forbid
required_door:
door: Stairs
HI:
ESACREWOL:
id: Look Room/Panel_blue_hi
colors: green
tag: forbid
required_door:
door: Stairs
HI (2):
EULB:
id: Look Room/Panel_blue_hi2
colors: green
tag: forbid
required_door:
door: Stairs
"31":
NUMBERS (1):
id: Look Room/Panel_numbers_31
colors: green
tag: forbid
required_door:
door: Stairs
"52":
NUMBERS (2):
id: Look Room/Panel_numbers_52
colors: green
tag: forbid
required_door:
door: Stairs
OIL:
MINT (2):
id: Look Room/Panel_aqua_oil
colors: green
tag: forbid
required_door:
door: Stairs
BACKSIDE (GREEN):
GREEN (1):
id: Look Room/Panel_eight_backside
colors: green
tag: forbid
required_door:
door: Stairs
SIDEWAYS:
GREEN (2):
id: Look Room/Panel_eight_sideways
colors: green
tag: forbid
@@ -1669,13 +1681,13 @@
id: Maze Area Doors/Door_backside
group: Backside Doors
panels:
- BACK
- SIDE
- FOUR (1)
- FOUR (2)
Stairs:
id: Maze Area Doors/Door_stairs
group: Observant Doors
panels:
- STAIRS
- SIX
The Incomparable:
entrances:
The Observant: True # Assuming that access to The Observant includes access to the right entrance
@@ -2005,7 +2017,7 @@
Courtyard: True
Roof: True # through the sunwarp
panels:
RUNT:
RUNT (1):
id: Shuffle Room/Panel_turn_runt2
colors: yellow
tag: midyellow
@@ -2219,6 +2231,7 @@
- Master Room Doors/Door_master_down
- Master Room Doors/Door_master_down2
skip_location: True
item_name: Mastery
panels:
- THE MASTER
Mastery Panels:
@@ -2235,25 +2248,25 @@
panel: MASTERY
- room: Hedge Maze
panel: MASTERY (1)
- room: Roof
panel: MASTERY (1)
- room: Roof
panel: MASTERY (2)
- room: Behind A Smile
panel: MASTERY
- room: Sixteen Colorful Squares
panel: MASTERY
- MASTERY
- room: Hedge Maze
panel: MASTERY (2)
- room: Roof
panel: MASTERY (3)
- room: Roof
panel: MASTERY (4)
- room: Roof
panel: MASTERY (5)
- room: Among Treetops
panel: MASTERY
- room: Horizon's Edge
panel: MASTERY
- room: Beneath The Lookout
panel: MASTERY
- room: Elements Area
panel: MASTERY
- room: Pilgrim Antechamber
panel: MASTERY
- room: Roof
panel: MASTERY (6)
- room: Rooftop Staircase
panel: MASTERY
paintings:
- id: map_painting2
orientation: north
@@ -2265,52 +2278,75 @@
Crossroads:
room: Crossroads
door: Roof Access
Behind A Smile:
entrances:
Roof: True
panels:
MASTERY (1):
MASTERY:
id: Master Room/Panel_mastery_mastery6
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
MASTERY (2):
id: Master Room/Panel_mastery_mastery7
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
MASTERY (3):
id: Master Room/Panel_mastery_mastery10
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
MASTERY (4):
id: Master Room/Panel_mastery_mastery11
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
MASTERY (5):
id: Master Room/Panel_mastery_mastery12
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
MASTERY (6):
id: Master Room/Panel_mastery_mastery15
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
STAIRCASE:
id: Open Areas/Panel_staircase
tag: midwhite
Sixteen Colorful Squares:
entrances:
Roof: True
panels:
MASTERY:
id: Master Room/Panel_mastery_mastery7
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
Among Treetops:
entrances:
Roof: True
panels:
MASTERY:
id: Master Room/Panel_mastery_mastery10
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
Horizon's Edge:
entrances:
Roof: True
panels:
MASTERY:
id: Master Room/Panel_mastery_mastery11
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
Beneath The Lookout:
entrances:
Roof: True
panels:
MASTERY:
id: Master Room/Panel_mastery_mastery12
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
Rooftop Staircase:
entrances:
Roof: True
panels:
MASTERY:
id: Master Room/Panel_mastery_mastery15
tag: midwhite
hunt: True
required_door:
room: Orange Tower Seventh Floor
door: Mastery
Orange Tower Basement:
entrances:
Orange Tower Sixth Floor:
@@ -2632,9 +2668,7 @@
tag: forbid
doors:
Progress Door:
id:
- Doorway Room Doors/Door_gray
- Doorway Room Doors/Door_gray2 # See comment below
id: Doorway Room Doors/Door_gray
item_name: The Colorful - Gray Door
location_name: The Colorful - Gray
group: Colorful Doors
@@ -2784,6 +2818,7 @@
door: Exit
Eight Alcove:
door: Eight Door
The Optimistic: True
panels:
SEVEN (1):
id: Backside Room/Panel_seven_seven_5
@@ -2833,21 +2868,11 @@
id: Rhyme Room/Panel_locked_knocked
colors: purple
tag: midpurp
BACKSIDE:
id: Backside Room/Panel_backside_1
tag: midwhite
The Optimistic:
id: Countdown Panels/Panel_optimistic_optimistic
check: True
tag: forbid
required_door:
door: Backsides
achievement: The Optimistic
PAST:
PAST (1):
id: Shuffle Room/Panel_past_present
colors: brown
tag: botbrown
FUTURE:
FUTURE (1):
id: Shuffle Room/Panel_future_present
colors:
- brown
@@ -2944,17 +2969,6 @@
panel: GREEN
- room: Outside The Agreeable
panel: PURPLE
Backsides:
event: True
panels:
- room: The Observant
panel: BACKSIDE
- room: Yellow Backside Area
panel: BACKSIDE
- room: Directional Gallery
panel: BACKSIDE
- room: The Bearer
panel: BACKSIDE
Eight Door:
id: Red Blue Purple Room Area Doors/Door_a_strands2
skip_location: True
@@ -3064,6 +3078,28 @@
id: Rhyme Room/Panel_bed_dead
colors: purple
tag: toppurp
The Optimistic:
entrances:
Outside The Initiated: True
panels:
BACKSIDE:
id: Backside Room/Panel_backside_1
tag: midwhite
Achievement:
id: Countdown Panels/Panel_optimistic_optimistic
check: True
tag: forbid
required_panel:
- panel: BACKSIDE
- room: The Observant
panel: BACKSIDE
- room: Yellow Backside Area
panel: BACKSIDE
- room: Directional Gallery
panel: BACKSIDE
- room: The Bearer
panel: BACKSIDE
achievement: The Optimistic
The Traveled:
entrances:
Hub Room:
@@ -3164,7 +3200,7 @@
Outside The Undeterred: True
Crossroads: True
Hedge Maze: True
Outside The Initiated: True # backside
The Optimistic: True # backside
Directional Gallery: True # backside
Yellow Backside Area: True
The Bearer:
@@ -3181,7 +3217,7 @@
door: Shortcut to The Steady
The Bearer:
room: The Bearer
door: Shortcut to The Bold
door: Entrance
Directional Gallery:
# There is a painting warp here from the Directional Gallery, but it
# only appears when the sixes are revealed. It could be its own item if
@@ -3252,7 +3288,7 @@
tag: midwhite
required_door:
door: Stargazer Door
MOUTH:
SOUND:
id: Cross Room/Panel_mouth_south
colors: purple
tag: midpurp
@@ -3596,7 +3632,7 @@
id: Blue Room/Panel_bone_skeleton
colors: blue
tag: botblue
EYE:
EYE (1):
id: Blue Room/Panel_mouth_face
colors: blue
tag: double botblue
@@ -4115,7 +4151,7 @@
The Bearer:
entrances:
Outside The Bold:
door: Shortcut to The Bold
door: Entrance
Orange Tower Fifth Floor:
room: Art Gallery
door: Exit
@@ -4192,7 +4228,7 @@
- yellow
tag: mid red yellow
doors:
Shortcut to The Bold:
Entrance:
id: Red Blue Purple Room Area Doors/Door_middle_middle
panels:
- MIDDLE
@@ -4321,21 +4357,21 @@
door: Side Area Shortcut
Roof: True
panels:
SNOW:
SMILE:
id: Cross Room/Panel_smile_lime
colors:
- red
- yellow
tag: mid yellow red
SMILE:
required_panel:
room: The Bearer (North)
panel: WARTS
SNOW:
id: Cross Room/Panel_snow_won
colors:
- red
- yellow
tag: mid red yellow
required_panel:
room: The Bearer (North)
panel: WARTS
doors:
Side Area Shortcut:
event: True
@@ -4414,7 +4450,7 @@
- room: The Bearer (West)
panel: SMILE
- room: Outside The Bold
panel: MOUTH
panel: SOUND
- room: Outside The Bold
panel: YEAST
- room: Outside The Bold
@@ -6129,7 +6165,7 @@
id: Painting Room/Panel_our_four
colors: blue
tag: midblue
ONE ROAD MANY TURNS:
ORDER:
id: Painting Room/Panel_order_onepathmanyturns
tag: forbid
colors:
@@ -6186,7 +6222,7 @@
include_reduce: True
item_name: Orange Tower Fifth Floor - Quadruple Intersection
panels:
- ONE ROAD MANY TURNS
- ORDER
paintings:
- id: smile_painting_3
orientation: west
@@ -6678,7 +6714,7 @@
- room: Rhyme Room (Target)
panel: PISTOL
- room: Rhyme Room (Target)
panel: QUARTZ
panel: GEM
Rhyme Room (Target):
entrances:
Rhyme Room (Smiley): # one-way
@@ -6706,7 +6742,7 @@
tag: syn rhyme
subtag: top
link: rhyme CRYSTAL
QUARTZ:
GEM:
id: Double Room/Panel_crystal_syn
colors: purple
tag: syn rhyme
@@ -6731,7 +6767,7 @@
group: Rhyme Room Doors
panels:
- PISTOL
- QUARTZ
- GEM
- INNOVATIVE (Top)
- INNOVATIVE (Bottom)
paintings:
@@ -6789,22 +6825,18 @@
id: Panel Room/Panel_room_floor_5
colors: gray
tag: forbid
FLOOR (7):
FLOOR (6):
id: Panel Room/Panel_room_floor_7
colors: gray
tag: forbid
FLOOR (8):
FLOOR (7):
id: Panel Room/Panel_room_floor_8
colors: gray
tag: forbid
FLOOR (9):
FLOOR (8):
id: Panel Room/Panel_room_floor_9
colors: gray
tag: forbid
FLOOR (10):
id: Panel Room/Panel_room_floor_10
colors: gray
tag: forbid
CEILING (1):
id: Panel Room/Panel_room_ceiling_1
colors: gray
@@ -6825,6 +6857,10 @@
id: Panel Room/Panel_room_ceiling_5
colors: gray
tag: forbid
CEILING (6):
id: Panel Room/Panel_room_floor_10
colors: gray
tag: forbid
WALL (1):
id: Panel Room/Panel_room_wall_1
colors: gray
@@ -6930,10 +6966,12 @@
MASTERY:
id: Master Room/Panel_mastery_mastery
tag: midwhite
colors: gray
required_door:
room: Orange Tower Seventh Floor
door: Mastery
required_panel:
room: Room Room
panel: WALL (2)
doors:
Excavation:
event: True
@@ -7083,7 +7121,7 @@
id: Hangry Room/Panel_red_top_3
colors: red
tag: topred
FLUMMOXED:
FLUSTERED:
id: Hangry Room/Panel_red_top_4
colors: red
tag: topred
@@ -7586,7 +7624,7 @@
- black
- blue
tag: chain mid black blue
BREAD:
CHEESE:
id: Challenge Room/Panel_bread_mold
colors: brown
tag: double botbrown
@@ -7633,7 +7671,7 @@
id: Challenge Room/Panel_double_anagram_5
colors: yellow
tag: midyellow
FACTS:
FACTS (Chain):
id: Challenge Room/Panel_facts
colors:
- red
@@ -7643,18 +7681,18 @@
id: Challenge Room/Panel_facts2
colors: red
tag: forbid
FACTS (3):
FACTS (2):
id: Challenge Room/Panel_facts3
tag: forbid
FACTS (4):
FACTS (3):
id: Challenge Room/Panel_facts4
colors: blue
tag: forbid
FACTS (5):
FACTS (4):
id: Challenge Room/Panel_facts5
colors: blue
tag: forbid
FACTS (6):
FACTS (5):
id: Challenge Room/Panel_facts6
colors: blue
tag: forbid

View File

@@ -31,12 +31,12 @@ panels:
LIES: 444408
The Seeker:
Achievement: 444409
BEAR: 444410
MINE: 444411
BEAR (1): 444410
MINE (1): 444411
MINE (2): 444412
BOW: 444413
DOES: 444414
MOBILE: 444415
MOBILE (1): 444415
MOBILE (2): 444416
DESERT: 444417
DESSERT: 444418
@@ -57,8 +57,6 @@ panels:
Hub Room:
ORDER: 444432
SLAUGHTER: 444433
NEAR: 444434
FAR: 444435
TRACE: 444436
RAT: 444437
OPEN: 444438
@@ -72,7 +70,7 @@ panels:
EIGHT: 444445
Pilgrim Antechamber:
HOT CRUST: 444446
PILGRIMAGE: 444447
PILGRIM: 444447
MASTERY: 444448
Pilgrim Room:
THIS: 444449
@@ -123,6 +121,9 @@ panels:
RACECAR (White): 444489
SOLOS (White): 444490
Achievement: 444491
Near Far Area:
NEAR: 444434
FAR: 444435
Warts Straw Area:
WARTS: 444492
STRAW: 444493
@@ -187,7 +188,7 @@ panels:
Achievement: 444546
GAZE: 444547
The Fearless (First Floor):
NAPS: 444548
SPAN: 444548
TEAM: 444549
TEEM: 444550
IMPATIENT: 444551
@@ -208,25 +209,25 @@ panels:
EVEN: 444564
The Observant:
Achievement: 444565
BACK: 444566
SIDE: 444567
FOUR (1): 444566
FOUR (2): 444567
BACKSIDE: 444568
STAIRS: 444569
WAYS: 444570
'ON': 444571
UP: 444572
SWIMS: 444573
UPSTAIRS: 444574
TOIL: 444575
STOP: 444576
TOP: 444577
HI: 444578
HI (2): 444579
'31': 444580
'52': 444581
OIL: 444582
BACKSIDE (GREEN): 444583
SIDEWAYS: 444584
SIX: 444569
FOUR (3): 444570
TWO (1): 444571
TWO (2): 444572
FIVE: 444573
BELOW (1): 444574
BLUE: 444575
BELOW (2): 444576
MINT (1): 444577
ESACREWOL: 444578
EULB: 444579
NUMBERS (1): 444580
NUMBERS (2): 444581
MINT (2): 444582
GREEN (1): 444583
GREEN (2): 444584
The Incomparable:
Achievement: 444585
A (One): 444586
@@ -254,7 +255,7 @@ panels:
RED: 444605
DEER + WREN: 444606
Orange Tower Fourth Floor:
RUNT: 444607
RUNT (1): 444607
RUNT (2): 444608
LEARNS + UNSEW: 444609
HOT CRUSTS: 444610
@@ -279,14 +280,19 @@ panels:
THE END: 444620
THE MASTER: 444621
MASTERY: 444622
Roof:
MASTERY (1): 444623
MASTERY (2): 444624
MASTERY (3): 444625
MASTERY (4): 444626
MASTERY (5): 444627
MASTERY (6): 444628
Behind A Smile:
MASTERY: 444623
STAIRCASE: 444629
Sixteen Colorful Squares:
MASTERY: 444624
Among Treetops:
MASTERY: 444625
Horizon's Edge:
MASTERY: 444626
Beneath The Lookout:
MASTERY: 444627
Rooftop Staircase:
MASTERY: 444628
Orange Tower Basement:
MASTERY: 444630
THE LIBRARY: 444631
@@ -341,16 +347,17 @@ panels:
ORANGE: 444663
UNCOVER: 444664
OXEN: 444665
BACKSIDE: 444666
The Optimistic: 444667
PAST: 444668
FUTURE: 444669
PAST (1): 444668
FUTURE (1): 444669
FUTURE (2): 444670
PAST (2): 444671
PRESENT: 444672
SMILE: 444673
ANGERED: 444674
VOTE: 444675
The Optimistic:
BACKSIDE: 444666
Achievement: 444667
The Initiated:
Achievement: 444676
DAUGHTER: 444677
@@ -400,7 +407,7 @@ panels:
ZEN: 444719
SON: 444720
STARGAZER: 444721
MOUTH: 444722
SOUND: 444722
YEAST: 444723
WET: 444724
The Bold:
@@ -442,7 +449,7 @@ panels:
The Undeterred:
Achievement: 444759
BONE: 444760
EYE: 444761
EYE (1): 444761
MOUTH: 444762
IRIS: 444763
EYE (2): 444764
@@ -524,8 +531,8 @@ panels:
TENT: 444832
BOWL: 444833
The Bearer (West):
SNOW: 444834
SMILE: 444835
SMILE: 444834
SNOW: 444835
Bearer Side Area:
SHORTCUT: 444836
POTS: 444837
@@ -720,7 +727,7 @@ panels:
TRUSTWORTHY: 444978
FREE: 444979
OUR: 444980
ONE ROAD MANY TURNS: 444981
ORDER: 444981
Art Gallery (Second Floor):
HOUSE: 444982
PATH: 444983
@@ -778,7 +785,7 @@ panels:
WILD: 445028
KID: 445029
PISTOL: 445030
QUARTZ: 445031
GEM: 445031
INNOVATIVE (Top): 445032
INNOVATIVE (Bottom): 445033
Room Room:
@@ -792,15 +799,15 @@ panels:
FLOOR (3): 445041
FLOOR (4): 445042
FLOOR (5): 445043
FLOOR (7): 445044
FLOOR (8): 445045
FLOOR (9): 445046
FLOOR (10): 445047
FLOOR (6): 445044
FLOOR (7): 445045
FLOOR (8): 445046
CEILING (1): 445048
CEILING (2): 445049
CEILING (3): 445050
CEILING (4): 445051
CEILING (5): 445052
CEILING (6): 445047
WALL (1): 445053
WALL (2): 445054
WALL (3): 445055
@@ -848,7 +855,7 @@ panels:
PANDEMIC (1): 445100
TRINITY: 445101
CHEMISTRY: 445102
FLUMMOXED: 445103
FLUSTERED: 445103
PANDEMIC (2): 445104
COUNTERCLOCKWISE: 445105
FEARLESS: 445106
@@ -934,7 +941,7 @@ panels:
CORNER: 445182
STRAWBERRIES: 445183
GRUB: 445184
BREAD: 445185
CHEESE: 445185
COLOR: 445186
WRITER: 445187
'02759': 445188
@@ -945,12 +952,12 @@ panels:
DUCK LOGO: 445193
AVIAN GREEN: 445194
FEVER TEAR: 445195
FACTS: 445196
FACTS (Chain): 445196
FACTS (1): 445197
FACTS (3): 445198
FACTS (4): 445199
FACTS (5): 445200
FACTS (6): 445201
FACTS (2): 445198
FACTS (3): 445199
FACTS (4): 445200
FACTS (5): 445201
LAPEL SHEEP: 445202
doors:
Starting Room:
@@ -980,9 +987,6 @@ doors:
Tenacious Entrance:
item: 444426
location: 444433
Symmetry Door:
item: 444428
location: 445204
Shortcut to Hedge Maze:
item: 444430
location: 444436
@@ -1039,6 +1043,10 @@ doors:
location: 445210
White Palindromes:
location: 445211
Near Far Area:
Door:
item: 444428
location: 445204
Warts Straw Area:
Door:
item: 444451
@@ -1292,7 +1300,7 @@ doors:
item: 444539
location: 444806
The Bearer:
Shortcut to The Bold:
Entrance:
item: 444540
location: 444820
Backside Door:

View File

@@ -24,14 +24,6 @@ class ItemData(NamedTuple):
return world.options.shuffle_colors > 0
elif self.mode == "doors":
return world.options.shuffle_doors != ShuffleDoors.option_none
elif self.mode == "orange tower":
# door shuffle is on and tower isn't progressive
return world.options.shuffle_doors != ShuffleDoors.option_none \
and not world.options.progressive_orange_tower
elif self.mode == "the colorful":
# complex door shuffle is on and colorful isn't progressive
return world.options.shuffle_doors == ShuffleDoors.option_complex \
and not world.options.progressive_colorful
elif self.mode == "complex door":
return world.options.shuffle_doors == ShuffleDoors.option_complex
elif self.mode == "door group":
@@ -72,12 +64,7 @@ def load_item_data():
door_groups.setdefault(door.group, []).extend(door.door_ids)
if room_name in PROGRESSION_BY_ROOM and door_name in PROGRESSION_BY_ROOM[room_name]:
if room_name == "Orange Tower":
door_mode = "orange tower"
elif room_name == "The Colorful":
door_mode = "the colorful"
else:
door_mode = "special"
door_mode = "special"
ALL_ITEM_TABLE[door.item_name] = \
ItemData(get_door_item_id(room_name, door_name),

View File

@@ -1,3 +1,4 @@
from enum import Enum
from typing import Dict, List, NamedTuple, Optional, Set, Tuple, TYPE_CHECKING
from .items import ALL_ITEM_TABLE
@@ -36,6 +37,27 @@ class PlayerLocation(NamedTuple):
access: AccessRequirements
class ProgressiveItemBehavior(Enum):
DISABLE = 1
SPLIT = 2
PROGRESSIVE = 3
def should_split_progression(progression_name: str, world: "LingoWorld") -> ProgressiveItemBehavior:
if progression_name == "Progressive Orange Tower":
if world.options.progressive_orange_tower:
return ProgressiveItemBehavior.PROGRESSIVE
else:
return ProgressiveItemBehavior.SPLIT
elif progression_name == "Progressive Colorful":
if world.options.progressive_colorful:
return ProgressiveItemBehavior.PROGRESSIVE
else:
return ProgressiveItemBehavior.SPLIT
return ProgressiveItemBehavior.PROGRESSIVE
class LingoPlayerLogic:
"""
Defines logic after a player's options have been applied
@@ -83,10 +105,13 @@ class LingoPlayerLogic:
def handle_non_grouped_door(self, room_name: str, door_data: Door, world: "LingoWorld"):
if room_name in PROGRESSION_BY_ROOM and door_data.name in PROGRESSION_BY_ROOM[room_name]:
if (room_name == "Orange Tower" and not world.options.progressive_orange_tower)\
or (room_name == "The Colorful" and not world.options.progressive_colorful):
progression_name = PROGRESSION_BY_ROOM[room_name][door_data.name].item_name
progression_handling = should_split_progression(progression_name, world)
if progression_handling == ProgressiveItemBehavior.SPLIT:
self.set_door_item(room_name, door_data.name, door_data.item_name)
else:
self.real_items.append(door_data.item_name)
elif progression_handling == ProgressiveItemBehavior.PROGRESSIVE:
progressive_item_name = PROGRESSION_BY_ROOM[room_name][door_data.name].item_name
self.set_door_item(room_name, door_data.name, progressive_item_name)
self.real_items.append(progressive_item_name)
@@ -196,7 +221,7 @@ class LingoPlayerLogic:
["Orange Tower Fourth Floor", "Hot Crusts Door"], ["Outside The Initiated", "Shortcut to Hub Room"],
["Orange Tower First Floor", "Shortcut to Hub Room"], ["Directional Gallery", "Shortcut to The Undeterred"],
["Orange Tower First Floor", "Salt Pepper Door"], ["Hub Room", "Crossroads Entrance"],
["Color Hunt", "Shortcut to The Steady"], ["The Bearer", "Shortcut to The Bold"], ["Art Gallery", "Exit"],
["Color Hunt", "Shortcut to The Steady"], ["The Bearer", "Entrance"], ["Art Gallery", "Exit"],
["The Tenacious", "Shortcut to Hub Room"], ["Outside The Agreeable", "Tenacious Entrance"]
]
pilgrimage_reqs = AccessRequirements()

View File

@@ -96,7 +96,7 @@ class TestProgressiveArtGallery(LingoTestBase):
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertFalse(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertFalse(self.can_reach_location("Art Gallery - ORDER"))
self.assertFalse(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
self.collect_by_name(["Second Room - Exit Door", "Crossroads - Tower Entrance",
@@ -105,7 +105,7 @@ class TestProgressiveArtGallery(LingoTestBase):
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertFalse(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertFalse(self.can_reach_location("Art Gallery - ORDER"))
self.assertFalse(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
progressive_gallery_room = self.get_items_by_name("Progressive Art Gallery")
@@ -115,7 +115,7 @@ class TestProgressiveArtGallery(LingoTestBase):
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertFalse(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertFalse(self.can_reach_location("Art Gallery - ORDER"))
self.assertFalse(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
self.collect(progressive_gallery_room[1])
@@ -123,7 +123,7 @@ class TestProgressiveArtGallery(LingoTestBase):
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertFalse(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertFalse(self.can_reach_location("Art Gallery - ORDER"))
self.assertFalse(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
self.collect(progressive_gallery_room[2])
@@ -131,7 +131,7 @@ class TestProgressiveArtGallery(LingoTestBase):
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertFalse(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertFalse(self.can_reach_location("Art Gallery - ORDER"))
self.assertFalse(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
self.collect(progressive_gallery_room[3])
@@ -139,7 +139,7 @@ class TestProgressiveArtGallery(LingoTestBase):
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertTrue(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertTrue(self.can_reach_location("Art Gallery - ORDER"))
self.assertFalse(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
self.collect_by_name("Orange Tower Fifth Floor - Quadruple Intersection")
@@ -147,7 +147,7 @@ class TestProgressiveArtGallery(LingoTestBase):
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertTrue(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertTrue(self.can_reach_location("Art Gallery - ORDER"))
self.assertTrue(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
@@ -162,7 +162,7 @@ class TestNoDoorsArtGallery(LingoTestBase):
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertFalse(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertFalse(self.can_reach_location("Art Gallery - ORDER"))
self.assertFalse(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
self.collect_by_name("Yellow")
@@ -170,7 +170,7 @@ class TestNoDoorsArtGallery(LingoTestBase):
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertFalse(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertFalse(self.can_reach_location("Art Gallery - ORDER"))
self.assertFalse(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
self.collect_by_name("Brown")
@@ -178,7 +178,7 @@ class TestNoDoorsArtGallery(LingoTestBase):
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertFalse(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertFalse(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertFalse(self.can_reach_location("Art Gallery - ORDER"))
self.assertFalse(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
self.collect_by_name("Blue")
@@ -186,7 +186,7 @@ class TestNoDoorsArtGallery(LingoTestBase):
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertFalse(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertFalse(self.can_reach_location("Art Gallery - ORDER"))
self.assertFalse(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))
self.collect_by_name(["Orange", "Gray"])
@@ -194,5 +194,5 @@ class TestNoDoorsArtGallery(LingoTestBase):
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Second Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Third Floor)", "Region", self.player))
self.assertTrue(self.multiworld.state.can_reach("Art Gallery (Fourth Floor)", "Region", self.player))
self.assertTrue(self.can_reach_location("Art Gallery - ONE ROAD MANY TURNS"))
self.assertTrue(self.can_reach_location("Art Gallery - ORDER"))
self.assertTrue(self.multiworld.state.can_reach("Orange Tower Fifth Floor", "Region", self.player))

View File

@@ -8,7 +8,8 @@ require 'set'
require 'yaml'
configpath = ARGV[0]
mappath = ARGV[1]
idspath = ARGV[1]
mappath = ARGV[2]
panels = Set["Countdown Panels/Panel_1234567890_wanderlust"]
doors = Set["Naps Room Doors/Door_hider_new1", "Tower Room Area Doors/Door_wanderer_entrance"]
@@ -46,6 +47,8 @@ painting_directives = Set["id", "enter_only", "exit_only", "orientation", "requi
non_counting = 0
ids = YAML.load_file(idspath)
config = YAML.load_file(configpath)
config.each do |room_name, room|
configured_rooms.add(room_name)
@@ -162,6 +165,10 @@ config.each do |room_name, room|
unless bad_subdirectives.empty? then
puts "#{room_name} - #{panel_name} :::: Panel has the following invalid subdirectives: #{bad_subdirectives.join(", ")}"
end
unless ids.include?("panels") and ids["panels"].include?(room_name) and ids["panels"][room_name].include?(panel_name)
puts "#{room_name} - #{panel_name} :::: Panel is missing a location ID"
end
end
(room["doors"] || {}).each do |door_name, door|
@@ -229,6 +236,18 @@ config.each do |room_name, room|
unless bad_subdirectives.empty? then
puts "#{room_name} - #{door_name} :::: Door has the following invalid subdirectives: #{bad_subdirectives.join(", ")}"
end
unless door["skip_item"] or door["event"]
unless ids.include?("doors") and ids["doors"].include?(room_name) and ids["doors"][room_name].include?(door_name) and ids["doors"][room_name][door_name].include?("item")
puts "#{room_name} - #{door_name} :::: Door is missing an item ID"
end
end
unless door["skip_location"] or door["event"]
unless ids.include?("doors") and ids["doors"].include?(room_name) and ids["doors"][room_name].include?(door_name) and ids["doors"][room_name][door_name].include?("location")
puts "#{room_name} - #{door_name} :::: Door is missing a location ID"
end
end
end
(room["paintings"] || []).each do |painting|
@@ -281,6 +300,10 @@ config.each do |room_name, room|
mentioned_doors.add("#{room_name} - #{door}")
end
end
unless ids.include?("progression") and ids["progression"].include?(progression_name)
puts "#{room_name} - #{progression_name} :::: Progression is missing an item ID"
end
end
end
@@ -303,6 +326,10 @@ door_groups.each do |group,num|
if num == 1 then
puts "Door group \"#{group}\" only has one door in it"
end
unless ids.include?("door_groups") and ids["door_groups"].include?(group)
puts "#{group} :::: Door group is missing an item ID"
end
end
slashed_rooms = configured_rooms.select do |room|

View File

@@ -17,7 +17,7 @@ client_version = 1
class MeritousWeb(WebWorld):
tutorials = [Tutorial(
"Meritous Setup Tutorial",
"Meritous Setup Guide",
"A guide to setting up the Archipelago Meritous software on your computer.",
"English",
"setup_en.md",

View File

@@ -17,7 +17,7 @@ class MessengerWeb(WebWorld):
bug_report_page = "https://github.com/alwaysintreble/TheMessengerRandomizerModAP/issues"
tut_en = Tutorial(
"Multiworld Setup Tutorial",
"Multiworld Setup Guide",
"A guide to setting up The Messenger randomizer on your computer.",
"English",
"setup_en.md",

View File

@@ -1,6 +1,7 @@
from test.TestBase import WorldTestBase
from .. import MessengerWorld
class MessengerTestBase(WorldTestBase):
game = "The Messenger"
player: int = 1
world: MessengerWorld

View File

@@ -12,5 +12,5 @@ class LocationsTest(MessengerTestBase):
return False
def test_locations_exist(self) -> None:
for location in self.multiworld.worlds[1].location_name_to_id:
for location in self.world.location_name_to_id:
self.assertIsInstance(self.multiworld.get_location(location, self.player), MessengerLocation)

View File

@@ -17,7 +17,7 @@ class ShopCostTest(MessengerTestBase):
self.assertFalse(self.can_reach_location(loc))
def test_shop_prices(self) -> None:
prices: Dict[str, int] = self.multiworld.worlds[self.player].shop_prices
prices: Dict[str, int] = self.world.shop_prices
for loc, price in prices.items():
with self.subTest("prices", loc=loc):
self.assertLessEqual(price, self.multiworld.get_location(f"The Shop - {loc}", self.player).cost)
@@ -51,7 +51,7 @@ class ShopCostMinTest(ShopCostTest):
}
def test_shop_rules(self) -> None:
if self.multiworld.worlds[self.player].total_shards:
if self.world.total_shards:
super().test_shop_rules()
else:
for loc in SHOP_ITEMS:
@@ -85,7 +85,7 @@ class PlandoTest(MessengerTestBase):
with self.subTest("has cost", loc=loc):
self.assertFalse(self.can_reach_location(loc))
prices = self.multiworld.worlds[self.player].shop_prices
prices = self.world.shop_prices
for loc, price in prices.items():
with self.subTest("prices", loc=loc):
if loc == "Karuta Plates":
@@ -98,7 +98,7 @@ class PlandoTest(MessengerTestBase):
self.assertTrue(loc.replace("The Shop - ", "") in SHOP_ITEMS)
self.assertEqual(len(prices), len(SHOP_ITEMS))
figures = self.multiworld.worlds[self.player].figurine_prices
figures = self.world.figurine_prices
for loc, price in figures.items():
with self.subTest("figure prices", loc=loc):
if loc == "Barmath'azel Figurine":

View File

@@ -41,8 +41,8 @@ class HalfSealsRequired(MessengerTestBase):
def test_seals_amount(self) -> None:
"""Should have 45 power seals in the item pool and half that required"""
self.assertEqual(self.multiworld.total_seals[self.player], 45)
self.assertEqual(self.multiworld.worlds[self.player].total_seals, 45)
self.assertEqual(self.multiworld.worlds[self.player].required_seals, 22)
self.assertEqual(self.world.total_seals, 45)
self.assertEqual(self.world.required_seals, 22)
total_seals = [seal for seal in self.multiworld.itempool if seal.name == "Power Seal"]
required_seals = [seal for seal in total_seals
if seal.classification == ItemClassification.progression_skip_balancing]
@@ -60,8 +60,8 @@ class ThirtyThirtySeals(MessengerTestBase):
def test_seals_amount(self) -> None:
"""Should have 30 power seals in the pool and 33 percent of that required."""
self.assertEqual(self.multiworld.total_seals[self.player], 30)
self.assertEqual(self.multiworld.worlds[self.player].total_seals, 30)
self.assertEqual(self.multiworld.worlds[self.player].required_seals, 10)
self.assertEqual(self.world.total_seals, 30)
self.assertEqual(self.world.required_seals, 10)
total_seals = [seal for seal in self.multiworld.itempool if seal.name == "Power Seal"]
required_seals = [seal for seal in total_seals
if seal.classification == ItemClassification.progression_skip_balancing]
@@ -78,7 +78,7 @@ class MaxSealsNoShards(MessengerTestBase):
def test_seals_amount(self) -> None:
"""Should set total seals to 70 since shards aren't shuffled."""
self.assertEqual(self.multiworld.total_seals[self.player], 85)
self.assertEqual(self.multiworld.worlds[self.player].total_seals, 70)
self.assertEqual(self.world.total_seals, 70)
class MaxSealsWithShards(MessengerTestBase):
@@ -91,8 +91,8 @@ class MaxSealsWithShards(MessengerTestBase):
def test_seals_amount(self) -> None:
"""Should have 85 seals in the pool with all required and be a valid seed."""
self.assertEqual(self.multiworld.total_seals[self.player], 85)
self.assertEqual(self.multiworld.worlds[self.player].total_seals, 85)
self.assertEqual(self.multiworld.worlds[self.player].required_seals, 85)
self.assertEqual(self.world.total_seals, 85)
self.assertEqual(self.world.required_seals, 85)
total_seals = [seal for seal in self.multiworld.itempool if seal.name == "Power Seal"]
required_seals = [seal for seal in total_seals
if seal.classification == ItemClassification.progression_skip_balancing]

View File

@@ -37,7 +37,7 @@ class MinecraftWebWorld(WebWorld):
bug_report_page = "https://github.com/KonoTyran/Minecraft_AP_Randomizer/issues/new?assignees=&labels=bug&template=bug_report.yaml&title=%5BBug%5D%3A+Brief+Description+of+bug+here"
setup = Tutorial(
"Multiworld Setup Tutorial",
"Multiworld Setup Guide",
"A guide to setting up the Archipelago Minecraft software on your computer. This guide covers"
"single-player, multiworld, and related software.",
"English",

Some files were not shown because too many files have changed in this diff Show More