diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 4138f93f04..be053bdc2d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -4,6 +4,11 @@ name: Build
on: workflow_dispatch
+env:
+ SNI_VERSION: v0.0.84
+ ENEMIZER_VERSION: 7.1
+ APPIMAGETOOL_VERSION: 13
+
jobs:
# build-release-macos: # LF volunteer
@@ -17,9 +22,9 @@ jobs:
python-version: '3.8'
- name: Download run-time dependencies
run: |
- Invoke-WebRequest -Uri https://github.com/alttpo/sni/releases/download/v0.0.82/sni-v0.0.82-windows-amd64.zip -OutFile sni.zip
+ Invoke-WebRequest -Uri https://github.com/alttpo/sni/releases/download/${Env:SNI_VERSION}/sni-${Env:SNI_VERSION}-windows-amd64.zip -OutFile sni.zip
Expand-Archive -Path sni.zip -DestinationPath SNI -Force
- Invoke-WebRequest -Uri https://github.com/Ijwu/Enemizer/releases/download/7.0.1/win-x64.zip -OutFile enemizer.zip
+ Invoke-WebRequest -Uri https://github.com/Ijwu/Enemizer/releases/download/${Env:ENEMIZER_VERSION}/win-x64.zip -OutFile enemizer.zip
Expand-Archive -Path enemizer.zip -DestinationPath EnemizerCLI -Force
- name: Build
run: |
@@ -43,6 +48,7 @@ jobs:
build-ubuntu1804:
runs-on: ubuntu-18.04
steps:
+ # - copy code below to release.yml -
- uses: actions/checkout@v2
- name: Install base dependencies
run: |
@@ -56,18 +62,18 @@ jobs:
- name: Install build-time dependencies
run: |
echo "PYTHON=python3.9" >> $GITHUB_ENV
- wget -nv https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage
+ wget -nv https://github.com/AppImage/AppImageKit/releases/download/$APPIMAGETOOL_VERSION/appimagetool-x86_64.AppImage
chmod a+rx appimagetool-x86_64.AppImage
./appimagetool-x86_64.AppImage --appimage-extract
echo -e '#/bin/sh\n./squashfs-root/AppRun "$@"' > appimagetool
chmod a+rx appimagetool
- name: Download run-time dependencies
run: |
- wget -nv https://github.com/alttpo/sni/releases/download/v0.0.82/sni-v0.0.82-manylinux2014-amd64.tar.xz
+ wget -nv https://github.com/alttpo/sni/releases/download/$SNI_VERSION/sni-$SNI_VERSION-manylinux2014-amd64.tar.xz
tar xf sni-*.tar.xz
rm sni-*.tar.xz
mv sni-* SNI
- wget -nv https://github.com/Ijwu/Enemizer/releases/download/7.0.1/ubuntu.16.04-x64.7z
+ wget -nv https://github.com/Ijwu/Enemizer/releases/download/$ENEMIZER_VERSION/ubuntu.16.04-x64.7z
7za x -oEnemizerCLI/ ubuntu.16.04-x64.7z
- name: Build
run: |
@@ -84,6 +90,7 @@ jobs:
(cd build && DIR_NAME="`ls | grep exe`" && mv "$DIR_NAME" Archipelago && tar -czvf ../dist/$TAR_NAME Archipelago && mv Archipelago "$DIR_NAME")
echo "APPIMAGE_NAME=$APPIMAGE_NAME" >> $GITHUB_ENV
echo "TAR_NAME=$TAR_NAME" >> $GITHUB_ENV
+ # - copy code above to release.yml -
- name: Store AppImage
uses: actions/upload-artifact@v2
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index aa82883ff1..23f018caf2 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -7,6 +7,11 @@ on:
tags:
- '*.*.*'
+env:
+ SNI_VERSION: v0.0.84
+ ENEMIZER_VERSION: 7.1
+ APPIMAGETOOL_VERSION: 13
+
jobs:
create-release:
runs-on: ubuntu-latest
@@ -44,22 +49,23 @@ jobs:
- name: Install build-time dependencies
run: |
echo "PYTHON=python3.9" >> $GITHUB_ENV
- wget -nv https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage
+ wget -nv https://github.com/AppImage/AppImageKit/releases/download/$APPIMAGETOOL_VERSION/appimagetool-x86_64.AppImage
chmod a+rx appimagetool-x86_64.AppImage
./appimagetool-x86_64.AppImage --appimage-extract
echo -e '#/bin/sh\n./squashfs-root/AppRun "$@"' > appimagetool
chmod a+rx appimagetool
- name: Download run-time dependencies
run: |
- wget -nv https://github.com/alttpo/sni/releases/download/v0.0.82/sni-v0.0.82-manylinux2014-amd64.tar.xz
+ wget -nv https://github.com/alttpo/sni/releases/download/$SNI_VERSION/sni-$SNI_VERSION-manylinux2014-amd64.tar.xz
tar xf sni-*.tar.xz
rm sni-*.tar.xz
mv sni-* SNI
- wget -nv https://github.com/Ijwu/Enemizer/releases/download/7.0.1/ubuntu.16.04-x64.7z
+ wget -nv https://github.com/Ijwu/Enemizer/releases/download/$ENEMIZER_VERSION/ubuntu.16.04-x64.7z
7za x -oEnemizerCLI/ ubuntu.16.04-x64.7z
- name: Build
run: |
- "${{ env.PYTHON }}" -m pip install --upgrade pip setuptools virtualenv PyGObject # pygobject should probably move to requirements
+ # pygobject is an optional dependency for kivy that's not in requirements
+ "${{ env.PYTHON }}" -m pip install --upgrade pip virtualenv PyGObject setuptools
"${{ env.PYTHON }}" -m venv venv
source venv/bin/activate
pip install -r requirements.txt
diff --git a/BaseClasses.py b/BaseClasses.py
index cea1d48e6f..df8ac02071 100644
--- a/BaseClasses.py
+++ b/BaseClasses.py
@@ -955,6 +955,13 @@ class Region:
return True
return False
+ def get_connecting_entrance(self, is_main_entrance: typing.Callable[[Entrance], bool]) -> Entrance:
+ for entrance in self.entrances:
+ if is_main_entrance(entrance):
+ return entrance
+ for entrance in self.entrances: # BFS might be better here, trying DFS for now.
+ return entrance.parent_region.get_connecting_entrance(is_main_entrance)
+
def __repr__(self):
return self.__str__()
@@ -1422,7 +1429,6 @@ class Spoiler():
"f" in self.world.shop_shuffle[player]))
outfile.write('Custom Potion Shop: %s\n' %
bool_to_text("w" in self.world.shop_shuffle[player]))
- outfile.write('Boss shuffle: %s\n' % self.world.boss_shuffle[player])
outfile.write('Enemy health: %s\n' % self.world.enemy_health[player])
outfile.write('Enemy damage: %s\n' % self.world.enemy_damage[player])
outfile.write('Prize shuffle %s\n' %
diff --git a/CommonClient.py b/CommonClient.py
index 574da16f2a..94d4359dd1 100644
--- a/CommonClient.py
+++ b/CommonClient.py
@@ -5,6 +5,7 @@ import urllib.parse
import sys
import typing
import time
+import functools
import ModuleUpdate
ModuleUpdate.update()
@@ -17,7 +18,8 @@ if __name__ == "__main__":
Utils.init_logging("TextClient", exception_logger="Client")
from MultiServer import CommandProcessor
-from NetUtils import Endpoint, decode, NetworkItem, encode, JSONtoTextParser, ClientStatus, Permission, NetworkSlot
+from NetUtils import Endpoint, decode, NetworkItem, encode, JSONtoTextParser, \
+ ClientStatus, Permission, NetworkSlot, RawJSONtoTextParser
from Utils import Version, stream_input
from worlds import network_data_package, AutoWorldRegister
import os
@@ -204,6 +206,10 @@ class CommonContext:
# execution
self.keep_alive_task = asyncio.create_task(keep_alive(self), name="Bouncy")
+ @functools.cached_property
+ def raw_text_parser(self) -> RawJSONtoTextParser:
+ return RawJSONtoTextParser(self)
+
@property
def total_locations(self) -> typing.Optional[int]:
"""Will return None until connected."""
diff --git a/FF1Client.py b/FF1Client.py
index c280fa3035..5a56d0dd08 100644
--- a/FF1Client.py
+++ b/FF1Client.py
@@ -1,4 +1,5 @@
import asyncio
+import copy
import json
import time
from asyncio import StreamReader, StreamWriter
@@ -6,7 +7,7 @@ from typing import List
import Utils
-from CommonClient import CommonContext, server_loop, gui_enabled, console_loop, ClientCommandProcessor, logger, \
+from CommonClient import CommonContext, server_loop, gui_enabled, ClientCommandProcessor, logger, \
get_base_parser
SYSTEM_MESSAGE_ID = 0
@@ -64,7 +65,7 @@ class FF1Context(CommonContext):
def _set_message(self, msg: str, msg_id: int):
if DISPLAY_MSGS:
- self.messages[(time.time(), msg_id)] = msg
+ self.messages[time.time(), msg_id] = msg
def on_package(self, cmd: str, args: dict):
if cmd == 'Connected':
@@ -73,32 +74,28 @@ class FF1Context(CommonContext):
msg = args['text']
if ': !' not in msg:
self._set_message(msg, SYSTEM_MESSAGE_ID)
- elif cmd == "ReceivedItems":
- msg = f"Received {', '.join([self.item_names[item.item] for item in args['items']])}"
- self._set_message(msg, SYSTEM_MESSAGE_ID)
- elif cmd == 'PrintJSON':
- print_type = args['type']
- item = args['item']
- receiving_player_id = args['receiving']
- receiving_player_name = self.player_names[receiving_player_id]
- sending_player_id = item.player
- sending_player_name = self.player_names[item.player]
- if print_type == 'Hint':
- msg = f"Hint: Your {self.item_names[item.item]} is at" \
- f" {self.player_names[item.player]}'s {self.location_names[item.location]}"
- self._set_message(msg, item.item)
- elif print_type == 'ItemSend' and receiving_player_id != self.slot:
- if sending_player_id == self.slot:
- if receiving_player_id == self.slot:
- msg = f"You found your own {self.item_names[item.item]}"
- else:
- msg = f"You sent {self.item_names[item.item]} to {receiving_player_name}"
- else:
- if receiving_player_id == sending_player_id:
- msg = f"{sending_player_name} found their {self.item_names[item.item]}"
- else:
- msg = f"{sending_player_name} sent {self.item_names[item.item]} to " \
- f"{receiving_player_name}"
+
+ def on_print_json(self, args: dict):
+ if self.ui:
+ self.ui.print_json(copy.deepcopy(args["data"]))
+ else:
+ text = self.jsontotextparser(copy.deepcopy(args["data"]))
+ logger.info(text)
+ relevant = args.get("type", None) in {"Hint", "ItemSend"}
+ if relevant:
+ item = args["item"]
+ # goes to this world
+ if self.slot_concerns_self(args["receiving"]):
+ relevant = True
+ # found in this world
+ elif self.slot_concerns_self(item.player):
+ relevant = True
+ # not related
+ else:
+ relevant = False
+ if relevant:
+ item = args["item"]
+ msg = self.raw_text_parser(copy.deepcopy(args["data"]))
self._set_message(msg, item.item)
def run_gui(self):
diff --git a/Fill.py b/Fill.py
index e44c80e720..c62eaabde8 100644
--- a/Fill.py
+++ b/Fill.py
@@ -136,33 +136,98 @@ def fill_restrictive(world: MultiWorld, base_state: CollectionState, locations:
itempool.extend(unplaced_items)
+def remaining_fill(world: MultiWorld,
+ locations: typing.List[Location],
+ itempool: typing.List[Item]) -> None:
+ unplaced_items: typing.List[Item] = []
+ placements: typing.List[Location] = []
+ swapped_items: typing.Counter[typing.Tuple[int, str]] = Counter()
+ while locations and itempool:
+ item_to_place = itempool.pop()
+ spot_to_fill: typing.Optional[Location] = None
+
+ for i, location in enumerate(locations):
+ if location.item_rule(item_to_place):
+ # popping by index is faster than removing by content,
+ spot_to_fill = locations.pop(i)
+ # skipping a scan for the element
+ break
+
+ else:
+ # we filled all reachable spots.
+ # try swapping this item with previously placed items
+
+ for (i, location) in enumerate(placements):
+ placed_item = location.item
+ # Unplaceable items can sometimes be swapped infinitely. Limit the
+ # number of times we will swap an individual item to prevent this
+
+ if swapped_items[placed_item.player,
+ placed_item.name] > 1:
+ continue
+
+ location.item = None
+ placed_item.location = None
+ if location.item_rule(item_to_place):
+ # Add this item to the existing placement, and
+ # add the old item to the back of the queue
+ spot_to_fill = placements.pop(i)
+
+ swapped_items[placed_item.player,
+ placed_item.name] += 1
+
+ itempool.append(placed_item)
+
+ break
+
+ # Item can't be placed here, restore original item
+ location.item = placed_item
+ placed_item.location = location
+
+ if spot_to_fill is None:
+ # Can't place this item, move on to the next
+ unplaced_items.append(item_to_place)
+ continue
+
+ world.push_item(spot_to_fill, item_to_place, False)
+ placements.append(spot_to_fill)
+
+ if unplaced_items and locations:
+ # There are leftover unplaceable items and locations that won't accept them
+ raise FillError(f'No more spots to place {unplaced_items}, locations {locations} are invalid. '
+ f'Already placed {len(placements)}: {", ".join(str(place) for place in placements)}')
+
+ itempool.extend(unplaced_items)
+
+
+def fast_fill(world: MultiWorld,
+ item_pool: typing.List[Item],
+ fill_locations: typing.List[Location]) -> typing.Tuple[typing.List[Item], typing.List[Location]]:
+ placing = min(len(item_pool), len(fill_locations))
+ for item, location in zip(item_pool, fill_locations):
+ world.push_item(location, item, False)
+ return item_pool[placing:], fill_locations[placing:]
+
+
def distribute_items_restrictive(world: MultiWorld) -> None:
fill_locations = sorted(world.get_unfilled_locations())
world.random.shuffle(fill_locations)
-
# get items to distribute
itempool = sorted(world.itempool)
world.random.shuffle(itempool)
progitempool: typing.List[Item] = []
- nonexcludeditempool: typing.List[Item] = []
- localrestitempool: typing.Dict[int, typing.List[Item]] = {player: [] for player in range(1, world.players + 1)}
- nonlocalrestitempool: typing.List[Item] = []
- restitempool: typing.List[Item] = []
+ usefulitempool: typing.List[Item] = []
+ filleritempool: typing.List[Item] = []
for item in itempool:
if item.advancement:
progitempool.append(item)
- elif item.useful: # this only gets nonprogression items which should not appear in excluded locations
- nonexcludeditempool.append(item)
- elif item.name in world.local_items[item.player].value:
- localrestitempool[item.player].append(item)
- elif item.name in world.non_local_items[item.player].value:
- nonlocalrestitempool.append(item)
+ elif item.useful:
+ usefulitempool.append(item)
else:
- restitempool.append(item)
+ filleritempool.append(item)
- call_all(world, "fill_hook", progitempool, nonexcludeditempool,
- localrestitempool, nonlocalrestitempool, restitempool, fill_locations)
+ call_all(world, "fill_hook", progitempool, usefulitempool, filleritempool, fill_locations)
locations: typing.Dict[LocationProgressType, typing.List[Location]] = {
loc_type: [] for loc_type in LocationProgressType}
@@ -184,50 +249,16 @@ def distribute_items_restrictive(world: MultiWorld) -> None:
raise FillError(
f'Not enough locations for progress items. There are {len(progitempool)} more items than locations')
- if nonexcludeditempool:
- world.random.shuffle(defaultlocations)
- # needs logical fill to not conflict with local items
- fill_restrictive(
- world, world.state, defaultlocations, nonexcludeditempool)
- if nonexcludeditempool:
- raise FillError(
- f'Not enough locations for non-excluded items. There are {len(nonexcludeditempool)} more items than locations')
+ remaining_fill(world, excludedlocations, filleritempool)
+ if excludedlocations:
+ raise FillError(
+ f"Not enough filler items for excluded locations. There are {len(excludedlocations)} more locations than items")
- defaultlocations = defaultlocations + excludedlocations
- world.random.shuffle(defaultlocations)
+ restitempool = usefulitempool + filleritempool
- if any(localrestitempool.values()): # we need to make sure some fills are limited to certain worlds
- local_locations: typing.Dict[int, typing.List[Location]] = {player: [] for player in world.player_ids}
- for location in defaultlocations:
- local_locations[location.player].append(location)
- for player_locations in local_locations.values():
- world.random.shuffle(player_locations)
+ remaining_fill(world, defaultlocations, restitempool)
- for player, items in localrestitempool.items(): # items already shuffled
- player_local_locations = local_locations[player]
- for item_to_place in items:
- if not player_local_locations:
- logging.warning(f"Ran out of local locations for player {player}, "
- f"cannot place {item_to_place}.")
- break
- spot_to_fill = player_local_locations.pop()
- world.push_item(spot_to_fill, item_to_place, False)
- defaultlocations.remove(spot_to_fill)
-
- for item_to_place in nonlocalrestitempool:
- for i, location in enumerate(defaultlocations):
- if location.player != item_to_place.player:
- world.push_item(defaultlocations.pop(i), item_to_place, False)
- break
- else:
- raise Exception(f"Could not place non_local_item {item_to_place} among {defaultlocations}. "
- f"Too many non-local items for too few remaining locations.")
-
- world.random.shuffle(defaultlocations)
-
- restitempool, defaultlocations = fast_fill(
- world, restitempool, defaultlocations)
- unplaced = progitempool + restitempool
+ unplaced = restitempool
unfilled = defaultlocations
if unplaced or unfilled:
@@ -241,15 +272,6 @@ def distribute_items_restrictive(world: MultiWorld) -> None:
logging.info(f'Per-Player counts: {print_data})')
-def fast_fill(world: MultiWorld,
- item_pool: typing.List[Item],
- fill_locations: typing.List[Location]) -> typing.Tuple[typing.List[Item], typing.List[Location]]:
- placing = min(len(item_pool), len(fill_locations))
- for item, location in zip(item_pool, fill_locations):
- world.push_item(location, item, False)
- return item_pool[placing:], fill_locations[placing:]
-
-
def flood_items(world: MultiWorld) -> None:
# get items to distribute
world.random.shuffle(world.itempool)
diff --git a/Generate.py b/Generate.py
index d13a78b375..f048e54383 100644
--- a/Generate.py
+++ b/Generate.py
@@ -23,7 +23,6 @@ from worlds.alttp.EntranceRandomizer import parse_arguments
from Main import main as ERmain
from BaseClasses import seeddigits, get_seed
import Options
-from worlds.alttp import Bosses
from worlds.alttp.Text import TextTable
from worlds.AutoWorld import AutoWorldRegister
import copy
@@ -337,19 +336,6 @@ def prefer_int(input_data: str) -> Union[str, int]:
return input_data
-available_boss_names: Set[str] = {boss.lower() for boss in Bosses.boss_table if boss not in
- {'Agahnim', 'Agahnim2', 'Ganon'}}
-available_boss_locations: Set[str] = {f"{loc.lower()}{f' {level}' if level else ''}" for loc, level in
- Bosses.boss_location_table}
-
-boss_shuffle_options = {None: 'none',
- 'none': 'none',
- 'basic': 'basic',
- 'full': 'full',
- 'chaos': 'chaos',
- 'singularity': 'singularity'
- }
-
goals = {
'ganon': 'ganon',
'crystals': 'crystals',
@@ -456,42 +442,7 @@ def roll_triggers(weights: dict, triggers: list) -> dict:
return weights
-def get_plando_bosses(boss_shuffle: str, plando_options: Set[str]) -> str:
- if boss_shuffle in boss_shuffle_options:
- return boss_shuffle_options[boss_shuffle]
- elif PlandoSettings.bosses in plando_options:
- options = boss_shuffle.lower().split(";")
- remainder_shuffle = "none" # vanilla
- bosses = []
- for boss in options:
- if boss in boss_shuffle_options:
- remainder_shuffle = boss_shuffle_options[boss]
- elif "-" in boss:
- loc, boss_name = boss.split("-")
- if boss_name not in available_boss_names:
- raise ValueError(f"Unknown Boss name {boss_name}")
- if loc not in available_boss_locations:
- raise ValueError(f"Unknown Boss Location {loc}")
- level = ''
- if loc.split(" ")[-1] in {"top", "middle", "bottom"}:
- # split off level
- loc = loc.split(" ")
- level = f" {loc[-1]}"
- loc = " ".join(loc[:-1])
- loc = loc.title().replace("Of", "of")
- if not Bosses.can_place_boss(boss_name.title(), loc, level):
- raise ValueError(f"Cannot place {boss_name} at {loc}{level}")
- bosses.append(boss)
- elif boss not in available_boss_names:
- raise ValueError(f"Unknown Boss name or Boss shuffle option {boss}.")
- else:
- bosses.append(boss)
- return ";".join(bosses + [remainder_shuffle])
- else:
- raise Exception(f"Boss Shuffle {boss_shuffle} is unknown and boss plando is turned off.")
-
-
-def handle_option(ret: argparse.Namespace, game_weights: dict, option_key: str, option: type(Options.Option)):
+def handle_option(ret: argparse.Namespace, game_weights: dict, option_key: str, option: type(Options.Option), plando_options: PlandoSettings):
if option_key in game_weights:
try:
if not option.supports_weighting:
@@ -502,10 +453,9 @@ def handle_option(ret: argparse.Namespace, game_weights: dict, option_key: str,
except Exception as e:
raise Exception(f"Error generating option {option_key} in {ret.game}") from e
else:
- if hasattr(player_option, "verify"):
- player_option.verify(AutoWorldRegister.world_types[ret.game])
+ player_option.verify(AutoWorldRegister.world_types[ret.game], ret.name, plando_options)
else:
- setattr(ret, option_key, option(option.default))
+ setattr(ret, option_key, option.from_any(option.default)) # call the from_any here to support default "random"
def roll_settings(weights: dict, plando_options: PlandoSettings = PlandoSettings.bosses):
@@ -549,11 +499,11 @@ def roll_settings(weights: dict, plando_options: PlandoSettings = PlandoSettings
if ret.game in AutoWorldRegister.world_types:
for option_key, option in world_type.option_definitions.items():
- handle_option(ret, game_weights, option_key, option)
+ handle_option(ret, game_weights, option_key, option, plando_options)
for option_key, option in Options.per_game_common_options.items():
# skip setting this option if already set from common_options, defaulting to root option
if not (option_key in Options.common_options and option_key not in game_weights):
- handle_option(ret, game_weights, option_key, option)
+ handle_option(ret, game_weights, option_key, option, plando_options)
if PlandoSettings.items in plando_options:
ret.plando_items = game_weights.get("plando_items", [])
if ret.game == "Minecraft" or ret.game == "Ocarina of Time":
@@ -636,8 +586,6 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
ret.item_functionality = get_choice_legacy('item_functionality', weights)
- boss_shuffle = get_choice_legacy('boss_shuffle', weights)
- ret.shufflebosses = get_plando_bosses(boss_shuffle, plando_options)
ret.enemy_damage = {None: 'default',
'default': 'default',
diff --git a/Launcher.py b/Launcher.py
index 92f43cd26c..8a3d53f866 100644
--- a/Launcher.py
+++ b/Launcher.py
@@ -19,8 +19,9 @@ from os.path import isfile
from shutil import which
from typing import Iterable, Sequence, Callable, Union, Optional
-import ModuleUpdate
-ModuleUpdate.update()
+if __name__ == "__main__":
+ import ModuleUpdate
+ ModuleUpdate.update()
from Utils import is_frozen, user_path, local_path, init_logging, open_filename, messagebox, \
is_windows, is_macos, is_linux
@@ -69,6 +70,7 @@ def browse_files():
webbrowser.open(file)
+# noinspection PyArgumentList
class Type(Enum):
TOOL = auto()
FUNC = auto() # not a real component
diff --git a/LttPAdjuster.py b/LttPAdjuster.py
index f516a20ec0..469e8920b3 100644
--- a/LttPAdjuster.py
+++ b/LttPAdjuster.py
@@ -83,9 +83,9 @@ def main():
parser.add_argument('--ow_palettes', default='default',
choices=['default', 'random', 'blackout', 'puke', 'classic', 'grayscale', 'negative', 'dizzy',
'sick'])
- parser.add_argument('--link_palettes', default='default',
- choices=['default', 'random', 'blackout', 'puke', 'classic', 'grayscale', 'negative', 'dizzy',
- 'sick'])
+ # parser.add_argument('--link_palettes', default='default',
+ # choices=['default', 'random', 'blackout', 'puke', 'classic', 'grayscale', 'negative', 'dizzy',
+ # 'sick'])
parser.add_argument('--shield_palettes', default='default',
choices=['default', 'random', 'blackout', 'puke', 'classic', 'grayscale', 'negative', 'dizzy',
'sick'])
diff --git a/Main.py b/Main.py
index acff74595a..bbd0c805df 100644
--- a/Main.py
+++ b/Main.py
@@ -12,7 +12,7 @@ from typing import Dict, Tuple, Optional, Set
from BaseClasses import MultiWorld, CollectionState, Region, RegionType, LocationProgressType, Location
from worlds.alttp.Items import item_name_groups
-from worlds.alttp.Regions import lookup_vanilla_location_to_entrance
+from worlds.alttp.Regions import is_main_entrance
from Fill import distribute_items_restrictive, flood_items, balance_multiworld_progression, distribute_planned
from worlds.alttp.Shops import SHOP_ID_START, total_shop_slots, FillDisabledShopSlots
from Utils import output_path, get_options, __version__, version_tuple
@@ -249,24 +249,9 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
output_file_futures.append(
pool.submit(AutoWorld.call_single, world, "generate_output", player, temp_dir))
- def get_entrance_to_region(region: Region):
- for entrance in region.entrances:
- if entrance.parent_region.type in (RegionType.DarkWorld, RegionType.LightWorld, RegionType.Generic):
- return entrance
- for entrance in region.entrances: # BFS might be better here, trying DFS for now.
- return get_entrance_to_region(entrance.parent_region)
-
# collect ER hint info
- 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]}
-
- for region in world.regions:
- if region.player in er_hint_data and region.locations:
- main_entrance = get_entrance_to_region(region)
- for location in region.locations:
- if type(location.address) == int: # skips events and crystals
- if lookup_vanilla_location_to_entrance[location.address] != main_entrance.name:
- er_hint_data[region.player][location.address] = main_entrance.name
+ er_hint_data: Dict[int, Dict[int, str]] = {}
+ AutoWorld.call_all(world, 'extend_hint_information', er_hint_data)
checks_in_area = {player: {area: list() for area in ordered_areas}
for player in range(1, world.players + 1)}
@@ -276,22 +261,23 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
for location in world.get_filled_locations():
if type(location.address) is int:
- main_entrance = get_entrance_to_region(location.parent_region)
if location.game != "A Link to the Past":
checks_in_area[location.player]["Light World"].append(location.address)
- elif location.parent_region.dungeon:
- dungeonname = {'Inverted Agahnims Tower': 'Agahnims Tower',
- 'Inverted Ganons Tower': 'Ganons Tower'} \
- .get(location.parent_region.dungeon.name, location.parent_region.dungeon.name)
- checks_in_area[location.player][dungeonname].append(location.address)
- elif location.parent_region.type == RegionType.LightWorld:
- checks_in_area[location.player]["Light World"].append(location.address)
- elif location.parent_region.type == RegionType.DarkWorld:
- checks_in_area[location.player]["Dark World"].append(location.address)
- elif main_entrance.parent_region.type == RegionType.LightWorld:
- checks_in_area[location.player]["Light World"].append(location.address)
- elif main_entrance.parent_region.type == RegionType.DarkWorld:
- checks_in_area[location.player]["Dark World"].append(location.address)
+ else:
+ main_entrance = location.parent_region.get_connecting_entrance(is_main_entrance)
+ if location.parent_region.dungeon:
+ dungeonname = {'Inverted Agahnims Tower': 'Agahnims Tower',
+ 'Inverted Ganons Tower': 'Ganons Tower'} \
+ .get(location.parent_region.dungeon.name, location.parent_region.dungeon.name)
+ checks_in_area[location.player][dungeonname].append(location.address)
+ elif location.parent_region.type == RegionType.LightWorld:
+ checks_in_area[location.player]["Light World"].append(location.address)
+ elif location.parent_region.type == RegionType.DarkWorld:
+ checks_in_area[location.player]["Dark World"].append(location.address)
+ elif main_entrance.parent_region.type == RegionType.LightWorld:
+ checks_in_area[location.player]["Light World"].append(location.address)
+ elif main_entrance.parent_region.type == RegionType.DarkWorld:
+ checks_in_area[location.player]["Dark World"].append(location.address)
checks_in_area[location.player]["Total"] += 1
oldmancaves = []
@@ -305,7 +291,7 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
player = region.player
location_id = SHOP_ID_START + total_shop_slots + index
- main_entrance = get_entrance_to_region(region)
+ main_entrance = region.get_connecting_entrance(is_main_entrance)
if main_entrance.parent_region.type == RegionType.LightWorld:
checks_in_area[player]["Light World"].append(location_id)
else:
@@ -340,7 +326,6 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
for player, world_precollected in world.precollected_items.items()}
precollected_hints = {player: set() for player in range(1, world.players + 1 + len(world.groups))}
-
for slot in world.player_ids:
slot_data[slot] = world.worlds[slot].fill_slot_data()
diff --git a/MultiServer.py b/MultiServer.py
index 6354f8e7a9..9f0865d425 100644
--- a/MultiServer.py
+++ b/MultiServer.py
@@ -126,6 +126,7 @@ class Context:
location_names: typing.Dict[int, str] = Utils.KeyedDefaultDict(lambda code: f'Unknown location (ID:{code})')
all_item_and_group_names: typing.Dict[str, typing.Set[str]]
forced_auto_forfeits: typing.Dict[str, bool]
+ non_hintable_names: typing.Dict[str, typing.Set[str]]
def __init__(self, host: str, port: int, server_password: str, password: str, location_check_points: int,
hint_cost: int, item_cheat: bool, forfeit_mode: str = "disabled", collect_mode="disabled",
@@ -196,7 +197,7 @@ class Context:
self.item_name_groups = {}
self.all_item_and_group_names = {}
self.forced_auto_forfeits = collections.defaultdict(lambda: False)
- self.non_hintable_names = {}
+ self.non_hintable_names = collections.defaultdict(frozenset)
self._load_game_data()
self._init_game_data()
@@ -221,11 +222,11 @@ class Context:
self.all_item_and_group_names[game_name] = \
set(game_package["item_name_to_id"]) | set(self.item_name_groups[game_name])
- def item_names_for_game(self, game: str) -> typing.Dict[str, int]:
- return self.gamespackage[game]["item_name_to_id"]
+ def item_names_for_game(self, game: str) -> typing.Optional[typing.Dict[str, int]]:
+ return self.gamespackage[game]["item_name_to_id"] if game in self.gamespackage else None
- def location_names_for_game(self, game: str) -> typing.Dict[str, int]:
- return self.gamespackage[game]["location_name_to_id"]
+ def location_names_for_game(self, game: str) -> typing.Optional[typing.Dict[str, int]]:
+ return self.gamespackage[game]["location_name_to_id"] if game in self.gamespackage else None
# General networking
async def send_msgs(self, endpoint: Endpoint, msgs: typing.Iterable[dict]) -> bool:
@@ -593,6 +594,7 @@ class Context:
forfeit_player(self, client.team, client.slot)
elif self.forced_auto_forfeits[self.games[client.slot]]:
forfeit_player(self, client.team, client.slot)
+ self.save() # save goal completion flag
def notify_hints(ctx: Context, team: int, hints: typing.List[NetUtils.Hint], only_new: bool = False):
@@ -742,6 +744,7 @@ async def countdown(ctx: Context, timer: int):
broadcast_countdown(ctx, 0, f"[Server]: GO")
ctx.countdown_timer = 0
+
def broadcast_text_all(ctx: Context, text: str, additional_arguments: dict = {}):
old_clients, new_clients = [], []
@@ -754,8 +757,10 @@ def broadcast_text_all(ctx: Context, text: str, additional_arguments: dict = {})
ctx.broadcast(old_clients, [{"cmd": "Print", "text": text }])
ctx.broadcast(new_clients, [{**{"cmd": "PrintJSON", "data": [{ "text": text }]}, **additional_arguments}])
+
def broadcast_countdown(ctx: Context, timer: int, message: str):
- broadcast_text_all(ctx, message, { "type": "Countdown", "countdown": timer })
+ broadcast_text_all(ctx, message, {"type": "Countdown", "countdown": timer})
+
def get_players_string(ctx: Context):
auth_clients = {(c.team, c.slot) for c in ctx.endpoints if c.auth}
@@ -896,14 +901,14 @@ def register_location_checks(ctx: Context, team: int, slot: int, locations: typi
ctx.save()
-def collect_hints(ctx: Context, team: int, slot: int, item_name: str) -> typing.List[NetUtils.Hint]:
+def collect_hints(ctx: Context, team: int, slot: int, item: typing.Union[int, str]) -> typing.List[NetUtils.Hint]:
hints = []
slots: typing.Set[int] = {slot}
for group_id, group in ctx.groups.items():
if slot in group:
slots.add(group_id)
- seeked_item_id = ctx.item_names_for_game(ctx.games[slot])[item_name]
+ seeked_item_id = item if isinstance(item, int) else ctx.item_names_for_game(ctx.games[slot])[item]
for finding_player, check_data in ctx.locations.items():
for location_id, (item_id, receiving_player, item_flags) in check_data.items():
if receiving_player in slots and item_id == seeked_item_id:
@@ -1331,13 +1336,33 @@ class ClientMessageProcessor(CommonCommandProcessor):
self.output(f"A hint costs {self.ctx.get_hint_cost(self.client.slot)} points. "
f"You have {points_available} points.")
return True
+
+ elif input_text.isnumeric():
+ game = self.ctx.games[self.client.slot]
+ hint_id = int(input_text)
+ hint_name = self.ctx.item_names[hint_id] \
+ if not for_location and hint_id in self.ctx.item_names \
+ else self.ctx.location_names[hint_id] \
+ if for_location and hint_id in self.ctx.location_names \
+ else None
+ if hint_name in self.ctx.non_hintable_names[game]:
+ self.output(f"Sorry, \"{hint_name}\" is marked as non-hintable.")
+ hints = []
+ elif not for_location:
+ hints = collect_hints(self.ctx, self.client.team, self.client.slot, hint_id)
+ else:
+ hints = collect_hint_location_id(self.ctx, self.client.team, self.client.slot, hint_id)
+
else:
game = self.ctx.games[self.client.slot]
+ if game not in self.ctx.all_item_and_group_names:
+ self.output("Can't look up item/location for unknown game. Hint for ID instead.")
+ return False
names = self.ctx.location_names_for_game(game) \
if for_location else \
self.ctx.all_item_and_group_names[game]
- hint_name, usable, response = get_intended_text(input_text,
- names)
+ hint_name, usable, response = get_intended_text(input_text, names)
+
if usable:
if hint_name in self.ctx.non_hintable_names[game]:
self.output(f"Sorry, \"{hint_name}\" is marked as non-hintable.")
@@ -1351,63 +1376,65 @@ class ClientMessageProcessor(CommonCommandProcessor):
hints = collect_hints(self.ctx, self.client.team, self.client.slot, hint_name)
else: # location name
hints = collect_hint_location_name(self.ctx, self.client.team, self.client.slot, hint_name)
- cost = self.ctx.get_hint_cost(self.client.slot)
- if hints:
- new_hints = set(hints) - self.ctx.hints[self.client.team, self.client.slot]
- old_hints = set(hints) - new_hints
- if old_hints:
- notify_hints(self.ctx, self.client.team, list(old_hints))
- if not new_hints:
- self.output("Hint was previously used, no points deducted.")
- if new_hints:
- found_hints = [hint for hint in new_hints if hint.found]
- not_found_hints = [hint for hint in new_hints if not hint.found]
- if not not_found_hints: # everything's been found, no need to pay
- can_pay = 1000
- elif cost:
- can_pay = int((points_available // cost) > 0) # limit to 1 new hint per call
- else:
- can_pay = 1000
-
- self.ctx.random.shuffle(not_found_hints)
- # By popular vote, make hints prefer non-local placements
- not_found_hints.sort(key=lambda hint: int(hint.receiving_player != hint.finding_player))
-
- hints = found_hints
- while can_pay > 0:
- if not not_found_hints:
- break
- hint = not_found_hints.pop()
- hints.append(hint)
- can_pay -= 1
- self.ctx.hints_used[self.client.team, self.client.slot] += 1
- points_available = get_client_points(self.ctx, self.client)
-
- if not_found_hints:
- if hints and cost and int((points_available // cost) == 0):
- self.output(
- f"There may be more hintables, however, you cannot afford to pay for any more. "
- f" You have {points_available} and need at least "
- f"{self.ctx.get_hint_cost(self.client.slot)}.")
- elif hints:
- self.output(
- "There may be more hintables, you can rerun the command to find more.")
- else:
- self.output(f"You can't afford the hint. "
- f"You have {points_available} points and need at least "
- f"{self.ctx.get_hint_cost(self.client.slot)}.")
- notify_hints(self.ctx, self.client.team, hints)
- self.ctx.save()
- return True
-
- else:
- self.output("Nothing found. Item/Location may not exist.")
- return False
else:
self.output(response)
return False
+ if hints:
+ cost = self.ctx.get_hint_cost(self.client.slot)
+ new_hints = set(hints) - self.ctx.hints[self.client.team, self.client.slot]
+ old_hints = set(hints) - new_hints
+ if old_hints:
+ notify_hints(self.ctx, self.client.team, list(old_hints))
+ if not new_hints:
+ self.output("Hint was previously used, no points deducted.")
+ if new_hints:
+ found_hints = [hint for hint in new_hints if hint.found]
+ not_found_hints = [hint for hint in new_hints if not hint.found]
+
+ if not not_found_hints: # everything's been found, no need to pay
+ can_pay = 1000
+ elif cost:
+ can_pay = int((points_available // cost) > 0) # limit to 1 new hint per call
+ else:
+ can_pay = 1000
+
+ self.ctx.random.shuffle(not_found_hints)
+ # By popular vote, make hints prefer non-local placements
+ not_found_hints.sort(key=lambda hint: int(hint.receiving_player != hint.finding_player))
+
+ hints = found_hints
+ while can_pay > 0:
+ if not not_found_hints:
+ break
+ hint = not_found_hints.pop()
+ hints.append(hint)
+ can_pay -= 1
+ self.ctx.hints_used[self.client.team, self.client.slot] += 1
+ points_available = get_client_points(self.ctx, self.client)
+
+ if not_found_hints:
+ if hints and cost and int((points_available // cost) == 0):
+ self.output(
+ f"There may be more hintables, however, you cannot afford to pay for any more. "
+ f" You have {points_available} and need at least "
+ f"{self.ctx.get_hint_cost(self.client.slot)}.")
+ elif hints:
+ self.output(
+ "There may be more hintables, you can rerun the command to find more.")
+ else:
+ self.output(f"You can't afford the hint. "
+ f"You have {points_available} points and need at least "
+ f"{self.ctx.get_hint_cost(self.client.slot)}.")
+ notify_hints(self.ctx, self.client.team, hints)
+ self.ctx.save()
+ return True
+
+ else:
+ self.output("Nothing found. Item/Location may not exist.")
+ return False
+
@mark_raw
def _cmd_hint(self, item_name: str = "") -> bool:
"""Use !hint {item_name},
@@ -1855,17 +1882,25 @@ class ServerCommandProcessor(CommonCommandProcessor):
seeked_player, usable, response = get_intended_text(player_name, self.ctx.player_names.values())
if usable:
team, slot = self.ctx.player_name_lookup[seeked_player]
- item_name = " ".join(item_name)
game = self.ctx.games[slot]
- item_name, usable, response = get_intended_text(item_name, self.ctx.all_item_and_group_names[game])
+ full_name = " ".join(item_name)
+
+ if full_name.isnumeric():
+ item, usable, response = int(full_name), True, None
+ elif game in self.ctx.all_item_and_group_names:
+ item, usable, response = get_intended_text(full_name, self.ctx.all_item_and_group_names[game])
+ else:
+ self.output("Can't look up item for unknown game. Hint for ID instead.")
+ return False
+
if usable:
- if item_name in self.ctx.item_name_groups[game]:
+ if game in self.ctx.item_name_groups and item in self.ctx.item_name_groups[game]:
hints = []
- for item_name_from_group in self.ctx.item_name_groups[game][item_name]:
+ for item_name_from_group in self.ctx.item_name_groups[game][item]:
if item_name_from_group in self.ctx.item_names_for_game(game): # ensure item has an ID
hints.extend(collect_hints(self.ctx, team, slot, item_name_from_group))
- else: # item name
- hints = collect_hints(self.ctx, team, slot, item_name)
+ else: # item name or id
+ hints = collect_hints(self.ctx, team, slot, item)
if hints:
notify_hints(self.ctx, team, hints)
@@ -1886,11 +1921,22 @@ class ServerCommandProcessor(CommonCommandProcessor):
seeked_player, usable, response = get_intended_text(player_name, self.ctx.player_names.values())
if usable:
team, slot = self.ctx.player_name_lookup[seeked_player]
- location_name = " ".join(location_name)
- location_name, usable, response = get_intended_text(location_name,
- self.ctx.location_names_for_game(self.ctx.games[slot]))
+ game = self.ctx.games[slot]
+ full_name = " ".join(location_name)
+
+ if full_name.isnumeric():
+ location, usable, response = int(full_name), True, None
+ elif self.ctx.location_names_for_game(game) is not None:
+ location, usable, response = get_intended_text(full_name, self.ctx.location_names_for_game(game))
+ else:
+ self.output("Can't look up location for unknown game. Hint for ID instead.")
+ return False
+
if usable:
- hints = collect_hint_location_name(self.ctx, team, slot, location_name)
+ if isinstance(location, int):
+ hints = collect_hint_location_id(self.ctx, team, slot, location)
+ else:
+ hints = collect_hint_location_name(self.ctx, team, slot, location)
if hints:
notify_hints(self.ctx, team, hints)
else:
@@ -2040,15 +2086,28 @@ async def main(args: argparse.Namespace):
args.auto_shutdown, args.compatibility, args.log_network)
data_filename = args.multidata
- try:
- if not data_filename:
+ if not data_filename:
+ try:
filetypes = (("Multiworld data", (".archipelago", ".zip")),)
data_filename = Utils.open_filename("Select multiworld data", filetypes)
+ except Exception as e:
+ if isinstance(e, ImportError) or (e.__class__.__name__ == "TclError" and "no display" in str(e)):
+ if not isinstance(e, ImportError):
+ logging.error(f"Failed to load tkinter ({e})")
+ logging.info("Pass a multidata filename on command line to run headless.")
+ exit(1)
+ raise
+
+ if not data_filename:
+ logging.info("No file selected. Exiting.")
+ exit(1)
+
+ try:
ctx.load(data_filename, args.use_embedded_options)
except Exception as e:
- logging.exception('Failed to read multiworld data (%s)' % e)
+ logging.exception(f"Failed to read multiworld data ({e})")
raise
ctx.init_save(not args.disable_save)
diff --git a/Options.py b/Options.py
index 7eb108c99d..49f044d8cd 100644
--- a/Options.py
+++ b/Options.py
@@ -26,15 +26,31 @@ class AssembleOptions(abc.ABCMeta):
attrs["name_lookup"].update({option_id: name for name, option_id in new_options.items()})
options.update(new_options)
-
# apply aliases, without name_lookup
aliases = {name[6:].lower(): option_id for name, option_id in attrs.items() if
name.startswith("alias_")}
assert "random" not in aliases, "Choice option 'random' cannot be manually assigned."
+ # auto-alias Off and On being parsed as True and False
+ if "off" in options:
+ options["false"] = options["off"]
+ if "on" in options:
+ options["true"] = options["on"]
+
options.update(aliases)
+ if "verify" not in attrs:
+ # not overridden by class -> look up bases
+ verifiers = [f for f in (getattr(base, "verify", None) for base in bases) if f]
+ if len(verifiers) > 1: # verify multiple bases/mixins
+ def verify(self, *args, **kwargs) -> None:
+ for f in verifiers:
+ f(self, *args, **kwargs)
+ attrs["verify"] = verify
+ else:
+ assert verifiers, "class Option is supposed to implement def verify"
+
# auto-validate schema on __init__
if "schema" in attrs.keys():
@@ -112,6 +128,41 @@ class Option(typing.Generic[T], metaclass=AssembleOptions):
def from_any(cls, data: typing.Any) -> Option[T]:
raise NotImplementedError
+ if typing.TYPE_CHECKING:
+ from Generate import PlandoSettings
+ from worlds.AutoWorld import World
+
+ def verify(self, world: World, player_name: str, plando_options: PlandoSettings) -> None:
+ pass
+ else:
+ def verify(self, *args, **kwargs) -> None:
+ pass
+
+
+class FreeText(Option):
+ """Text option that allows users to enter strings.
+ Needs to be validated by the world or option definition."""
+
+ def __init__(self, value: str):
+ assert isinstance(value, str), "value of FreeText must be a string"
+ self.value = value
+
+ @property
+ def current_key(self) -> str:
+ return self.value
+
+ @classmethod
+ def from_text(cls, text: str) -> FreeText:
+ return cls(text)
+
+ @classmethod
+ def from_any(cls, data: typing.Any) -> FreeText:
+ return cls.from_text(str(data))
+
+ @classmethod
+ def get_option_name(cls, value: T) -> str:
+ return value
+
class NumericOption(Option[int], numbers.Integral):
# note: some of the `typing.Any`` here is a result of unresolved issue in python standards
@@ -368,6 +419,53 @@ class Choice(NumericOption):
__hash__ = Option.__hash__ # see https://docs.python.org/3/reference/datamodel.html#object.__hash__
+class TextChoice(Choice):
+ """Allows custom string input and offers choices. Choices will resolve to int and text will resolve to string"""
+
+ def __init__(self, value: typing.Union[str, int]):
+ assert isinstance(value, str) or isinstance(value, int), \
+ f"{value} is not a valid option for {self.__class__.__name__}"
+ self.value = value
+ super(TextChoice, self).__init__()
+
+ @property
+ def current_key(self) -> str:
+ if isinstance(self.value, str):
+ return self.value
+ else:
+ return self.name_lookup[self.value]
+
+ @classmethod
+ def from_text(cls, text: str) -> TextChoice:
+ if text.lower() == "random": # chooses a random defined option but won't use any free text options
+ return cls(random.choice(list(cls.name_lookup)))
+ for option_name, value in cls.options.items():
+ if option_name.lower() == text.lower():
+ return cls(value)
+ return cls(text)
+
+ @classmethod
+ def get_option_name(cls, value: T) -> str:
+ if isinstance(value, str):
+ return value
+ return cls.name_lookup[value]
+
+ def __eq__(self, other: typing.Any):
+ if isinstance(other, self.__class__):
+ return other.value == self.value
+ elif isinstance(other, str):
+ if other in self.options:
+ return other == self.current_key
+ return other == self.value
+ elif isinstance(other, int):
+ assert other in self.name_lookup, f"compared against an int that could never be equal. {self} == {other}"
+ return other == self.value
+ elif isinstance(other, bool):
+ return other == bool(self.value)
+ else:
+ raise TypeError(f"Can't compare {self.__class__.__name__} with {other.__class__.__name__}")
+
+
class Range(NumericOption):
range_start = 0
range_end = 1
@@ -385,7 +483,7 @@ class Range(NumericOption):
if text.startswith("random"):
return cls.weighted_range(text)
elif text == "default" and hasattr(cls, "default"):
- return cls(cls.default)
+ return cls.from_any(cls.default)
elif text == "high":
return cls(cls.range_end)
elif text == "low":
@@ -396,7 +494,7 @@ class Range(NumericOption):
and text in ("true", "false"):
# these are the conditions where "true" and "false" make sense
if text == "true":
- return cls(cls.default)
+ return cls.from_any(cls.default)
else: # "false"
return cls(0)
return cls(int(text))
@@ -507,7 +605,7 @@ class VerifyKeys:
raise Exception(f"Found unexpected key {', '.join(extra)} in {cls}. "
f"Allowed keys: {cls.valid_keys}.")
- def verify(self, world):
+ def verify(self, world, player_name: str, plando_options) -> None:
if self.convert_name_groups and self.verify_item_name:
new_value = type(self.value)() # empty container of whatever value is
for item_name in self.value:
@@ -600,10 +698,7 @@ class OptionSet(Option[typing.Set[str]], VerifyKeys):
@classmethod
def from_any(cls, data: typing.Any):
- if type(data) == list:
- cls.verify_keys(data)
- return cls(data)
- elif type(data) == set:
+ if isinstance(data, (list, set, frozenset)):
cls.verify_keys(data)
return cls(data)
return cls.from_text(str(data))
@@ -732,8 +827,8 @@ class ItemLinks(OptionList):
pool |= {item_name}
return pool
- def verify(self, world):
- super(ItemLinks, self).verify(world)
+ def verify(self, world, player_name: str, plando_options) -> None:
+ super(ItemLinks, self).verify(world, player_name, plando_options)
existing_links = set()
for link in self.value:
if link["name"] in existing_links:
diff --git a/Patch.py b/Patch.py
index f90e376656..aaa4fc2404 100644
--- a/Patch.py
+++ b/Patch.py
@@ -17,7 +17,7 @@ ModuleUpdate.update()
import Utils
-current_patch_version = 4
+current_patch_version = 5
class AutoPatchRegister(type):
@@ -128,6 +128,7 @@ class APDeltaPatch(APContainer, metaclass=AutoPatchRegister):
manifest = super(APDeltaPatch, self).get_manifest()
manifest["base_checksum"] = self.hash
manifest["result_file_ending"] = self.result_file_ending
+ manifest["patch_file_ending"] = self.patch_file_ending
return manifest
@classmethod
diff --git a/SNIClient.py b/SNIClient.py
index 3d90fafc17..477cde86a2 100644
--- a/SNIClient.py
+++ b/SNIClient.py
@@ -15,9 +15,6 @@ import typing
from json import loads, dumps
-import ModuleUpdate
-ModuleUpdate.update()
-
from Utils import init_logging, messagebox
if __name__ == "__main__":
@@ -1271,7 +1268,8 @@ async def game_watcher(ctx: Context):
snes_buffered_write(ctx, SMZ3_RECV_PROGRESS_ADDR + 0x680, bytes([recv_index & 0xFF, (recv_index >> 8) & 0xFF]))
from worlds.smz3.TotalSMZ3.Location import locations_start_id
- location_id = locations_start_id + itemIndex
+ from worlds.smz3 import convertLocSMZ3IDToAPID
+ location_id = locations_start_id + convertLocSMZ3IDToAPID(itemIndex)
ctx.locations_checked.add(location_id)
location = ctx.location_names[location_id]
diff --git a/Starcraft2Client.py b/Starcraft2Client.py
index b8f6086914..d91adffb08 100644
--- a/Starcraft2Client.py
+++ b/Starcraft2Client.py
@@ -19,10 +19,11 @@ from sc2.data import Race
from sc2.main import run_game
from sc2.player import Bot
+import NetUtils
from MultiServer import mark_raw
from Utils import init_logging, is_windows
from worlds.sc2wol import SC2WoLWorld
-from worlds.sc2wol.Items import lookup_id_to_name, item_table
+from worlds.sc2wol.Items import lookup_id_to_name, item_table, ItemData, type_flaggroups
from worlds.sc2wol.Locations import SC2WOL_LOC_ID_OFFSET
from worlds.sc2wol.MissionTables import lookup_id_to_mission
from worlds.sc2wol.Regions import MissionInfo
@@ -135,7 +136,7 @@ class SC2Context(CommonContext):
last_loc_list = None
difficulty_override = -1
mission_id_to_location_ids: typing.Dict[int, typing.List[int]] = {}
- raw_text_parser: RawJSONtoTextParser
+ last_bot: typing.Optional[ArchipelagoBot] = None
def __init__(self, *args, **kwargs):
super(SC2Context, self).__init__(*args, **kwargs)
@@ -164,10 +165,13 @@ class SC2Context(CommonContext):
check_mod_install()
def on_print_json(self, args: dict):
+ # goes to this world
if "receiving" in args and self.slot_concerns_self(args["receiving"]):
relevant = True
+ # found in this world
elif "item" in args and self.slot_concerns_self(args["item"].player):
relevant = True
+ # not related
else:
relevant = False
@@ -291,34 +295,37 @@ class SC2Context(CommonContext):
category_panel.add_widget(
Label(text=category, size_hint_y=None, height=50, outline_width=1))
- # Map is completed
for mission in categories[category]:
- text = mission
- tooltip = ""
+ text: str = mission
+ tooltip: str = ""
# Map has uncollected locations
if mission in unfinished_missions:
text = f"[color=6495ED]{text}[/color]"
- tooltip = f"Uncollected locations:\n"
- tooltip += "\n".join([self.ctx.location_names[loc] for loc in
- self.ctx.locations_for_mission(mission)
- if loc in self.ctx.missing_locations])
elif mission in available_missions:
text = f"[color=FFFFFF]{text}[/color]"
# Map requirements not met
else:
text = f"[color=a9a9a9]{text}[/color]"
tooltip = f"Requires: "
- if len(self.ctx.mission_req_table[mission].required_world) > 0:
+ if self.ctx.mission_req_table[mission].required_world:
tooltip += ", ".join(list(self.ctx.mission_req_table)[req_mission - 1] for
req_mission in
self.ctx.mission_req_table[mission].required_world)
- if self.ctx.mission_req_table[mission].number > 0:
+ if self.ctx.mission_req_table[mission].number:
tooltip += " and "
- if self.ctx.mission_req_table[mission].number > 0:
+ if self.ctx.mission_req_table[mission].number:
tooltip += f"{self.ctx.mission_req_table[mission].number} missions completed"
+ remaining_location_names: typing.List[str] = [
+ self.ctx.location_names[loc] for loc in self.ctx.locations_for_mission(mission)
+ if loc in self.ctx.missing_locations]
+ if remaining_location_names:
+ if tooltip:
+ tooltip += "\n"
+ tooltip += f"Uncollected locations:\n"
+ tooltip += "\n".join(remaining_location_names)
mission_button = MissionButton(text=text, size_hint_y=None, height=50)
mission_button.tooltip_text = tooltip
@@ -340,9 +347,8 @@ class SC2Context(CommonContext):
def mission_callback(self, button):
if not self.launching:
- mission_id: int = list(self.mission_id_to_button.values()).index(button)
- self.ctx.play_mission(list(self.mission_id_to_button)
- [mission_id])
+ mission_id: int = next(k for k, v in self.mission_id_to_button.items() if v == button)
+ self.ctx.play_mission(mission_id)
self.launching = mission_id
Clock.schedule_once(self.finish_launching, 10)
@@ -356,10 +362,12 @@ class SC2Context(CommonContext):
async def shutdown(self):
await super(SC2Context, self).shutdown()
+ if self.last_bot:
+ self.last_bot.want_close = True
if self.sc2_run_task:
self.sc2_run_task.cancel()
- def play_mission(self, mission_id):
+ def play_mission(self, mission_id: int):
if self.missions_unlocked or \
is_mission_available(self, mission_id):
if self.sc2_run_task:
@@ -432,47 +440,27 @@ wol_default_categories = [
]
-def calculate_items(items):
- unit_unlocks = 0
- armory1_unlocks = 0
- armory2_unlocks = 0
- upgrade_unlocks = 0
- building_unlocks = 0
- merc_unlocks = 0
- lab_unlocks = 0
- protoss_unlock = 0
- minerals = 0
- vespene = 0
- supply = 0
+def calculate_items(items: typing.List[NetUtils.NetworkItem]) -> typing.List[int]:
+ network_item: NetUtils.NetworkItem
+ accumulators: typing.List[int] = [0 for _ in type_flaggroups]
- for item in items:
- data = lookup_id_to_name[item.item]
+ for network_item in items:
+ name: str = lookup_id_to_name[network_item.item]
+ item_data: ItemData = item_table[name]
- if item_table[data].type == "Unit":
- unit_unlocks += (1 << item_table[data].number)
- elif item_table[data].type == "Upgrade":
- upgrade_unlocks += (1 << item_table[data].number)
- elif item_table[data].type == "Armory 1":
- armory1_unlocks += (1 << item_table[data].number)
- elif item_table[data].type == "Armory 2":
- armory2_unlocks += (1 << item_table[data].number)
- elif item_table[data].type == "Building":
- building_unlocks += (1 << item_table[data].number)
- elif item_table[data].type == "Mercenary":
- merc_unlocks += (1 << item_table[data].number)
- elif item_table[data].type == "Laboratory":
- lab_unlocks += (1 << item_table[data].number)
- elif item_table[data].type == "Protoss":
- protoss_unlock += (1 << item_table[data].number)
- elif item_table[data].type == "Minerals":
- minerals += item_table[data].number
- elif item_table[data].type == "Vespene":
- vespene += item_table[data].number
- elif item_table[data].type == "Supply":
- supply += item_table[data].number
+ # exists exactly once
+ if item_data.quantity == 1:
+ accumulators[type_flaggroups[item_data.type]] |= 1 << item_data.number
- return [unit_unlocks, upgrade_unlocks, armory1_unlocks, armory2_unlocks, building_unlocks, merc_unlocks,
- lab_unlocks, protoss_unlock, minerals, vespene, supply]
+ # exists multiple times
+ elif item_data.type == "Upgrade":
+ accumulators[type_flaggroups[item_data.type]] += 1 << item_data.number
+
+ # sum
+ else:
+ accumulators[type_flaggroups[item_data.type]] += item_data.number
+
+ return accumulators
def calc_difficulty(difficulty):
@@ -503,7 +491,7 @@ class ArchipelagoBot(sc2.bot_ai.BotAI):
setup_done: bool
ctx: SC2Context
mission_id: int
-
+ want_close: bool = False
can_read_game = False
last_received_update: int = 0
@@ -511,12 +499,17 @@ class ArchipelagoBot(sc2.bot_ai.BotAI):
def __init__(self, ctx: SC2Context, mission_id):
self.setup_done = False
self.ctx = ctx
+ self.ctx.last_bot = self
self.mission_id = mission_id
self.boni = [False for _ in range(max_bonus)]
super(ArchipelagoBot, self).__init__()
async def on_step(self, iteration: int):
+ if self.want_close:
+ self.want_close = False
+ await self._client.leave()
+ return
game_state = 0
if not self.setup_done:
self.setup_done = True
@@ -800,7 +793,12 @@ def check_game_install_path() -> bool:
with open(einfo) as f:
content = f.read()
if content:
- base = re.search(r" = (.*)Versions", content).group(1)
+ try:
+ base = re.search(r" = (.*)Versions", content).group(1)
+ except AttributeError:
+ sc2_logger.warning(f"Found {einfo}, but it was empty. Run SC2 through the Blizzard launcher, then "
+ f"try again.")
+ return False
if os.path.exists(base):
executable = sc2.paths.latest_executeble(Path(base).expanduser() / "Versions")
@@ -817,7 +815,8 @@ def check_game_install_path() -> bool:
else:
sc2_logger.warning(f"{einfo} pointed to {base}, but we could not find an SC2 install there.")
else:
- sc2_logger.warning(f"Couldn't find {einfo}. Please run /set_path with your SC2 install directory.")
+ sc2_logger.warning(f"Couldn't find {einfo}. Run SC2 through the Blizzard launcher, then try again. "
+ f"If that fails, please run /set_path with your SC2 install directory.")
return False
diff --git a/WebHostLib/customserver.py b/WebHostLib/customserver.py
index da7b54ba6d..6272633f4e 100644
--- a/WebHostLib/customserver.py
+++ b/WebHostLib/customserver.py
@@ -1,15 +1,16 @@
from __future__ import annotations
-import functools
-import websockets
import asyncio
+import collections
+import datetime
+import functools
+import logging
+import pickle
+import random
import socket
import threading
import time
-import random
-import pickle
-import logging
-import datetime
+import websockets
import Utils
from .models import db_session, Room, select, commit, Command, db
@@ -49,6 +50,8 @@ class DBCommandProcessor(ServerCommandProcessor):
class WebHostContext(Context):
+ room_id: int
+
def __init__(self, static_server_data: dict):
# static server data is used during _load_game_data to load required data,
# without needing to import worlds system, which takes quite a bit of memory
@@ -62,6 +65,8 @@ class WebHostContext(Context):
def _load_game_data(self):
for key, value in self.static_server_data.items():
setattr(self, key, value)
+ self.forced_auto_forfeits = collections.defaultdict(lambda: False, self.forced_auto_forfeits)
+ self.non_hintable_names = collections.defaultdict(frozenset, self.non_hintable_names)
def listen_to_db_commands(self):
cmdprocessor = DBCommandProcessor(self)
diff --git a/WebHostLib/downloads.py b/WebHostLib/downloads.py
index 528cbe5ec0..c3a373c2e9 100644
--- a/WebHostLib/downloads.py
+++ b/WebHostLib/downloads.py
@@ -32,9 +32,12 @@ def download_patch(room_id, patch_id):
new_zip.writestr("archipelago.json", json.dumps(manifest))
else:
new_zip.writestr(file.filename, zf.read(file), file.compress_type, 9)
-
+ if "patch_file_ending" in manifest:
+ patch_file_ending = manifest["patch_file_ending"]
+ else:
+ patch_file_ending = AutoPatchRegister.patch_types[patch.game].patch_file_ending
fname = f"P{patch.player_id}_{patch.player_name}_{app.jinja_env.filters['suuid'](room_id)}" \
- f"{AutoPatchRegister.patch_types[patch.game].patch_file_ending}"
+ f"{patch_file_ending}"
new_file.seek(0)
return send_file(new_file, as_attachment=True, download_name=fname)
else:
diff --git a/WebHostLib/requirements.txt b/WebHostLib/requirements.txt
index 52d0316b2a..a4dd710e83 100644
--- a/WebHostLib/requirements.txt
+++ b/WebHostLib/requirements.txt
@@ -1,7 +1,7 @@
-flask>=2.1.3
+flask>=2.2.2
pony>=0.7.16
-waitress>=2.1.1
+waitress>=2.1.2
Flask-Caching>=2.0.1
Flask-Compress>=1.12
-Flask-Limiter>=2.5.0
+Flask-Limiter>=2.6.2
bokeh>=2.4.3
diff --git a/data/lua/FF1/ff1_connector.lua b/data/lua/FF1/ff1_connector.lua
index ed3ee1ca60..6b2eec269a 100644
--- a/data/lua/FF1/ff1_connector.lua
+++ b/data/lua/FF1/ff1_connector.lua
@@ -97,6 +97,11 @@ local extensionConsumableLookup = {
[443] = 0x3F
}
+local noOverworldItemsLookup = {
+ [499] = 0x2B,
+ [500] = 0x12,
+}
+
local itemMessages = {}
local consumableStacks = nil
local prevstate = ""
@@ -341,7 +346,7 @@ function processBlock(block)
-- This is a key item
memoryLocation = memoryLocation - 0x0E0
wU8(memoryLocation, 0x01)
- elseif v >= 0x1E0 then
+ elseif v >= 0x1E0 and v <= 0x1F2 then
-- This is a movement item
-- Minus Offset (0x100) - movement offset (0xE0)
memoryLocation = memoryLocation - 0x1E0
@@ -351,7 +356,10 @@ function processBlock(block)
else
wU8(memoryLocation, 0x01)
end
-
+ elseif v >= 0x1F3 and v <= 0x1F4 then
+ -- NoOverworld special items
+ memoryLocation = noOverworldItemsLookup[v]
+ wU8(memoryLocation, 0x01)
elseif v >= 0x16C and v <= 0x1AF then
-- This is a gold item
amountToAdd = goldLookup[v]
diff --git a/docs/apworld specification.md b/docs/apworld specification.md
index 2dcc3f0bef..9b37fd831f 100644
--- a/docs/apworld specification.md
+++ b/docs/apworld specification.md
@@ -23,3 +23,10 @@ No metadata is specified yet.
## Extra Data
The zip can contain arbitrary files in addition what was specified above.
+
+
+## Caveats
+
+Imports from other files inside the apworld have to use relative imports.
+
+Imports from AP base have to use absolute imports, e.g. Options.py and worlds/AutoWorld.py.
diff --git a/docs/world api.md b/docs/world api.md
index ffc0749e8c..cf26cfd967 100644
--- a/docs/world api.md
+++ b/docs/world api.md
@@ -103,8 +103,9 @@ or boss drops for RPG-like games but could also be progress in a research tree.
Each location has a `name` and an `id` (a.k.a. "code" or "address"), is placed
in a Region and has access rules.
-The name needs to be unique in each game, the ID needs to be unique across all
-games and is best in the same range as the item IDs.
+The name needs to be unique in each game and must not be numeric (has to
+contain least 1 letter or symbol). The ID needs to be unique across all games
+and is best in the same range as the item IDs.
World-specific IDs are 1 to 253-1, IDs ≤ 0 are global and reserved.
Special locations with ID `None` can hold events.
@@ -121,6 +122,9 @@ their world. Progression items will be assigned to locations with higher
priority and moved around to meet defined rules and accomplish progression
balancing.
+The name needs to be unique in each game, meaning a duplicate item has the
+same ID. Name must not be numeric (has to contain at least 1 letter or symbol).
+
Special items with ID `None` can mark events (read below).
Other classifications include
@@ -188,15 +192,17 @@ the `/worlds` directory. The starting point for the package is `__init.py__`.
Conventionally, your world class is placed in that file.
World classes must inherit from the `World` class in `/worlds/AutoWorld.py`,
-which can be imported as `..AutoWorld.World` from your package.
+which can be imported as `worlds.AutoWorld.World` from your package.
AP will pick up your world automatically due to the `AutoWorld` implementation.
### Requirements
If your world needs specific python packages, they can be listed in
-`world/[world_name]/requirements.txt`.
-See [pip documentation](https://pip.pypa.io/en/stable/cli/pip_install/#requirements-file-format)
+`world/[world_name]/requirements.txt`. ModuleUpdate.py will automatically
+pick up and install them.
+
+See [pip documentation](https://pip.pypa.io/en/stable/cli/pip_install/#requirements-file-format).
### Relative Imports
@@ -209,6 +215,10 @@ e.g. `from .Options import mygame_options` from your `__init__.py` will load
When imported names pile up it may be easier to use `from . import Options`
and access the variable as `Options.mygame_options`.
+Imports from directories outside your world should use absolute imports.
+Correct use of relative / absolute imports is required for zipped worlds to
+function, see [apworld specification.md](apworld%20specification.md).
+
### Your Item Type
Each world uses its own subclass of `BaseClasses.Item`. The constuctor can be
@@ -274,14 +284,12 @@ Define a property `option_ = ` per selectable value and
`default = ` to set the default selection. Aliases can be set by
defining a property `alias_ = `.
-One special case where aliases are required is when option name is `yes`, `no`,
-`on` or `off` because they parse to `True` or `False`:
```python
option_off = 0
option_on = 1
option_some = 2
-alias_false = 0
-alias_true = 1
+alias_disabled = 0
+alias_enabled = 1
default = 0
```
@@ -323,7 +331,7 @@ mygame_options: typing.Dict[str, type(Option)] = {
```python
# __init__.py
-from ..AutoWorld import World
+from worlds.AutoWorld import World
from .Options import mygame_options # import the options dict
class MyGameWorld(World):
@@ -352,7 +360,7 @@ more natural. These games typically have been edited to 'bake in' the items.
from .Options import mygame_options # the options we defined earlier
from .Items import mygame_items # data used below to add items to the World
from .Locations import mygame_locations # same as above
-from ..AutoWorld import World
+from worlds.AutoWorld import World
from BaseClasses import Region, Location, Entrance, Item, RegionType, ItemClassification
from Utils import get_options, output_path
@@ -553,7 +561,7 @@ def generate_basic(self) -> None:
### Setting Rules
```python
-from ..generic.Rules import add_rule, set_rule, forbid_item
+from worlds.generic.Rules import add_rule, set_rule, forbid_item
from Items import get_item_type
def set_rules(self) -> None:
@@ -603,14 +611,16 @@ implement more complex logic in logic mixins, even if there is no need to add
properties to the `BaseClasses.CollectionState` state object.
When importing a file that defines a class that inherits from
-`..AutoWorld.LogicMixin` the state object's class is automatically extended by
+`worlds.AutoWorld.LogicMixin` the state object's class is automatically extended by
the mixin's members. These members should be prefixed with underscore following
the name of the implementing world. This is due to sharing a namespace with all
other logic mixins.
Typical uses are defining methods that are used instead of `state.has`
-in lambdas, e.g.`state._mygame_has(custom, world, player)` or recurring checks
-like `state._mygame_can_do_something(world, player)` to simplify lambdas.
+in lambdas, e.g.`state.mygame_has(custom, player)` or recurring checks
+like `state.mygame_can_do_something(player)` to simplify lambdas.
+Private members, only accessible from mixins, should start with `_mygame_`,
+public members with `mygame_`.
More advanced uses could be to add additional variables to the state object,
override `World.collect(self, state, item)` and `remove(self, state, item)`
@@ -622,25 +632,26 @@ Please do this with caution and only when neccessary.
```python
# Logic.py
-from ..AutoWorld import LogicMixin
+from worlds.AutoWorld import LogicMixin
class MyGameLogic(LogicMixin):
- def _mygame_has_key(self, world: MultiWorld, player: int):
+ def mygame_has_key(self, player: int):
# Arguments above are free to choose
- # it may make sense to use World as argument instead of MultiWorld
+ # MultiWorld can be accessed through self.world, explicitly passing in
+ # MyGameWorld instance for easy options access is also a valid approach
return self.has("key", player) # or whatever
```
```python
# __init__.py
-from ..generic.Rules import set_rule
+from worlds.generic.Rules import set_rule
import .Logic # apply the mixin by importing its file
class MyGameWorld(World):
# ...
def set_rules(self):
set_rule(self.world.get_location("A Door", self.player),
- lamda state: state._mygame_has_key(self.world, self.player))
+ lamda state: state.mygame_has_key(self.player))
```
### Generate Output
diff --git a/inno_setup.iss b/inno_setup.iss
index ff2da1211a..cfdfec7ba8 100644
--- a/inno_setup.iss
+++ b/inno_setup.iss
@@ -196,7 +196,7 @@ begin
begin
// Is the installed version at least the packaged one ?
Log('VC Redist x64 Version : found ' + strVersion);
- Result := (CompareStr(strVersion, 'v14.29.30037') < 0);
+ Result := (CompareStr(strVersion, 'v14.32.31332') < 0);
end
else
begin
diff --git a/requirements.txt b/requirements.txt
index 661209e072..6c9e3b9d2d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,6 +3,6 @@ websockets>=10.3
PyYAML>=6.0
jellyfish>=0.9.0
jinja2>=3.1.2
-schema>=0.7.4
+schema>=0.7.5
kivy>=2.1.0
bsdiff4>=1.2.2
\ No newline at end of file
diff --git a/test/general/TestFill.py b/test/general/TestFill.py
index 189aafafb2..8ce5b3b281 100644
--- a/test/general/TestFill.py
+++ b/test/general/TestFill.py
@@ -371,13 +371,13 @@ class TestDistributeItemsRestrictive(unittest.TestCase):
distribute_items_restrictive(multi_world)
- self.assertEqual(locations[0].item, basic_items[0])
+ self.assertEqual(locations[0].item, basic_items[1])
self.assertFalse(locations[0].event)
self.assertEqual(locations[1].item, prog_items[0])
self.assertTrue(locations[1].event)
self.assertEqual(locations[2].item, prog_items[1])
self.assertTrue(locations[2].event)
- self.assertEqual(locations[3].item, basic_items[1])
+ self.assertEqual(locations[3].item, basic_items[0])
self.assertFalse(locations[3].event)
def test_excluded_distribute(self):
@@ -500,8 +500,8 @@ class TestDistributeItemsRestrictive(unittest.TestCase):
removed_item: list[Item] = []
removed_location: list[Location] = []
- def fill_hook(progitempool, nonexcludeditempool, localrestitempool, nonlocalrestitempool, restitempool, fill_locations):
- removed_item.append(restitempool.pop(0))
+ def fill_hook(progitempool, usefulitempool, filleritempool, fill_locations):
+ removed_item.append(filleritempool.pop(0))
removed_location.append(fill_locations.pop(0))
multi_world.worlds[player1.id].fill_hook = fill_hook
diff --git a/test/general/TestItems.py b/test/general/TestItems.py
index bd1bd50665..3dd589995e 100644
--- a/test/general/TestItems.py
+++ b/test/general/TestItems.py
@@ -1,5 +1,6 @@
import unittest
from worlds.AutoWorld import AutoWorldRegister
+from . import setup_default_world
class TestBase(unittest.TestCase):
@@ -29,3 +30,17 @@ class TestBase(unittest.TestCase):
with self.subTest(group_name, group_name=group_name):
for item in items:
self.assertIn(item, world_type.item_name_to_id)
+
+ def testItemCountGreaterEqualLocations(self):
+ for game_name, world_type in AutoWorldRegister.world_types.items():
+
+ if game_name in {"Final Fantasy"}:
+ continue
+ with self.subTest("Game", game=game_name):
+ world = setup_default_world(world_type)
+ location_count = sum(0 if location.event or location.item else 1 for location in world.get_locations())
+ self.assertGreaterEqual(
+ len(world.itempool),
+ location_count,
+ f"{game_name} Item count MUST meet or exceede the number of locations",
+ )
diff --git a/test/general/TestNames.py b/test/general/TestNames.py
new file mode 100644
index 0000000000..6dae53240d
--- /dev/null
+++ b/test/general/TestNames.py
@@ -0,0 +1,20 @@
+import unittest
+from worlds.AutoWorld import AutoWorldRegister
+
+
+class TestNames(unittest.TestCase):
+ def testItemNamesFormat(self):
+ """Item names must not be all numeric in order to differentiate between ID and name in !hint"""
+ for gamename, world_type in AutoWorldRegister.world_types.items():
+ with self.subTest(game=gamename):
+ for item_name in world_type.item_name_to_id:
+ self.assertFalse(item_name.isnumeric(),
+ f"Item name \"{item_name}\" is invalid. It must not be numeric.")
+
+ def testLocationNameFormat(self):
+ """Location names must not be all numeric in order to differentiate between ID and name in !hint_location"""
+ for gamename, world_type in AutoWorldRegister.world_types.items():
+ with self.subTest(game=gamename):
+ for location_name in world_type.location_name_to_id:
+ self.assertFalse(location_name.isnumeric(),
+ f"Location name \"{location_name}\" is invalid. It must not be numeric.")
diff --git a/test/webhost/TestFileGeneration.py b/test/webhost/TestFileGeneration.py
index 7f56864ea3..656206cdec 100644
--- a/test/webhost/TestFileGeneration.py
+++ b/test/webhost/TestFileGeneration.py
@@ -14,9 +14,20 @@ class TestFileGeneration(unittest.TestCase):
def testOptions(self):
WebHost.create_options_files()
- self.assertTrue(os.path.exists(os.path.join(self.correct_path, "static", "generated", "configs")))
+ target = os.path.join(self.correct_path, "static", "generated", "configs")
+ self.assertTrue(os.path.exists(target))
self.assertFalse(os.path.exists(os.path.join(self.incorrect_path, "static", "generated", "configs")))
+ # folder seems fine, so now we try to generate Options based on the default file
+ from WebHostLib.check import roll_options
+ file: os.DirEntry
+ for file in os.scandir(target):
+ if file.is_file() and file.name.endswith(".yaml"):
+ with self.subTest(file=file.name):
+ with open(file) as f:
+ for value in roll_options({file.name: f.read()})[0].values():
+ self.assertTrue(value is True, f"Default Options for template {file.name} cannot be run.")
+
def testTutorial(self):
WebHost.create_ordered_tutorials_file()
self.assertTrue(os.path.exists(os.path.join(self.correct_path, "static", "generated", "tutorials.json")))
diff --git a/worlds/AutoWorld.py b/worlds/AutoWorld.py
index 8d9a1b0829..db72ca6a95 100644
--- a/worlds/AutoWorld.py
+++ b/worlds/AutoWorld.py
@@ -221,10 +221,8 @@ class World(metaclass=AutoWorldRegister):
@classmethod
def fill_hook(cls,
progitempool: List["Item"],
- nonexcludeditempool: List["Item"],
- localrestitempool: Dict[int, List["Item"]],
- nonlocalrestitempool: Dict[int, List["Item"]],
- restitempool: List["Item"],
+ usefulitempool: List["Item"],
+ filleritempool: List["Item"],
fill_locations: List["Location"]) -> None:
"""Special method that gets called as part of distribute_items_restrictive (main fill).
This gets called once per present world type."""
@@ -242,6 +240,11 @@ class World(metaclass=AutoWorldRegister):
"""Fill in the slot_data field in the Connected network package."""
return {}
+ def extend_hint_information(self, hint_data: Dict[int, Dict[int, str]]):
+ """Fill in additional entrance information text into locations, which is displayed when hinted.
+ structure is {player_id: {location_id: text}} You will need to insert your own player_id."""
+ pass
+
def modify_multidata(self, multidata: Dict[str, Any]) -> None: # TODO: TypedDict for multidata?
"""For deeper modification of server multidata."""
pass
diff --git a/worlds/__init__.py b/worlds/__init__.py
index 46b383b303..e36eb275a3 100644
--- a/worlds/__init__.py
+++ b/worlds/__init__.py
@@ -27,7 +27,8 @@ class WorldSource(typing.NamedTuple):
world_sources: typing.List[WorldSource] = []
file: os.DirEntry # for me (Berserker) at least, PyCharm doesn't seem to infer the type correctly
for file in os.scandir(folder):
- if not file.name.startswith("_"): # prevent explicitly loading __pycache__ and allow _* names for non-world folders
+ # prevent loading of __pycache__ and allow _* for non-world folders, disable files/folders starting with "."
+ if not file.name.startswith(("_", ".")):
if file.is_dir():
world_sources.append(WorldSource(file.name))
elif file.is_file() and file.name.endswith(".apworld"):
diff --git a/worlds/alttp/Bosses.py b/worlds/alttp/Bosses.py
index 5ea7aba5fc..1c381b9a1c 100644
--- a/worlds/alttp/Bosses.py
+++ b/worlds/alttp/Bosses.py
@@ -1,8 +1,9 @@
import logging
-from typing import Optional
+from typing import Optional, Union, List, Tuple, Callable, Dict
from BaseClasses import Boss
from Fill import FillError
+from .Options import Bosses
def BossFactory(boss: str, player: int) -> Optional[Boss]:
@@ -12,7 +13,7 @@ def BossFactory(boss: str, player: int) -> Optional[Boss]:
raise Exception('Unknown Boss: %s', boss)
-def ArmosKnightsDefeatRule(state, player: int):
+def ArmosKnightsDefeatRule(state, player: int) -> bool:
# Magic amounts are probably a bit overkill
return (
state.has_melee_weapon(player) or
@@ -25,7 +26,7 @@ def ArmosKnightsDefeatRule(state, player: int):
state.has('Red Boomerang', player))
-def LanmolasDefeatRule(state, player: int):
+def LanmolasDefeatRule(state, player: int) -> bool:
return (
state.has_melee_weapon(player) or
state.has('Fire Rod', player) or
@@ -35,16 +36,16 @@ def LanmolasDefeatRule(state, player: int):
state.can_shoot_arrows(player))
-def MoldormDefeatRule(state, player: int):
+def MoldormDefeatRule(state, player: int) -> bool:
return state.has_melee_weapon(player)
-def HelmasaurKingDefeatRule(state, player: int):
+def HelmasaurKingDefeatRule(state, player: int) -> bool:
# TODO: technically possible with the hammer
return state.has_sword(player) or state.can_shoot_arrows(player)
-def ArrghusDefeatRule(state, player: int):
+def ArrghusDefeatRule(state, player: int) -> bool:
if not state.has('Hookshot', player):
return False
# TODO: ideally we would have a check for bow and silvers, which combined with the
@@ -58,7 +59,7 @@ def ArrghusDefeatRule(state, player: int):
(state.has('Ice Rod', player) and (state.can_shoot_arrows(player) or state.can_extend_magic(player, 16))))
-def MothulaDefeatRule(state, player: int):
+def MothulaDefeatRule(state, player: int) -> bool:
return (
state.has_melee_weapon(player) or
(state.has('Fire Rod', player) and state.can_extend_magic(player, 10)) or
@@ -70,11 +71,11 @@ def MothulaDefeatRule(state, player: int):
)
-def BlindDefeatRule(state, player: int):
+def BlindDefeatRule(state, player: int) -> bool:
return state.has_melee_weapon(player) or state.has('Cane of Somaria', player) or state.has('Cane of Byrna', player)
-def KholdstareDefeatRule(state, player: int):
+def KholdstareDefeatRule(state, player: int) -> bool:
return (
(
state.has('Fire Rod', player) or
@@ -96,11 +97,11 @@ def KholdstareDefeatRule(state, player: int):
)
-def VitreousDefeatRule(state, player: int):
+def VitreousDefeatRule(state, player: int) -> bool:
return state.can_shoot_arrows(player) or state.has_melee_weapon(player)
-def TrinexxDefeatRule(state, player: int):
+def TrinexxDefeatRule(state, player: int) -> bool:
if not (state.has('Fire Rod', player) and state.has('Ice Rod', player)):
return False
return state.has('Hammer', player) or state.has('Tempered Sword', player) or state.has('Golden Sword', player) or \
@@ -108,11 +109,11 @@ def TrinexxDefeatRule(state, player: int):
(state.has_sword(player) and state.can_extend_magic(player, 32))
-def AgahnimDefeatRule(state, player: int):
+def AgahnimDefeatRule(state, player: int) -> bool:
return state.has_sword(player) or state.has('Hammer', player) or state.has('Bug Catching Net', player)
-def GanonDefeatRule(state, player: int):
+def GanonDefeatRule(state, player: int) -> bool:
if state.world.swordless[player]:
return state.has('Hammer', player) and \
state.has_fire_source(player) and \
@@ -132,7 +133,7 @@ def GanonDefeatRule(state, player: int):
return common and state.has('Silver Bow', player) and state.can_shoot_arrows(player)
-boss_table = {
+boss_table: Dict[str, Tuple[str, Optional[Callable]]] = {
'Armos Knights': ('Armos', ArmosKnightsDefeatRule),
'Lanmolas': ('Lanmola', LanmolasDefeatRule),
'Moldorm': ('Moldorm', MoldormDefeatRule),
@@ -147,7 +148,7 @@ boss_table = {
'Agahnim2': ('Agahnim2', AgahnimDefeatRule)
}
-boss_location_table = [
+boss_location_table: List[Tuple[str, str]] = [
('Ganons Tower', 'top'),
('Tower of Hera', None),
('Skull Woods', None),
@@ -164,6 +165,34 @@ boss_location_table = [
]
+def place_plando_bosses(bosses: List[str], world, player: int) -> Tuple[List[str], List[Tuple[str, str]]]:
+ # Most to least restrictive order
+ boss_locations = boss_location_table.copy()
+ world.random.shuffle(boss_locations)
+ boss_locations.sort(key=lambda location: -int(restrictive_boss_locations[location]))
+ already_placed_bosses: List[str] = []
+
+ for boss in bosses:
+ if "-" in boss: # handle plando locations
+ loc, boss = boss.split("-")
+ boss = boss.title()
+ level: str = None
+ if loc.split(" ")[-1] in {"top", "middle", "bottom"}:
+ # split off level
+ loc = loc.split(" ")
+ level = loc[-1]
+ loc = " ".join(loc[:-1])
+ loc = loc.title().replace("Of", "of")
+ place_boss(world, player, boss, loc, level)
+ already_placed_bosses.append(boss)
+ boss_locations.remove((loc, level))
+ else: # boss chosen with no specified locations
+ boss = boss.title()
+ boss_locations, already_placed_bosses = place_where_possible(world, player, boss, boss_locations)
+
+ return already_placed_bosses, boss_locations
+
+
def can_place_boss(boss: str, dungeon_name: str, level: Optional[str] = None) -> bool:
# blacklist approach
if boss in {"Agahnim", "Agahnim2", "Ganon"}:
@@ -187,62 +216,50 @@ def can_place_boss(boss: str, dungeon_name: str, level: Optional[str] = None) ->
return True
-restrictive_boss_locations = {}
+
+restrictive_boss_locations: Dict[Tuple[str, str], bool] = {}
for location in boss_location_table:
restrictive_boss_locations[location] = not all(can_place_boss(boss, *location)
for boss in boss_table if not boss.startswith("Agahnim"))
-def place_boss(world, player: int, boss: str, location: str, level: Optional[str]):
+
+def place_boss(world, player: int, boss: str, location: str, level: Optional[str]) -> None:
if location == 'Ganons Tower' and world.mode[player] == 'inverted':
location = 'Inverted Ganons Tower'
logging.debug('Placing boss %s at %s', boss, location + (' (' + level + ')' if level else ''))
world.get_dungeon(location, player).bosses[level] = BossFactory(boss, player)
-def format_boss_location(location, level):
+
+def format_boss_location(location: str, level: str) -> str:
return location + (' (' + level + ')' if level else '')
-def place_bosses(world, player: int):
- if world.boss_shuffle[player] == 'none':
+
+def place_bosses(world, player: int) -> None:
+ # will either be an int or a lower case string with ';' between options
+ boss_shuffle: Union[str, int] = world.boss_shuffle[player].value
+ already_placed_bosses: List[str] = []
+ remaining_locations: List[Tuple[str, str]] = []
+ # handle plando
+ if isinstance(boss_shuffle, str):
+ # figure out our remaining mode, convert it to an int and remove it from plando_args
+ options = boss_shuffle.split(";")
+ boss_shuffle = Bosses.options[options.pop()]
+ # place our plando bosses
+ already_placed_bosses, remaining_locations = place_plando_bosses(options, world, player)
+ if boss_shuffle == Bosses.option_none: # vanilla boss locations
return
+
# Most to least restrictive order
- boss_locations = boss_location_table.copy()
- world.random.shuffle(boss_locations)
- boss_locations.sort(key= lambda location: -int(restrictive_boss_locations[location]))
+ if not remaining_locations and not already_placed_bosses:
+ remaining_locations = boss_location_table.copy()
+ world.random.shuffle(remaining_locations)
+ remaining_locations.sort(key=lambda location: -int(restrictive_boss_locations[location]))
all_bosses = sorted(boss_table.keys()) # sorted to be deterministic on older pythons
placeable_bosses = [boss for boss in all_bosses if boss not in ['Agahnim', 'Agahnim2', 'Ganon']]
- shuffle_mode = world.boss_shuffle[player]
- already_placed_bosses = []
- if ";" in shuffle_mode:
- bosses = shuffle_mode.split(";")
- shuffle_mode = bosses.pop()
- for boss in bosses:
- if "-" in boss:
- loc, boss = boss.split("-")
- boss = boss.title()
- level = None
- if loc.split(" ")[-1] in {"top", "middle", "bottom"}:
- # split off level
- loc = loc.split(" ")
- level = loc[-1]
- loc = " ".join(loc[:-1])
- loc = loc.title().replace("Of", "of")
- if can_place_boss(boss, loc, level) and (loc, level) in boss_locations:
- place_boss(world, player, boss, loc, level)
- already_placed_bosses.append(boss)
- boss_locations.remove((loc, level))
- else:
- raise Exception(f"Cannot place {boss} at {format_boss_location(loc, level)} for player {player}.")
- else:
- boss = boss.title()
- boss_locations, already_placed_bosses = place_where_possible(world, player, boss, boss_locations)
-
- if shuffle_mode == "none":
- return # vanilla bosses come pre-placed
-
- if shuffle_mode in ["basic", "full"]:
- if world.boss_shuffle[player] == "basic": # vanilla bosses shuffled
+ if boss_shuffle == Bosses.option_basic or boss_shuffle == Bosses.option_full:
+ if boss_shuffle == Bosses.option_basic: # vanilla bosses shuffled
bosses = placeable_bosses + ['Armos Knights', 'Lanmolas', 'Moldorm']
else: # all bosses present, the three duplicates chosen at random
bosses = placeable_bosses + world.random.sample(placeable_bosses, 3)
@@ -258,7 +275,7 @@ def place_bosses(world, player: int):
logging.debug('Bosses chosen %s', bosses)
world.random.shuffle(bosses)
- for loc, level in boss_locations:
+ for loc, level in remaining_locations:
for _ in range(len(bosses)):
boss = bosses.pop()
if can_place_boss(boss, loc, level):
@@ -272,8 +289,8 @@ def place_bosses(world, player: int):
place_boss(world, player, boss, loc, level)
- elif shuffle_mode == "chaos": # all bosses chosen at random
- for loc, level in boss_locations:
+ elif boss_shuffle == Bosses.option_chaos: # all bosses chosen at random
+ for loc, level in remaining_locations:
try:
boss = world.random.choice(
[b for b in placeable_bosses if can_place_boss(b, loc, level)])
@@ -282,9 +299,9 @@ def place_bosses(world, player: int):
else:
place_boss(world, player, boss, loc, level)
- elif shuffle_mode == "singularity":
+ elif boss_shuffle == Bosses.option_singularity:
primary_boss = world.random.choice(placeable_bosses)
- remaining_boss_locations, _ = place_where_possible(world, player, primary_boss, boss_locations)
+ remaining_boss_locations, _ = place_where_possible(world, player, primary_boss, remaining_locations)
if remaining_boss_locations:
# pick a boss to go into the remaining locations
remaining_boss = world.random.choice([boss for boss in placeable_bosses if all(
@@ -293,12 +310,12 @@ def place_bosses(world, player: int):
if remaining_boss_locations:
raise Exception("Unfilled boss locations!")
else:
- raise FillError(f"Could not find boss shuffle mode {shuffle_mode}")
+ raise FillError(f"Could not find boss shuffle mode {boss_shuffle}")
-def place_where_possible(world, player: int, boss: str, boss_locations):
- remainder = []
- placed_bosses = []
+def place_where_possible(world, player: int, boss: str, boss_locations) -> Tuple[List[Tuple[str, str]], List[str]]:
+ remainder: List[Tuple[str, str]] = []
+ placed_bosses: List[str] = []
for loc, level in boss_locations:
# place that boss where it can go
if can_place_boss(boss, loc, level):
diff --git a/worlds/alttp/ItemPool.py b/worlds/alttp/ItemPool.py
index d7ab3b8491..aa8d7ef3f0 100644
--- a/worlds/alttp/ItemPool.py
+++ b/worlds/alttp/ItemPool.py
@@ -480,7 +480,7 @@ def set_up_take_anys(world, player):
old_man_take_any.shop = TakeAny(old_man_take_any, 0x0112, 0xE2, True, True, total_shop_slots)
world.shops.append(old_man_take_any.shop)
- swords = [item for item in world.itempool if item.type == 'Sword' and item.player == player]
+ swords = [item for item in world.itempool if item.player == player and item.type == 'Sword']
if swords:
sword = world.random.choice(swords)
world.itempool.remove(sword)
diff --git a/worlds/alttp/Options.py b/worlds/alttp/Options.py
index 183f3eda91..b13d99f1e7 100644
--- a/worlds/alttp/Options.py
+++ b/worlds/alttp/Options.py
@@ -1,7 +1,7 @@
import typing
from BaseClasses import MultiWorld
-from Options import Choice, Range, Option, Toggle, DefaultOnToggle, DeathLink
+from Options import Choice, Range, Option, Toggle, DefaultOnToggle, DeathLink, TextChoice
class Logic(Choice):
@@ -39,8 +39,6 @@ class OpenPyramid(Choice):
option_auto = 3
default = option_goal
- alias_true = option_open
- alias_false = option_closed
alias_yes = option_open
alias_no = option_closed
@@ -140,13 +138,143 @@ class WorldState(Choice):
option_inverted = 2
-class Bosses(Choice):
- option_vanilla = 0
- option_simple = 1
+class Bosses(TextChoice):
+ """Shuffles bosses around to different locations.
+ Basic will shuffle all bosses except Ganon and Agahnim anywhere they can be placed.
+ Full chooses 3 bosses at random to be placed twice instead of Lanmolas, Moldorm, and Helmasaur.
+ Chaos allows any boss to appear any number of times.
+ Singularity places a single boss in as many places as possible, and a second boss in any remaining locations.
+ Supports plando placement. Formatting here: https://archipelago.gg/tutorial/A%20Link%20to%20the%20Past/plando/en"""
+ display_name = "Boss Shuffle"
+ option_none = 0
+ option_basic = 1
option_full = 2
option_chaos = 3
option_singularity = 4
+ bosses: set = {
+ "Armos Knights",
+ "Lanmolas",
+ "Moldorm",
+ "Helmasaur King",
+ "Arrghus",
+ "Mothula",
+ "Blind",
+ "Kholdstare",
+ "Vitreous",
+ "Trinexx",
+ }
+
+ locations: set = {
+ "Ganons Tower Top",
+ "Tower of Hera",
+ "Skull Woods",
+ "Ganons Tower Middle",
+ "Eastern Palace",
+ "Desert Palace",
+ "Palace of Darkness",
+ "Swamp Palace",
+ "Thieves Town",
+ "Ice Palace",
+ "Misery Mire",
+ "Turtle Rock",
+ "Ganons Tower Bottom"
+ }
+
+ def __init__(self, value: typing.Union[str, int]):
+ assert isinstance(value, str) or isinstance(value, int), \
+ f"{value} is not a valid option for {self.__class__.__name__}"
+ self.value = value
+
+ @classmethod
+ def from_text(cls, text: str):
+ import random
+ # set all of our text to lower case for name checking
+ text = text.lower()
+ cls.bosses = {boss_name.lower() for boss_name in cls.bosses}
+ cls.locations = {boss_location.lower() for boss_location in cls.locations}
+ if text == "random":
+ return cls(random.choice(list(cls.options.values())))
+ for option_name, value in cls.options.items():
+ if option_name == text:
+ return cls(value)
+ options = text.split(";")
+
+ # since plando exists in the option verify the plando values given are valid
+ cls.validate_plando_bosses(options)
+
+ # find out what type of boss shuffle we should use for placing bosses after plando
+ # and add as a string to look nice in the spoiler
+ if "random" in options:
+ shuffle = random.choice(list(cls.options))
+ options.remove("random")
+ options = ";".join(options) + ";" + shuffle
+ boss_class = cls(options)
+ else:
+ for option in options:
+ if option in cls.options:
+ boss_class = cls(";".join(options))
+ break
+ else:
+ if len(options) == 1:
+ if cls.valid_boss_name(options[0]):
+ options = options[0] + ";singularity"
+ boss_class = cls(options)
+ else:
+ options = options[0] + ";none"
+ boss_class = cls(options)
+ else:
+ options = ";".join(options) + ";none"
+ boss_class = cls(options)
+ return boss_class
+
+ @classmethod
+ def validate_plando_bosses(cls, options: typing.List[str]) -> None:
+ from .Bosses import can_place_boss, format_boss_location
+ for option in options:
+ if option == "random" or option in cls.options:
+ if option != options[-1]:
+ raise ValueError(f"{option} option must be at the end of the boss_shuffle options!")
+ continue
+ if "-" in option:
+ location, boss = option.split("-")
+ level = ''
+ if not cls.valid_boss_name(boss):
+ raise ValueError(f"{boss} is not a valid boss name for location {location}.")
+ if not cls.valid_location_name(location):
+ raise ValueError(f"{location} is not a valid boss location name.")
+ if location.split(" ")[-1] in ("top", "middle", "bottom"):
+ location = location.split(" ")
+ level = location[-1]
+ location = " ".join(location[:-1])
+ location = location.title().replace("Of", "of")
+ if not can_place_boss(boss.title(), location, level):
+ raise ValueError(f"{format_boss_location(location, level)} "
+ f"is not a valid location for {boss.title()}.")
+ else:
+ if not cls.valid_boss_name(option):
+ raise ValueError(f"{option} is not a valid boss name.")
+
+ @classmethod
+ def valid_boss_name(cls, value: str) -> bool:
+ return value.lower() in cls.bosses
+
+ @classmethod
+ def valid_location_name(cls, value: str) -> bool:
+ return value in cls.locations
+
+ def verify(self, world, player_name: str, plando_options) -> None:
+ if isinstance(self.value, int):
+ return
+ from Generate import PlandoSettings
+ if not(PlandoSettings.bosses & plando_options):
+ import logging
+ # plando is disabled but plando options were given so pull the option and change it to an int
+ option = self.value.split(";")[-1]
+ self.value = self.options[option]
+ logging.warning(f"The plando bosses module is turned off, so {self.name_lookup[self.value].title()} "
+ f"boss shuffle will be used for player {player_name}.")
+
class Enemies(Choice):
option_vanilla = 0
@@ -159,8 +287,6 @@ class Progressive(Choice):
option_off = 0
option_grouped_random = 1
option_on = 2
- alias_false = 0
- alias_true = 2
default = 2
def want_progressives(self, random):
@@ -168,8 +294,8 @@ class Progressive(Choice):
class Swordless(Toggle):
- """No swords. Curtains in Skull Woods and Agahnim\'s
- Tower are removed, Agahnim\'s Tower barrier can be
+ """No swords. Curtains in Skull Woods and Agahnim's
+ Tower are removed, Agahnim's Tower barrier can be
destroyed with hammer. Misery Mire and Turtle Rock
can be opened without a sword. Hammer damages Ganon.
Ether and Bombos Tablet can be activated with Hammer
@@ -202,8 +328,6 @@ class Hints(Choice):
option_on = 2
option_full = 3
default = 2
- alias_false = 0
- alias_true = 2
class Scams(Choice):
@@ -213,7 +337,6 @@ class Scams(Choice):
option_king_zora = 1
option_bottle_merchant = 2
option_all = 3
- alias_false = 0
@property
def gives_king_zora_hint(self):
@@ -282,8 +405,8 @@ class ShieldPalette(Palette):
display_name = "Shield Palette"
-class LinkPalette(Palette):
- display_name = "Link Palette"
+# class LinkPalette(Palette):
+# display_name = "Link Palette"
class HeartBeep(Choice):
@@ -293,7 +416,6 @@ class HeartBeep(Choice):
option_half = 2
option_quarter = 3
option_off = 4
- alias_false = 4
class HeartColor(Choice):
@@ -375,6 +497,7 @@ alttp_options: typing.Dict[str, type(Option)] = {
"hints": Hints,
"scams": Scams,
"restrict_dungeon_item_on_boss": RestrictBossItem,
+ "boss_shuffle": Bosses,
"pot_shuffle": PotShuffle,
"enemy_shuffle": EnemyShuffle,
"killable_thieves": KillableThieves,
@@ -387,7 +510,7 @@ alttp_options: typing.Dict[str, type(Option)] = {
"hud_palettes": HUDPalette,
"sword_palettes": SwordPalette,
"shield_palettes": ShieldPalette,
- "link_palettes": LinkPalette,
+ # "link_palettes": LinkPalette,
"heartbeep": HeartBeep,
"heartcolor": HeartColor,
"quickswap": QuickSwap,
diff --git a/worlds/alttp/Regions.py b/worlds/alttp/Regions.py
index 80c4767d23..5f8bd0a43d 100644
--- a/worlds/alttp/Regions.py
+++ b/worlds/alttp/Regions.py
@@ -4,6 +4,10 @@ import typing
from BaseClasses import Region, Entrance, RegionType
+def is_main_entrance(entrance: Entrance) -> bool:
+ return entrance.parent_region.type in {RegionType.DarkWorld, RegionType.LightWorld, RegionType.Generic}
+
+
def create_regions(world, player):
world.regions += [
diff --git a/worlds/alttp/__init__.py b/worlds/alttp/__init__.py
index 3e32584352..bbdd941127 100644
--- a/worlds/alttp/__init__.py
+++ b/worlds/alttp/__init__.py
@@ -12,7 +12,8 @@ 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 .Regions import lookup_name_to_id, create_regions, mark_light_world_regions
+from .Regions import lookup_name_to_id, create_regions, mark_light_world_regions, lookup_vanilla_location_to_entrance, \
+ is_main_entrance
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
@@ -24,6 +25,7 @@ lttp_logger = logging.getLogger("A Link to the Past")
extras_list = sum(difficulties['normal'].extras[0:5], [])
+
class ALTTPWeb(WebWorld):
setup_en = Tutorial(
"Multiworld Setup Tutorial",
@@ -349,7 +351,7 @@ class ALTTPWorld(World):
def use_enemizer(self):
world = self.world
player = self.player
- return (world.boss_shuffle[player] != 'none' or world.enemy_shuffle[player]
+ return (world.boss_shuffle[player] or world.enemy_shuffle[player]
or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default'
or world.pot_shuffle[player] or world.bush_shuffle[player]
or world.killable_thieves[player])
@@ -378,7 +380,7 @@ class ALTTPWorld(World):
'hud': world.hud_palettes[player],
'sword': world.sword_palettes[player],
'shield': world.shield_palettes[player],
- 'link': world.link_palettes[player]
+ # 'link': world.link_palettes[player]
}
palettes_options = {key: option.current_key for key, option in palettes_options.items()}
@@ -410,6 +412,20 @@ class ALTTPWorld(World):
finally:
self.rom_name_available_event.set() # make sure threading continues and errors are collected
+ @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]}
+
+ for region in world.regions:
+ if region.player in er_hint_data and region.locations:
+ main_entrance = region.get_connecting_entrance(is_main_entrance)
+ for location in region.locations:
+ if type(location.address) == int: # skips events and crystals
+ if lookup_vanilla_location_to_entrance[location.address] != main_entrance.name:
+ er_hint_data[region.player][location.address] = main_entrance.name
+ hint_data.update(er_hint_data)
+
def modify_multidata(self, multidata: dict):
import base64
# wait for self.rom_name to be available.
@@ -424,8 +440,7 @@ class ALTTPWorld(World):
return ALttPItem(name, self.player, **item_init_table[name])
@classmethod
- def stage_fill_hook(cls, world, progitempool, nonexcludeditempool, localrestitempool, nonlocalrestitempool,
- restitempool, fill_locations):
+ def stage_fill_hook(cls, world, progitempool, usefulitempool, filleritempool, fill_locations):
trash_counts = {}
standard_keyshuffle_players = set()
for player in world.get_game_players("A Link to the Past"):
@@ -472,26 +487,15 @@ class ALTTPWorld(World):
for player, trash_count in trash_counts.items():
gtower_locations = locations_mapping[player]
world.random.shuffle(gtower_locations)
- localrest = localrestitempool[player]
- if localrest:
- gt_item_pool = restitempool + localrest
- world.random.shuffle(gt_item_pool)
- else:
- gt_item_pool = restitempool.copy()
- while gtower_locations and gt_item_pool and trash_count > 0:
+ while gtower_locations and filleritempool and trash_count > 0:
spot_to_fill = gtower_locations.pop()
- item_to_place = gt_item_pool.pop()
+ item_to_place = filleritempool.pop()
if spot_to_fill.item_rule(item_to_place):
- if item_to_place in localrest:
- localrest.remove(item_to_place)
- else:
- restitempool.remove(item_to_place)
world.push_item(spot_to_fill, item_to_place, False)
fill_locations.remove(spot_to_fill) # very slow, unfortunately
trash_count -= 1
-
def get_filler_item_name(self) -> str:
if self.world.goal[self.player] == "icerodhunt":
item = "Nothing"
diff --git a/worlds/alttp/docs/plando_en.md b/worlds/alttp/docs/plando_en.md
index 36322d9933..af8cbfe1b0 100644
--- a/worlds/alttp/docs/plando_en.md
+++ b/worlds/alttp/docs/plando_en.md
@@ -26,10 +26,14 @@
- Example: `Trinexx`
- Takes a particular boss and places that boss in any remaining slots in which this boss can function.
- In this example, it would fill Desert Palace, but not Tower of Hera.
+ - If no other options are provided this will follow normal singularity rules with that boss.
- Boss Shuffle:
- - Example: `simple`
+ - Example: `basic`
- Runs a particular boss shuffle mode to finish construction instead of vanilla placement, typically used as
a last instruction.
+ - Supports `random` which will choose a random option from the normal choices.
+ - If one is not supplied any remaining locations will be unshuffled unless a single specific boss is
+ supplied in which case it will use singularity as noted above.
- [Available Bosses](https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/alttp/Bosses.py#L135)
- [Available Arenas](https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/alttp/Bosses.py#L150)
diff --git a/worlds/factorio/Mod.py b/worlds/factorio/Mod.py
index 9889e58bf3..89666ffbdd 100644
--- a/worlds/factorio/Mod.py
+++ b/worlds/factorio/Mod.py
@@ -34,7 +34,8 @@ base_info = {
"factorio_version": "1.1",
"dependencies": [
"base >= 1.1.0",
- "? science-not-invited"
+ "? science-not-invited",
+ "? factory-levels"
]
}
diff --git a/worlds/factorio/Options.py b/worlds/factorio/Options.py
index b7d13c6464..64e03c4338 100644
--- a/worlds/factorio/Options.py
+++ b/worlds/factorio/Options.py
@@ -137,8 +137,6 @@ class Progressive(Choice):
option_off = 0
option_grouped_random = 1
option_on = 2
- alias_false = 0
- alias_true = 2
default = 2
def want_progressives(self, random):
diff --git a/worlds/factorio/data/mod/info.json b/worlds/factorio/data/mod/info.json
index b93686d060..70a9518344 100644
--- a/worlds/factorio/data/mod/info.json
+++ b/worlds/factorio/data/mod/info.json
@@ -7,7 +7,8 @@
"description": "Integration client for the Archipelago Randomizer",
"factorio_version": "1.1",
"dependencies": [
- "base >= 1.1.0",
- "? science-not-invited"
- ]
+ "base >= 1.1.0",
+ "? science-not-invited",
+ "? factory-levels"
+ ]
}
diff --git a/worlds/factorio/data/mod_template/data-final-fixes.lua b/worlds/factorio/data/mod_template/data-final-fixes.lua
index cc813b2fff..70bc1eac0a 100644
--- a/worlds/factorio/data/mod_template/data-final-fixes.lua
+++ b/worlds/factorio/data/mod_template/data-final-fixes.lua
@@ -183,6 +183,18 @@ end
data.raw["assembling-machine"]["assembling-machine-1"].crafting_categories = table.deepcopy(data.raw["assembling-machine"]["assembling-machine-3"].crafting_categories)
data.raw["assembling-machine"]["assembling-machine-2"].crafting_categories = table.deepcopy(data.raw["assembling-machine"]["assembling-machine-3"].crafting_categories)
data.raw["assembling-machine"]["assembling-machine-1"].fluid_boxes = table.deepcopy(data.raw["assembling-machine"]["assembling-machine-2"].fluid_boxes)
+if mods["factory-levels"] then
+ -- Factory-Levels allows the assembling machines to get faster (and depending on settings), more productive at crafting products, the more the
+ -- assembling machine crafts the product. If the machine crafts enough, it may auto-upgrade to the next tier.
+ for i = 1, 25, 1 do
+ data.raw["assembling-machine"]["assembling-machine-1-level-" .. i].crafting_categories = table.deepcopy(data.raw["assembling-machine"]["assembling-machine-3"].crafting_categories)
+ data.raw["assembling-machine"]["assembling-machine-1-level-" .. i].fluid_boxes = table.deepcopy(data.raw["assembling-machine"]["assembling-machine-2"].fluid_boxes)
+ end
+ for i = 1, 50, 1 do
+ data.raw["assembling-machine"]["assembling-machine-2-level-" .. i].crafting_categories = table.deepcopy(data.raw["assembling-machine"]["assembling-machine-3"].crafting_categories)
+ end
+end
+
data.raw["ammo"]["artillery-shell"].stack_size = 10
{# each randomized tech gets set to be invisible, with new nodes added that trigger those #}
diff --git a/worlds/ff1/Items.py b/worlds/ff1/Items.py
index e045fbaf18..469cf6f051 100644
--- a/worlds/ff1/Items.py
+++ b/worlds/ff1/Items.py
@@ -20,7 +20,7 @@ FF1_STARTER_ITEMS = [
FF1_PROGRESSION_LIST = [
"Rod", "Cube", "Lute", "Key", "Chime", "Oxyale",
- "Ship", "Canoe", "Floater", "Canal",
+ "Ship", "Canoe", "Floater", "Mark", "Sigil", "Canal",
"Crown", "Crystal", "Herb", "Tnt", "Adamant", "Slab", "Ruby", "Bottle",
"Shard",
"EarthOrb", "FireOrb", "WaterOrb", "AirOrb"
diff --git a/worlds/ff1/__init__.py b/worlds/ff1/__init__.py
index 0d731ace4b..24b8e7081b 100644
--- a/worlds/ff1/__init__.py
+++ b/worlds/ff1/__init__.py
@@ -31,7 +31,7 @@ class FF1World(World):
game = "Final Fantasy"
topology_present = False
remote_items = True
- data_version = 1
+ data_version = 2
remote_start_inventory = True
ff1_items = FF1Items()
@@ -66,7 +66,10 @@ class FF1World(World):
def goal_rule_and_shards(state):
return goal_rule(state) and state.has("Shard", self.player, 32)
terminated_event.access_rule = goal_rule_and_shards
-
+ if "MARK" in items.keys():
+ # Fail generation for Noverworld and provide link to old FFR website
+ raise Exception("FFR Noverworld seeds must be generated on an older version of FFR. Please ensure you generated the settings using "
+ "4-4-0.finalfantasyrandomizer.com")
menu_region.locations.append(terminated_event)
self.world.regions += [menu_region]
diff --git a/worlds/ff1/data/items.json b/worlds/ff1/data/items.json
index 99611837fb..333080973d 100644
--- a/worlds/ff1/data/items.json
+++ b/worlds/ff1/data/items.json
@@ -190,5 +190,7 @@
"Ship": 480,
"Bridge": 488,
"Canal": 492,
- "Canoe": 498
+ "Canoe": 498,
+ "Sigil": 499,
+ "Mark": 500
}
diff --git a/worlds/hk/Options.py b/worlds/hk/Options.py
index fd8d036175..04923e70f8 100644
--- a/worlds/hk/Options.py
+++ b/worlds/hk/Options.py
@@ -409,7 +409,6 @@ class DeathLink(Choice):
shade: DeathLink functions like a normal death if you do not already have a shade, shadeless otherwise.
"""
option_off = 0
- alias_false = 0
alias_no = 0
alias_true = 1
alias_on = 1
@@ -435,10 +434,8 @@ class CostSanity(Choice):
These costs can be in Geo (except Grubfather, Seer and Eggshop), Grubs, Charms, Essence and/or Rancid Eggs
"""
option_off = 0
- alias_false = 0
alias_no = 0
option_on = 1
- alias_true = 1
alias_yes = 1
option_shopsonly = 2
option_notshops = 3
diff --git a/worlds/oot/Options.py b/worlds/oot/Options.py
index ea9a8160fb..deee558755 100644
--- a/worlds/oot/Options.py
+++ b/worlds/oot/Options.py
@@ -101,7 +101,6 @@ class InteriorEntrances(Choice):
option_off = 0
option_simple = 1
option_all = 2
- alias_false = 0
alias_true = 2
@@ -141,7 +140,6 @@ class MixEntrancePools(Choice):
option_off = 0
option_indoor = 1
option_all = 2
- alias_false = 0
class DecoupleEntrances(Toggle):
@@ -308,7 +306,6 @@ class ShopShuffle(Choice):
option_off = 0
option_fixed_number = 1
option_random_number = 2
- alias_false = 0
class ShopSlots(Range):
@@ -326,7 +323,6 @@ class TokenShuffle(Choice):
option_dungeons = 1
option_overworld = 2
option_all = 3
- alias_false = 0
class ScrubShuffle(Choice):
@@ -336,7 +332,6 @@ class ScrubShuffle(Choice):
option_low = 1
option_regular = 2
option_random_prices = 3
- alias_false = 0
alias_affordable = 1
alias_expensive = 2
@@ -569,7 +564,6 @@ class Hints(Choice):
option_agony = 2
option_always = 3
default = 3
- alias_false = 0
class MiscHints(DefaultOnToggle):
@@ -673,8 +667,6 @@ class IceTraps(Choice):
option_mayhem = 3
option_onslaught = 4
default = 1
- alias_false = 0
- alias_true = 2
alias_extra = 2
@@ -742,7 +734,6 @@ class Music(Choice):
option_normal = 0
option_off = 1
option_randomized = 2
- alias_false = 1
class BackgroundMusic(Music):
diff --git a/worlds/oot/__init__.py b/worlds/oot/__init__.py
index a9b7d5a1b6..b65882c874 100644
--- a/worlds/oot/__init__.py
+++ b/worlds/oot/__init__.py
@@ -190,7 +190,11 @@ class OOTWorld(World):
# Determine which dungeons are MQ
# Possible future plan: allow user to pick which dungeons are MQ
- mq_dungeons = self.world.random.sample(dungeon_table, self.mq_dungeons)
+ if self.logic_rules == 'glitchless':
+ mq_dungeons = self.world.random.sample(dungeon_table, self.mq_dungeons)
+ else:
+ self.mq_dungeons = 0
+ mq_dungeons = []
self.dungeon_mq = {item['name']: (item in mq_dungeons) for item in dungeon_table}
# Determine tricks in logic
diff --git a/worlds/raft/Options.py b/worlds/raft/Options.py
index 482f1d343a..5f09db07c0 100644
--- a/worlds/raft/Options.py
+++ b/worlds/raft/Options.py
@@ -1,8 +1,4 @@
-from Options import Range, Toggle, DefaultOnToggle, Choice
-
-class UseResourcePacks(DefaultOnToggle):
- """Uses Resource Packs to fill out the item pool from Raft. Resource Packs have basic earlygame items such as planks, plastic, or food."""
- display_name = "Use resource packs"
+from Options import Range, Toggle, DefaultOnToggle, Choice, DeathLink
class MinimumResourcePackAmount(Range):
"""The minimum amount of resources available in a resource pack"""
@@ -19,23 +15,30 @@ class MaximumResourcePackAmount(Range):
default = 5
class DuplicateItems(Choice):
- """Adds duplicates of items to the item pool. These will be selected alongside
- Resource Packs (if configured). Note that there are not many progression items,
- and selecting Progression may produce many of the same duplicate item."""
+ """Adds duplicates of items to the item pool (if configured in Filler items). These will be selected alongside Resource Packs (if configured). Note that there are not many progression items, and selecting Progression may produce many of the same duplicate item."""
display_name = "Duplicate items"
- option_disabled = 0
- option_progression = 1
- option_non_progression = 2
- option_any = 3
+ option_progression = 0
+ option_non_progression = 1
+ option_any = 2
+ default = 2
+
+class FillerItemTypes(Choice):
+ """Determines whether to use Resource Packs, Duplicate Items (as configured), or both."""
+ display_name = "Filler items"
+ option_resource_packs = 0
+ option_duplicates = 1
+ option_both = 2
class IslandFrequencyLocations(Choice):
"""Sets where frequencies for story islands are located."""
display_name = "Frequency locations"
option_vanilla = 0
option_random_on_island = 1
- option_progressive = 2
- option_anywhere = 3
- default = 1
+ option_random_island_order = 2
+ option_random_on_island_random_order = 3
+ option_progressive = 4
+ option_anywhere = 5
+ default = 2
class IslandGenerationDistance(Choice):
"""Sets how far away islands spawn from you when you input their coordinates into the Receiver."""
@@ -56,7 +59,7 @@ class ProgressiveItems(DefaultOnToggle):
display_name = "Progressive items"
class BigIslandEarlyCrafting(Toggle):
- """Allows recipes that require items from big islands (eg leather) to lock earlygame items like the Receiver, Bolt, or Smelter."""
+ """Allows recipes that require items from big islands (eg leather) to lock earlygame items like the Receiver, Bolt, or Smelter. Big islands are available from the start of the game, however it can take a long time to find them."""
display_name = "Early recipes behind big islands"
class PaddleboardMode(Toggle):
@@ -64,14 +67,15 @@ class PaddleboardMode(Toggle):
display_name = "Paddleboard Mode"
raft_options = {
- "use_resource_packs": UseResourcePacks,
"minimum_resource_pack_amount": MinimumResourcePackAmount,
"maximum_resource_pack_amount": MaximumResourcePackAmount,
"duplicate_items": DuplicateItems,
+ "filler_item_types": FillerItemTypes,
"island_frequency_locations": IslandFrequencyLocations,
"island_generation_distance": IslandGenerationDistance,
"expensive_research": ExpensiveResearch,
"progressive_items": ProgressiveItems,
"big_island_early_crafting": BigIslandEarlyCrafting,
- "paddleboard_mode": PaddleboardMode
+ "paddleboard_mode": PaddleboardMode,
+ "death_link": DeathLink
}
diff --git a/worlds/raft/Rules.py b/worlds/raft/Rules.py
index 3ca565d9d6..0432c2806f 100644
--- a/worlds/raft/Rules.py
+++ b/worlds/raft/Rules.py
@@ -12,9 +12,6 @@ class RaftLogic(LogicMixin):
def raft_can_smelt_items(self, player):
return self.has("Smelter", player)
-
- def raft_can_find_titanium(self, player):
- return self.has("Metal detector", player)
def raft_can_craft_bolt(self, player):
return self.raft_can_smelt_items(player) and self.has("Bolt", player)
@@ -27,12 +24,19 @@ class RaftLogic(LogicMixin):
def raft_can_craft_circuitBoard(self, player):
return self.raft_can_smelt_items(player) and self.has("Circuit board", player)
+
+ def raft_can_craft_shovel(self, player):
+ return self.raft_can_smelt_items(player) and self.has("Shovel", player) and self.raft_can_craft_bolt(player)
def raft_can_craft_reciever(self, player):
return self.raft_can_craft_circuitBoard(player) and self.raft_can_craft_hinge(player) and self.has("Receiver", player)
def raft_can_craft_antenna(self, player):
return self.raft_can_craft_circuitBoard(player) and self.raft_can_craft_bolt(player) and self.has("Antenna", player)
+
+ def raft_can_find_titanium(self, player):
+ return (self.has("Metal detector", player) and self.raft_can_craft_battery(player)
+ and self.raft_can_craft_shovel(player))
def raft_can_craft_plasticBottle(self, player):
return self.raft_can_smelt_items(player) and self.has("Empty bottle", player)
@@ -60,7 +64,7 @@ class RaftLogic(LogicMixin):
return self.raft_can_craft_hinge(player) and self.raft_can_craft_bolt(player) and self.has("Zipline tool", player)
def raft_can_get_dirt(self, player):
- return self.raft_can_smelt_items(player) and self.raft_can_craft_bolt(player) and self.has("Shovel", player)
+ return self.raft_can_craft_shovel(player) and self.raft_big_islands_available(player)
def raft_can_craft_grassPlot(self, player):
return self.raft_can_get_dirt(player) and self.has("Grass plot", player)
@@ -88,60 +92,69 @@ class RaftLogic(LogicMixin):
return self.raft_can_access_radio_tower(player)
def raft_can_access_vasagatan(self, player):
- return self.raft_can_complete_radio_tower(player) and self.raft_can_navigate(player) and self.has("Vasagatan Frequency", player)
+ return self.raft_can_navigate(player) and self.has("Vasagatan Frequency", player)
def raft_can_complete_vasagatan(self, player):
return self.raft_can_access_vasagatan(player)
def raft_can_access_balboa_island(self, player):
- return (self.raft_can_complete_vasagatan(player)
- and self.raft_can_drive(player)
- and self.has("Balboa Island Frequency", player))
+ return self.raft_can_drive(player) and self.has("Balboa Island Frequency", player)
def raft_can_complete_balboa_island(self, player):
return self.raft_can_access_balboa_island(player) and self.raft_can_craft_machete(player)
def raft_can_access_caravan_island(self, player):
- return self.raft_can_complete_balboa_island(player) and self.raft_can_drive(player) and self.has("Caravan Island Frequency", player)
+ return self.raft_can_drive(player) and self.has("Caravan Island Frequency", player)
def raft_can_complete_caravan_island(self, player):
return self.raft_can_access_caravan_island(player) and self.raft_can_craft_ziplineTool(player)
def raft_can_access_tangaroa(self, player):
- return self.raft_can_complete_caravan_island(player) and self.raft_can_drive(player) and self.has("Tangaroa Frequency", player)
+ return self.raft_can_drive(player) and self.has("Tangaroa Frequency", player)
def raft_can_complete_tangaroa(self, player):
- return self.raft_can_access_tangaroa(player)
+ return self.raft_can_access_tangaroa(player) and self.raft_can_craft_ziplineTool(player)
def raft_can_access_varuna_point(self, player):
- return self.raft_can_complete_tangaroa(player) and self.raft_can_drive(player) and self.has("Varuna Point Frequency", player)
+ return self.raft_can_drive(player) and self.has("Varuna Point Frequency", player)
def raft_can_complete_varuna_point(self, player):
- return self.raft_can_access_varuna_point(player)
+ return self.raft_can_access_varuna_point(player) and self.raft_can_craft_ziplineTool(player)
def raft_can_access_temperance(self, player):
- return self.raft_can_complete_varuna_point(player) and self.raft_can_drive(player) and self.has("Temperance Frequency", player)
+ return self.raft_can_drive(player) and self.has("Temperance Frequency", player)
def raft_can_complete_temperance(self, player):
- return self.raft_can_access_temperance(player)
+ return self.raft_can_access_temperance(player) # No zipline required on Temperance
def raft_can_access_utopia(self, player):
- return self.raft_can_complete_temperance(player) and self.raft_can_drive(player) and self.has("Utopia Frequency", player)
+ return (self.raft_can_drive(player)
+ # Access checks are to prevent frequencies for other
+ # islands from appearing in Utopia
+ and self.raft_can_access_radio_tower(player)
+ and self.raft_can_access_vasagatan(player)
+ and self.raft_can_access_balboa_island(player)
+ and self.raft_can_access_caravan_island(player)
+ and self.raft_can_access_tangaroa(player)
+ and self.raft_can_access_varuna_point(player)
+ and self.raft_can_access_temperance(player)
+ and self.has("Utopia Frequency", player)
+ and self.raft_can_craft_shovel(player)) # Shovels are available but we don't want to softlock players
def raft_can_complete_utopia(self, player):
- return self.raft_can_access_utopia(player)
+ return self.raft_can_access_utopia(player) and self.raft_can_craft_ziplineTool(player)
def set_rules(world, player):
regionChecks = {
"Raft": lambda state: True,
"ResearchTable": lambda state: True,
"RadioTower": lambda state: state.raft_can_access_radio_tower(player), # All can_access functions have state as implicit parameter for function
- "Vasagatan": lambda state: state.raft_can_complete_radio_tower(player) and state.raft_can_access_vasagatan(player),
- "BalboaIsland": lambda state: state.raft_can_complete_vasagatan(player) and state.raft_can_access_balboa_island(player),
- "CaravanIsland": lambda state: state.raft_can_complete_balboa_island(player) and state.raft_can_access_caravan_island(player),
- "Tangaroa": lambda state: state.raft_can_complete_caravan_island(player) and state.raft_can_access_tangaroa(player),
- "Varuna Point": lambda state: state.raft_can_complete_tangaroa(player) and state.raft_can_access_varuna_point(player),
- "Temperance": lambda state: state.raft_can_complete_varuna_point(player) and state.raft_can_access_temperance(player),
+ "Vasagatan": lambda state: state.raft_can_access_vasagatan(player),
+ "BalboaIsland": lambda state: state.raft_can_access_balboa_island(player),
+ "CaravanIsland": lambda state: state.raft_can_access_caravan_island(player),
+ "Tangaroa": lambda state: state.raft_can_access_tangaroa(player),
+ "Varuna Point": lambda state: state.raft_can_access_varuna_point(player),
+ "Temperance": lambda state: state.raft_can_access_temperance(player),
"Utopia": lambda state: state.raft_can_complete_temperance(player) and state.raft_can_access_utopia(player)
}
itemChecks = {
@@ -183,7 +196,7 @@ def set_rules(world, player):
if region != "Menu":
for exitRegion in world.get_region(region, player).exits:
set_rule(world.get_entrance(exitRegion.name, player), regionChecks[region])
-
+
# Location access rules
for location in location_table:
locFromWorld = world.get_location(location["name"], player)
diff --git a/worlds/raft/__init__.py b/worlds/raft/__init__.py
index da4b58f24f..860ba9aab5 100644
--- a/worlds/raft/__init__.py
+++ b/worlds/raft/__init__.py
@@ -56,21 +56,21 @@ class RaftWorld(World):
extraItemNamePool = []
extras = len(location_table) - len(item_table) - 1 # Victory takes up 1 unaccounted-for slot
if extras > 0:
- if (self.world.use_resource_packs[self.player].value):
+ if (self.world.filler_item_types[self.player].value != 1): # Use resource packs
for packItem in resourcePackItems:
for i in range(minimumResourcePackAmount, maximumResourcePackAmount + 1):
extraItemNamePool.append(createResourcePackName(i, packItem))
- if self.world.duplicate_items[self.player].value != 0:
+ if self.world.filler_item_types[self.player].value != 0: # Use duplicate items
dupeItemPool = item_table.copy()
# Remove frequencies if necessary
- if self.world.island_frequency_locations[self.player].value != 3: # Not completely random locations
+ if self.world.island_frequency_locations[self.player].value != 5: # Not completely random locations
dupeItemPool = (itm for itm in dupeItemPool if "Frequency" not in itm["name"])
# Remove progression or non-progression items if necessary
- if (self.world.duplicate_items[self.player].value == 1): # Progression only
+ if (self.world.duplicate_items[self.player].value == 0): # Progression only
dupeItemPool = (itm for itm in dupeItemPool if itm["progression"] == True)
- elif (self.world.duplicate_items[self.player].value == 2): # Non-progression only
+ elif (self.world.duplicate_items[self.player].value == 1): # Non-progression only
dupeItemPool = (itm for itm in dupeItemPool if itm["progression"] == False)
dupeItemPool = list(dupeItemPool)
@@ -91,19 +91,15 @@ class RaftWorld(World):
def create_regions(self):
create_regions(self.world, self.player)
-
- def fill_slot_data(self):
- slot_data = {}
- return slot_data
def get_pre_fill_items(self):
- if self.world.island_frequency_locations[self.player] in [0, 1]:
+ if self.world.island_frequency_locations[self.player] in [0, 1, 2, 3]:
return [loc.item for loc in self.world.get_filled_locations()]
return []
def create_item_replaceAsNecessary(self, name: str) -> Item:
isFrequency = "Frequency" in name
- shouldUseProgressive = ((isFrequency and self.world.island_frequency_locations[self.player].value == 2)
+ shouldUseProgressive = ((isFrequency and self.world.island_frequency_locations[self.player].value == 4)
or (not isFrequency and self.world.progressive_items[self.player].value))
if shouldUseProgressive and name in progressive_table:
name = progressive_table[name]
@@ -148,6 +144,40 @@ class RaftWorld(World):
self.setLocationItemFromRegion("Tangaroa", "Varuna Point Frequency")
self.setLocationItemFromRegion("Varuna Point", "Temperance Frequency")
self.setLocationItemFromRegion("Temperance", "Utopia Frequency")
+ elif self.world.island_frequency_locations[self.player] in [2, 3]:
+ locationToFrequencyItemMap = {
+ "Vasagatan": "Vasagatan Frequency",
+ "BalboaIsland": "Balboa Island Frequency",
+ "CaravanIsland": "Caravan Island Frequency",
+ "Tangaroa": "Tangaroa Frequency",
+ "Varuna Point": "Varuna Point Frequency",
+ "Temperance": "Temperance Frequency",
+ "Utopia": "Utopia Frequency"
+ }
+ locationToVanillaFrequencyLocationMap = {
+ "RadioTower": "Radio Tower Frequency to Vasagatan",
+ "Vasagatan": "Vasagatan Frequency to Balboa",
+ "BalboaIsland": "Relay Station quest",
+ "CaravanIsland": "Caravan Island Frequency to Tangaroa",
+ "Tangaroa": "Tangaroa Frequency to Varuna Point",
+ "Varuna Point": "Varuna Point Frequency to Temperance",
+ "Temperance": "Temperance Frequency to Utopia"
+ }
+ # Utopia is never chosen until the end, otherwise these are chosen randomly
+ availableLocationList = ["Vasagatan", "BalboaIsland", "CaravanIsland", "Tangaroa", "Varuna Point", "Temperance", "Utopia"]
+ previousLocation = "RadioTower"
+ while (len(availableLocationList) > 0):
+ if (len(availableLocationList) > 1):
+ currentLocation = availableLocationList[random.randint(0, len(availableLocationList) - 2)]
+ else:
+ currentLocation = availableLocationList[0] # Utopia (only one left in list)
+ availableLocationList.remove(currentLocation)
+ if self.world.island_frequency_locations[self.player] == 2:
+ self.setLocationItem(locationToVanillaFrequencyLocationMap[previousLocation], locationToFrequencyItemMap[currentLocation])
+ elif self.world.island_frequency_locations[self.player] == 3:
+ self.setLocationItemFromRegion(previousLocation, locationToFrequencyItemMap[currentLocation])
+ previousLocation = currentLocation
+
# Victory item
self.world.get_location("Utopia Complete", self.player).place_locked_item(
RaftItem("Victory", ItemClassification.progression, None, player=self.player))
@@ -166,7 +196,8 @@ class RaftWorld(World):
def fill_slot_data(self):
return {
"IslandGenerationDistance": self.world.island_generation_distance[self.player].value,
- "ExpensiveResearch": self.world.expensive_research[self.player].value
+ "ExpensiveResearch": bool(self.world.expensive_research[self.player].value),
+ "DeathLink": bool(self.world.death_link[self.player].value)
}
def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None):
diff --git a/worlds/raft/docs/en_Raft.md b/worlds/raft/docs/en_Raft.md
index adcf5ea6cb..385377d456 100644
--- a/worlds/raft/docs/en_Raft.md
+++ b/worlds/raft/docs/en_Raft.md
@@ -22,7 +22,7 @@ Decoration Packages are unchanged.
Researches and pickups remain visually unchanged, regardless of what the unlock is.
## When the player receives an item, what happens?
-A Raft notification will appear with the item information. The unlock will also appear in the chat. Unlocks that would normally give you the item (eg Machete) will NOT give it to you, but must instead be crafted.
+A Raft notification will appear with the item information. The unlock will also appear in the chat. Unlocks that would normally give you the item (eg Zipline) will NOT give it to you, but must instead be crafted.
## Are there any limitations compared to vanilla Raft?
- Mods that add new researchable technologies, modify story islands, or give items like blueprints are likely incompatible with Raftipelago.
diff --git a/worlds/raft/docs/setup_en.md b/worlds/raft/docs/setup_en.md
index ad69eacdf8..4d84ef0f65 100644
--- a/worlds/raft/docs/setup_en.md
+++ b/worlds/raft/docs/setup_en.md
@@ -4,23 +4,50 @@
- [Raft](https://store.steampowered.com/app/648800/Raft/)
- [Raft Mod Loader](https://www.raftmodding.com/loader) ("*RML*")
+- [ModUtils mod](https://www.raftmodding.com/mods/modutils)
- [Raftipelago mod](https://www.raftmodding.com/mods/raftipelago)
## Installation Procedures
-1. Install Raft. The currently-supported Raft version is Version 1.0: The Final Chapter. If you plan on playing Raft mainly with Archipelago, it's recommended to disable Raft auto-updating through Steam, as there is no beta channel to get old builds.
+1. Install Raft. The currently-supported Raft version is Version 1.0: The Final Chapter. Any minor version (such as 1.08) should be compatible.
2. Install RML.
-3. Install the Raftipelago mod from the Raft Modding website. You should open the auto-installation link on the webpage through RML. Alternatively, you can download the .rmod file and place it in the Mods folder manually.
+3. Install the Raftipelago and ModUtils mods from the Raft Modding website. You should open the auto-installation link on the webpage through RML. Alternatively, you can download the .rmod file and place it in the Mods folder manually.
-4. Open RML and click Play. If you've already installed it, the shortcut in the Start Menu is called "RMLLauncher.exe". Raft should start.
+4. Open RML and click Play. If you've already installed it, the executable that was used to install RML ("RMLLauncher.exe" unless renamed) should be used to run RML. Raft should start after clicking Play.
5. Open the RML menu. This should open automatically when Raft first loads. If it does not, and you see RML information in the top center of the Raft main menu, press F9 to open it.
6. Navigate to the "Mod manager" tab in the left-hand menu.
-7. Click on the plug icon for Raftipelago to load the mod.
+7. Click on the plug icon for ModUtils to load the mod. You can also click on the (i) next to the plug icon, then check the "Load this mod at startup" button. This will make the mod always load at startup.
+
+8. Click on the plug icon for Raftipelago to load the mod. While it's possible to also make this mod load at startup, it's recommended *not* to do so; if this mod loads before ModUtils, the mod will fail to load properly.
+
+## Joining a MultiWorld Game
+
+1. Ensure you're on the Main Menu with Raftipelago loaded.
+
+2. Open the Debug Console by pressing F10.
+
+3. Type */connect {serverAddress} {username} {password}* into the console and hit Enter.
+ - Example: */connect archipelago.gg:12345 SunnyBat*
+ - If there is no password, the password argument may be omitted (as is the case in the above example).
+ - serverAddress must not contain spaces.
+ - If your username or password contains spaces, surround that value with quotation marks ("). Adding quotation marks even when not necessary (eg "SunnyBat") is fine.
+ - If your username or password starts with a quotation mark, surround the value with an additional set of quotation marks (eg the value *"myP@s$w0rD* would be entered as *""myP@s$w0rD"*).
+
+4. Start a new game or load an existing one. It's recommended to avoid using an existing game that was not created with your current run of Raftipelago (either vanilla or a different Raftipelago run). It will work, but if anything is unlocked, it will be automatically registered with Archipelago once the world is loaded. This is irreversible.
+
+5. You can disconnect from an Archipelago server by typing */disconnect confirmDisconnect* into the console and hitting Enter.
+
+## Multiplayer Raft
+
+You're able to have multiple Raft players on a single Raftipelago world. This will work, with a few notes:
+- Only the player that creates/loads the world can connect to Archipelago (this is the "host" of the Raft world). Other players do not need to connect; everything will be routed through the the host.
+- Players other than the host will be labeled as a "Raft Player (Steam name)" when using ingame chat, which will be routed through Archipelago chat.
+- Ingame chat will only work when the host is connected to the Archipelago server.
## Installation Troubleshooting
@@ -45,38 +72,12 @@ If this happens, then RML is configured to only start a new instance of Raft, th
You can either:
- Close the existing instance of Raft then click Play
- Check the box next to the "Disable Automatic Game Start" setting in the Settings menu then click Play.
-
-## Joining a MultiWorld Game
-
-1. Ensure you're on the Main Menu with Raftipelago loaded.
-
-2. Open the Debug Console by pressing F10.
-
-3. Type */connect {serverAddress} {username} {password}* into the console and hit Enter.
- - Example: */connect archipelago.gg:12345 SunnyBat*
- - serverAddress must not contain spaces.
- - If your username or password contains spaces, surround that value with quotation marks ("). Adding quotation marks even when not necessary (eg "SunnyBat") is fine.
- - If your username or password starts with a quotation mark, surround the value with an additional set of quotation marks (eg the value *"myP@s$w0rD* would be entered as *""myP@s$w0rD"*).
-
-4. Start a new game or load an existing one.
- - Raftipelago save games are marked as *incompatible* with vanilla Raft. This means when Raftipelago is not loaded, saves made with Raftipelago will show as corrupt/unselectable.
- - Avoid using an existing game that was not created with your current run of Raftipelago (either vanilla or a different Raftipelago run). It will work, but if anything is unlocked, it will be automatically registered with Archipelago once the world is loaded. This is irreversible.
-
-5. You can disconnect from an Archipelago server by typing */disconnect confirmDisconnect* into the console and hitting Enter.
-
-## Multiplayer Raft
-
-You're able to have multiple Raft players on a single Raftipelago world. This will work, with a few notes:
-- Only the player that creates/loads the world can connect to Archipelago (this is the "host" of the Raft world). Other players do not need to connect; everything will be routed through the the host.
-- Resource Packs are only received by the host and any other players connected to the Raft world when the resource pack is received.
-- Players other than the host will be labeled as a "Raft Player (Steam name)" when using ingame chat, which will be routed through Archipelago chat.
-- Ingame chat will only work when the host is connected to the Archipelago server.
## Game Troubleshooting
### The "Load game" button is disabled for my world / my world is corrupt
-Be sure that you click the "Load game" button **after** you load Raftipelago. You can click the Load Game button again to reload all of the saves in your folder (there is no need to restart Raft if the mod loaded successfully).
+Be sure that you click the "Load game" button **after** you load Raftipelago. You can click the Load Game button again to refresh all of the saves in your folder (there is no need to restart Raft if the mod loaded successfully).
### I'm certain I'm doing things correctly, but the world is still not loadable
diff --git a/worlds/raft/regions.json b/worlds/raft/regions.json
index b2737a1298..e593a0ab61 100644
--- a/worlds/raft/regions.json
+++ b/worlds/raft/regions.json
@@ -1,12 +1,12 @@
{
- "Raft": ["RadioTower", "ResearchTable"],
+ "Raft": ["ResearchTable", "RadioTower", "Vasagatan", "BalboaIsland", "CaravanIsland", "Tangaroa", "Varuna Point", "Temperance", "Utopia"],
"ResearchTable": [],
- "RadioTower": ["Vasagatan"],
- "Vasagatan": ["BalboaIsland"],
- "BalboaIsland": ["CaravanIsland"],
- "CaravanIsland": ["Tangaroa"],
- "Tangaroa": ["Varuna Point"],
- "Varuna Point": ["Temperance"],
- "Temperance": ["Utopia"],
+ "RadioTower": [],
+ "Vasagatan": [],
+ "BalboaIsland": [],
+ "CaravanIsland": [],
+ "Tangaroa": [],
+ "Varuna Point": [],
+ "Temperance": [],
"Utopia": []
}
\ No newline at end of file
diff --git a/worlds/sa2b/__init__.py b/worlds/sa2b/__init__.py
index 84a38f221c..ea24809521 100644
--- a/worlds/sa2b/__init__.py
+++ b/worlds/sa2b/__init__.py
@@ -46,7 +46,7 @@ def check_for_impossible_shuffle(shuffled_levels: typing.List[int], gate_0_range
class SA2BWorld(World):
"""
- Sonic Adventure 2 Battle is an action platforming game. Play as Sonic, Tails, Knuckles, Shadow, Rogue, and Eggman across 31 stages and prevent the destruction of the earth.
+ Sonic Adventure 2 Battle is an action platforming game. Play as Sonic, Tails, Knuckles, Shadow, Rouge, and Eggman across 31 stages and prevent the destruction of the earth.
"""
game: str = "Sonic Adventure 2 Battle"
option_definitions = sa2b_options
@@ -282,8 +282,7 @@ class SA2BWorld(World):
spoiler_handle.writelines(text)
@classmethod
- def stage_fill_hook(cls, world, progitempool, nonexcludeditempool, localrestitempool, nonlocalrestitempool,
- restitempool, fill_locations):
+ def stage_fill_hook(cls, world, progitempool, usefulitempool, filleritempool, fill_locations):
if world.get_game_players("Sonic Adventure 2 Battle"):
progitempool.sort(
key=lambda item: 0 if (item.name != 'Emblem') else 1)
diff --git a/worlds/sc2wol/Items.py b/worlds/sc2wol/Items.py
index 8da40de5ab..6bb74076fb 100644
--- a/worlds/sc2wol/Items.py
+++ b/worlds/sc2wol/Items.py
@@ -163,3 +163,17 @@ filler_items: typing.Tuple[str, ...] = (
lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in get_full_item_list().items() if
data.code}
+# Map type to expected int
+type_flaggroups: typing.Dict[str, int] = {
+ "Unit": 0,
+ "Upgrade": 1,
+ "Armory 1": 2,
+ "Armory 2": 3,
+ "Building": 4,
+ "Mercenary": 5,
+ "Laboratory": 6,
+ "Protoss": 7,
+ "Minerals": 8,
+ "Vespene": 9,
+ "Supply": 10,
+}
diff --git a/worlds/sm/Options.py b/worlds/sm/Options.py
index 814b19f4d4..2f0c70a242 100644
--- a/worlds/sm/Options.py
+++ b/worlds/sm/Options.py
@@ -122,8 +122,6 @@ class AreaRandomization(Choice):
option_off = 0
option_light = 1
option_on = 2
- alias_false = 0
- alias_true = 2
default = 0
class AreaLayout(Toggle):
diff --git a/worlds/sm/__init__.py b/worlds/sm/__init__.py
index fbf3825e0f..0bf12ca7eb 100644
--- a/worlds/sm/__init__.py
+++ b/worlds/sm/__init__.py
@@ -660,8 +660,7 @@ class SMWorld(World):
loc.address = loc.item.code = None
@classmethod
- def stage_fill_hook(cls, world, progitempool, nonexcludeditempool, localrestitempool, nonlocalrestitempool,
- restitempool, fill_locations):
+ def stage_fill_hook(cls, world, progitempool, usefulitempool, filleritempool, fill_locations):
if world.get_game_players("Super Metroid"):
progitempool.sort(
key=lambda item: 1 if (item.name == 'Morph Ball') else 0)
diff --git a/worlds/sm/data/SMBasepatch_prebuilt/multiworld-basepatch.ips b/worlds/sm/data/SMBasepatch_prebuilt/multiworld-basepatch.ips
index 7ac3ea0184..f8fba9b0cf 100644
Binary files a/worlds/sm/data/SMBasepatch_prebuilt/multiworld-basepatch.ips and b/worlds/sm/data/SMBasepatch_prebuilt/multiworld-basepatch.ips differ
diff --git a/worlds/sm/data/SMBasepatch_prebuilt/multiworld.sym b/worlds/sm/data/SMBasepatch_prebuilt/multiworld.sym
index 5def2b7d9c..e507501c86 100644
--- a/worlds/sm/data/SMBasepatch_prebuilt/multiworld.sym
+++ b/worlds/sm/data/SMBasepatch_prebuilt/multiworld.sym
@@ -2,14 +2,14 @@
; generated by asar
[labels]
-B8:80C1 :neg_1_1
+B8:83C1 :neg_1_1
85:B9B4 :neg_1_2
85:B9E6 :neg_1_3
B8:C81F :neg_1_4
B8:C831 :neg_1_5
B8:C843 :neg_1_6
-B8:800C :pos_1_0
-B8:82D7 :pos_1_1
+B8:830C :pos_1_0
+B8:85D7 :pos_1_1
84:FA6B :pos_1_2
84:FA75 :pos_1_3
B8:C862 :pos_1_4
@@ -20,7 +20,7 @@ B8:C87C :pos_1_6
85:990F CLIPLEN_end
85:990C CLIPLEN_no_multi
85:FF1D CLIPSET
-B8:81E8 COLLECTTANK
+B8:84E8 COLLECTTANK
85:FF45 MISCFX
84:8BF2 NORMAL
85:FF4E SETFX
@@ -38,11 +38,11 @@ CE:FF00 config_multiworld
CE:FF08 config_player_id
CE:FF06 config_remote_items
CE:FF02 config_sprite
-B8:8119 copy_config_to_sram
-B8:80FD copy_memory
-B8:8117 copy_memory_done
-B8:8109 copy_memory_even
-B8:810F copy_memory_loop
+B8:8419 copy_config_to_sram
+B8:83FD copy_memory
+B8:8417 copy_memory_done
+B8:8409 copy_memory_even
+B8:840F copy_memory_loop
84:F894 h_item
84:F8AD i_chozo_item
84:F8B4 i_hidden_item
@@ -51,11 +51,11 @@ B8:885C i_item_setup_shared
B8:8878 i_item_setup_shared_all_items
B8:8883 i_item_setup_shared_alwaysloaded
84:FA79 i_live_pickup
-B8:8278 i_live_pickup_multiworld
-B8:82BD i_live_pickup_multiworld_end
-B8:8294 i_live_pickup_multiworld_local_item_or_offworld
-B8:82A9 i_live_pickup_multiworld_own_item
-B8:82B5 i_live_pickup_multiworld_own_item1
+B8:8578 i_live_pickup_multiworld
+B8:85BD i_live_pickup_multiworld_end
+B8:8594 i_live_pickup_multiworld_local_item_or_offworld
+B8:85A9 i_live_pickup_multiworld_own_item
+B8:85B5 i_live_pickup_multiworld_own_item1
84:FA1E i_load_custom_graphics
84:FA39 i_load_custom_graphics_all_items
84:FA49 i_load_custom_graphics_alwaysloaded
@@ -90,27 +90,27 @@ B8:82B5 i_live_pickup_multiworld_own_item1
85:B9CA message_write_placeholders_loop
85:B9DC message_write_placeholders_notfound
85:B9DF message_write_placeholders_value_ok
-B8:818B mw_display_item_sent
-B8:81F8 mw_handle_queue
-B8:8271 mw_handle_queue_end
-B8:81FA mw_handle_queue_loop
-B8:824A mw_handle_queue_new_remote_item
-B8:8266 mw_handle_queue_next
-B8:825C mw_handle_queue_perform_receive
-B8:82C1 mw_hook_main_game
-B8:8011 mw_init
-B8:8066 mw_init_continuereset
-B8:80EA mw_init_end
-B8:8000 mw_init_memory
-B8:803B mw_init_reset_sram
-B8:8051 mw_init_smstringdata
-B8:8174 mw_load_sram
-B8:8182 mw_load_sram_done
-B8:8185 mw_load_sram_setnewgame
-B8:81A9 mw_receive_item
-B8:81E1 mw_receive_item_end
-B8:8169 mw_save_sram
-B8:8142 mw_write_message
+B8:848B mw_display_item_sent
+B8:84F8 mw_handle_queue
+B8:8571 mw_handle_queue_end
+B8:84FA mw_handle_queue_loop
+B8:854A mw_handle_queue_new_remote_item
+B8:8566 mw_handle_queue_next
+B8:855C mw_handle_queue_perform_receive
+B8:85C1 mw_hook_main_game
+B8:8311 mw_init
+B8:8366 mw_init_continuereset
+B8:83EA mw_init_end
+B8:8300 mw_init_memory
+B8:833B mw_init_reset_sram
+B8:8351 mw_init_smstringdata
+B8:8474 mw_load_sram
+B8:8482 mw_load_sram_done
+B8:8485 mw_load_sram_setnewgame
+B8:84A9 mw_receive_item
+B8:84E1 mw_receive_item_end
+B8:8469 mw_save_sram
+B8:8442 mw_write_message
84:F888 nonprog_item_eight_palette_indices
89:9200 offworld_graphics_data_item
89:9100 offworld_graphics_data_progression_item
@@ -135,7 +135,7 @@ B8:8142 mw_write_message
84:F96E p_visible_item_end
84:F95B p_visible_item_loop
84:F967 p_visible_item_trigger
-B8:82D8 patch_load_multiworld
+B8:85D8 patch_load_multiworld
84:FA7E perform_item_pickup
84:F886 plm_graphics_entry_offworld_item
84:F87C plm_graphics_entry_offworld_progression_item
@@ -154,19 +154,19 @@ B8:C808 start_item_data_minor
B8:C818 start_item_data_reserve
B8:C856 update_graphic
84:F890 v_item
-B8:80EF write_repeated_memory
-B8:80F4 write_repeated_memory_loop
+B8:83EF write_repeated_memory
+B8:83F4 write_repeated_memory_loop
[source files]
-0000 e25029c5 main.asm
+0000 f30c3fdc main.asm
0001 06780555 ../common/nofanfare.asm
0002 4f9a780e ../common/multiworld.asm
-0003 613d24e1 ../common/itemextras.asm
+0003 f7e9db95 ../common/itemextras.asm
0004 d6616c0c ../common/items.asm
-0005 440b54fe ../common/startitem.asm
+0005 dbfcb38d ../common/startitem.asm
[rom checksum]
-ad81eda1
+b526d5c7
[addr-to-line mapping]
ff:ffff 0000:00000001
@@ -216,316 +216,316 @@ ff:ffff 0000:00000001
84:8bf2 0001:00000152
84:8bf6 0001:00000153
84:8bf7 0001:00000153
-b8:8000 0002:0000005a
-b8:8002 0002:0000005b
-b8:8006 0002:0000005c
-b8:8008 0002:0000005d
-b8:800c 0002:00000061
-b8:800e 0002:00000062
-b8:8010 0002:00000063
-b8:8011 0002:00000066
-b8:8012 0002:00000066
-b8:8013 0002:00000066
-b8:8014 0002:00000066
-b8:8015 0000:00000013
-b8:8017 0002:0000006a
-b8:801b 0002:0000006b
-b8:801e 0002:0000006c
-b8:8020 0002:0000006d
-b8:8024 0002:0000006e
-b8:8028 0002:0000006f
-b8:802a 0002:00000070
-b8:802e 0002:00000071
-b8:8032 0002:00000072
-b8:8034 0002:00000074
-b8:8038 0002:00000075
-b8:803b 0002:00000078
-b8:803c 0002:00000079
-b8:803f 0002:0000007a
-b8:8042 0002:0000007b
-b8:8045 0002:0000007c
-b8:8048 0002:0000007d
-b8:8049 0002:0000007e
-b8:804a 0002:0000007f
-b8:804e 0002:00000080
-b8:804f 0002:00000082
-b8:8066 0002:00000086
-b8:8068 0002:00000087
-b8:8069 0002:00000088
-b8:806a 0002:00000089
-b8:806c 0002:0000008a
-b8:806e 0002:0000008b
-b8:8070 0002:0000008c
-b8:8072 0002:0000008d
-b8:8075 0002:0000008e
-b8:8077 0002:0000008f
-b8:807a 0002:00000090
-b8:807d 0002:00000091
-b8:807f 0002:00000092
-b8:8083 0002:00000094
-b8:8085 0002:00000095
-b8:8087 0002:00000096
-b8:8089 0002:00000097
-b8:808b 0002:00000098
-b8:808d 0002:00000099
-b8:808f 0002:0000009a
-b8:8092 0002:0000009b
-b8:8094 0002:0000009c
-b8:8097 0002:0000009d
-b8:809a 0002:0000009e
-b8:809c 0002:0000009f
-b8:80a0 0002:000000a1
-b8:80a3 0002:000000a2
-b8:80a7 0002:000000a3
-b8:80ab 0002:000000a4
-b8:80af 0002:000000a5
-b8:80b3 0002:000000a6
-b8:80b7 0002:000000a8
-b8:80bb 0002:000000b0
-b8:80be 0002:000000b1
-b8:80c1 0002:000000b3
-b8:80c2 0002:000000b4
-b8:80c3 0002:000000b5
-b8:80c7 0002:000000b6
-b8:80cb 0002:000000b7
-b8:80cd 0002:000000c4
-b8:80d1 0002:000000c5
-b8:80d4 0002:000000c6
-b8:80d6 0002:000000c7
-b8:80da 0002:000000c8
-b8:80dd 0002:000000c9
-b8:80df 0002:000000ce
-b8:80e2 0002:000000cf
-b8:80e6 0002:000000d0
-b8:80ea 0002:000000d3
-b8:80eb 0002:000000d3
-b8:80ec 0002:000000d3
-b8:80ed 0002:000000d3
-b8:80ee 0002:000000d4
-b8:80ef 0002:000000db
-b8:80f0 0002:000000dc
-b8:80f1 0002:000000dd
-b8:80f2 0002:000000de
-b8:80f3 0002:000000df
-b8:80f4 0002:000000e1
-b8:80f7 0002:000000e2
-b8:80f8 0002:000000e3
-b8:80f9 0002:000000e4
-b8:80fa 0002:000000e5
-b8:80fc 0002:000000e7
-b8:80fd 0002:000000ee
-b8:80fe 0002:000000ef
-b8:80ff 0002:000000f0
-b8:8100 0002:000000f1
-b8:8102 0002:000000f3
-b8:8104 0002:000000f4
-b8:8105 0002:000000f5
-b8:8107 0002:000000f6
-b8:8109 0002:000000f8
-b8:810b 0002:000000f9
-b8:810c 0002:000000fa
-b8:810d 0002:000000fb
-b8:810f 0002:000000fd
-b8:8111 0002:000000fe
-b8:8113 0002:000000ff
-b8:8114 0002:00000100
-b8:8115 0002:00000101
-b8:8117 0002:00000103
-b8:8118 0002:00000104
-b8:8119 0002:00000108
-b8:811d 0002:00000109
-b8:8121 0002:0000010a
-b8:8125 0002:0000010b
-b8:8129 0002:0000010c
-b8:812d 0002:0000010d
-b8:8131 0002:0000010e
-b8:8135 0002:0000010f
-b8:8139 0002:00000110
-b8:813d 0002:00000111
-b8:8141 0002:00000112
-b8:8142 0002:00000118
-b8:8143 0002:00000118
-b8:8144 0002:00000119
-b8:8145 0002:00000119
-b8:8146 0002:0000011a
-b8:814a 0002:0000011b
-b8:814d 0002:0000011b
-b8:814e 0002:0000011c
-b8:814f 0002:0000011d
-b8:8153 0002:0000011e
-b8:8154 0002:0000011f
-b8:8158 0002:00000120
-b8:8159 0002:00000121
-b8:815d 0002:00000123
-b8:8161 0002:00000124
-b8:8162 0002:00000125
-b8:8166 0002:00000126
-b8:8167 0002:00000126
-b8:8168 0002:00000127
-b8:8169 0002:0000012c
-b8:816a 0002:0000012c
-b8:816b 0000:00000013
-b8:816d 0002:0000012f
-b8:816e 0002:0000012f
-b8:816f 0002:00000131
-b8:8170 0002:00000132
-b8:8173 0002:00000133
-b8:8174 0002:00000138
-b8:8175 0002:00000138
-b8:8176 0000:00000013
-b8:8178 0002:0000013a
-b8:817c 0002:0000013b
-b8:8180 0002:0000013c
-b8:8182 0002:0000013e
-b8:8183 0002:0000013e
-b8:8184 0002:0000013f
-b8:8185 0002:00000147
-b8:8189 0002:00000148
-b8:818b 0002:0000014e
-b8:818d 0002:0000014f
-b8:818f 0002:00000152
-b8:8192 0002:00000153
-b8:8194 0002:00000154
-b8:8197 0002:00000155
-b8:8199 0002:00000156
-b8:819c 0002:00000157
-b8:81a0 0002:00000158
-b8:81a2 0002:00000159
-b8:81a4 0002:0000015a
-b8:81a6 0002:0000015b
-b8:81a8 0002:0000015c
-b8:81a9 0002:00000160
-b8:81aa 0002:00000160
-b8:81ab 0002:00000161
-b8:81ae 0002:00000162
-b8:81b0 0002:00000163
-b8:81b3 0002:00000164
-b8:81b5 0002:00000165
-b8:81b6 0002:00000166
-b8:81b7 0002:00000168
-b8:81ba 0002:00000169
-b8:81bc 0002:0000016a
-b8:81bf 0002:0000016b
-b8:81c0 0002:0000016c
-b8:81c3 0002:0000016d
-b8:81c4 0002:0000016d
-b8:81c5 0002:0000016e
-b8:81c9 0002:0000016f
-b8:81ca 0002:00000170
-b8:81cd 0002:00000171
-b8:81d1 0002:00000172
-b8:81d3 0002:00000174
-b8:81d6 0002:00000175
-b8:81d8 0002:00000176
-b8:81db 0002:00000177
-b8:81dd 0002:00000179
-b8:81e1 0002:0000017b
-b8:81e3 0002:0000017c
-b8:81e5 0002:0000017d
-b8:81e6 0002:0000017d
-b8:81e7 0002:0000017e
-b8:81e8 0002:00000189
-b8:81e9 0002:0000018a
-b8:81ed 0002:0000018b
-b8:81ee 0002:0000018c
-b8:81f2 0002:0000018d
-b8:81f3 0002:0000018f
-b8:81f7 0002:00000190
-b8:81f8 0002:000001c2
-b8:81f9 0002:000001c2
-b8:81fa 0002:000001c5
-b8:81fe 0002:000001c6
-b8:8202 0002:000001c7
-b8:8204 0002:000001c9
-b8:8206 0002:000001c9
-b8:8207 0002:000001cc
-b8:820b 0002:000001cd
-b8:820d 0002:000001ce
-b8:8211 0002:000001cf
-b8:8213 0002:000001d0
-b8:8217 0002:000001d1
-b8:821a 0002:000001d2
-b8:821c 0002:000001d3
-b8:821e 0002:000001d4
-b8:8222 0002:000001d5
-b8:8224 0002:000001d6
-b8:8226 0002:000001d7
-b8:8229 0002:000001d8
-b8:822c 0002:000001d9
-b8:822e 0002:000001da
-b8:8236 0002:000001de
-b8:8237 0002:000001df
-b8:8238 0002:000001e0
-b8:823c 0002:000001e3
-b8:8240 0002:000001e4
-b8:8244 0002:000001e5
-b8:8246 0002:000001e7
-b8:8247 0002:000001e8
-b8:8248 0002:000001e9
-b8:824a 0002:000001ee
-b8:824b 0002:000001ef
-b8:824f 0002:000001f2
-b8:8253 0002:000001f3
-b8:8257 0002:000001f4
-b8:825b 0002:000001f5
-b8:825c 0002:000001f9
-b8:825e 0002:000001fa
-b8:8261 0002:000001fb
-b8:8263 0002:000001fc
-b8:8266 0002:000001ff
-b8:826a 0002:00000200
-b8:826b 0002:00000201
-b8:826f 0002:00000203
-b8:8271 0002:00000206
-b8:8273 0002:00000207
-b8:8275 0002:00000208
-b8:8276 0002:00000208
-b8:8277 0002:00000209
-b8:8278 0002:0000020d
-b8:8279 0002:0000020d
-b8:827a 0002:0000020d
-b8:827b 0002:0000020e
-b8:827f 0002:0000020f
-b8:8282 0002:0000020f
-b8:8283 0002:00000211
-b8:8287 0002:00000212
-b8:8288 0002:00000213
-b8:828c 0002:00000214
-b8:828f 0002:00000215
-b8:8291 0002:00000217
-b8:8294 0002:0000021a
-b8:8298 0002:0000021b
-b8:829c 0002:0000021c
-b8:829e 0002:0000021e
-b8:82a2 0002:0000021f
-b8:82a3 0002:00000221
-b8:82a7 0002:00000222
-b8:82a9 0002:00000225
-b8:82ad 0002:00000226
-b8:82b0 0002:00000227
-b8:82b2 0002:00000228
-b8:82b5 0002:0000022b
-b8:82b6 0002:0000022c
-b8:82b7 0002:0000022d
-b8:82bb 0002:0000022e
-b8:82bd 0002:00000231
-b8:82be 0002:00000231
-b8:82bf 0002:00000231
-b8:82c0 0002:00000232
-b8:82c1 0002:00000236
-b8:82c5 0002:00000237
-b8:82c9 0002:00000238
-b8:82cb 0002:00000239
-b8:82cf 0002:0000023a
-b8:82d2 0002:0000023b
-b8:82d4 0002:0000023c
-b8:82d7 0002:0000023e
-b8:82d8 0002:00000241
-b8:82dc 0002:00000243
-b8:82dd 0002:00000244
-b8:82de 0002:00000245
-b8:82df 0002:00000246
-b8:82e0 0002:00000247
+b8:8300 0002:0000005a
+b8:8302 0002:0000005b
+b8:8306 0002:0000005c
+b8:8308 0002:0000005d
+b8:830c 0002:00000061
+b8:830e 0002:00000062
+b8:8310 0002:00000063
+b8:8311 0002:00000066
+b8:8312 0002:00000066
+b8:8313 0002:00000066
+b8:8314 0002:00000066
+b8:8315 0000:00000013
+b8:8317 0002:0000006a
+b8:831b 0002:0000006b
+b8:831e 0002:0000006c
+b8:8320 0002:0000006d
+b8:8324 0002:0000006e
+b8:8328 0002:0000006f
+b8:832a 0002:00000070
+b8:832e 0002:00000071
+b8:8332 0002:00000072
+b8:8334 0002:00000074
+b8:8338 0002:00000075
+b8:833b 0002:00000078
+b8:833c 0002:00000079
+b8:833f 0002:0000007a
+b8:8342 0002:0000007b
+b8:8345 0002:0000007c
+b8:8348 0002:0000007d
+b8:8349 0002:0000007e
+b8:834a 0002:0000007f
+b8:834e 0002:00000080
+b8:834f 0002:00000082
+b8:8366 0002:00000086
+b8:8368 0002:00000087
+b8:8369 0002:00000088
+b8:836a 0002:00000089
+b8:836c 0002:0000008a
+b8:836e 0002:0000008b
+b8:8370 0002:0000008c
+b8:8372 0002:0000008d
+b8:8375 0002:0000008e
+b8:8377 0002:0000008f
+b8:837a 0002:00000090
+b8:837d 0002:00000091
+b8:837f 0002:00000092
+b8:8383 0002:00000094
+b8:8385 0002:00000095
+b8:8387 0002:00000096
+b8:8389 0002:00000097
+b8:838b 0002:00000098
+b8:838d 0002:00000099
+b8:838f 0002:0000009a
+b8:8392 0002:0000009b
+b8:8394 0002:0000009c
+b8:8397 0002:0000009d
+b8:839a 0002:0000009e
+b8:839c 0002:0000009f
+b8:83a0 0002:000000a1
+b8:83a3 0002:000000a2
+b8:83a7 0002:000000a3
+b8:83ab 0002:000000a4
+b8:83af 0002:000000a5
+b8:83b3 0002:000000a6
+b8:83b7 0002:000000a8
+b8:83bb 0002:000000b0
+b8:83be 0002:000000b1
+b8:83c1 0002:000000b3
+b8:83c2 0002:000000b4
+b8:83c3 0002:000000b5
+b8:83c7 0002:000000b6
+b8:83cb 0002:000000b7
+b8:83cd 0002:000000c4
+b8:83d1 0002:000000c5
+b8:83d4 0002:000000c6
+b8:83d6 0002:000000c7
+b8:83da 0002:000000c8
+b8:83dd 0002:000000c9
+b8:83df 0002:000000ce
+b8:83e2 0002:000000cf
+b8:83e6 0002:000000d0
+b8:83ea 0002:000000d3
+b8:83eb 0002:000000d3
+b8:83ec 0002:000000d3
+b8:83ed 0002:000000d3
+b8:83ee 0002:000000d4
+b8:83ef 0002:000000db
+b8:83f0 0002:000000dc
+b8:83f1 0002:000000dd
+b8:83f2 0002:000000de
+b8:83f3 0002:000000df
+b8:83f4 0002:000000e1
+b8:83f7 0002:000000e2
+b8:83f8 0002:000000e3
+b8:83f9 0002:000000e4
+b8:83fa 0002:000000e5
+b8:83fc 0002:000000e7
+b8:83fd 0002:000000ee
+b8:83fe 0002:000000ef
+b8:83ff 0002:000000f0
+b8:8400 0002:000000f1
+b8:8402 0002:000000f3
+b8:8404 0002:000000f4
+b8:8405 0002:000000f5
+b8:8407 0002:000000f6
+b8:8409 0002:000000f8
+b8:840b 0002:000000f9
+b8:840c 0002:000000fa
+b8:840d 0002:000000fb
+b8:840f 0002:000000fd
+b8:8411 0002:000000fe
+b8:8413 0002:000000ff
+b8:8414 0002:00000100
+b8:8415 0002:00000101
+b8:8417 0002:00000103
+b8:8418 0002:00000104
+b8:8419 0002:00000108
+b8:841d 0002:00000109
+b8:8421 0002:0000010a
+b8:8425 0002:0000010b
+b8:8429 0002:0000010c
+b8:842d 0002:0000010d
+b8:8431 0002:0000010e
+b8:8435 0002:0000010f
+b8:8439 0002:00000110
+b8:843d 0002:00000111
+b8:8441 0002:00000112
+b8:8442 0002:00000118
+b8:8443 0002:00000118
+b8:8444 0002:00000119
+b8:8445 0002:00000119
+b8:8446 0002:0000011a
+b8:844a 0002:0000011b
+b8:844d 0002:0000011b
+b8:844e 0002:0000011c
+b8:844f 0002:0000011d
+b8:8453 0002:0000011e
+b8:8454 0002:0000011f
+b8:8458 0002:00000120
+b8:8459 0002:00000121
+b8:845d 0002:00000123
+b8:8461 0002:00000124
+b8:8462 0002:00000125
+b8:8466 0002:00000126
+b8:8467 0002:00000126
+b8:8468 0002:00000127
+b8:8469 0002:0000012c
+b8:846a 0002:0000012c
+b8:846b 0000:00000013
+b8:846d 0002:0000012f
+b8:846e 0002:0000012f
+b8:846f 0002:00000131
+b8:8470 0002:00000132
+b8:8473 0002:00000133
+b8:8474 0002:00000138
+b8:8475 0002:00000138
+b8:8476 0000:00000013
+b8:8478 0002:0000013a
+b8:847c 0002:0000013b
+b8:8480 0002:0000013c
+b8:8482 0002:0000013e
+b8:8483 0002:0000013e
+b8:8484 0002:0000013f
+b8:8485 0002:00000147
+b8:8489 0002:00000148
+b8:848b 0002:0000014e
+b8:848d 0002:0000014f
+b8:848f 0002:00000152
+b8:8492 0002:00000153
+b8:8494 0002:00000154
+b8:8497 0002:00000155
+b8:8499 0002:00000156
+b8:849c 0002:00000157
+b8:84a0 0002:00000158
+b8:84a2 0002:00000159
+b8:84a4 0002:0000015a
+b8:84a6 0002:0000015b
+b8:84a8 0002:0000015c
+b8:84a9 0002:00000160
+b8:84aa 0002:00000160
+b8:84ab 0002:00000161
+b8:84ae 0002:00000162
+b8:84b0 0002:00000163
+b8:84b3 0002:00000164
+b8:84b5 0002:00000165
+b8:84b6 0002:00000166
+b8:84b7 0002:00000168
+b8:84ba 0002:00000169
+b8:84bc 0002:0000016a
+b8:84bf 0002:0000016b
+b8:84c0 0002:0000016c
+b8:84c3 0002:0000016d
+b8:84c4 0002:0000016d
+b8:84c5 0002:0000016e
+b8:84c9 0002:0000016f
+b8:84ca 0002:00000170
+b8:84cd 0002:00000171
+b8:84d1 0002:00000172
+b8:84d3 0002:00000174
+b8:84d6 0002:00000175
+b8:84d8 0002:00000176
+b8:84db 0002:00000177
+b8:84dd 0002:00000179
+b8:84e1 0002:0000017b
+b8:84e3 0002:0000017c
+b8:84e5 0002:0000017d
+b8:84e6 0002:0000017d
+b8:84e7 0002:0000017e
+b8:84e8 0002:00000189
+b8:84e9 0002:0000018a
+b8:84ed 0002:0000018b
+b8:84ee 0002:0000018c
+b8:84f2 0002:0000018d
+b8:84f3 0002:0000018f
+b8:84f7 0002:00000190
+b8:84f8 0002:000001c2
+b8:84f9 0002:000001c2
+b8:84fa 0002:000001c5
+b8:84fe 0002:000001c6
+b8:8502 0002:000001c7
+b8:8504 0002:000001c9
+b8:8506 0002:000001c9
+b8:8507 0002:000001cc
+b8:850b 0002:000001cd
+b8:850d 0002:000001ce
+b8:8511 0002:000001cf
+b8:8513 0002:000001d0
+b8:8517 0002:000001d1
+b8:851a 0002:000001d2
+b8:851c 0002:000001d3
+b8:851e 0002:000001d4
+b8:8522 0002:000001d5
+b8:8524 0002:000001d6
+b8:8526 0002:000001d7
+b8:8529 0002:000001d8
+b8:852c 0002:000001d9
+b8:852e 0002:000001da
+b8:8536 0002:000001de
+b8:8537 0002:000001df
+b8:8538 0002:000001e0
+b8:853c 0002:000001e3
+b8:8540 0002:000001e4
+b8:8544 0002:000001e5
+b8:8546 0002:000001e7
+b8:8547 0002:000001e8
+b8:8548 0002:000001e9
+b8:854a 0002:000001ee
+b8:854b 0002:000001ef
+b8:854f 0002:000001f2
+b8:8553 0002:000001f3
+b8:8557 0002:000001f4
+b8:855b 0002:000001f5
+b8:855c 0002:000001f9
+b8:855e 0002:000001fa
+b8:8561 0002:000001fb
+b8:8563 0002:000001fc
+b8:8566 0002:000001ff
+b8:856a 0002:00000200
+b8:856b 0002:00000201
+b8:856f 0002:00000203
+b8:8571 0002:00000206
+b8:8573 0002:00000207
+b8:8575 0002:00000208
+b8:8576 0002:00000208
+b8:8577 0002:00000209
+b8:8578 0002:0000020d
+b8:8579 0002:0000020d
+b8:857a 0002:0000020d
+b8:857b 0002:0000020e
+b8:857f 0002:0000020f
+b8:8582 0002:0000020f
+b8:8583 0002:00000211
+b8:8587 0002:00000212
+b8:8588 0002:00000213
+b8:858c 0002:00000214
+b8:858f 0002:00000215
+b8:8591 0002:00000217
+b8:8594 0002:0000021a
+b8:8598 0002:0000021b
+b8:859c 0002:0000021c
+b8:859e 0002:0000021e
+b8:85a2 0002:0000021f
+b8:85a3 0002:00000221
+b8:85a7 0002:00000222
+b8:85a9 0002:00000225
+b8:85ad 0002:00000226
+b8:85b0 0002:00000227
+b8:85b2 0002:00000228
+b8:85b5 0002:0000022b
+b8:85b6 0002:0000022c
+b8:85b7 0002:0000022d
+b8:85bb 0002:0000022e
+b8:85bd 0002:00000231
+b8:85be 0002:00000231
+b8:85bf 0002:00000231
+b8:85c0 0002:00000232
+b8:85c1 0002:00000236
+b8:85c5 0002:00000237
+b8:85c9 0002:00000238
+b8:85cb 0002:00000239
+b8:85cf 0002:0000023a
+b8:85d2 0002:0000023b
+b8:85d4 0002:0000023c
+b8:85d7 0002:0000023e
+b8:85d8 0002:00000241
+b8:85dc 0002:00000243
+b8:85dd 0002:00000244
+b8:85de 0002:00000245
+b8:85df 0002:00000246
+b8:85e0 0002:00000247
8b:914a 0002:0000024c
81:80f7 0002:0000024f
81:8027 0002:00000252
diff --git a/worlds/sm/data/SMBasepatch_prebuilt/sm-basepatch-symbols.json b/worlds/sm/data/SMBasepatch_prebuilt/sm-basepatch-symbols.json
index 222548ba1e..949b60f5b0 100644
--- a/worlds/sm/data/SMBasepatch_prebuilt/sm-basepatch-symbols.json
+++ b/worlds/sm/data/SMBasepatch_prebuilt/sm-basepatch-symbols.json
@@ -4,7 +4,7 @@
"CLIPLEN_end": "85:990F",
"CLIPLEN_no_multi": "85:990C",
"CLIPSET": "85:FF1D",
- "COLLECTTANK": "B8:81E8",
+ "COLLECTTANK": "B8:84E8",
"MISCFX": "85:FF45",
"NORMAL": "84:8BF2",
"SETFX": "85:FF4E",
@@ -22,11 +22,11 @@
"config_player_id": "CE:FF08",
"config_remote_items": "CE:FF06",
"config_sprite": "CE:FF02",
- "copy_config_to_sram": "B8:8119",
- "copy_memory": "B8:80FD",
- "copy_memory_done": "B8:8117",
- "copy_memory_even": "B8:8109",
- "copy_memory_loop": "B8:810F",
+ "copy_config_to_sram": "B8:8419",
+ "copy_memory": "B8:83FD",
+ "copy_memory_done": "B8:8417",
+ "copy_memory_even": "B8:8409",
+ "copy_memory_loop": "B8:840F",
"h_item": "84:F894",
"i_chozo_item": "84:F8AD",
"i_hidden_item": "84:F8B4",
@@ -35,11 +35,11 @@
"i_item_setup_shared_all_items": "B8:8878",
"i_item_setup_shared_alwaysloaded": "B8:8883",
"i_live_pickup": "84:FA79",
- "i_live_pickup_multiworld": "B8:8278",
- "i_live_pickup_multiworld_end": "B8:82BD",
- "i_live_pickup_multiworld_local_item_or_offworld": "B8:8294",
- "i_live_pickup_multiworld_own_item": "B8:82A9",
- "i_live_pickup_multiworld_own_item1": "B8:82B5",
+ "i_live_pickup_multiworld": "B8:8578",
+ "i_live_pickup_multiworld_end": "B8:85BD",
+ "i_live_pickup_multiworld_local_item_or_offworld": "B8:8594",
+ "i_live_pickup_multiworld_own_item": "B8:85A9",
+ "i_live_pickup_multiworld_own_item1": "B8:85B5",
"i_load_custom_graphics": "84:FA1E",
"i_load_custom_graphics_all_items": "84:FA39",
"i_load_custom_graphics_alwaysloaded": "84:FA49",
@@ -74,27 +74,27 @@
"message_write_placeholders_loop": "85:B9CA",
"message_write_placeholders_notfound": "85:B9DC",
"message_write_placeholders_value_ok": "85:B9DF",
- "mw_display_item_sent": "B8:818B",
- "mw_handle_queue": "B8:81F8",
- "mw_handle_queue_end": "B8:8271",
- "mw_handle_queue_loop": "B8:81FA",
- "mw_handle_queue_new_remote_item": "B8:824A",
- "mw_handle_queue_next": "B8:8266",
- "mw_handle_queue_perform_receive": "B8:825C",
- "mw_hook_main_game": "B8:82C1",
- "mw_init": "B8:8011",
- "mw_init_continuereset": "B8:8066",
- "mw_init_end": "B8:80EA",
- "mw_init_memory": "B8:8000",
- "mw_init_reset_sram": "B8:803B",
- "mw_init_smstringdata": "B8:8051",
- "mw_load_sram": "B8:8174",
- "mw_load_sram_done": "B8:8182",
- "mw_load_sram_setnewgame": "B8:8185",
- "mw_receive_item": "B8:81A9",
- "mw_receive_item_end": "B8:81E1",
- "mw_save_sram": "B8:8169",
- "mw_write_message": "B8:8142",
+ "mw_display_item_sent": "B8:848B",
+ "mw_handle_queue": "B8:84F8",
+ "mw_handle_queue_end": "B8:8571",
+ "mw_handle_queue_loop": "B8:84FA",
+ "mw_handle_queue_new_remote_item": "B8:854A",
+ "mw_handle_queue_next": "B8:8566",
+ "mw_handle_queue_perform_receive": "B8:855C",
+ "mw_hook_main_game": "B8:85C1",
+ "mw_init": "B8:8311",
+ "mw_init_continuereset": "B8:8366",
+ "mw_init_end": "B8:83EA",
+ "mw_init_memory": "B8:8300",
+ "mw_init_reset_sram": "B8:833B",
+ "mw_init_smstringdata": "B8:8351",
+ "mw_load_sram": "B8:8474",
+ "mw_load_sram_done": "B8:8482",
+ "mw_load_sram_setnewgame": "B8:8485",
+ "mw_receive_item": "B8:84A9",
+ "mw_receive_item_end": "B8:84E1",
+ "mw_save_sram": "B8:8469",
+ "mw_write_message": "B8:8442",
"nonprog_item_eight_palette_indices": "84:F888",
"offworld_graphics_data_item": "89:9200",
"offworld_graphics_data_progression_item": "89:9100",
@@ -119,7 +119,7 @@
"p_visible_item_end": "84:F96E",
"p_visible_item_loop": "84:F95B",
"p_visible_item_trigger": "84:F967",
- "patch_load_multiworld": "B8:82D8",
+ "patch_load_multiworld": "B8:85D8",
"perform_item_pickup": "84:FA7E",
"plm_graphics_entry_offworld_item": "84:F886",
"plm_graphics_entry_offworld_progression_item": "84:F87C",
@@ -138,8 +138,8 @@
"start_item_data_reserve": "B8:C818",
"update_graphic": "B8:C856",
"v_item": "84:F890",
- "write_repeated_memory": "B8:80EF",
- "write_repeated_memory_loop": "B8:80F4",
+ "write_repeated_memory": "B8:83EF",
+ "write_repeated_memory_loop": "B8:83F4",
"ITEM_RAM": "7E:09A2",
"SRAM_MW_ITEMS_RECV": "70:2000",
"SRAM_MW_ITEMS_RECV_WCOUNT": "70:2602",
diff --git a/worlds/sm64ex/Options.py b/worlds/sm64ex/Options.py
index 7d9a75dde9..f29a65c58d 100644
--- a/worlds/sm64ex/Options.py
+++ b/worlds/sm64ex/Options.py
@@ -1,48 +1,57 @@
import typing
from Options import Option, DefaultOnToggle, Range, Toggle, DeathLink, Choice
+
class EnableCoinStars(DefaultOnToggle):
"""Disable to Ignore 100 Coin Stars. You can still collect them, but they don't do anything"""
display_name = "Enable 100 Coin Stars"
+
class StrictCapRequirements(DefaultOnToggle):
"""If disabled, Stars that expect special caps may have to be acquired without the caps"""
display_name = "Strict Cap Requirements"
+
class StrictCannonRequirements(DefaultOnToggle):
"""If disabled, Stars that expect cannons may have to be acquired without them. Only makes a difference if Buddy Checks are enabled"""
display_name = "Strict Cannon Requirements"
+
class FirstBowserStarDoorCost(Range):
"""How many stars are required at the Star Door to Bowser in the Dark World"""
range_start = 0
range_end = 50
default = 8
+
class BasementStarDoorCost(Range):
"""How many stars are required at the Star Door in the Basement"""
range_start = 0
range_end = 70
default = 30
+
class SecondFloorStarDoorCost(Range):
"""How many stars are required to access the third floor"""
range_start = 0
range_end = 90
default = 50
+
class MIPS1Cost(Range):
"""How many stars are required to spawn MIPS the first time"""
range_start = 0
range_end = 40
default = 15
+
class MIPS2Cost(Range):
"""How many stars are required to spawn MIPS the secound time. Must be bigger or equal MIPS1Cost"""
range_start = 0
range_end = 80
default = 50
+
class StarsToFinish(Range):
"""How many stars are required at the infinite stairs"""
display_name = "Endless Stairs Stars"
@@ -50,35 +59,40 @@ class StarsToFinish(Range):
range_end = 100
default = 70
+
class AmountOfStars(Range):
"""How many stars exist. Disabling 100 Coin Stars removes 15 from the Pool. At least max of any Cost set"""
range_start = 35
range_end = 120
default = 120
+
class AreaRandomizer(Choice):
"""Randomize Entrances"""
display_name = "Entrance Randomizer"
- alias_false = 0
option_Off = 0
option_Courses_Only = 1
option_Courses_and_Secrets = 2
+
class BuddyChecks(Toggle):
"""Bob-omb Buddies are checks, Cannon Unlocks are items"""
display_name = "Bob-omb Buddy Checks"
+
class ExclamationBoxes(Choice):
"""Include 1Up Exclamation Boxes during randomization"""
display_name = "Randomize 1Up !-Blocks"
option_Off = 0
option_1Ups_Only = 1
+
class ProgressiveKeys(DefaultOnToggle):
"""Keys will first grant you access to the Basement, then to the Secound Floor"""
display_name = "Progressive Keys"
-sm64_options: typing.Dict[str,type(Option)] = {
+
+sm64_options: typing.Dict[str, type(Option)] = {
"AreaRandomizer": AreaRandomizer,
"ProgressiveKeys": ProgressiveKeys,
"EnableCoinStars": EnableCoinStars,
@@ -93,5 +107,5 @@ sm64_options: typing.Dict[str,type(Option)] = {
"StarsToFinish": StarsToFinish,
"death_link": DeathLink,
"BuddyChecks": BuddyChecks,
- "ExclamationBoxes": ExclamationBoxes
-}
\ No newline at end of file
+ "ExclamationBoxes": ExclamationBoxes,
+}
diff --git a/worlds/sm64ex/Rules.py b/worlds/sm64ex/Rules.py
index eae9868583..2462206246 100644
--- a/worlds/sm64ex/Rules.py
+++ b/worlds/sm64ex/Rules.py
@@ -86,6 +86,7 @@ def set_rules(world, player: int, area_connections):
# which would make it impossible to reach downtown area without the cannon.
add_rule(world.get_location("WDW: Quick Race Through Downtown!", player), lambda state: state.has("Cannon Unlock WDW", player))
add_rule(world.get_location("WDW: Go to Town for Red Coins", player), lambda state: state.has("Cannon Unlock WDW", player))
+ add_rule(world.get_location("WDW: 1Up Block in Downtown", player), lambda state: state.has("Cannon Unlock WDW", player))
if world.StrictCapRequirements[player]:
add_rule(world.get_location("BoB: Mario Wings to the Sky", player), lambda state: state.has("Wing Cap", player))
diff --git a/worlds/sm64ex/__init__.py b/worlds/sm64ex/__init__.py
index cf8a8e875d..88b2261a23 100644
--- a/worlds/sm64ex/__init__.py
+++ b/worlds/sm64ex/__init__.py
@@ -9,6 +9,7 @@ from .Regions import create_regions, sm64courses, sm64entrances_s, sm64_internal
from BaseClasses import Item, Tutorial, ItemClassification
from ..AutoWorld import World, WebWorld
+
class SM64Web(WebWorld):
tutorials = [Tutorial(
"Multiworld Setup Guide",
diff --git a/worlds/smz3/Options.py b/worlds/smz3/Options.py
index 2bbddf7ab3..e3d8b8dd10 100644
--- a/worlds/smz3/Options.py
+++ b/worlds/smz3/Options.py
@@ -107,7 +107,6 @@ class HeartBeepSpeed(Choice):
option_Half = 2
option_Normal = 3
option_Double = 4
- alias_false = 0
default = 3
class HeartColor(Choice):
diff --git a/worlds/smz3/__init__.py b/worlds/smz3/__init__.py
index 15ac85c7c3..b796c2a43c 100644
--- a/worlds/smz3/__init__.py
+++ b/worlds/smz3/__init__.py
@@ -25,6 +25,10 @@ from Options import Accessibility
world_folder = os.path.dirname(__file__)
logger = logging.getLogger("SMZ3")
+# Location IDs in the range 256+196 to 256+202 shifted +34 between 11.2 and 11.3
+# this is required to keep backward compatibility
+def convertLocSMZ3IDToAPID(value):
+ return (value - 34) if value >= 256+230 and value <= 256+236 else value
class SMZ3CollectionState(metaclass=AutoLogicRegister):
def init_mixin(self, parent: MultiWorld):
@@ -61,12 +65,13 @@ class SMZ3World(World):
"""
game: str = "SMZ3"
topology_present = False
- data_version = 2
+ data_version = 3
option_definitions = smz3_options
item_names: Set[str] = frozenset(TotalSMZ3Item.lookup_name_to_id)
location_names: Set[str]
item_name_to_id = TotalSMZ3Item.lookup_name_to_id
- location_name_to_id: Dict[str, int] = {key : locations_start_id + value.Id for key, value in TotalSMZ3World(Config(), "", 0, "").locationLookup.items()}
+ location_name_to_id: Dict[str, int] = {key : locations_start_id + convertLocSMZ3IDToAPID(value.Id)
+ for key, value in TotalSMZ3World(Config(), "", 0, "").locationLookup.items()}
web = SMZ3Web()
remote_items: bool = False
@@ -526,9 +531,11 @@ class SMZ3World(World):
def JunkFillGT(self, factor):
poolLength = len(self.world.itempool)
+ playerGroups = self.world.get_player_groups(self.player)
+ playerGroups.add(self.player)
junkPoolIdx = [i for i in range(0, poolLength)
if self.world.itempool[i].classification in (ItemClassification.filler, ItemClassification.trap) and
- self.world.itempool[i].player == self.player]
+ self.world.itempool[i].player in playerGroups]
toRemove = []
for loc in self.locations.values():
# commenting this for now since doing a partial GT pre fill would allow for non SMZ3 progression in GT
diff --git a/worlds/soe/Logic.py b/worlds/soe/Logic.py
index d08e6a3e96..97c73a1bd1 100644
--- a/worlds/soe/Logic.py
+++ b/worlds/soe/Logic.py
@@ -35,7 +35,7 @@ class SecretOfEvermoreLogic(LogicMixin):
if pvd[1] == progress and pvd[0] > 0:
has = True
for req in rule.requires:
- if not self._soe_has(req[1], world, player, req[0]):
+ if not self.soe_has(req[1], world, player, req[0]):
has = False
break
if has:
@@ -44,7 +44,7 @@ class SecretOfEvermoreLogic(LogicMixin):
return n
return n
- def _soe_has(self, progress: int, world: MultiWorld, player: int, count: int = 1) -> bool:
+ def soe_has(self, progress: int, world: MultiWorld, player: int, count: int = 1) -> bool:
"""
Returns True if count of one of evermizer's progress steps is reached based on collected items. i.e. 2 * P_DE
"""
diff --git a/worlds/soe/Options.py b/worlds/soe/Options.py
index 4ec0ce2bcc..c718cb4abd 100644
--- a/worlds/soe/Options.py
+++ b/worlds/soe/Options.py
@@ -21,8 +21,6 @@ class OffOnFullChoice(Choice):
option_on = 1
option_full = 2
alias_chaos = 2
- alias_false = 0
- alias_true = 1
class Difficulty(EvermizerFlags, Choice):
diff --git a/worlds/soe/__init__.py b/worlds/soe/__init__.py
index f86fc48e93..a0dc41c3ce 100644
--- a/worlds/soe/__init__.py
+++ b/worlds/soe/__init__.py
@@ -283,7 +283,7 @@ class SoEWorld(World):
self.world.completion_condition[self.player] = lambda state: state.has('Victory', self.player)
# set Done from goal option once we have multiple goals
set_rule(self.world.get_location('Done', self.player),
- lambda state: state._soe_has(pyevermizer.P_FINAL_BOSS, self.world, self.player))
+ lambda state: state.soe_has(pyevermizer.P_FINAL_BOSS, self.world, self.player))
set_rule(self.world.get_entrance('New Game', self.player), lambda state: True)
for loc in _locations:
location = self.world.get_location(loc.name, self.player)
@@ -292,7 +292,7 @@ class SoEWorld(World):
def make_rule(self, requires: typing.List[typing.Tuple[int]]) -> typing.Callable[[typing.Any], bool]:
def rule(state) -> bool:
for count, progress in requires:
- if not state._soe_has(progress, self.world, self.player, count):
+ if not state.soe_has(progress, self.world, self.player, count):
return False
return True
diff --git a/worlds/subnautica/Items.py b/worlds/subnautica/Items.py
index 9917921a4b..4201cf3910 100644
--- a/worlds/subnautica/Items.py
+++ b/worlds/subnautica/Items.py
@@ -139,7 +139,7 @@ item_table: Dict[int, ItemDict] = {
'name': 'Power Transmitter Fragment',
'tech_type': 'PowerTransmitterFragment'},
35032: {'classification': ItemClassification.progression,
- 'count': 4,
+ 'count': 5,
'name': 'Prawn Suit Fragment',
'tech_type': 'ExosuitFragment'},
35033: {'classification': ItemClassification.useful,
@@ -163,7 +163,7 @@ item_table: Dict[int, ItemDict] = {
'name': 'Scanner Room Fragment',
'tech_type': 'BaseMapRoomFragment'},
35038: {'classification': ItemClassification.progression,
- 'count': 5,
+ 'count': 4,
'name': 'Seamoth Fragment',
'tech_type': 'SeamothFragment'},
35039: {'classification': ItemClassification.progression,
@@ -203,9 +203,9 @@ item_table: Dict[int, ItemDict] = {
'name': 'Picture Frame',
'tech_type': 'PictureFrameFragment'},
35048: {'classification': ItemClassification.filler,
- 'count': 2,
- 'name': 'Bench Fragment',
- 'tech_type': 'BenchFragment'},
+ 'count': 1,
+ 'name': 'Bench',
+ 'tech_type': 'Bench'},
35049: {'classification': ItemClassification.filler,
'count': 1,
'name': 'Basic Plant Pot',
@@ -333,7 +333,12 @@ item_table: Dict[int, ItemDict] = {
35080: {'classification': ItemClassification.filler,
'count': 1,
'name': 'Water Filtration Machine',
- 'tech_type': 'BaseFiltrationMachine'}}
+ 'tech_type': 'BaseFiltrationMachine'},
+ 35081: {'classification': ItemClassification.progression,
+ 'count': 1,
+ 'name': 'Ultra High Capacity Tank',
+ 'tech_type': 'HighCapacityTank'},
+}
advancement_item_names: Set[str] = set()
non_advancement_item_names: Set[str] = set()
diff --git a/worlds/subnautica/__init__.py b/worlds/subnautica/__init__.py
index a4447ccbc1..7dc23bf405 100644
--- a/worlds/subnautica/__init__.py
+++ b/worlds/subnautica/__init__.py
@@ -41,7 +41,7 @@ class SubnauticaWorld(World):
location_name_to_id = all_locations
option_definitions = Options.options
- data_version = 6
+ data_version = 7
required_client_version = (0, 3, 5)
prefill_items: List[Item]
diff --git a/worlds/timespinner/Options.py b/worlds/timespinner/Options.py
index 588416dd52..574259c9e0 100644
--- a/worlds/timespinner/Options.py
+++ b/worlds/timespinner/Options.py
@@ -3,66 +3,82 @@ from BaseClasses import MultiWorld
from Options import Toggle, DefaultOnToggle, DeathLink, Choice, Range, Option, OptionDict
from schema import Schema, And, Optional
+
class StartWithJewelryBox(Toggle):
"Start with Jewelry Box unlocked"
display_name = "Start with Jewelry Box"
+
#class ProgressiveVerticalMovement(Toggle):
# "Always find vertical movement in the following order Succubus Hairpin -> Light Wall -> Celestial Sash"
# display_name = "Progressive vertical movement"
+
#class ProgressiveKeycards(Toggle):
# "Always find Security Keycard's in the following order D -> C -> B -> A"
# display_name = "Progressive keycards"
+
class DownloadableItems(DefaultOnToggle):
"With the tablet you will be able to download items at terminals"
display_name = "Downloadable items"
+
class EyeSpy(Toggle):
"Requires Oculus Ring in inventory to be able to break hidden walls."
display_name = "Eye Spy"
+
class StartWithMeyef(Toggle):
"Start with Meyef, ideal for when you want to play multiplayer."
display_name = "Start with Meyef"
+
class QuickSeed(Toggle):
"Start with Talaria Attachment, Nyoom!"
display_name = "Quick seed"
+
class SpecificKeycards(Toggle):
"Keycards can only open corresponding doors"
display_name = "Specific Keycards"
+
class Inverted(Toggle):
"Start in the past"
display_name = "Inverted"
+
#class StinkyMaw(Toggle):
# "Require gasmask for Maw"
# display_name = "Stinky Maw"
+
class GyreArchives(Toggle):
"Gyre locations are in logic. New warps are gated by Merchant Crow and Kobo"
display_name = "Gyre Archives"
+
class Cantoran(Toggle):
"Cantoran's fight and check are available upon revisiting his room"
display_name = "Cantoran"
+
class LoreChecks(Toggle):
"Memories and journal entries contain items."
display_name = "Lore Checks"
+
class BossRando(Toggle):
"Shuffles the positions of all bosses."
display_name = "Boss Randomization"
+
class BossScaling(DefaultOnToggle):
"When Boss Rando is enabled, scales the bosses' HP, XP, and ATK to the stats of the location they replace (Reccomended)"
display_name = "Scale Random Boss Stats"
+
class DamageRando(Choice):
"Randomly nerfs and buffs some orbs and their associated spells as well as some associated rings."
display_name = "Damage Rando"
@@ -73,9 +89,9 @@ class DamageRando(Choice):
option_mostlybuffs = 4
option_allbuffs = 5
option_manual = 6
- alias_false = 0
alias_true = 2
+
class DamageRandoOverrides(OptionDict):
"Manual +/-/normal odds for an orb. Put 0 if you don't want a certain nerf or buff to be a possibility. Orbs that you don't specify will roll with 1/1/1 as odds"
schema = Schema({
@@ -180,6 +196,7 @@ class DamageRandoOverrides(OptionDict):
"Radiant": { "MinusOdds": 1, "NormalOdds": 1, "PlusOdds": 1 },
}
+
class HpCap(Range):
"Sets the number that Lunais's HP maxes out at."
display_name = "HP Cap"
@@ -187,10 +204,12 @@ class HpCap(Range):
range_end = 999
default = 999
+
class BossHealing(DefaultOnToggle):
"Enables/disables healing after boss fights. NOTE: Currently only applicable when Boss Rando is enabled."
display_name = "Heal After Bosses"
+
class ShopFill(Choice):
"""Sets the items for sale in Merchant Crow's shops.
Default: No sunglasses or trendy jacket, but sand vials for sale.
@@ -203,10 +222,12 @@ class ShopFill(Choice):
option_vanilla = 2
option_empty = 3
+
class ShopWarpShards(DefaultOnToggle):
"Shops always sell warp shards (when keys possessed), ignoring inventory setting."
display_name = "Always Sell Warp Shards"
+
class ShopMultiplier(Range):
"Multiplier for the cost of items in the shop. Set to 0 for free shops."
display_name = "Shop Price Multiplier"
@@ -214,6 +235,7 @@ class ShopMultiplier(Range):
range_end = 10
default = 1
+
class LootPool(Choice):
"""Sets the items that drop from enemies (does not apply to boss reward checks)
Vanilla: Drops are the same as the base game
@@ -224,6 +246,7 @@ class LootPool(Choice):
option_randomized = 1
option_empty = 2
+
class DropRateCategory(Choice):
"""Sets the drop rate when 'Loot Pool' is set to 'Random'
Tiered: Based on item rarity/value
@@ -237,6 +260,7 @@ class DropRateCategory(Choice):
option_randomized = 2
option_fixed = 3
+
class FixedDropRate(Range):
"Base drop rate percentage when 'Drop Rate Category' is set to 'Fixed'"
display_name = "Fixed Drop Rate"
@@ -244,6 +268,7 @@ class FixedDropRate(Range):
range_end = 100
default = 5
+
class LootTierDistro(Choice):
"""Sets how often items of each rarity tier are placed when 'Loot Pool' is set to 'Random'
Default Weight: Rarer items will be assigned to enemy drop slots less frequently than common items
@@ -255,14 +280,17 @@ class LootTierDistro(Choice):
option_full_random = 1
option_inverted_weight = 2
+
class ShowBestiary(Toggle):
"All entries in the bestiary are visible, without needing to kill one of a given enemy first"
display_name = "Show Bestiary Entries"
+
class ShowDrops(Toggle):
"All item drops in the bestiary are visible, without needing an enemy to drop one of a given item first"
display_name = "Show Bestiary Item Drops"
+
# Some options that are available in the timespinner randomizer arent currently implemented
timespinner_options: Dict[str, Option] = {
"StartWithJewelryBox": StartWithJewelryBox,
@@ -296,9 +324,11 @@ timespinner_options: Dict[str, Option] = {
"DeathLink": DeathLink,
}
+
def is_option_enabled(world: MultiWorld, player: int, name: str) -> bool:
return get_option_value(world, player, name) > 0
+
def get_option_value(world: MultiWorld, player: int, name: str) -> Union[int, dict]:
option = getattr(world, name, None)
if option == None:
diff --git a/worlds/witness/Options.py b/worlds/witness/Options.py
index 631a5bc076..2cb9ade007 100644
--- a/worlds/witness/Options.py
+++ b/worlds/witness/Options.py
@@ -15,9 +15,9 @@ class DisableNonRandomizedPuzzles(DefaultOnToggle):
class EarlySecretArea(Toggle):
- """Opens the Mountainside shortcut to the Mountain Secret Area from the start.
+ """Opens the Mountainside shortcut to the Caves from the start.
(Otherwise known as "UTM", "Caves" or the "Challenge Area")"""
- display_name = "Early Secret Area"
+ display_name = "Early Caves"
class ShuffleSymbols(DefaultOnToggle):
@@ -58,15 +58,9 @@ class ShuffleVaultBoxes(Toggle):
display_name = "Shuffle Vault Boxes"
-class ShuffleUncommonLocations(Toggle):
- """Adds some optional puzzles that are somewhat difficult or out of the way.
- Examples: Mountaintop River Shape, Tutorial Patio Floor, Theater Videos"""
- display_name = "Shuffle Uncommon Locations"
-
-
class ShufflePostgame(Toggle):
- """Adds locations into the pool that are guaranteed to be locked behind your goal. Use this if you don't play with
- forfeit on victory."""
+ """Adds locations into the pool that are guaranteed to become accessible before or at the same time as your goal.
+ Use this if you don't play with forfeit on victory."""
display_name = "Shuffle Postgame"
@@ -90,7 +84,7 @@ class MountainLasers(Range):
class ChallengeLasers(Range):
- """Sets the amount of beams required to enter the secret area through the Mountain Bottom Layer Discard."""
+ """Sets the amount of beams required to enter the Caves through the Mountain Bottom Floor Discard."""
display_name = "Required Lasers for Challenge"
range_start = 1
range_end = 11
@@ -122,7 +116,6 @@ the_witness_options: Dict[str, type] = {
"disable_non_randomized_puzzles": DisableNonRandomizedPuzzles,
"shuffle_discarded_panels": ShuffleDiscardedPanels,
"shuffle_vault_boxes": ShuffleVaultBoxes,
- "shuffle_uncommon": ShuffleUncommonLocations,
"shuffle_postgame": ShufflePostgame,
"victory_condition": VictoryCondition,
"mountain_lasers": MountainLasers,
diff --git a/worlds/witness/WitnessItems.txt b/worlds/witness/WitnessItems.txt
index 4449602529..fd9b10f97a 100644
--- a/worlds/witness/WitnessItems.txt
+++ b/worlds/witness/WitnessItems.txt
@@ -28,38 +28,38 @@ Traps:
610 - Power Surge
Doors:
-1100 - Glass Factory Entry Door (Panel) - 0x01A54
-1105 - Door to Symmetry Island Lower (Panel) - 0x000B0
-1107 - Door to Symmetry Island Upper (Panel) - 0x1C349
-1110 - Door to Desert Flood Light Room (Panel) - 0x0C339
-1111 - Desert Flood Room Flood Controls (Panel) - 0x1C2DF,0x1831E,0x1C260,0x1831C,0x1C2F3,0x1831D,0x1C2B1,0x1831B
-1119 - Quarry Door to Mill (Panel) - 0x01E5A,0x01E59
+1100 - Glass Factory Entry (Panel) - 0x01A54
+1105 - Symmetry Island Lower (Panel) - 0x000B0
+1107 - Symmetry Island Upper (Panel) - 0x1C349
+1110 - Desert Light Room Entry (Panel) - 0x0C339
+1111 - Desert Flood Controls (Panel) - 0x1C2DF,0x1831E,0x1C260,0x1831C,0x1C2F3,0x1831D,0x1C2B1,0x1831B
+1119 - Quarry Mill Entry (Panel) - 0x01E5A,0x01E59
1120 - Quarry Mill Ramp Controls (Panel) - 0x03678,0x03676
-1122 - Quarry Mill Elevator Controls (Panel) - 0x03679,0x03675
+1122 - Quarry Mill Lift Controls (Panel) - 0x03679,0x03675
1125 - Quarry Boathouse Ramp Height Control (Panel) - 0x03852
1127 - Quarry Boathouse Ramp Horizontal Control (Panel) - 0x03858
1131 - Shadows Door Timer (Panel) - 0x334DB,0x334DC
-1150 - Monastery Entry Door Left (Panel) - 0x00B10
-1151 - Monastery Entry Door Right (Panel) - 0x00C92
-1162 - Town Door to RGB House (Panel) - 0x28998
-1163 - Town Door to Church (Panel) - 0x28A0D
+1150 - Monastery Entry Left (Panel) - 0x00B10
+1151 - Monastery Entry Right (Panel) - 0x00C92
+1162 - Town Tinted Glass Door (Panel) - 0x28998
+1163 - Town Church Entry (Panel) - 0x28A0D
1166 - Town Maze Panel (Drop-Down Staircase) (Panel) - 0x28A79
-1169 - Windmill Door (Panel) - 0x17F5F
+1169 - Windmill Entry (Panel) - 0x17F5F
1200 - Treehouse First & Second Doors (Panel) - 0x0288C,0x02886
1202 - Treehouse Third Door (Panel) - 0x0A182
1205 - Treehouse Laser House Door Timer (Panel) - 0x2700B,0x334DC
-1208 - Treehouse Shortcut Drop-Down Bridge (Panel) - 0x17CBC
+1208 - Treehouse Drawbridge (Panel) - 0x17CBC
1175 - Jungle Popup Wall (Panel) - 0x17CAB
-1180 - Bunker Entry Door (Panel) - 0x17C2E
-1183 - Inside Bunker Door to Bunker Proper (Panel) - 0x0A099
+1180 - Bunker Entry (Panel) - 0x17C2E
+1183 - Bunker Tinted Glass Door (Panel) - 0x0A099
1186 - Bunker Elevator Control (Panel) - 0x0A079
-1190 - Swamp Entry Door (Panel) - 0x0056E
+1190 - Swamp Entry (Panel) - 0x0056E
1192 - Swamp Sliding Bridge (Panel) - 0x00609,0x18488
1195 - Swamp Rotating Bridge (Panel) - 0x181F5
1197 - Swamp Maze Control (Panel) - 0x17C0A
1310 - Boat - 0x17CDF,0x17CC8,0x17CA6,0x09DB8,0x17C95,0x0A054
-1400 - Caves Mountain Shortcut - 0x2D73F
+1400 - Caves Mountain Shortcut (Door) - 0x2D73F
1500 - Symmetry Laser - 0x00509
1501 - Desert Laser - 0x012FB,0x01317
@@ -73,101 +73,101 @@ Doors:
1509 - Swamp Laser - 0x00BF6
1510 - Treehouse Laser - 0x028A4
-1600 - Outside Tutorial Optional Door - 0x03BA2
-1603 - Outside Tutorial Outpost Entry Door - 0x0A170
-1606 - Outside Tutorial Outpost Exit Door - 0x04CA3
-1609 - Glass Factory Entry Door - 0x01A29
-1612 - Glass Factory Back Wall - 0x0D7ED
-1615 - Symmetry Island Lower Door - 0x17F3E
-1618 - Symmetry Island Upper Door - 0x18269
-1619 - Orchard Middle Gate - 0x03307
-1620 - Orchard Final Gate - 0x03313
-1621 - Desert Door to Flood Light Room - 0x09FEE
-1624 - Desert Door to Pond Room - 0x0C2C3
-1627 - Desert Door to Water Levels Room - 0x0A24B
-1630 - Desert Door to Elevator Room - 0x0C316
-1633 - Quarry Main Entry 1 - 0x09D6F
-1636 - Quarry Main Entry 2 - 0x17C07
-1639 - Quarry Door to Mill - 0x02010
-1642 - Quarry Mill Side Door - 0x275FF
-1645 - Quarry Mill Rooftop Shortcut - 0x17CE8
-1648 - Quarry Mill Stairs - 0x0368A
-1651 - Quarry Boathouse Boat Staircase - 0x2769B,0x27163
-1653 - Quarry Boathouse First Barrier - 0x17C50
-1654 - Quarry Boathouse Shortcut - 0x3865F
-1656 - Shadows Timed Door - 0x19B24
-1657 - Shadows Laser Room Right Door - 0x194B2
-1660 - Shadows Laser Room Left Door - 0x19665
-1663 - Shadows Barrier to Quarry - 0x19865,0x0A2DF
-1666 - Shadows Barrier to Ledge - 0x1855B,0x19ADE
-1669 - Keep Hedge Maze 1 Exit Door - 0x01954
-1672 - Keep Pressure Plates 1 Exit Door - 0x01BEC
-1675 - Keep Hedge Maze 2 Shortcut - 0x018CE
-1678 - Keep Hedge Maze 2 Exit Door - 0x019D8
-1681 - Keep Hedge Maze 3 Shortcut - 0x019B5
-1684 - Keep Hedge Maze 3 Exit Door - 0x019E6
-1687 - Keep Hedge Maze 4 Shortcut - 0x0199A
-1690 - Keep Hedge Maze 4 Exit Door - 0x01A0E
-1693 - Keep Pressure Plates 2 Exit Door - 0x01BEA
-1696 - Keep Pressure Plates 3 Exit Door - 0x01CD5
-1699 - Keep Pressure Plates 4 Exit Door - 0x01D40
-1702 - Keep Shortcut to Shadows - 0x09E3D
-1705 - Keep Tower Shortcut - 0x04F8F
-1708 - Monastery Shortcut - 0x0364E
-1711 - Monastery Inner Door - 0x0C128
-1714 - Monastery Outer Door - 0x0C153
-1717 - Monastery Door to Garden - 0x03750
-1718 - Town Cargo Box Door - 0x0A0C9
-1720 - Town Wooden Roof Staircase - 0x034F5
-1723 - Town Tinted Door to RGB House - 0x28A61
-1726 - Town Door to Church - 0x03BB0
-1729 - Town Maze Staircase - 0x28AA2
-1732 - Town Windmill Door - 0x1845B
-1735 - Town RGB House Staircase - 0x2897B
-1738 - Town Tower Blue Panels Door - 0x27798
-1741 - Town Tower Lattice Door - 0x27799
-1744 - Town Tower Environmental Set Door - 0x2779A
-1747 - Town Tower Wooden Roof Set Door - 0x2779C
-1750 - Theater Entry Door - 0x17F88
-1753 - Theater Exit Door Left - 0x0A16D
-1756 - Theater Exit Door Right - 0x3CCDF
-1759 - Jungle Bamboo Shortcut to River - 0x3873B
-1760 - Jungle Popup Wall - 0x1475B
-1762 - River Shortcut to Monastery Garden - 0x0CF2A
-1765 - Bunker Bunker Entry Door - 0x0C2A4
-1768 - Bunker Tinted Glass Door - 0x17C79
-1771 - Bunker Door to Ultraviolet Room - 0x0C2A3
-1774 - Bunker Door to Elevator - 0x0A08D
-1777 - Swamp Entry Door - 0x00C1C
-1780 - Swamp Door to Broken Shapers - 0x184B7
+1600 - Outside Tutorial Outpost Path (Door) - 0x03BA2
+1603 - Outside Tutorial Outpost Entry (Door) - 0x0A170
+1606 - Outside Tutorial Outpost Exit (Door) - 0x04CA3
+1609 - Glass Factory Entry (Door) - 0x01A29
+1612 - Glass Factory Back Wall (Door) - 0x0D7ED
+1615 - Symmetry Island Lower (Door) - 0x17F3E
+1618 - Symmetry Island Upper (Door) - 0x18269
+1619 - Orchard First Gate (Door) - 0x03307
+1620 - Orchard Second Gate (Door) - 0x03313
+1621 - Desert Light Room Entry (Door) - 0x09FEE
+1624 - Desert Pond Room Entry (Door) - 0x0C2C3
+1627 - Desert Flood Room Entry (Door) - 0x0A24B
+1630 - Desert Elevator Room Entry (Door) - 0x0C316
+1633 - Quarry Entry 1 (Door) - 0x09D6F
+1636 - Quarry Entry 2 (Door) - 0x17C07
+1639 - Quarry Mill Entry (Door) - 0x02010
+1642 - Quarry Mill Side Exit (Door) - 0x275FF
+1645 - Quarry Mill Roof Exit (Door) - 0x17CE8
+1648 - Quarry Mill Stairs (Door) - 0x0368A
+1651 - Quarry Boathouse Dock (Door) - 0x2769B,0x27163
+1653 - Quarry Boathouse First Barrier (Door) - 0x17C50
+1654 - Quarry Boathouse Second Barrier (Door) - 0x3865F
+1656 - Shadows Timed Door (Door) - 0x19B24
+1657 - Shadows Laser Entry Right (Door) - 0x194B2
+1660 - Shadows Laser Entry Left (Door) - 0x19665
+1663 - Shadows Quarry Barrier (Door) - 0x19865,0x0A2DF
+1666 - Shadows Ledge Barrier (Door) - 0x1855B,0x19ADE
+1669 - Keep Hedge Maze 1 Exit (Door) - 0x01954
+1672 - Keep Pressure Plates 1 Exit (Door) - 0x01BEC
+1675 - Keep Hedge Maze 2 Shortcut (Door) - 0x018CE
+1678 - Keep Hedge Maze 2 Exit (Door) - 0x019D8
+1681 - Keep Hedge Maze 3 Shortcut (Door) - 0x019B5
+1684 - Keep Hedge Maze 3 Exit (Door) - 0x019E6
+1687 - Keep Hedge Maze 4 Shortcut (Door) - 0x0199A
+1690 - Keep Hedge Maze 4 Exit (Door) - 0x01A0E
+1693 - Keep Pressure Plates 2 Exit (Door) - 0x01BEA
+1696 - Keep Pressure Plates 3 Exit (Door) - 0x01CD5
+1699 - Keep Pressure Plates 4 Exit (Door) - 0x01D40
+1702 - Keep Shadows Shortcut (Door) - 0x09E3D
+1705 - Keep Tower Shortcut (Door) - 0x04F8F
+1708 - Monastery Shortcut (Door) - 0x0364E
+1711 - Monastery Entry Inner (Door) - 0x0C128
+1714 - Monastery Entry Outer (Door) - 0x0C153
+1717 - Monastery Garden Entry (Door) - 0x03750
+1718 - Town Cargo Box Entry (Door) - 0x0A0C9
+1720 - Town Wooden Roof Stairs (Door) - 0x034F5
+1723 - Town Tinted Glass Door (Door) - 0x28A61
+1726 - Town Church Entry (Door) - 0x03BB0
+1729 - Town Maze Stairs (Door) - 0x28AA2
+1732 - Town Windmill Entry (Door) - 0x1845B
+1735 - Town RGB House Stairs (Door) - 0x2897B
+1738 - Town Tower First Door (Door) - 0x27798
+1741 - Town Tower Third Door (Door) - 0x27799
+1744 - Town Tower Fourth Door (Door) - 0x2779A
+1747 - Town Tower Second Door (Door) - 0x2779C
+1750 - Theater Entry (Door) - 0x17F88
+1753 - Theater Exit Left (Door) - 0x0A16D
+1756 - Theater Exit Right (Door) - 0x3CCDF
+1759 - Jungle Bamboo Laser Shortcut (Door) - 0x3873B
+1760 - Jungle Popup Wall (Door) - 0x1475B
+1762 - River Monastery Shortcut (Door) - 0x0CF2A
+1765 - Bunker Entry (Door) - 0x0C2A4
+1768 - Bunker Tinted Glass Door (Door) - 0x17C79
+1771 - Bunker UV Room Entry (Door) - 0x0C2A3
+1774 - Bunker Elevator Room Entry (Door) - 0x0A08D
+1777 - Swamp Entry (Door) - 0x00C1C
+1780 - Swamp Between Bridges First Door - 0x184B7
1783 - Swamp Platform Shortcut Door - 0x38AE6
-1786 - Swamp Cyan Water Pump - 0x04B7F
-1789 - Swamp Door to Rotated Shapers - 0x18507
-1792 - Swamp Red Water Pump - 0x183F2
-1795 - Swamp Red Underwater Exit - 0x305D5
-1798 - Swamp Blue Water Pump - 0x18482
-1801 - Swamp Purple Water Pump - 0x0A1D6
-1804 - Swamp Near Laser Shortcut - 0x2D880
-1807 - Treehouse First Door - 0x0C309
-1810 - Treehouse Second Door - 0x0C310
-1813 - Treehouse Beyond Yellow Bridge Door - 0x0A181
-1816 - Treehouse Drawbridge - 0x0C32D
-1819 - Treehouse Timed Door to Laser House - 0x0C323
-1822 - Inside Mountain First Layer Exit Door - 0x09E54
-1825 - Inside Mountain Second Layer Staircase Near - 0x09FFB
-1828 - Inside Mountain Second Layer Exit Door - 0x09EDD
-1831 - Inside Mountain Second Layer Staircase Far - 0x09E07
-1834 - Inside Mountain Giant Puzzle Exit Door - 0x09F89
-1840 - Inside Mountain Door to Final Room - 0x0C141
-1843 - Inside Mountain Bottom Layer Rock - 0x17F33
-1846 - Inside Mountain Door to Secret Area - 0x2D77D
-1849 - Caves Pillar Door - 0x019A5
-1855 - Caves Swamp Shortcut - 0x2D859
-1858 - Challenge Entry Door - 0x0A19A
-1861 - Challenge Door to Theater Walkway - 0x0348A
-1864 - Theater Walkway Door to Windmill Interior - 0x27739
-1867 - Theater Walkway Door to Desert Elevator Room - 0x27263
-1870 - Theater Walkway Door to Town - 0x09E87
+1786 - Swamp Cyan Water Pump (Door) - 0x04B7F
+1789 - Swamp Between Bridges Second Door - 0x18507
+1792 - Swamp Red Water Pump (Door) - 0x183F2
+1795 - Swamp Red Underwater Exit (Door) - 0x305D5
+1798 - Swamp Blue Water Pump (Door) - 0x18482
+1801 - Swamp Purple Water Pump (Door) - 0x0A1D6
+1804 - Swamp Laser Shortcut (Door) - 0x2D880
+1807 - Treehouse First Door (Door) - 0x0C309
+1810 - Treehouse Second Door (Door) - 0x0C310
+1813 - Treehouse Third Door (Door) - 0x0A181
+1816 - Treehouse Drawbridge (Door) - 0x0C32D
+1819 - Treehouse Laser House Entry (Door) - 0x0C323
+1822 - Mountain Floor 1 Exit (Door) - 0x09E54
+1825 - Mountain Floor 2 Staircase Near (Door) - 0x09FFB
+1828 - Mountain Floor 2 Exit (Door) - 0x09EDD
+1831 - Mountain Floor 2 Staircase Far (Door) - 0x09E07
+1834 - Mountain Bottom Floor Giant Puzzle Exit (Door) - 0x09F89
+1840 - Mountain Bottom Floor Final Room Entry (Door) - 0x0C141
+1843 - Mountain Bottom Floor Rock (Door) - 0x17F33
+1846 - Caves Entry (Door) - 0x2D77D
+1849 - Caves Pillar Door (Door) - 0x019A5
+1855 - Caves Swamp Shortcut (Door) - 0x2D859
+1858 - Challenge Entry (Door) - 0x0A19A
+1861 - Challenge Tunnels Entry (Door) - 0x0348A
+1864 - Tunnels Theater Shortcut (Door) - 0x27739
+1867 - Tunnels Desert Shortcut (Door) - 0x27263
+1870 - Tunnels Town Shortcut (Door) - 0x09E87
1903 - Outside Tutorial Outpost Doors - 0x03BA2,0x0A170,0x04CA3
1906 - Symmetry Island Doors - 0x17F3E,0x18269
@@ -181,18 +181,18 @@ Doors:
1930 - Keep Hedge Maze Doors - 0x01954,0x018CE,0x019D8,0x019B5,0x019E6,0x0199A,0x01A0E
1933 - Keep Pressure Plates Doors - 0x01BEC,0x01BEA,0x01CD5,0x01D40
1936 - Keep Shortcuts - 0x09E3D,0x04F8F
-1939 - Monastery Entry Door - 0x0C128,0x0C153
+1939 - Monastery Entry - 0x0C128,0x0C153
1942 - Monastery Shortcuts - 0x0364E,0x03750
1945 - Town Doors - 0x0A0C9,0x034F5,0x28A61,0x03BB0,0x28AA2,0x1845B,0x2897B
1948 - Town Tower Doors - 0x27798,0x27799,0x2779A,0x2779C
-1951 - Theater Exit Door - 0x0A16D,0x3CCDF
+1951 - Theater Exit - 0x0A16D,0x3CCDF
1954 - Jungle & River Shortcuts - 0x3873B,0x0CF2A
1957 - Bunker Doors - 0x0C2A4,0x17C79,0x0C2A3,0x0A08D
1960 - Swamp Doors - 0x00C1C,0x184B7,0x38AE6,0x18507
1963 - Swamp Water Pumps - 0x04B7F,0x183F2,0x305D5,0x18482,0x0A1D6
1966 - Treehouse Entry Doors - 0x0C309,0x0C310,0x0A181
-1975 - Inside Mountain Second Layer Stairs & Doors - 0x09FFB,0x09EDD,0x09E07
-1978 - Inside Mountain Bottom Layer Doors to Caves - 0x17F33,0x2D77D
+1975 - Mountain Floor 2 Stairs & Doors - 0x09FFB,0x09EDD,0x09E07
+1978 - Mountain Bottom Floor Doors to Caves - 0x17F33,0x2D77D
1981 - Caves Doors to Challenge - 0x019A5,0x0A19A
1984 - Caves Exits to Main Island - 0x2D859,0x2D73F
-1987 - Theater Walkway Doors - 0x27739,0x27263,0x09E87
\ No newline at end of file
+1987 - Tunnels Doors - 0x27739,0x27263,0x09E87
\ No newline at end of file
diff --git a/worlds/witness/WitnessLogic.txt b/worlds/witness/WitnessLogic.txt
index c98257fb73..650cf14c52 100644
--- a/worlds/witness/WitnessLogic.txt
+++ b/worlds/witness/WitnessLogic.txt
@@ -14,49 +14,49 @@ Tutorial (Tutorial) - Outside Tutorial - 0x03629:
158010 - 0x0C373 (Patio Floor) - 0x0C335 - Dots
Outside Tutorial (Outside Tutorial) - Outside Tutorial Path To Outpost - 0x03BA2:
-158650 - 0x033D4 (Vault) - True - Dots & Squares & Black/White Squares
+158650 - 0x033D4 (Vault) - True - Dots & Black/White Squares
158651 - 0x03481 (Vault Box) - 0x033D4 - True
-158013 - 0x0005D (Dots Introduction 1) - True - Dots
-158014 - 0x0005E (Dots Introduction 2) - 0x0005D - Dots
-158015 - 0x0005F (Dots Introduction 3) - 0x0005E - Dots
-158016 - 0x00060 (Dots Introduction 4) - 0x0005F - Dots
-158017 - 0x00061 (Dots Introduction 5) - 0x00060 - Dots
-158018 - 0x018AF (Squares Introduction 1) - True - Squares & Black/White Squares
-158019 - 0x0001B (Squares Introduction 2) - 0x018AF - Squares & Black/White Squares
-158020 - 0x012C9 (Squares Introduction 3) - 0x0001B - Squares & Black/White Squares
-158021 - 0x0001C (Squares Introduction 4) - 0x012C9 - Squares & Black/White Squares
-158022 - 0x0001D (Squares Introduction 5) - 0x0001C - Squares & Black/White Squares
-158023 - 0x0001E (Squares Introduction 6) - 0x0001D - Squares & Black/White Squares
-158024 - 0x0001F (Squares Introduction 7) - 0x0001E - Squares & Black/White Squares
-158025 - 0x00020 (Squares Introduction 8) - 0x0001F - Squares & Black/White Squares
-158026 - 0x00021 (Squares Introduction 9) - 0x00020 - Squares & Black/White Squares
-Door - 0x03BA2 (Optional Door 1) - 0x0A3B5
+158013 - 0x0005D (Shed Row 1) - True - Dots
+158014 - 0x0005E (Shed Row 2) - 0x0005D - Dots
+158015 - 0x0005F (Shed Row 3) - 0x0005E - Dots
+158016 - 0x00060 (Shed Row 4) - 0x0005F - Dots
+158017 - 0x00061 (Shed Row 5) - 0x00060 - Dots
+158018 - 0x018AF (Tree Row 1) - True - Black/White Squares
+158019 - 0x0001B (Tree Row 2) - 0x018AF - Black/White Squares
+158020 - 0x012C9 (Tree Row 3) - 0x0001B - Black/White Squares
+158021 - 0x0001C (Tree Row 4) - 0x012C9 - Black/White Squares
+158022 - 0x0001D (Tree Row 5) - 0x0001C - Black/White Squares
+158023 - 0x0001E (Tree Row 6) - 0x0001D - Black/White Squares
+158024 - 0x0001F (Tree Row 7) - 0x0001E - Black/White Squares
+158025 - 0x00020 (Tree Row 8) - 0x0001F - Black/White Squares
+158026 - 0x00021 (Tree Row 9) - 0x00020 - Black/White Squares
+Door - 0x03BA2 (Outpost Path) - 0x0A3B5
Outside Tutorial Path To Outpost (Outside Tutorial) - Outside Tutorial Outpost - 0x0A170:
-158011 - 0x0A171 (Door to Outpost Panel) - True - Dots
-Door - 0x0A170 (Door to Outpost) - 0x0A171
+158011 - 0x0A171 (Outpost Entry Panel) - True - Dots
+Door - 0x0A170 (Outpost Entry) - 0x0A171
Outside Tutorial Outpost (Outside Tutorial) - Outside Tutorial - 0x04CA3:
-158012 - 0x04CA4 (Exit Door from Outpost Panel) - True - Dots & Squares & Black/White Squares
-Door - 0x04CA3 (Exit Door from Outpost) - 0x04CA4
+158012 - 0x04CA4 (Outpost Exit Panel) - True - Dots & Black/White Squares
+Door - 0x04CA3 (Outpost Exit) - 0x04CA4
158600 - 0x17CFB (Discard) - True - Triangles
Main Island () - Outside Tutorial - True:
Outside Glass Factory (Glass Factory) - Main Island - True - Inside Glass Factory - 0x01A29:
-158027 - 0x01A54 (Entry Door Panel) - True - Symmetry
-Door - 0x01A29 (Entry Door) - 0x01A54
+158027 - 0x01A54 (Entry Panel) - True - Symmetry
+Door - 0x01A29 (Entry) - 0x01A54
158601 - 0x3C12B (Discard) - True - Triangles
Inside Glass Factory (Glass Factory) - Inside Glass Factory Behind Back Wall - 0x0D7ED:
-158028 - 0x00086 (Vertical Symmetry 1) - True - Symmetry
-158029 - 0x00087 (Vertical Symmetry 2) - 0x00086 - Symmetry
-158030 - 0x00059 (Vertical Symmetry 3) - 0x00087 - Symmetry
-158031 - 0x00062 (Vertical Symmetry 4) - 0x00059 - Symmetry
-158032 - 0x0005C (Vertical Symmetry 5) - 0x00062 - Symmetry
-158033 - 0x0008D (Rotational Symmetry 1) - 0x0005C - Symmetry
-158034 - 0x00081 (Rotational Symmetry 2) - 0x0008D - Symmetry
-158035 - 0x00083 (Rotational Symmetry 3) - 0x00081 - Symmetry
+158028 - 0x00086 (Back Wall 1) - True - Symmetry
+158029 - 0x00087 (Back Wall 2) - 0x00086 - Symmetry
+158030 - 0x00059 (Back Wall 3) - 0x00087 - Symmetry
+158031 - 0x00062 (Back Wall 4) - 0x00059 - Symmetry
+158032 - 0x0005C (Back Wall 5) - 0x00062 - Symmetry
+158033 - 0x0008D (Front 1) - 0x0005C - Symmetry
+158034 - 0x00081 (Front 2) - 0x0008D - Symmetry
+158035 - 0x00083 (Front 3) - 0x00081 - Symmetry
158036 - 0x00084 (Melting 1) - 0x00083 - Symmetry
158037 - 0x00082 (Melting 2) - 0x00084 - Symmetry
158038 - 0x0343A (Melting 3) - 0x00082 - Symmetry
@@ -66,35 +66,35 @@ Inside Glass Factory Behind Back Wall (Glass Factory) - Boat - 0x17CC8:
158039 - 0x17CC8 (Boat Spawn) - 0x17CA6 | 0x17CDF | 0x09DB8 | 0x17C95 - Boat
Outside Symmetry Island (Symmetry Island) - Main Island - True - Symmetry Island Lower - 0x17F3E:
-158040 - 0x000B0 (Door to Symmetry Island Lower Panel) - 0x0343A - Dots
-Door - 0x17F3E (Door to Symmetry Island Lower) - 0x000B0
+158040 - 0x000B0 (Lower Panel) - 0x0343A - Dots
+Door - 0x17F3E (Lower) - 0x000B0
Symmetry Island Lower (Symmetry Island) - Symmetry Island Upper - 0x18269:
-158041 - 0x00022 (Black Dots 1) - True - Symmetry & Dots
-158042 - 0x00023 (Black Dots 2) - 0x00022 - Symmetry & Dots
-158043 - 0x00024 (Black Dots 3) - 0x00023 - Symmetry & Dots
-158044 - 0x00025 (Black Dots 4) - 0x00024 - Symmetry & Dots
-158045 - 0x00026 (Black Dots 5) - 0x00025 - Symmetry & Dots
-158046 - 0x0007C (Colored Dots 1) - 0x00026 - Symmetry & Colored Dots
-158047 - 0x0007E (Colored Dots 2) - 0x0007C - Symmetry & Colored Dots
-158048 - 0x00075 (Colored Dots 3) - 0x0007E - Symmetry & Colored Dots
-158049 - 0x00073 (Colored Dots 4) - 0x00075 - Symmetry & Colored Dots
-158050 - 0x00077 (Colored Dots 5) - 0x00073 - Symmetry & Colored Dots
-158051 - 0x00079 (Colored Dots 6) - 0x00077 - Symmetry & Colored Dots
-158052 - 0x00065 (Fading Lines 1) - 0x00079 - Symmetry & Colored Dots
-158053 - 0x0006D (Fading Lines 2) - 0x00065 - Symmetry & Colored Dots
-158054 - 0x00072 (Fading Lines 3) - 0x0006D - Symmetry & Colored Dots
-158055 - 0x0006F (Fading Lines 4) - 0x00072 - Symmetry & Colored Dots
-158056 - 0x00070 (Fading Lines 5) - 0x0006F - Symmetry & Colored Dots
-158057 - 0x00071 (Fading Lines 6) - 0x00070 - Symmetry & Colored Dots
-158058 - 0x00076 (Fading Lines 7) - 0x00071 - Symmetry & Colored Dots
-158059 - 0x009B8 (Scenery Outlines 1) - True - Symmetry & Environment
-158060 - 0x003E8 (Scenery Outlines 2) - 0x009B8 - Symmetry & Environment
-158061 - 0x00A15 (Scenery Outlines 3) - 0x003E8 - Symmetry & Environment
-158062 - 0x00B53 (Scenery Outlines 4) - 0x00A15 - Symmetry & Environment
-158063 - 0x00B8D (Scenery Outlines 5) - 0x00B53 - Symmetry & Environment
-158064 - 0x1C349 (Door to Symmetry Island Upper Panel) - 0x00076 - Symmetry & Dots
-Door - 0x18269 (Door to Symmetry Island Upper) - 0x1C349
+158041 - 0x00022 (Right 1) - True - Symmetry & Dots
+158042 - 0x00023 (Right 2) - 0x00022 - Symmetry & Dots
+158043 - 0x00024 (Right 3) - 0x00023 - Symmetry & Dots
+158044 - 0x00025 (Right 4) - 0x00024 - Symmetry & Dots
+158045 - 0x00026 (Right 5) - 0x00025 - Symmetry & Dots
+158046 - 0x0007C (Back 1) - 0x00026 - Symmetry & Colored Dots
+158047 - 0x0007E (Back 2) - 0x0007C - Symmetry & Colored Dots
+158048 - 0x00075 (Back 3) - 0x0007E - Symmetry & Colored Dots
+158049 - 0x00073 (Back 4) - 0x00075 - Symmetry & Colored Dots
+158050 - 0x00077 (Back 5) - 0x00073 - Symmetry & Colored Dots
+158051 - 0x00079 (Back 6) - 0x00077 - Symmetry & Colored Dots
+158052 - 0x00065 (Left 1) - 0x00079 - Symmetry & Colored Dots
+158053 - 0x0006D (Left 2) - 0x00065 - Symmetry & Colored Dots
+158054 - 0x00072 (Left 3) - 0x0006D - Symmetry & Colored Dots
+158055 - 0x0006F (Left 4) - 0x00072 - Symmetry & Colored Dots
+158056 - 0x00070 (Left 5) - 0x0006F - Symmetry & Colored Dots
+158057 - 0x00071 (Left 6) - 0x00070 - Symmetry & Colored Dots
+158058 - 0x00076 (Left 7) - 0x00071 - Symmetry & Colored Dots
+158059 - 0x009B8 (Scenery Outlines 1) - True - Symmetry
+158060 - 0x003E8 (Scenery Outlines 2) - 0x009B8 - Symmetry
+158061 - 0x00A15 (Scenery Outlines 3) - 0x003E8 - Symmetry
+158062 - 0x00B53 (Scenery Outlines 4) - 0x00A15 - Symmetry
+158063 - 0x00B8D (Scenery Outlines 5) - 0x00B53 - Symmetry
+158064 - 0x1C349 (Upper Panel) - 0x00076 - Symmetry & Dots
+Door - 0x18269 (Upper) - 0x1C349
Symmetry Island Upper (Symmetry Island):
158065 - 0x00A52 (Yellow 1) - True - Symmetry & Colored Dots
@@ -107,15 +107,15 @@ Symmetry Island Upper (Symmetry Island):
Laser - 0x00509 (Laser) - 0x0360D - True
Orchard (Orchard) - Main Island - True - Orchard Beyond First Gate - 0x03307:
-158071 - 0x00143 (Apple Tree 1) - True - Environment
-158072 - 0x0003B (Apple Tree 2) - 0x00143 - Environment
-158073 - 0x00055 (Apple Tree 3) - 0x0003B - Environment
-Door - 0x03307 (Mid Gate) - 0x00055
+158071 - 0x00143 (Apple Tree 1) - True - True
+158072 - 0x0003B (Apple Tree 2) - 0x00143 - True
+158073 - 0x00055 (Apple Tree 3) - 0x0003B - True
+Door - 0x03307 (First Gate) - 0x00055
Orchard Beyond First Gate (Orchard) - Orchard End - 0x03313:
-158074 - 0x032F7 (Apple Tree 4) - 0x00055 - Environment
-158075 - 0x032FF (Apple Tree 5) - 0x032F7 - Environment
-Door - 0x03313 (Final Gate) - 0x032FF
+158074 - 0x032F7 (Apple Tree 4) - 0x00055 - True
+158075 - 0x032FF (Apple Tree 5) - 0x032F7 - True
+Door - 0x03313 (Second Gate) - 0x032FF
Orchard End (Orchard):
@@ -123,34 +123,36 @@ Desert Outside (Desert) - Main Island - True - Desert Floodlight Room - 0x09FEE:
158652 - 0x0CC7B (Vault) - True - Dots & Shapers & Rotated Shapers & Negative Shapers
158653 - 0x0339E (Vault Box) - 0x0CC7B - True
158602 - 0x17CE7 (Discard) - True - Triangles
-158076 - 0x00698 (Sun Reflection 1) - True - Reflection
-158077 - 0x0048F (Sun Reflection 2) - 0x00698 - Reflection
-158078 - 0x09F92 (Sun Reflection 3) - 0x0048F & 0x09FA0 - Reflection
-158079 - 0x09FA0 (Reflection 3 Control) - 0x0048F - True
-158080 - 0x0A036 (Sun Reflection 4) - 0x09F92 - Reflection
-158081 - 0x09DA6 (Sun Reflection 5) - 0x09F92 - Reflection
-158082 - 0x0A049 (Sun Reflection 6) - 0x09F92 - Reflection
-158083 - 0x0A053 (Sun Reflection 7) - 0x0A036 & 0x09DA6 & 0x0A049 - Reflection
-158084 - 0x09F94 (Sun Reflection 8) - 0x0A053 & 0x09F86 - Reflection
-158085 - 0x09F86 (Reflection 8 Control) - 0x0A053 - True
-158086 - 0x0C339 (Door to Desert Flood Light Room Panel) - 0x09F94 - True
-Door - 0x09FEE (Door to Desert Flood Light Room) - 0x0C339 - True
+158076 - 0x00698 (Surface 1) - True - True
+158077 - 0x0048F (Surface 2) - 0x00698 - True
+158078 - 0x09F92 (Surface 3) - 0x0048F & 0x09FA0 - True
+158079 - 0x09FA0 (Surface 3 Control) - 0x0048F - True
+158080 - 0x0A036 (Surface 4) - 0x09F92 - True
+158081 - 0x09DA6 (Surface 5) - 0x09F92 - True
+158082 - 0x0A049 (Surface 6) - 0x09F92 - True
+158083 - 0x0A053 (Surface 7) - 0x0A036 & 0x09DA6 & 0x0A049 - True
+158084 - 0x09F94 (Surface 8) - 0x0A053 & 0x09F86 - True
+158085 - 0x09F86 (Surface 8 Control) - 0x0A053 - True
+158086 - 0x0C339 (Light Room Entry Panel) - 0x09F94 - True
+Door - 0x09FEE (Light Room Entry) - 0x0C339 - True
+158701 - 0x03608 (Laser Panel) - 0x012D7 & 0x0A15F - True
+Laser - 0x012FB (Laser) - 0x03608
Desert Floodlight Room (Desert) - Desert Pond Room - 0x0C2C3:
158087 - 0x09FAA (Light Control) - True - True
-158088 - 0x00422 (Artificial Light Reflection 1) - 0x09FAA - Reflection
-158089 - 0x006E3 (Artificial Light Reflection 2) - 0x09FAA - Reflection
-158090 - 0x0A02D (Artificial Light Reflection 3) - 0x09FAA & 0x00422 & 0x006E3 - Reflection
-Door - 0x0C2C3 (Door to Pond Room) - 0x0A02D
+158088 - 0x00422 (Light Room 1) - 0x09FAA - True
+158089 - 0x006E3 (Light Room 2) - 0x09FAA - True
+158090 - 0x0A02D (Light Room 3) - 0x09FAA & 0x00422 & 0x006E3 - True
+Door - 0x0C2C3 (Pond Room Entry) - 0x0A02D
Desert Pond Room (Desert) - Desert Water Levels Room - 0x0A24B:
-158091 - 0x00C72 (Pond Reflection 1) - True - Reflection
-158092 - 0x0129D (Pond Reflection 2) - 0x00C72 - Reflection
-158093 - 0x008BB (Pond Reflection 3) - 0x0129D - Reflection
-158094 - 0x0078D (Pond Reflection 4) - 0x008BB - Reflection
-158095 - 0x18313 (Pond Reflection 5) - 0x0078D - Reflection
-158096 - 0x0A249 (Door to Water Levels Room Panel) - 0x18313 - Reflection
-Door - 0x0A24B (Door to Water Levels Room) - 0x0A249
+158091 - 0x00C72 (Pond Room 1) - True - True
+158092 - 0x0129D (Pond Room 2) - 0x00C72 - True
+158093 - 0x008BB (Pond Room 3) - 0x0129D - True
+158094 - 0x0078D (Pond Room 4) - 0x008BB - True
+158095 - 0x18313 (Pond Room 5) - 0x0078D - True
+158096 - 0x0A249 (Flood Room Entry Panel) - 0x18313 - True
+Door - 0x0A24B (Flood Room Entry) - 0x0A249
Desert Water Levels Room (Desert) - Desert Elevator Room - 0x0C316:
158097 - 0x1C2DF (Reduce Water Level Far Left) - True - True
@@ -161,249 +163,247 @@ Desert Water Levels Room (Desert) - Desert Elevator Room - 0x0C316:
158102 - 0x1831D (Raise Water Level Far Right) - True - True
158103 - 0x1C2B1 (Raise Water Level Near Left) - True - True
158104 - 0x1831B (Raise Water Level Near Right) - True - True
-158105 - 0x04D18 (Flood Reflection 1) - 0x1C260 & 0x1831C - Reflection
-158106 - 0x01205 (Flood Reflection 2) - 0x04D18 & 0x1C260 & 0x1831C - Reflection
-158107 - 0x181AB (Flood Reflection 3) - 0x01205 & 0x1C260 & 0x1831C - Reflection
-158108 - 0x0117A (Flood Reflection 4) - 0x181AB & 0x1C260 & 0x1831C - Reflection
-158109 - 0x17ECA (Flood Reflection 5) - 0x0117A & 0x1C260 & 0x1831C - Reflection
-158110 - 0x18076 (Flood Reflection 6) - 0x17ECA & 0x1C260 & 0x1831C - Reflection
-Door - 0x0C316 (Door to Elevator Room) - 0x18076
+158105 - 0x04D18 (Flood Room 1) - 0x1C260 & 0x1831C - True
+158106 - 0x01205 (Flood Room 2) - 0x04D18 & 0x1C260 & 0x1831C - True
+158107 - 0x181AB (Flood Room 3) - 0x01205 & 0x1C260 & 0x1831C - True
+158108 - 0x0117A (Flood Room 4) - 0x181AB & 0x1C260 & 0x1831C - True
+158109 - 0x17ECA (Flood Room 5) - 0x0117A & 0x1C260 & 0x1831C - True
+158110 - 0x18076 (Flood Room 6) - 0x17ECA & 0x1C260 & 0x1831C - True
+Door - 0x0C316 (Elevator Room Entry) - 0x18076
Desert Elevator Room (Desert) - Desert Lowest Level Inbetween Shortcuts - 0x012FB:
-158111 - 0x17C31 (Final Transparent Reflection) - True - Reflection
-158113 - 0x012D7 (Final Reflection) - 0x17C31 & 0x0A015 - Reflection
-158114 - 0x0A015 (Final Reflection Control) - 0x17C31 - True
-158115 - 0x0A15C (Final Bent Reflection 1) - True - Reflection
-158116 - 0x09FFF (Final Bent Reflection 2) - 0x0A15C - Reflection
-158117 - 0x0A15F (Final Bent Reflection 3) - 0x09FFF - Reflection
-158701 - 0x03608 (Laser Panel) - 0x012D7 & 0x0A15F - True
-Laser - 0x012FB (Laser) - 0x03608
+158111 - 0x17C31 (Final Transparent) - True - True
+158113 - 0x012D7 (Final Hexagonal) - 0x17C31 & 0x0A015 - True
+158114 - 0x0A015 (Final Hexagonal Control) - 0x17C31 - True
+158115 - 0x0A15C (Final Bent 1) - True - True
+158116 - 0x09FFF (Final Bent 2) - 0x0A15C - True
+158117 - 0x0A15F (Final Bent 3) - 0x09FFF - True
Desert Lowest Level Inbetween Shortcuts (Desert):
-Outside Quarry (Quarry) - Main Island - True - Quarry Between Entry Doors - 0x09D6F:
-158118 - 0x09E57 (Door to Quarry 1 Panel) - True - Squares & Black/White Squares
+Outside Quarry (Quarry) - Main Island - True - Quarry Between Entrys - 0x09D6F:
+158118 - 0x09E57 (Entry 1 Panel) - True - Black/White Squares
158120 - 0x17CC4 (Elevator Control) - 0x0367C - Dots & Eraser
158603 - 0x17CF0 (Discard) - True - Triangles
158702 - 0x03612 (Laser Panel) - 0x0A3D0 & 0x0367C - Eraser & Shapers
Laser - 0x01539 (Laser) - 0x03612
-Door - 0x09D6F (Door to Quarry 1) - 0x09E57
+Door - 0x09D6F (Entry 1) - 0x09E57
-Quarry Between Entry Doors (Quarry) - Quarry - 0x17C07:
-158119 - 0x17C09 (Door to Quarry 2 Panel) - True - Shapers
-Door - 0x17C07 (Door to Quarry 2) - 0x17C09
+Quarry Between Entrys (Quarry) - Quarry - 0x17C07:
+158119 - 0x17C09 (Entry 2 Panel) - True - Shapers
+Door - 0x17C07 (Entry 2) - 0x17C09
Quarry (Quarry) - Quarry Mill Ground Floor - 0x02010:
-158121 - 0x01E5A (Door to Mill Left) - True - Squares & Black/White Squares
-158122 - 0x01E59 (Door to Mill Right) - True - Dots
-Door - 0x02010 (Door to Mill) - 0x01E59 & 0x01E5A
+158121 - 0x01E5A (Mill Entry Left Panel) - True - Black/White Squares
+158122 - 0x01E59 (Mill Entry Right Panel) - True - Dots
+Door - 0x02010 (Mill Entry) - 0x01E59 & 0x01E5A
Quarry Mill Ground Floor (Quarry Mill) - Quarry - 0x275FF - Quarry Mill Middle Floor - 0x03678 - Outside Quarry - 0x17CE8:
-158123 - 0x275ED (Ground Floor Shortcut Door Panel) - True - True
-Door - 0x275FF (Ground Floor Shortcut Door) - 0x275ED
+158123 - 0x275ED (Side Exit Panel) - True - True
+Door - 0x275FF (Side Exit) - 0x275ED
158124 - 0x03678 (Lower Ramp Control) - True - Dots & Eraser
-158145 - 0x17CAC (Door to Outside Quarry Stairs Panel) - True - True
-Door - 0x17CE8 (Door to Outside Quarry Stairs) - 0x17CAC
+158145 - 0x17CAC (Roof Exit Panel) - True - True
+Door - 0x17CE8 (Roof Exit) - 0x17CAC
Quarry Mill Middle Floor (Quarry Mill) - Quarry Mill Ground Floor - 0x03675 - Quarry Mill Upper Floor - 0x03679:
-158125 - 0x00E0C (Eraser and Dots 1) - True - Dots & Eraser
-158126 - 0x01489 (Eraser and Dots 2) - 0x00E0C - Dots & Eraser
-158127 - 0x0148A (Eraser and Dots 3) - 0x01489 - Dots & Eraser
-158128 - 0x014D9 (Eraser and Dots 4) - 0x0148A - Dots & Eraser
-158129 - 0x014E7 (Eraser and Dots 5) - 0x014D9 - Dots & Eraser
-158130 - 0x014E8 (Eraser and Dots 6) - 0x014E7 - Dots & Eraser
+158125 - 0x00E0C (Lower Row 1) - True - Dots & Eraser
+158126 - 0x01489 (Lower Row 2) - 0x00E0C - Dots & Eraser
+158127 - 0x0148A (Lower Row 3) - 0x01489 - Dots & Eraser
+158128 - 0x014D9 (Lower Row 4) - 0x0148A - Dots & Eraser
+158129 - 0x014E7 (Lower Row 5) - 0x014D9 - Dots & Eraser
+158130 - 0x014E8 (Lower Row 6) - 0x014E7 - Dots & Eraser
158131 - 0x03679 (Lower Lift Control) - 0x014E8 - Dots & Eraser
Quarry Mill Upper Floor (Quarry Mill) - Quarry Mill Middle Floor - 0x03676 & 0x03679 - Quarry Mill Ground Floor - 0x0368A:
158132 - 0x03676 (Upper Ramp Control) - True - Dots & Eraser
158133 - 0x03675 (Upper Lift Control) - True - Dots & Eraser
-158134 - 0x00557 (Eraser and Squares 1) - True - Squares & Colored Squares & Eraser
-158135 - 0x005F1 (Eraser and Squares 2) - 0x00557 - Squares & Colored Squares & Eraser
-158136 - 0x00620 (Eraser and Squares 3) - 0x005F1 - Squares & Colored Squares & Eraser
-158137 - 0x009F5 (Eraser and Squares 4) - 0x00620 - Squares & Colored Squares & Eraser
-158138 - 0x0146C (Eraser and Squares 5) - 0x009F5 - Squares & Colored Squares & Eraser
-158139 - 0x3C12D (Eraser and Squares 6) - 0x0146C - Squares & Colored Squares & Eraser
-158140 - 0x03686 (Eraser and Squares 7) - 0x3C12D - Squares & Colored Squares & Eraser
-158141 - 0x014E9 (Eraser and Squares 8) - 0x03686 - Squares & Colored Squares & Eraser
-158142 - 0x03677 (Stair Control) - True - Squares & Colored Squares & Eraser
+158134 - 0x00557 (Upper Row 1) - True - Colored Squares & Eraser
+158135 - 0x005F1 (Upper Row 2) - 0x00557 - Colored Squares & Eraser
+158136 - 0x00620 (Upper Row 3) - 0x005F1 - Colored Squares & Eraser
+158137 - 0x009F5 (Upper Row 4) - 0x00620 - Colored Squares & Eraser
+158138 - 0x0146C (Upper Row 5) - 0x009F5 - Colored Squares & Eraser
+158139 - 0x3C12D (Upper Row 6) - 0x0146C - Colored Squares & Eraser
+158140 - 0x03686 (Upper Row 7) - 0x3C12D - Colored Squares & Eraser
+158141 - 0x014E9 (Upper Row 8) - 0x03686 - Colored Squares & Eraser
+158142 - 0x03677 (Stair Control) - True - Colored Squares & Eraser
Door - 0x0368A (Stairs) - 0x03677
-158143 - 0x3C125 (Big Squares & Dots & Eraser) - 0x0367C - Squares & Black/White Squares & Dots & Eraser
-158144 - 0x0367C (Small Squares & Dots & Eraser) - 0x014E9 - Squares & Colored Squares & Dots & Eraser
+158143 - 0x3C125 (Control Room Left) - 0x0367C - Black/White Squares & Dots & Eraser
+158144 - 0x0367C (Control Room Right) - 0x014E9 - Colored Squares & Dots & Eraser
Quarry Boathouse (Quarry Boathouse) - Quarry - True - Quarry Boathouse Upper Front - 0x03852 - Quarry Boathouse Behind Staircase - 0x2769B:
-158146 - 0x034D4 (Intro Stars) - True - Stars
-158147 - 0x021D5 (Intro Shapers) - True - Shapers & Rotated Shapers
+158146 - 0x034D4 (Intro Left) - True - Stars
+158147 - 0x021D5 (Intro Right) - True - Shapers & Rotated Shapers
158148 - 0x03852 (Ramp Height Control) - 0x034D4 & 0x021D5 - Rotated Shapers
158166 - 0x17CA6 (Boat Spawn) - True - Boat
-Door - 0x2769B (Boat Staircase) - 0x17CA6
-Door - 0x27163 (Boat Staircase Invis Barrier) - 0x17CA6
+Door - 0x2769B (Dock) - 0x17CA6
+Door - 0x27163 (Dock Invis Barrier) - 0x17CA6
Quarry Boathouse Behind Staircase (Quarry Boathouse) - Boat - 0x17CA6:
Quarry Boathouse Upper Front (Quarry Boathouse) - Quarry Boathouse Upper Middle - 0x17C50:
-158149 - 0x021B3 (Eraser and Shapers 1) - True - Shapers & Eraser
-158150 - 0x021B4 (Eraser and Shapers 2) - 0x021B3 - Shapers & Eraser
-158151 - 0x021B0 (Eraser and Shapers 3) - 0x021B4 - Shapers & Eraser
-158152 - 0x021AF (Eraser and Shapers 4) - 0x021B0 - Shapers & Eraser
-158153 - 0x021AE (Eraser and Shapers 5) - 0x021AF - Shapers & Eraser & Broken Shapers
-Door - 0x17C50 (Boathouse Barrier 1) - 0x021AE
+158149 - 0x021B3 (Front Row 1) - True - Shapers & Eraser
+158150 - 0x021B4 (Front Row 2) - 0x021B3 - Shapers & Eraser
+158151 - 0x021B0 (Front Row 3) - 0x021B4 - Shapers & Eraser
+158152 - 0x021AF (Front Row 4) - 0x021B0 - Shapers & Eraser
+158153 - 0x021AE (Front Row 5) - 0x021AF - Shapers & Eraser
+Door - 0x17C50 (First Barrier) - 0x021AE
Quarry Boathouse Upper Middle (Quarry Boathouse) - Quarry Boathouse Upper Back - 0x03858:
158154 - 0x03858 (Ramp Horizontal Control) - True - Shapers & Eraser
Quarry Boathouse Upper Back (Quarry Boathouse) - Quarry Boathouse Upper Middle - 0x3865F:
-158155 - 0x38663 (Shortcut Door Panel) - True - True
-Door - 0x3865F (Shortcut Door) - 0x38663
-158156 - 0x021B5 (Stars and Colored Eraser 1) - True - Stars & Stars + Same Colored Symbol & Eraser
-158157 - 0x021B6 (Stars and Colored Eraser 2) - 0x021B5 - Stars & Stars + Same Colored Symbol & Eraser
-158158 - 0x021B7 (Stars and Colored Eraser 3) - 0x021B6 - Stars & Stars + Same Colored Symbol & Eraser
-158159 - 0x021BB (Stars and Colored Eraser 4) - 0x021B7 - Stars & Stars + Same Colored Symbol & Eraser
-158160 - 0x09DB5 (Stars and Colored Eraser 5) - 0x021BB - Stars & Stars + Same Colored Symbol & Eraser
-158161 - 0x09DB1 (Stars and Colored Eraser 6) - 0x09DB5 - Stars & Stars + Same Colored Symbol & Eraser
-158162 - 0x3C124 (Stars and Colored Eraser 7) - 0x09DB1 - Stars & Stars + Same Colored Symbol & Eraser
-158163 - 0x09DB3 (Stars & Eraser & Shapers 1) - 0x3C124 - Stars & Eraser & Shapers
-158164 - 0x09DB4 (Stars & Eraser & Shapers 2) - 0x09DB3 - Stars & Eraser & Shapers
+158155 - 0x38663 (Second Barrier Panel) - True - True
+Door - 0x3865F (Second Barrier) - 0x38663
+158156 - 0x021B5 (Back First Row 1) - True - Stars & Stars + Same Colored Symbol & Eraser
+158157 - 0x021B6 (Back First Row 2) - 0x021B5 - Stars & Stars + Same Colored Symbol & Eraser
+158158 - 0x021B7 (Back First Row 3) - 0x021B6 - Stars & Stars + Same Colored Symbol & Eraser
+158159 - 0x021BB (Back First Row 4) - 0x021B7 - Stars & Stars + Same Colored Symbol & Eraser
+158160 - 0x09DB5 (Back First Row 5) - 0x021BB - Stars & Stars + Same Colored Symbol & Eraser
+158161 - 0x09DB1 (Back First Row 6) - 0x09DB5 - Stars & Stars + Same Colored Symbol & Eraser
+158162 - 0x3C124 (Back First Row 7) - 0x09DB1 - Stars & Stars + Same Colored Symbol & Eraser
+158163 - 0x09DB3 (Back First Row 8) - 0x3C124 - Stars & Eraser & Shapers
+158164 - 0x09DB4 (Back First Row 9) - 0x09DB3 - Stars & Eraser & Shapers
158165 - 0x275FA (Hook Control) - True - Shapers & Eraser
-158167 - 0x0A3CB (Stars & Eraser & Shapers 3) - 0x09DB4 - Stars & Eraser & Shapers
-158168 - 0x0A3CC (Stars & Eraser & Shapers 4) - 0x0A3CB - Stars & Eraser & Shapers
-158169 - 0x0A3D0 (Stars & Eraser & Shapers 5) - 0x0A3CC - Stars & Eraser & Shapers
+158167 - 0x0A3CB (Back Second Row 1) - 0x09DB4 - Stars & Eraser & Shapers
+158168 - 0x0A3CC (Back Second Row 2) - 0x0A3CB - Stars & Eraser & Shapers
+158169 - 0x0A3D0 (Back Second Row 3) - 0x0A3CC - Stars & Eraser & Shapers
Shadows (Shadows) - Main Island - True - Shadows Ledge - 0x19B24 - Shadows Laser Room - 0x194B2 & 0x19665:
158170 - 0x334DB (Door Timer Outside) - True - True
Door - 0x19B24 (Timed Door) - 0x334DB
-158171 - 0x0AC74 (Lower Avoid 6) - 0x0A8DC - Shadows Avoid
-158172 - 0x0AC7A (Lower Avoid 7) - 0x0AC74 - Shadows Avoid
-158173 - 0x0A8E0 (Lower Avoid 8) - 0x0AC7A - Shadows Avoid
-158174 - 0x386FA (Environmental Avoid 1) - 0x0A8E0 - Shadows Avoid & Environment
-158175 - 0x1C33F (Environmental Avoid 2) - 0x386FA - Shadows Avoid & Environment
-158176 - 0x196E2 (Environmental Avoid 3) - 0x1C33F - Shadows Avoid & Environment
-158177 - 0x1972A (Environmental Avoid 4) - 0x196E2 - Shadows Avoid & Environment
-158178 - 0x19809 (Environmental Avoid 5) - 0x1972A - Shadows Avoid & Environment
-158179 - 0x19806 (Environmental Avoid 6) - 0x19809 - Shadows Avoid & Environment
-158180 - 0x196F8 (Environmental Avoid 7) - 0x19806 - Shadows Avoid & Environment
-158181 - 0x1972F (Environmental Avoid 8) - 0x196F8 - Shadows Avoid & Environment
-Door - 0x194B2 (Laser Room Right Door) - 0x1972F
-158182 - 0x19797 (Follow 1) - 0x0A8E0 - Shadows Follow
-158183 - 0x1979A (Follow 2) - 0x19797 - Shadows Follow
-158184 - 0x197E0 (Follow 3) - 0x1979A - Shadows Follow
-158185 - 0x197E8 (Follow 4) - 0x197E0 - Shadows Follow
-158186 - 0x197E5 (Follow 5) - 0x197E8 - Shadows Follow
-Door - 0x19665 (Laser Room Left Door) - 0x197E5
+158171 - 0x0AC74 (Intro 6) - 0x0A8DC - True
+158172 - 0x0AC7A (Intro 7) - 0x0AC74 - True
+158173 - 0x0A8E0 (Intro 8) - 0x0AC7A - True
+158174 - 0x386FA (Far 1) - 0x0A8E0 - True
+158175 - 0x1C33F (Far 2) - 0x386FA - True
+158176 - 0x196E2 (Far 3) - 0x1C33F - True
+158177 - 0x1972A (Far 4) - 0x196E2 - True
+158178 - 0x19809 (Far 5) - 0x1972A - True
+158179 - 0x19806 (Far 6) - 0x19809 - True
+158180 - 0x196F8 (Far 7) - 0x19806 - True
+158181 - 0x1972F (Far 8) - 0x196F8 - True
+Door - 0x194B2 (Laser Entry Right) - 0x1972F
+158182 - 0x19797 (Near 1) - 0x0A8E0 - True
+158183 - 0x1979A (Near 2) - 0x19797 - True
+158184 - 0x197E0 (Near 3) - 0x1979A - True
+158185 - 0x197E8 (Near 4) - 0x197E0 - True
+158186 - 0x197E5 (Near 5) - 0x197E8 - True
+Door - 0x19665 (Laser Entry Left) - 0x197E5
Shadows Ledge (Shadows) - Shadows - 0x1855B - Quarry - 0x19865 & 0x0A2DF:
158187 - 0x334DC (Door Timer Inside) - True - True
-158188 - 0x198B5 (Lower Avoid 1) - True - Shadows Avoid
-158189 - 0x198BD (Lower Avoid 2) - 0x198B5 - Shadows Avoid
-158190 - 0x198BF (Lower Avoid 3) - 0x198BD & 0x334DC & 0x19B24 - Shadows Avoid
-Door - 0x19865 (Barrier to Quarry) - 0x198BF
-Door - 0x0A2DF (Barrier to Quarry 2) - 0x198BF
-158191 - 0x19771 (Lower Avoid 4) - 0x198BF - Shadows Avoid
-158192 - 0x0A8DC (Lower Avoid 5) - 0x19771 - Shadows Avoid
-Door - 0x1855B (Barrier to Shadows) - 0x0A8DC
-Door - 0x19ADE (Barrier to Shadows 2) - 0x0A8DC
+158188 - 0x198B5 (Intro 1) - True - True
+158189 - 0x198BD (Intro 2) - 0x198B5 - True
+158190 - 0x198BF (Intro 3) - 0x198BD & 0x334DC & 0x19B24 - True
+Door - 0x19865 (Quarry Barrier) - 0x198BF
+Door - 0x0A2DF (Quarry Barrier 2) - 0x198BF
+158191 - 0x19771 (Intro 4) - 0x198BF - True
+158192 - 0x0A8DC (Intro 5) - 0x19771 - True
+Door - 0x1855B (Ledge Barrier) - 0x0A8DC
+Door - 0x19ADE (Ledge Barrier 2) - 0x0A8DC
Shadows Laser Room (Shadows):
-158703 - 0x19650 (Laser Panel) - True - Shadows Avoid & Shadows Follow
+158703 - 0x19650 (Laser Panel) - True - True
Laser - 0x181B3 (Laser) - 0x19650
Keep (Keep) - Main Island - True - Keep 2nd Maze - 0x01954 - Keep 2nd Pressure Plate - 0x01BEC:
-158193 - 0x00139 (Hedge Maze 1) - True - Environment
+158193 - 0x00139 (Hedge Maze 1) - True - True
158197 - 0x0A3A8 (Reset Pressure Plates 1) - True - True
-158198 - 0x033EA (Pressure Plates 1) - 0x0A3A8 - Pressure Plates & Dots
-Door - 0x01954 (Hedge Maze 1 Exit Door) - 0x00139
-Door - 0x01BEC (Pressure Plates 1 Exit Door) - 0x033EA
+158198 - 0x033EA (Pressure Plates 1) - 0x0A3A8 - Dots
+Door - 0x01954 (Hedge Maze 1 Exit) - 0x00139
+Door - 0x01BEC (Pressure Plates 1 Exit) - 0x033EA
Keep 2nd Maze (Keep) - Keep - 0x018CE - Keep 3rd Maze - 0x019D8:
Door - 0x018CE (Hedge Maze 2 Shortcut) - 0x00139
-158194 - 0x019DC (Hedge Maze 2) - True - Environment
-Door - 0x019D8 (Hedge Maze 2 Exit Door) - 0x019DC
+158194 - 0x019DC (Hedge Maze 2) - True - True
+Door - 0x019D8 (Hedge Maze 2 Exit) - 0x019DC
Keep 3rd Maze (Keep) - Keep - 0x019B5 - Keep 4th Maze - 0x019E6:
Door - 0x019B5 (Hedge Maze 3 Shortcut) - 0x019DC
-158195 - 0x019E7 (Hedge Maze 3) - True - Environment & Sound
-Door - 0x019E6 (Hedge Maze 3 Exit Door) - 0x019E7
+158195 - 0x019E7 (Hedge Maze 3) - True - True
+Door - 0x019E6 (Hedge Maze 3 Exit) - 0x019E7
Keep 4th Maze (Keep) - Keep - 0x0199A - Keep Tower - 0x01A0E:
Door - 0x0199A (Hedge Maze 4 Shortcut) - 0x019E7
-158196 - 0x01A0F (Hedge Maze 4) - True - Environment
-Door - 0x01A0E (Hedge Maze 4 Exit Door) - 0x01A0F
+158196 - 0x01A0F (Hedge Maze 4) - True - True
+Door - 0x01A0E (Hedge Maze 4 Exit) - 0x01A0F
Keep 2nd Pressure Plate (Keep) - Keep 3rd Pressure Plate - 0x01BEA:
158199 - 0x0A3B9 (Reset Pressure Plates 2) - True - True
-158200 - 0x01BE9 (Pressure Plates 2) - 0x0A3B9 - Pressure Plates & Stars & Stars + Same Colored Symbol & Squares & Black/White Squares
-Door - 0x01BEA (Pressure Plates 2 Exit Door) - 0x01BE9
+158200 - 0x01BE9 (Pressure Plates 2) - 0x0A3B9 - Stars & Stars + Same Colored Symbol & Black/White Squares
+Door - 0x01BEA (Pressure Plates 2 Exit) - 0x01BE9
Keep 3rd Pressure Plate (Keep) - Keep 4th Pressure Plate - 0x01CD5:
158201 - 0x0A3BB (Reset Pressure Plates 3) - True - True
-158202 - 0x01CD3 (Pressure Plates 3) - 0x0A3BB - Pressure Plates & Shapers & Squares & Black/White Squares & Colored Squares
-Door - 0x01CD5 (Pressure Plates 3 Exit Door) - 0x01CD3
+158202 - 0x01CD3 (Pressure Plates 3) - 0x0A3BB - Shapers & Black/White Squares & Colored Squares
+Door - 0x01CD5 (Pressure Plates 3 Exit) - 0x01CD3
Keep 4th Pressure Plate (Keep) - Keep - 0x09E3D - Keep Tower - 0x01D40:
158203 - 0x0A3AD (Reset Pressure Plates 4) - True - True
-158204 - 0x01D3F (Pressure Plates 4) - 0x0A3AD - Pressure Plates & Shapers & Dots & Symmetry
-Door - 0x01D40 (Pressure Plates 4 Exit Door) - 0x01D3F
+158204 - 0x01D3F (Pressure Plates 4) - 0x0A3AD - Shapers & Dots & Symmetry
+Door - 0x01D40 (Pressure Plates 4 Exit) - 0x01D3F
158604 - 0x17D27 (Discard) - True - Triangles
-158205 - 0x09E49 (Shortcut to Shadows Panel) - True - True
-Door - 0x09E3D (Shortcut to Shadows) - 0x09E49
+158205 - 0x09E49 (Shadows Shortcut Panel) - True - True
+Door - 0x09E3D (Shadows Shortcut) - 0x09E49
Shipwreck (Shipwreck) - Keep 3rd Pressure Plate - True:
-158654 - 0x00AFB (Vault) - True - Symmetry & Sound & Sound Dots & Colored Dots
+158654 - 0x00AFB (Vault) - True - Symmetry & Sound Dots & Colored Dots
158655 - 0x03535 (Vault Box) - 0x00AFB - True
158605 - 0x17D28 (Discard) - True - Triangles
Keep Tower (Keep) - Keep - 0x04F8F:
-158206 - 0x0361B (Tower Shortcut to Keep Panel) - True - True
-Door - 0x04F8F (Tower Shortcut to Keep) - 0x0361B
-158704 - 0x0360E (Laser Panel Hedges) - 0x01A0F & 0x019E7 & 0x019DC & 0x00139 - Environment & Sound
-158705 - 0x03317 (Laser Panel Pressure Plates) - 0x01D3F - Shapers & Squares & Black/White Squares & Colored Squares & Stars & Stars + Same Colored Symbol & Dots
+158206 - 0x0361B (Tower Shortcut Panel) - True - True
+Door - 0x04F8F (Tower Shortcut) - 0x0361B
+158704 - 0x0360E (Laser Panel Hedges) - 0x01A0F & 0x019E7 & 0x019DC & 0x00139 - True
+158705 - 0x03317 (Laser Panel Pressure Plates) - 0x01D3F - Shapers & Black/White Squares & Colored Squares & Stars & Stars + Same Colored Symbol & Dots
Laser - 0x014BB (Laser) - 0x0360E | 0x03317
Outside Monastery (Monastery) - Main Island - True - Main Island - 0x0364E - Inside Monastery - 0x0C128 & 0x0C153 - Monastery Garden - 0x03750:
-158207 - 0x03713 (Shortcut Door Panel) - True - True
+158207 - 0x03713 (Shortcut Panel) - True - True
Door - 0x0364E (Shortcut) - 0x03713
-158208 - 0x00B10 (Door Open Left) - True - True
-158209 - 0x00C92 (Door Open Right) - True - True
-Door - 0x0C128 (Left Door) - 0x00B10
-Door - 0x0C153 (Right Door) - 0x00C92
-158210 - 0x00290 (Rhombic Avoid 1) - 0x09D9B - Environment
-158211 - 0x00038 (Rhombic Avoid 2) - 0x09D9B & 0x00290 - Environment
-158212 - 0x00037 (Rhombic Avoid 3) - 0x09D9B & 0x00038 - Environment
-Door - 0x03750 (Door to Garden) - 0x00037
+158208 - 0x00B10 (Entry Left) - True - True
+158209 - 0x00C92 (Entry Right) - True - True
+Door - 0x0C128 (Entry Inner) - 0x00B10
+Door - 0x0C153 (Entry Outer) - 0x00C92
+158210 - 0x00290 (Outside 1) - 0x09D9B - True
+158211 - 0x00038 (Outside 2) - 0x09D9B & 0x00290 - True
+158212 - 0x00037 (Outside 3) - 0x09D9B & 0x00038 - True
+Door - 0x03750 (Garden Entry) - 0x00037
158706 - 0x17CA4 (Laser Panel) - 0x193A6 - True
Laser - 0x17C65 (Laser) - 0x17CA4
Inside Monastery (Monastery):
-158213 - 0x09D9B (Overhead Door Control) - True - Dots
-158214 - 0x193A7 (Branch Avoid 1) - 0x00037 - Environment
-158215 - 0x193AA (Branch Avoid 2) - 0x193A7 - Environment
-158216 - 0x193AB (Branch Follow 1) - 0x193AA - Environment
-158217 - 0x193A6 (Branch Follow 2) - 0x193AB - Environment
+158213 - 0x09D9B (Shutters Control) - True - Dots
+158214 - 0x193A7 (Inside 1) - 0x00037 - True
+158215 - 0x193AA (Inside 2) - 0x193A7 - True
+158216 - 0x193AB (Inside 3) - 0x193AA - True
+158217 - 0x193A6 (Inside 4) - 0x193AB - True
Monastery Garden (Monastery):
Town (Town) - Main Island - True - Boat - 0x0A054 - Town Maze Rooftop - 0x28AA2 - Town Church - True - Town Wooden Rooftop - 0x034F5 - RGB House - 0x28A61 - Windmill Interior - 0x1845B - Town Inside Cargo Box - 0x0A0C9:
158218 - 0x0A054 (Boat Spawn) - 0x17CA6 | 0x17CDF | 0x09DB8 | 0x17C95 - Boat
-158219 - 0x0A0C8 (Cargo Box Panel) - True - Squares & Black/White Squares & Shapers
-Door - 0x0A0C9 (Cargo Box Door) - 0x0A0C8
+158219 - 0x0A0C8 (Cargo Box Entry Panel) - True - Black/White Squares & Shapers
+Door - 0x0A0C9 (Cargo Box Entry) - 0x0A0C8
158707 - 0x09F98 (Desert Laser Redirect) - True - True
-158220 - 0x18590 (Tree Outlines) - True - Symmetry & Environment
-158221 - 0x28AE3 (Vines Shadows Follow) - 0x18590 - Shadows Follow & Environment
-158222 - 0x28938 (Four-way Apple Tree) - 0x28AE3 - Environment
-158223 - 0x079DF (Triple Environmental Puzzle) - 0x28938 - Shadows Avoid & Environment & Reflection
-158235 - 0x2899C (Full Dot Grid Shapers 1) - True - Rotated Shapers & Dots
-158236 - 0x28A33 (Full Dot Grid Shapers 2) - 0x2899C - Shapers & Dots
-158237 - 0x28ABF (Full Dot Grid Shapers 3) - 0x28A33 - Shapers & Rotated Shapers & Dots
-158238 - 0x28AC0 (Full Dot Grid Shapers 4) - 0x28ABF - Rotated Shapers & Dots
-158239 - 0x28AC1 (Full Dot Grid Shapers 5) - 0x28AC0 - Rotated Shapers & Dots
-Door - 0x034F5 (Wooden Roof Staircase) - 0x28AC1
-158225 - 0x28998 (Tinted Door Panel) - True - Stars & Rotated Shapers
-Door - 0x28A61 (Tinted Door to RGB House) - 0x28998
-158226 - 0x28A0D (Door to Church Stars Panel) - 0x28998 - Stars & RGB & Environment
-Door - 0x03BB0 (Door to Church) - 0x28A0D
-158228 - 0x28A79 (Maze Stair Control) - True - Environment
-Door - 0x28AA2 (Maze Staircase) - 0x28A79
-158241 - 0x17F5F (Windmill Door Panel) - True - Dots
-Door - 0x1845B (Windmill Door) - 0x17F5F
+158220 - 0x18590 (Transparent) - True - Symmetry
+158221 - 0x28AE3 (Vines) - 0x18590 - True
+158222 - 0x28938 (Apple Tree) - 0x28AE3 - True
+158223 - 0x079DF (Triple Exit) - 0x28938 - True
+158235 - 0x2899C (Wooden Roof Lower Row 1) - True - Rotated Shapers & Dots
+158236 - 0x28A33 (Wooden Roof Lower Row 2) - 0x2899C - Shapers & Dots
+158237 - 0x28ABF (Wooden Roof Lower Row 3) - 0x28A33 - Shapers & Rotated Shapers & Dots
+158238 - 0x28AC0 (Wooden Roof Lower Row 4) - 0x28ABF - Rotated Shapers & Dots
+158239 - 0x28AC1 (Wooden Roof Lower Row 5) - 0x28AC0 - Rotated Shapers & Dots
+Door - 0x034F5 (Wooden Roof Stairs) - 0x28AC1
+158225 - 0x28998 (Tinted Glass Door Panel) - True - Stars & Rotated Shapers
+Door - 0x28A61 (Tinted Glass Door) - 0x28998
+158226 - 0x28A0D (Church Entry Panel) - 0x28A61 - Stars
+Door - 0x03BB0 (Church Entry) - 0x28A0D
+158228 - 0x28A79 (Maze Stair Control) - True - True
+Door - 0x28AA2 (Maze Stairs) - 0x28A79
+158241 - 0x17F5F (Windmill Entry Panel) - True - Dots
+Door - 0x1845B (Windmill Entry) - 0x17F5F
Town Inside Cargo Box (Town):
158606 - 0x17D01 (Cargo Box Discard) - True - Triangles
@@ -413,34 +413,34 @@ Town Maze Rooftop (Town) - Town Red Rooftop - 0x2896A:
Town Red Rooftop (Town):
158607 - 0x17C71 (Rooftop Discard) - True - Triangles
-158230 - 0x28AC7 (Symmetry Squares 1) - True - Symmetry & Squares & Black/White Squares
-158231 - 0x28AC8 (Symmetry Squares 2) - 0x28AC7 - Symmetry & Squares & Black/White Squares
-158232 - 0x28ACA (Symmetry Squares 3 + Dots) - 0x28AC8 - Symmetry & Squares & Black/White Squares & Dots
-158233 - 0x28ACB (Symmetry Squares 4 + Dots) - 0x28ACA - Symmetry & Squares & Black/White Squares & Dots
-158234 - 0x28ACC (Symmetry Squares 5 + Dots) - 0x28ACB - Symmetry & Squares & Black/White Squares & Dots
-158224 - 0x28B39 (Hexagonal Reflection) - 0x079DF - Reflection
+158230 - 0x28AC7 (Red Rooftop 1) - True - Symmetry & Black/White Squares
+158231 - 0x28AC8 (Red Rooftop 2) - 0x28AC7 - Symmetry & Black/White Squares
+158232 - 0x28ACA (Red Rooftop 3) - 0x28AC8 - Symmetry & Black/White Squares & Dots
+158233 - 0x28ACB (Red Rooftop 4) - 0x28ACA - Symmetry & Black/White Squares & Dots
+158234 - 0x28ACC (Red Rooftop 5) - 0x28ACB - Symmetry & Black/White Squares & Dots
+158224 - 0x28B39 (Tall Hexagonal) - 0x079DF - True
Town Wooden Rooftop (Town):
-158240 - 0x28AD9 (Shapers & Dots & Eraser) - 0x28AC1 - Rotated Shapers & Dots & Eraser
+158240 - 0x28AD9 (Wooden Rooftop) - 0x28AC1 - Rotated Shapers & Dots & Eraser
Town Church (Town):
-158227 - 0x28A69 (Church Lattice) - 0x03BB0 - Environment
+158227 - 0x28A69 (Church Lattice) - 0x03BB0 - True
RGB House (Town) - RGB Room - 0x2897B:
-158242 - 0x034E4 (Sound Room Left) - True - Sound & Sound Waves
-158243 - 0x034E3 (Sound Room Right) - True - Sound & Sound Dots
-Door - 0x2897B (RGB House Staircase) - 0x034E4 & 0x034E3
+158242 - 0x034E4 (Sound Room Left) - True - True
+158243 - 0x034E3 (Sound Room Right) - True - Sound Dots
+Door - 0x2897B (RGB House Stairs) - 0x034E4 & 0x034E3
RGB Room (Town):
-158244 - 0x334D8 (RGB Control) - True - Rotated Shapers & RGB & Squares & Colored Squares
-158245 - 0x03C0C (RGB Squares) - 0x334D8 - RGB & Squares & Colored Squares & Black/White Squares
-158246 - 0x03C08 (RGB Stars) - 0x334D8 - RGB & Stars
+158244 - 0x334D8 (RGB Control) - True - Rotated Shapers & Colored Squares
+158245 - 0x03C0C (RGB Room Left) - 0x334D8 - Colored Squares & Black/White Squares
+158246 - 0x03C08 (RGB Room Right) - 0x334D8 - Stars
Town Tower (Town Tower) - Town - True - Town Tower Top - 0x27798 & 0x27799 & 0x2779A & 0x2779C:
-Door - 0x27798 (Blue Panels Door) - 0x28ACC
-Door - 0x27799 (Church Lattice Door) - 0x28A69
-Door - 0x2779A (Environmental Set Door) - 0x28B39
-Door - 0x2779C (Eraser Set Door) - 0x28AD9
+Door - 0x27798 (First Door) - 0x28ACC
+Door - 0x2779C (Second Door) - 0x28AD9
+Door - 0x27799 (Third Door) - 0x28A69
+Door - 0x2779A (Fourth Door) - 0x28B39
Town Tower Top (Town):
158708 - 0x032F5 (Laser Panel) - True - True
@@ -448,8 +448,8 @@ Laser - 0x032F9 (Laser) - 0x032F5
Windmill Interior (Windmill) - Theater - 0x17F88:
158247 - 0x17D02 (Turn Control) - True - Dots
-158248 - 0x17F89 (Door to Front of Theater Panel) - True - Squares & Black/White Squares
-Door - 0x17F88 (Door to Front of Theater) - 0x17F89
+158248 - 0x17F89 (Theater Entry Panel) - True - Black/White Squares
+Door - 0x17F88 (Theater Entry) - 0x17F89
Theater (Theater) - Town - 0x0A16D | 0x3CCDF:
158656 - 0x00815 (Video Input) - True - True
@@ -459,73 +459,73 @@ Theater (Theater) - Town - 0x0A16D | 0x3CCDF:
158660 - 0x03549 (Challenge Video) - 0x00815 & 0x0356B - True
158661 - 0x0354F (Shipwreck Video) - 0x00815 & 0x03535 - True
158662 - 0x03545 (Mountain Video) - 0x00815 & 0x03542 - True
-158249 - 0x0A168 (Door to Cargo Box Left Panel) - True - Squares & Black/White Squares & Eraser
-158250 - 0x33AB2 (Door to Cargo Box Right Panel) - True - Squares & Black/White Squares & Shapers
-Door - 0x0A16D (Door to Cargo Box Left) - 0x0A168
-Door - 0x3CCDF (Door to Cargo Box Right) - 0x33AB2
+158249 - 0x0A168 (Exit Left Panel) - True - Black/White Squares & Eraser
+158250 - 0x33AB2 (Exit Right Panel) - True - Black/White Squares & Shapers
+Door - 0x0A16D (Exit Left) - 0x0A168
+Door - 0x3CCDF (Exit Right) - 0x33AB2
158608 - 0x17CF7 (Discard) - True - Triangles
Jungle (Jungle) - Main Island - True - Outside Jungle River - 0x3873B - Boat - 0x17CDF:
158251 - 0x17CDF (Shore Boat Spawn) - True - Boat
158609 - 0x17F9B (Discard) - True - Triangles
-158252 - 0x002C4 (Waves 1) - True - Sound & Sound Waves
-158253 - 0x00767 (Waves 2) - 0x002C4 - Sound & Sound Waves
-158254 - 0x002C6 (Waves 3) - 0x00767 - Sound & Sound Waves
-158255 - 0x0070E (Waves 4) - 0x002C6 - Sound & Sound Waves
-158256 - 0x0070F (Waves 5) - 0x0070E - Sound & Sound Waves
-158257 - 0x0087D (Waves 6) - 0x0070F - Sound & Sound Waves
-158258 - 0x002C7 (Waves 7) - 0x0087D - Sound & Sound Waves
+158252 - 0x002C4 (First Row 1) - True - True
+158253 - 0x00767 (First Row 2) - 0x002C4 - True
+158254 - 0x002C6 (First Row 3) - 0x00767 - True
+158255 - 0x0070E (Second Row 1) - 0x002C6 - True
+158256 - 0x0070F (Second Row 2) - 0x0070E - True
+158257 - 0x0087D (Second Row 3) - 0x0070F - True
+158258 - 0x002C7 (Second Row 4) - 0x0087D - True
158259 - 0x17CAB (Popup Wall Control) - 0x002C7 - True
Door - 0x1475B (Popup Wall) - 0x17CAB
-158260 - 0x0026D (Popup Wall 1) - 0x1475B - Sound & Sound Dots
-158261 - 0x0026E (Popup Wall 2) - 0x0026D - Sound & Sound Dots
-158262 - 0x0026F (Popup Wall 3) - 0x0026E - Sound & Sound Dots
-158263 - 0x00C3F (Popup Wall 4) - 0x0026F - Sound & Sound Dots
-158264 - 0x00C41 (Popup Wall 5) - 0x00C3F - Sound & Sound Dots
-158265 - 0x014B2 (Popup Wall 6) - 0x00C41 - Sound & Sound Dots
+158260 - 0x0026D (Popup Wall 1) - 0x1475B - Sound Dots
+158261 - 0x0026E (Popup Wall 2) - 0x0026D - Sound Dots
+158262 - 0x0026F (Popup Wall 3) - 0x0026E - Sound Dots
+158263 - 0x00C3F (Popup Wall 4) - 0x0026F - Sound Dots
+158264 - 0x00C41 (Popup Wall 5) - 0x00C3F - Sound Dots
+158265 - 0x014B2 (Popup Wall 6) - 0x00C41 - Sound Dots
158709 - 0x03616 (Laser Panel) - 0x014B2 - True
Laser - 0x00274 (Laser) - 0x03616
-158266 - 0x337FA (Shortcut to River Panel) - True - True
-Door - 0x3873B (Shortcut to River) - 0x337FA
+158266 - 0x337FA (Laser Shortcut Panel) - True - True
+Door - 0x3873B (Laser Shortcut) - 0x337FA
Outside Jungle River (River) - Main Island - True - Monastery Garden - 0x0CF2A:
-158267 - 0x17CAA (Rhombic Avoid to Monastery Garden) - True - Environment
-Door - 0x0CF2A (Shortcut to Monastery Garden) - 0x17CAA
-158663 - 0x15ADD (Vault) - True - Environment & Black/White Squares & Dots
+158267 - 0x17CAA (Monastery Shortcut Panel) - True - True
+Door - 0x0CF2A (Monastery Shortcut) - 0x17CAA
+158663 - 0x15ADD (Vault) - True - Black/White Squares & Dots
158664 - 0x03702 (Vault Box) - 0x15ADD - True
-Outside Bunker (Bunker) - Main Island - True - Inside Bunker - 0x0C2A4:
-158268 - 0x17C2E (Bunker Entry Panel) - True - Squares & Black/White Squares & Colored Squares
-Door - 0x0C2A4 (Bunker Entry Door) - 0x17C2E
+Outside Bunker (Bunker) - Main Island - True - Bunker - 0x0C2A4:
+158268 - 0x17C2E (Entry Panel) - True - Black/White Squares & Colored Squares
+Door - 0x0C2A4 (Entry) - 0x17C2E
-Inside Bunker (Bunker) - Inside Bunker Glass Room - 0x17C79:
-158269 - 0x09F7D (Drawn Squares 1) - True - Squares & Colored Squares
-158270 - 0x09FDC (Drawn Squares 2) - 0x09F7D - Squares & Colored Squares & Black/White Squares
-158271 - 0x09FF7 (Drawn Squares 3) - 0x09FDC - Squares & Colored Squares & Black/White Squares
-158272 - 0x09F82 (Drawn Squares 4) - 0x09FF7 - Squares & Colored Squares & Black/White Squares
-158273 - 0x09FF8 (Drawn Squares 5) - 0x09F82 - Squares & Colored Squares & Black/White Squares
-158274 - 0x09D9F (Drawn Squares 6) - 0x09FF8 - Squares & Colored Squares & Black/White Squares
-158275 - 0x09DA1 (Drawn Squares 7) - 0x09D9F - Squares & Colored Squares
-158276 - 0x09DA2 (Drawn Squares 8) - 0x09DA1 - Squares & Colored Squares
-158277 - 0x09DAF (Drawn Squares 9) - 0x09DA2 - Squares & Colored Squares
-158278 - 0x0A099 (Door to Bunker Proper Panel) - 0x09DAF - True
-Door - 0x17C79 (Door to Bunker Proper) - 0x0A099
+Bunker (Bunker) - Bunker Glass Room - 0x17C79:
+158269 - 0x09F7D (Intro Left 1) - True - Colored Squares
+158270 - 0x09FDC (Intro Left 2) - 0x09F7D - Colored Squares & Black/White Squares
+158271 - 0x09FF7 (Intro Left 3) - 0x09FDC - Colored Squares & Black/White Squares
+158272 - 0x09F82 (Intro Left 4) - 0x09FF7 - Colored Squares & Black/White Squares
+158273 - 0x09FF8 (Intro Left 5) - 0x09F82 - Colored Squares & Black/White Squares
+158274 - 0x09D9F (Intro Back 1) - 0x09FF8 - Colored Squares & Black/White Squares
+158275 - 0x09DA1 (Intro Back 2) - 0x09D9F - Colored Squares
+158276 - 0x09DA2 (Intro Back 3) - 0x09DA1 - Colored Squares
+158277 - 0x09DAF (Intro Back 4) - 0x09DA2 - Colored Squares
+158278 - 0x0A099 (Tinted Glass Door Panel) - 0x09DAF - True
+Door - 0x17C79 (Tinted Glass Door) - 0x0A099
-Inside Bunker Glass Room (Bunker) - Inside Bunker Ultraviolet Room - 0x0C2A3:
-158279 - 0x0A010 (Drawn Squares through Tinted Glass 1) - True - Squares & Colored Squares & RGB & Environment
-158280 - 0x0A01B (Drawn Squares through Tinted Glass 2) - 0x0A010 - Squares & Colored Squares & Black/White Squares & RGB & Environment
-158281 - 0x0A01F (Drawn Squares through Tinted Glass 3) - 0x0A01B - Squares & Colored Squares & Black/White Squares & RGB & Environment
-Door - 0x0C2A3 (Door to Ultraviolet Room) - 0x0A01F
+Bunker Glass Room (Bunker) - Bunker Ultraviolet Room - 0x0C2A3:
+158279 - 0x0A010 (Glass Room 1) - True - Colored Squares
+158280 - 0x0A01B (Glass Room 2) - 0x0A010 - Colored Squares & Black/White Squares
+158281 - 0x0A01F (Glass Room 3) - 0x0A01B - Colored Squares & Black/White Squares
+Door - 0x0C2A3 (UV Room Entry) - 0x0A01F
-Inside Bunker Ultraviolet Room (Bunker) - Inside Bunker Elevator Section - 0x0A08D:
+Bunker Ultraviolet Room (Bunker) - Bunker Elevator Section - 0x0A08D:
158282 - 0x34BC5 (Drop-Down Door Open) - True - True
158283 - 0x34BC6 (Drop-Down Door Close) - 0x34BC5 - True
-158284 - 0x17E63 (Drop-Down Door Squares 1) - 0x34BC5 - Squares & Colored Squares & RGB & Environment
-158285 - 0x17E67 (Drop-Down Door Squares 2) - 0x17E63 & 0x34BC6 - Squares & Colored Squares & Black/White Squares & RGB
-Door - 0x0A08D (Door to Elevator) - 0x17E67
+158284 - 0x17E63 (UV Room 1) - 0x34BC5 - Colored Squares
+158285 - 0x17E67 (UV Room 2) - 0x17E63 & 0x34BC6 - Colored Squares & Black/White Squares
+Door - 0x0A08D (Elevator Room Entry) - 0x17E67
-Inside Bunker Elevator Section (Bunker) - Bunker Laser Platform - 0x0A079:
-158286 - 0x0A079 (Elevator Control) - True - Squares & Colored Squares & Black/White Squares & RGB
+Bunker Elevator Section (Bunker) - Bunker Laser Platform - 0x0A079:
+158286 - 0x0A079 (Elevator Control) - True - Colored Squares & Black/White Squares
Bunker Laser Platform (Bunker):
158710 - 0x09DE0 (Laser Panel) - True - True
@@ -533,76 +533,76 @@ Laser - 0x0C2B2 (Laser) - 0x09DE0
Outside Swamp (Swamp) - Swamp Entry Area - 0x00C1C - Main Island - True:
158287 - 0x0056E (Entry Panel) - True - Shapers
-Door - 0x00C1C (Entry Door) - 0x0056E
+Door - 0x00C1C (Entry) - 0x0056E
Swamp Entry Area (Swamp) - Swamp Sliding Bridge - TrueOneWay:
-158288 - 0x00469 (Seperatable Shapers 1) - True - Shapers
-158289 - 0x00472 (Seperatable Shapers 2) - 0x00469 - Shapers
-158290 - 0x00262 (Seperatable Shapers 3) - 0x00472 - Shapers
-158291 - 0x00474 (Seperatable Shapers 4) - 0x00262 - Shapers
-158292 - 0x00553 (Seperatable Shapers 5) - 0x00474 - Shapers
-158293 - 0x0056F (Seperatable Shapers 6) - 0x00553 - Shapers
-158294 - 0x00390 (Combinable Shapers 1) - 0x0056F - Shapers
-158295 - 0x010CA (Combinable Shapers 2) - 0x00390 - Shapers
-158296 - 0x00983 (Combinable Shapers 3) - 0x010CA - Shapers
-158297 - 0x00984 (Combinable Shapers 4) - 0x00983 - Shapers
-158298 - 0x00986 (Combinable Shapers 5) - 0x00984 - Shapers
-158299 - 0x00985 (Combinable Shapers 6) - 0x00986 - Shapers
-158300 - 0x00987 (Combinable Shapers 7) - 0x00985 - Shapers
-158301 - 0x181A9 (Combinable Shapers 8) - 0x00987 - Shapers
+158288 - 0x00469 (Intro Front 1) - True - Shapers
+158289 - 0x00472 (Intro Front 2) - 0x00469 - Shapers
+158290 - 0x00262 (Intro Front 3) - 0x00472 - Shapers
+158291 - 0x00474 (Intro Front 4) - 0x00262 - Shapers
+158292 - 0x00553 (Intro Front 5) - 0x00474 - Shapers
+158293 - 0x0056F (Intro Front 6) - 0x00553 - Shapers
+158294 - 0x00390 (Intro Back 1) - 0x0056F - Shapers
+158295 - 0x010CA (Intro Back 2) - 0x00390 - Shapers
+158296 - 0x00983 (Intro Back 3) - 0x010CA - Shapers
+158297 - 0x00984 (Intro Back 4) - 0x00983 - Shapers
+158298 - 0x00986 (Intro Back 5) - 0x00984 - Shapers
+158299 - 0x00985 (Intro Back 6) - 0x00986 - Shapers
+158300 - 0x00987 (Intro Back 7) - 0x00985 - Shapers
+158301 - 0x181A9 (Intro Back 8) - 0x00987 - Shapers
Swamp Sliding Bridge (Swamp) - Swamp Entry Area - 0x00609 - Swamp Near Platform - 0x00609:
158302 - 0x00609 (Sliding Bridge) - True - Shapers
-Swamp Near Platform (Swamp) - Swamp Cyan Underwater - 0x04B7F - Swamp Near Boat - 0x38AE6 - Swamp Broken Shapers - 0x184B7 - Swamp Sliding Bridge - TrueOneWay:
-158313 - 0x00982 (Platform Shapers 1) - True - Shapers
-158314 - 0x0097F (Platform Shapers 2) - 0x00982 - Shapers
-158315 - 0x0098F (Platform Shapers 3) - 0x0097F - Shapers
-158316 - 0x00990 (Platform Shapers 4) - 0x0098F - Shapers
-Door - 0x184B7 (Door to Broken Shapers) - 0x00990
+Swamp Near Platform (Swamp) - Swamp Cyan Underwater - 0x04B7F - Swamp Near Boat - 0x38AE6 - Swamp Between Bridges Near - 0x184B7 - Swamp Sliding Bridge - TrueOneWay:
+158313 - 0x00982 (Platform Row 1) - True - Shapers
+158314 - 0x0097F (Platform Row 2) - 0x00982 - Shapers
+158315 - 0x0098F (Platform Row 3) - 0x0097F - Shapers
+158316 - 0x00990 (Platform Row 4) - 0x0098F - Shapers
+Door - 0x184B7 (Between Bridges First Door) - 0x00990
158317 - 0x17C0D (Platform Shortcut Left Panel) - True - Shapers
158318 - 0x17C0E (Platform Shortcut Right Panel) - True - Shapers
Door - 0x38AE6 (Platform Shortcut Door) - 0x17C0E
Door - 0x04B7F (Cyan Water Pump) - 0x00006
Swamp Cyan Underwater (Swamp):
-158307 - 0x00002 (Cyan Underwater Negative Shapers 1) - True - Shapers & Negative Shapers
-158308 - 0x00004 (Cyan Underwater Negative Shapers 2) - 0x00002 - Shapers & Negative Shapers
-158309 - 0x00005 (Cyan Underwater Negative Shapers 3) - 0x00004 - Shapers & Negative Shapers
-158310 - 0x013E6 (Cyan Underwater Negative Shapers 4) - 0x00005 - Shapers & Negative Shapers
-158311 - 0x00596 (Cyan Underwater Negative Shapers 5) - 0x013E6 - Shapers & Negative Shapers
+158307 - 0x00002 (Cyan Underwater 1) - True - Shapers & Negative Shapers
+158308 - 0x00004 (Cyan Underwater 2) - 0x00002 - Shapers & Negative Shapers
+158309 - 0x00005 (Cyan Underwater 3) - 0x00004 - Shapers & Negative Shapers
+158310 - 0x013E6 (Cyan Underwater 4) - 0x00005 - Shapers & Negative Shapers
+158311 - 0x00596 (Cyan Underwater 5) - 0x013E6 - Shapers & Negative Shapers
158312 - 0x18488 (Cyan Underwater Sliding Bridge Control) - True - Shapers
-Swamp Broken Shapers (Swamp) - Swamp Rotated Shapers - 0x18507:
-158303 - 0x00999 (Broken Shapers 1) - 0x00990 - Shapers & Broken Shapers
-158304 - 0x0099D (Broken Shapers 2) - 0x00999 - Shapers & Broken Shapers
-158305 - 0x009A0 (Broken Shapers 3) - 0x0099D - Shapers & Broken Shapers
-158306 - 0x009A1 (Broken Shapers 4) - 0x009A0 - Shapers & Broken Shapers
-Door - 0x18507 (Door to Rotated Shapers) - 0x009A1
+Swamp Between Bridges Near (Swamp) - Swamp Between Bridges Far - 0x18507:
+158303 - 0x00999 (Between Bridges Near Row 1) - 0x00990 - Shapers
+158304 - 0x0099D (Between Bridges Near Row 2) - 0x00999 - Shapers
+158305 - 0x009A0 (Between Bridges Near Row 3) - 0x0099D - Shapers
+158306 - 0x009A1 (Between Bridges Near Row 4) - 0x009A0 - Shapers
+Door - 0x18507 (Between Bridges Second Door) - 0x009A1
-Swamp Rotated Shapers (Swamp) - Swamp Red Underwater - 0x183F2 - Swamp Rotating Bridge - TrueOneWay:
-158319 - 0x00007 (Rotated Shapers 1) - 0x009A1 - Rotated Shapers
-158320 - 0x00008 (Rotated Shapers 2) - 0x00007 - Rotated Shapers & Shapers
-158321 - 0x00009 (Rotated Shapers 3) - 0x00008 - Rotated Shapers
-158322 - 0x0000A (Rotated Shapers 4) - 0x00009 - Rotated Shapers
+Swamp Between Bridges Far (Swamp) - Swamp Red Underwater - 0x183F2 - Swamp Rotating Bridge - TrueOneWay:
+158319 - 0x00007 (Between Bridges Far Row 1) - 0x009A1 - Rotated Shapers
+158320 - 0x00008 (Between Bridges Far Row 2) - 0x00007 - Rotated Shapers & Shapers
+158321 - 0x00009 (Between Bridges Far Row 3) - 0x00008 - Rotated Shapers
+158322 - 0x0000A (Between Bridges Far Row 4) - 0x00009 - Rotated Shapers
Door - 0x183F2 (Red Water Pump) - 0x00596
-Swamp Red Underwater (Swamp) - Swamp Maze - 0x014D1:
-158323 - 0x00001 (Red Underwater Negative Shapers 1) - True - Shapers & Negative Shapers
-158324 - 0x014D2 (Red Underwater Negative Shapers 2) - True - Shapers & Negative Shapers
-158325 - 0x014D4 (Red Underwater Negative Shapers 3) - True - Shapers & Negative Shapers
-158326 - 0x014D1 (Red Underwater Negative Shapers 4) - True - Shapers & Negative Shapers
+Swamp Red Underwater (Swamp) - Swamp Maze - 0x305D5:
+158323 - 0x00001 (Red Underwater 1) - True - Shapers & Negative Shapers
+158324 - 0x014D2 (Red Underwater 2) - True - Shapers & Negative Shapers
+158325 - 0x014D4 (Red Underwater 3) - True - Shapers & Negative Shapers
+158326 - 0x014D1 (Red Underwater 4) - True - Shapers & Negative Shapers
Door - 0x305D5 (Red Underwater Exit) - 0x014D1
-Swamp Rotating Bridge (Swamp) - Swamp Rotated Shapers - 0x181F5 - Swamp Near Boat - 0x181F5 - Swamp Purple Area - 0x181F5:
+Swamp Rotating Bridge (Swamp) - Swamp Between Bridges Far - 0x181F5 - Swamp Near Boat - 0x181F5 - Swamp Purple Area - 0x181F5:
158327 - 0x181F5 (Rotating Bridge) - True - Rotated Shapers & Shapers
Swamp Near Boat (Swamp) - Swamp Rotating Bridge - TrueOneWay - Swamp Blue Underwater - 0x18482:
158328 - 0x09DB8 (Boat Spawn) - True - Boat
-158329 - 0x003B2 (More Rotated Shapers 1) - 0x0000A - Rotated Shapers
-158330 - 0x00A1E (More Rotated Shapers 2) - 0x003B2 - Rotated Shapers
-158331 - 0x00C2E (More Rotated Shapers 3) - 0x00A1E - Rotated Shapers
-158332 - 0x00E3A (More Rotated Shapers 4) - 0x00C2E - Rotated Shapers
+158329 - 0x003B2 (Beyond Rotating Bridge 1) - 0x0000A - Rotated Shapers
+158330 - 0x00A1E (Beyond Rotating Bridge 2) - 0x003B2 - Rotated Shapers
+158331 - 0x00C2E (Beyond Rotating Bridge 3) - 0x00A1E - Rotated Shapers
+158332 - 0x00E3A (Beyond Rotating Bridge 4) - 0x00C2E - Rotated Shapers
158339 - 0x17E2B (Long Bridge Control) - True - Rotated Shapers & Shapers
Door - 0x18482 (Blue Water Pump) - 0x00E3A
@@ -610,25 +610,25 @@ Swamp Purple Area (Swamp) - Swamp Rotating Bridge - TrueOneWay - Swamp Purple Un
Door - 0x0A1D6 (Purple Water Pump) - 0x00E3A
Swamp Purple Underwater (Swamp):
-158333 - 0x009A6 (Underwater Back Optional) - True - Shapers
+158333 - 0x009A6 (Purple Underwater) - True - Shapers
Swamp Blue Underwater (Swamp):
-158334 - 0x009AB (Blue Underwater Negative Shapers 1) - True - Shapers & Negative Shapers
-158335 - 0x009AD (Blue Underwater Negative Shapers 2) - 0x009AB - Shapers & Negative Shapers
-158336 - 0x009AE (Blue Underwater Negetive Shapers 3) - 0x009AD - Shapers & Negative Shapers
-158337 - 0x009AF (Blue Underwater Negative Shapers 4) - 0x009AE - Shapers & Negative Shapers
-158338 - 0x00006 (Blue Underwater Negative Shapers 5) - 0x009AF - Shapers & Negative Shapers & Broken Negative Shapers
+158334 - 0x009AB (Blue Underwater 1) - True - Shapers & Negative Shapers
+158335 - 0x009AD (Blue Underwater 2) - 0x009AB - Shapers & Negative Shapers
+158336 - 0x009AE (Blue Underwater 3) - 0x009AD - Shapers & Negative Shapers
+158337 - 0x009AF (Blue Underwater 4) - 0x009AE - Shapers & Negative Shapers
+158338 - 0x00006 (Blue Underwater 5) - 0x009AF - Shapers & Negative Shapers
Swamp Maze (Swamp) - Swamp Laser Area - 0x17C0A & 0x17E07:
-158340 - 0x17C0A (Maze Control) - True - Shapers & Negative Shapers & Rotated Shapers & Environment
-158112 - 0x17E07 (Maze Control Other Side) - True - Shapers & Negative Shapers & Rotated Shapers & Environment
+158340 - 0x17C0A (Maze Control) - True - Shapers & Negative Shapers & Rotated Shapers
+158112 - 0x17E07 (Maze Control Other Side) - True - Shapers & Negative Shapers & Rotated Shapers
Swamp Laser Area (Swamp) - Outside Swamp - 0x2D880:
158711 - 0x03615 (Laser Panel) - True - True
Laser - 0x00BF6 (Laser) - 0x03615
-158341 - 0x17C05 (Near Laser Shortcut Left Panel) - True - Rotated Shapers
-158342 - 0x17C02 (Near Laser Shortcut Right Panel) - 0x17C05 - Shapers & Negative Shapers & Rotated Shapers
-Door - 0x2D880 (Near Laser Shortcut) - 0x17C02
+158341 - 0x17C05 (Laser Shortcut Left Panel) - True - Rotated Shapers
+158342 - 0x17C02 (Laser Shortcut Right Panel) - 0x17C05 - Shapers & Negative Shapers & Rotated Shapers
+Door - 0x2D880 (Laser Shortcut) - 0x17C02
Treehouse Entry Area (Treehouse) - Treehouse Between Doors - 0x0C309:
158343 - 0x17C95 (Boat Spawn) - True - Boat
@@ -651,8 +651,8 @@ Treehouse Yellow Bridge (Treehouse) - Treehouse After Yellow Bridge - 0x17DC4:
158354 - 0x17DC4 (Yellow Bridge 9) - 0x17DC2 - Stars
Treehouse After Yellow Bridge (Treehouse) - Treehouse Junction - 0x0A181:
-158355 - 0x0A182 (Beyond Yellow Bridge Door Panel) - True - Stars
-Door - 0x0A181 (Beyond Yellow Bridge Door) - 0x0A182
+158355 - 0x0A182 (Third Door Panel) - True - Stars
+Door - 0x0A181 (Third Door) - 0x0A182
Treehouse Junction (Treehouse) - Treehouse Right Orange Bridge - True - Treehouse First Purple Bridge - True - Treehouse Green Bridge - True:
158356 - 0x2700B (Laser House Door Timer Outside Control) - True - True
@@ -668,7 +668,7 @@ Treehouse Right Orange Bridge (Treehouse) - Treehouse Bridge Platform - 0x17DA2:
158391 - 0x17D88 (Right Orange Bridge 1) - True - Stars
158392 - 0x17DB4 (Right Orange Bridge 2) - 0x17D88 - Stars
158393 - 0x17D8C (Right Orange Bridge 3) - 0x17DB4 - Stars
-158394 - 0x17CE3 (Right Orange Bridge 4 & Directional) - 0x17D8C - Stars & Environment
+158394 - 0x17CE3 (Right Orange Bridge 4 & Directional) - 0x17D8C - Stars
158395 - 0x17DCD (Right Orange Bridge 5) - 0x17CE3 - Stars
158396 - 0x17DB2 (Right Orange Bridge 6) - 0x17DCD - Stars
158397 - 0x17DCC (Right Orange Bridge 7) - 0x17DB2 - Stars
@@ -683,246 +683,248 @@ Treehouse Bridge Platform (Treehouse) - Main Island - 0x0C32D:
Door - 0x0C32D (Drawbridge) - 0x037FF
Treehouse Second Purple Bridge (Treehouse) - Treehouse Left Orange Bridge - 0x17DC6:
-158362 - 0x17D9B (Second Purple Bridge 1) - True - Stars & Squares & Black/White Squares
-158363 - 0x17D99 (Second Purple Bridge 2) - 0x17D9B - Stars & Squares & Black/White Squares
-158364 - 0x17DAA (Second Purple Bridge 3) - 0x17D99 - Stars & Squares & Black/White Squares
-158365 - 0x17D97 (Second Purple Bridge 4) - 0x17DAA - Stars & Squares & Black/White Squares & Colored Squares
-158366 - 0x17BDF (Second Purple Bridge 5) - 0x17D97 - Stars & Squares & Colored Squares
-158367 - 0x17D91 (Second Purple Bridge 6) - 0x17BDF - Stars & Squares & Colored Squares
-158368 - 0x17DC6 (Second Purple Bridge 7) - 0x17D91 - Stars & Squares & Colored Squares
+158362 - 0x17D9B (Second Purple Bridge 1) - True - Stars & Black/White Squares
+158363 - 0x17D99 (Second Purple Bridge 2) - 0x17D9B - Stars & Black/White Squares
+158364 - 0x17DAA (Second Purple Bridge 3) - 0x17D99 - Stars & Black/White Squares
+158365 - 0x17D97 (Second Purple Bridge 4) - 0x17DAA - Stars & Black/White Squares & Colored Squares
+158366 - 0x17BDF (Second Purple Bridge 5) - 0x17D97 - Stars & Colored Squares
+158367 - 0x17D91 (Second Purple Bridge 6) - 0x17BDF - Stars & Colored Squares
+158368 - 0x17DC6 (Second Purple Bridge 7) - 0x17D91 - Stars & Colored Squares
Treehouse Left Orange Bridge (Treehouse) - Treehouse Laser Room Front Platform - 0x17DDB - Treehouse Laser Room Back Platform - 0x17DDB:
-158376 - 0x17DB3 (Left Orange Bridge 1) - True - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158377 - 0x17DB5 (Left Orange Bridge 2) - 0x17DB3 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158378 - 0x17DB6 (Left Orange Bridge 3) - 0x17DB5 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158379 - 0x17DC0 (Left Orange Bridge 4) - 0x17DB6 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158380 - 0x17DD7 (Left Orange Bridge 5) - 0x17DC0 - Stars & Squares & Black/White Squares & Colored Squares & Stars + Same Colored Symbol
-158381 - 0x17DD9 (Left Orange Bridge 6) - 0x17DD7 - Stars & Squares & Black/White Squares & Colored Squares & Stars + Same Colored Symbol
-158382 - 0x17DB8 (Left Orange Bridge 7) - 0x17DD9 - Stars & Squares & Black/White Squares & Colored Squares & Stars + Same Colored Symbol
-158383 - 0x17DDC (Left Orange Bridge 8) - 0x17DB8 - Stars & Squares & Colored Squares & Stars + Same Colored Symbol
-158384 - 0x17DD1 (Left Orange Bridge 9 & Directional) - 0x17DDC - Stars & Squares & Colored Squares & Stars + Same Colored Symbol & Environment
-158385 - 0x17DDE (Left Orange Bridge 10) - 0x17DD1 - Stars & Squares & Colored Squares & Stars + Same Colored Symbol
-158386 - 0x17DE3 (Left Orange Bridge 11) - 0x17DDE - Stars & Squares & Colored Squares & Stars + Same Colored Symbol
-158387 - 0x17DEC (Left Orange Bridge 12) - 0x17DE3 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158388 - 0x17DAE (Left Orange Bridge 13) - 0x17DEC - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158389 - 0x17DB0 (Left Orange Bridge 14) - 0x17DAE - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158390 - 0x17DDB (Left Orange Bridge 15) - 0x17DB0 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
+158376 - 0x17DB3 (Left Orange Bridge 1) - True - Stars & Black/White Squares & Stars + Same Colored Symbol
+158377 - 0x17DB5 (Left Orange Bridge 2) - 0x17DB3 - Stars & Black/White Squares & Stars + Same Colored Symbol
+158378 - 0x17DB6 (Left Orange Bridge 3) - 0x17DB5 - Stars & Black/White Squares & Stars + Same Colored Symbol
+158379 - 0x17DC0 (Left Orange Bridge 4) - 0x17DB6 - Stars & Black/White Squares & Stars + Same Colored Symbol
+158380 - 0x17DD7 (Left Orange Bridge 5) - 0x17DC0 - Stars & Black/White Squares & Colored Squares & Stars + Same Colored Symbol
+158381 - 0x17DD9 (Left Orange Bridge 6) - 0x17DD7 - Stars & Black/White Squares & Colored Squares & Stars + Same Colored Symbol
+158382 - 0x17DB8 (Left Orange Bridge 7) - 0x17DD9 - Stars & Black/White Squares & Colored Squares & Stars + Same Colored Symbol
+158383 - 0x17DDC (Left Orange Bridge 8) - 0x17DB8 - Stars & Colored Squares & Stars + Same Colored Symbol
+158384 - 0x17DD1 (Left Orange Bridge 9 & Directional) - 0x17DDC - Stars & Colored Squares & Stars + Same Colored Symbol
+158385 - 0x17DDE (Left Orange Bridge 10) - 0x17DD1 - Stars & Colored Squares & Stars + Same Colored Symbol
+158386 - 0x17DE3 (Left Orange Bridge 11) - 0x17DDE - Stars & Colored Squares & Stars + Same Colored Symbol
+158387 - 0x17DEC (Left Orange Bridge 12) - 0x17DE3 - Stars & Black/White Squares & Stars + Same Colored Symbol
+158388 - 0x17DAE (Left Orange Bridge 13) - 0x17DEC - Stars & Black/White Squares & Stars + Same Colored Symbol
+158389 - 0x17DB0 (Left Orange Bridge 14) - 0x17DAE - Stars & Black/White Squares & Stars + Same Colored Symbol
+158390 - 0x17DDB (Left Orange Bridge 15) - 0x17DB0 - Stars & Black/White Squares & Stars + Same Colored Symbol
Treehouse Green Bridge (Treehouse):
158369 - 0x17E3C (Green Bridge 1) - True - Stars & Shapers
158370 - 0x17E4D (Green Bridge 2) - 0x17E3C - Stars & Shapers
158371 - 0x17E4F (Green Bridge 3) - 0x17E4D - Stars & Shapers & Rotated Shapers
-158372 - 0x17E52 (Green Bridge 4 & Directional) - 0x17E4F - Stars & Rotated Shapers & Environment
-158373 - 0x17E5B (Green Bridge 5) - 0x17E52 - Stars & Shapers & Colored Shapers & Stars + Same Colored Symbol
-158374 - 0x17E5F (Green Bridge 6) - 0x17E5B - Stars & Shapers & Colored Shapers & Negative Shapers & Colored Negative Shapers & Stars + Same Colored Symbol
+158372 - 0x17E52 (Green Bridge 4 & Directional) - 0x17E4F - Stars & Rotated Shapers
+158373 - 0x17E5B (Green Bridge 5) - 0x17E52 - Stars & Shapers & Stars + Same Colored Symbol
+158374 - 0x17E5F (Green Bridge 6) - 0x17E5B - Stars & Shapers & Negative Shapers & Stars + Same Colored Symbol
158375 - 0x17E61 (Green Bridge 7) - 0x17E5F - Stars & Shapers & Rotated Shapers
158610 - 0x17FA9 (Green Bridge Discard) - 0x17E61 - Triangles
Treehouse Laser Room Front Platform (Treehouse) - Treehouse Laser Room - 0x0C323:
-Door - 0x0C323 (Door to Laser House) - 0x17DA2 & 0x2700B & 0x17DDB
+Door - 0x0C323 (Laser House Entry) - 0x17DA2 & 0x2700B & 0x17DDB
Treehouse Laser Room Back Platform (Treehouse):
-158611 - 0x17FA0 (Burnt House Discard) - True - Triangles
+158611 - 0x17FA0 (Laser Discard) - True - Triangles
Treehouse Laser Room (Treehouse):
158712 - 0x03613 (Laser Panel) - True - True
-158403 - 0x17CBC (Laser House Door Timer Inside Control) - True - True
+158403 - 0x17CBC (Laser House Door Timer Inside) - True - True
Laser - 0x028A4 (Laser) - 0x03613
-Mountaintop (Mountaintop) - Main Island - True - Inside Mountain Top Layer - 0x17C34:
+Mountainside (Mountainside) - Main Island - True - Mountaintop - True:
+158612 - 0x17C42 (Discard) - True - Triangles
+158665 - 0x002A6 (Vault) - True - Symmetry & Colored Dots & Black/White Squares & Dots
+158666 - 0x03542 (Vault Box) - 0x002A6 - True
+
+Mountaintop (Mountaintop) - Mountain Top Layer - 0x17C34:
158405 - 0x0042D (River Shape) - True - True
158406 - 0x09F7F (Box Short) - 7 Lasers - True
-158407 - 0x17C34 (Trap Door Triple Exit) - 0x09F7F - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158612 - 0x17C42 (Discard) - True - Triangles
-158665 - 0x002A6 (Vault) - True - Symmetry & Colored Dots & Squares & Black/White Squares & Dots
-158666 - 0x03542 (Vault Box) - 0x002A6 - True
+158407 - 0x17C34 (Trap Door Triple Exit) - 0x09F7F - Stars & Black/White Squares & Stars + Same Colored Symbol
158800 - 0xFFF00 (Box Long) - 7 Lasers & 11 Lasers & 0x17C34 - True
-Inside Mountain Top Layer (Inside Mountain) - Inside Mountain Top Layer Bridge - 0x09E39:
-158408 - 0x09E39 (Light Bridge Controller) - True - Squares & Black/White Squares & Colored Squares & Eraser & Colored Eraser
+Mountain Top Layer (Mountain Floor 1) - Mountain Top Layer Bridge - 0x09E39:
+158408 - 0x09E39 (Light Bridge Controller) - True - Black/White Squares & Colored Squares & Eraser
-Inside Mountain Top Layer Bridge (Inside Mountain) - Inside Mountain Second Layer - 0x09E54:
-158409 - 0x09E7A (Obscured Vision 1) - True - Obscured & Squares & Black/White Squares & Dots
-158410 - 0x09E71 (Obscured Vision 2) - 0x09E7A - Obscured & Squares & Black/White Squares & Dots
-158411 - 0x09E72 (Obscured Vision 3) - 0x09E71 - Obscured & Squares & Black/White Squares & Shapers & Dots
-158412 - 0x09E69 (Obscured Vision 4) - 0x09E72 - Obscured & Squares & Black/White Squares & Dots
-158413 - 0x09E7B (Obscured Vision 5) - 0x09E69 - Obscured & Squares & Black/White Squares & Dots
-158414 - 0x09E73 (Moving Background 1) - True - Moving & Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158415 - 0x09E75 (Moving Background 2) - 0x09E73 - Moving & Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158416 - 0x09E78 (Moving Background 3) - 0x09E75 - Moving & Shapers
-158417 - 0x09E79 (Moving Background 4) - 0x09E78 - Moving & Shapers & Rotated Shapers
-158418 - 0x09E6C (Moving Background 5) - 0x09E79 - Moving & Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158419 - 0x09E6F (Moving Background 6) - 0x09E6C - Moving & Stars & Rotated Shapers & Shapers
-158420 - 0x09E6B (Moving Background 7) - 0x09E6F - Moving & Stars & Dots
-158421 - 0x33AF5 (Physically Obstructed 1) - True - Squares & Black/White Squares & Environment & Symmetry
-158422 - 0x33AF7 (Physically Obstructed 2) - 0x33AF5 - Squares & Black/White Squares & Stars & Environment
-158423 - 0x09F6E (Physically Obstructed 3) - 0x33AF7 - Symmetry & Dots & Environment
-158424 - 0x09EAD (Angled Inside Trash 1) - True - Squares & Black/White Squares & Shapers & Angled
-158425 - 0x09EAF (Angled Inside Trash 2) - 0x09EAD - Squares & Black/White Squares & Shapers & Angled
-Door - 0x09E54 (Door to Second Layer) - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B
+Mountain Top Layer Bridge (Mountain Floor 1) - Mountain Floor 2 - 0x09E54:
+158409 - 0x09E7A (Right Row 1) - True - Black/White Squares & Dots
+158410 - 0x09E71 (Right Row 2) - 0x09E7A - Black/White Squares & Dots
+158411 - 0x09E72 (Right Row 3) - 0x09E71 - Black/White Squares & Shapers & Dots
+158412 - 0x09E69 (Right Row 4) - 0x09E72 - Black/White Squares & Dots
+158413 - 0x09E7B (Right Row 5) - 0x09E69 - Black/White Squares & Dots
+158414 - 0x09E73 (Left Row 1) - True - Stars & Black/White Squares & Stars + Same Colored Symbol
+158415 - 0x09E75 (Left Row 2) - 0x09E73 - Stars & Black/White Squares & Stars + Same Colored Symbol
+158416 - 0x09E78 (Left Row 3) - 0x09E75 - Shapers
+158417 - 0x09E79 (Left Row 4) - 0x09E78 - Shapers & Rotated Shapers
+158418 - 0x09E6C (Left Row 5) - 0x09E79 - Stars & Black/White Squares & Stars + Same Colored Symbol
+158419 - 0x09E6F (Left Row 6) - 0x09E6C - Stars & Rotated Shapers & Shapers
+158420 - 0x09E6B (Left Row 7) - 0x09E6F - Stars & Dots
+158421 - 0x33AF5 (Back Row 1) - True - Black/White Squares & Symmetry
+158422 - 0x33AF7 (Back Row 2) - 0x33AF5 - Black/White Squares & Stars
+158423 - 0x09F6E (Back Row 3) - 0x33AF7 - Symmetry & Dots
+158424 - 0x09EAD (Trash Pillar 1) - True - Black/White Squares & Shapers
+158425 - 0x09EAF (Trash Pillar 2) - 0x09EAD - Black/White Squares & Shapers
+Door - 0x09E54 (Exit) - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B
-Inside Mountain Second Layer (Inside Mountain) - Inside Mountain Second Layer Light Bridge Room Near - 0x09FFB - Inside Mountain Second Layer Blue Bridge - 0x09E86:
-158426 - 0x09FD3 (Color Cycle 1) - True - Color Cycle & RGB & Stars & Squares & Colored Squares & Stars + Same Colored Symbol
-158427 - 0x09FD4 (Color Cycle 2) - 0x09FD3 - Color Cycle & RGB & Stars & Squares & Colored Squares & Stars + Same Colored Symbol
-158428 - 0x09FD6 (Color Cycle 3) - 0x09FD4 - Color Cycle & RGB & Stars & Squares & Colored Squares & Stars + Same Colored Symbol
-158429 - 0x09FD7 (Color Cycle 4) - 0x09FD6 - Color Cycle & RGB & Stars & Squares & Colored Squares & Stars + Same Colored Symbol & Shapers & Colored Shapers
-158430 - 0x09FD8 (Color Cycle 5) - 0x09FD7 - Color Cycle & RGB & Squares & Colored Squares & Symmetry & Colored Dots
+Mountain Floor 2 (Mountain Floor 2) - Mountain Floor 2 Light Bridge Room Near - 0x09FFB - Mountain Floor 2 Blue Bridge - 0x09E86:
+158426 - 0x09FD3 (Near Row 1) - True - Stars & Colored Squares & Stars + Same Colored Symbol
+158427 - 0x09FD4 (Near Row 2) - 0x09FD3 - Stars & Colored Squares & Stars + Same Colored Symbol
+158428 - 0x09FD6 (Near Row 3) - 0x09FD4 - Stars & Colored Squares & Stars + Same Colored Symbol
+158429 - 0x09FD7 (Near Row 4) - 0x09FD6 - Stars & Colored Squares & Stars + Same Colored Symbol & Shapers
+158430 - 0x09FD8 (Near Row 5) - 0x09FD7 - Colored Squares & Symmetry & Colored Dots
Door - 0x09FFB (Staircase Near) - 0x09FD8
-Inside Mountain Second Layer Blue Bridge (Inside Mountain) - Inside Mountain Second Layer Beyond Bridge - TrueOneWay - Inside Mountain Second Layer At Door - TrueOneWay:
+Mountain Floor 2 Blue Bridge (Mountain Floor 2) - Mountain Floor 2 Beyond Bridge - TrueOneWay - Mountain Floor 2 At Door - TrueOneWay:
-Inside Mountain Second Layer At Door (Inside Mountain) - Inside Mountain Second Layer Elevator Room - 0x09EDD:
-Door - 0x09EDD (Door to Elevator) - 0x09ED8 & 0x09E86
+Mountain Floor 2 At Door (Mountain Floor 2) - Mountain Floor 2 Elevator Room - 0x09EDD:
+Door - 0x09EDD (Elevator Room Entry) - 0x09ED8 & 0x09E86
-Inside Mountain Second Layer Light Bridge Room Near (Inside Mountain):
-158431 - 0x09E86 (Light Bridge Controller 2) - True - Stars & Stars + Same Colored Symbol & Colored Rotated Shapers & Rotated Shapers & Eraser & Two Lines
+Mountain Floor 2 Light Bridge Room Near (Mountain Floor 2):
+158431 - 0x09E86 (Light Bridge Controller Near) - True - Stars & Stars + Same Colored Symbol & Rotated Shapers & Eraser
-Inside Mountain Second Layer Beyond Bridge (Inside Mountain) - Inside Mountain Second Layer Light Bridge Room Far - 0x09E07:
-158432 - 0x09FCC (Same Solution 1) - True - Dots & Same Solution
-158433 - 0x09FCE (Same Solution 2) - 0x09FCC - Squares & Black/White Squares & Same Solution
-158434 - 0x09FCF (Same Solution 3) - 0x09FCE - Stars & Same Solution
-158435 - 0x09FD0 (Same Solution 4) - 0x09FCF - Rotated Shapers & Same Solution
-158436 - 0x09FD1 (Same Solution 5) - 0x09FD0 - Stars & Squares & Colored Squares & Stars + Same Colored Symbol & Same Solution
-158437 - 0x09FD2 (Same Solution 6) - 0x09FD1 - Shapers & Same Solution
+Mountain Floor 2 Beyond Bridge (Mountain Floor 2) - Mountain Floor 2 Light Bridge Room Far - 0x09E07:
+158432 - 0x09FCC (Far Row 1) - True - Dots
+158433 - 0x09FCE (Far Row 2) - 0x09FCC - Black/White Squares
+158434 - 0x09FCF (Far Row 3) - 0x09FCE - Stars
+158435 - 0x09FD0 (Far Row 4) - 0x09FCF - Rotated Shapers
+158436 - 0x09FD1 (Far Row 5) - 0x09FD0 - Stars & Colored Squares & Stars + Same Colored Symbol
+158437 - 0x09FD2 (Far Row 6) - 0x09FD1 - Shapers
Door - 0x09E07 (Staircase Far) - 0x09FD2
-Inside Mountain Second Layer Light Bridge Room Far (Inside Mountain):
-158438 - 0x09ED8 (Light Bridge Controller 3) - True - Stars & Stars + Same Colored Symbol & Colored Rotated Shapers & Rotated Shapers & Eraser & Two Lines
+Mountain Floor 2 Light Bridge Room Far (Mountain Floor 2):
+158438 - 0x09ED8 (Light Bridge Controller Far) - True - Stars & Stars + Same Colored Symbol & Rotated Shapers & Eraser
-Inside Mountain Second Layer Elevator Room (Inside Mountain) - Inside Mountain Second Layer Elevator - TrueOneWay:
+Mountain Floor 2 Elevator Room (Mountain Floor 2) - Mountain Floor 2 Elevator - TrueOneWay:
158613 - 0x17F93 (Elevator Discard) - True - Triangles
-Inside Mountain Second Layer Elevator (Inside Mountain) - Inside Mountain Second Layer Elevator Room - 0x09EEB - Inside Mountain Third Layer - 0x09EEB:
+Mountain Floor 2 Elevator (Mountain Floor 2) - Mountain Floor 2 Elevator Room - 0x09EEB - Mountain Third Layer - 0x09EEB:
158439 - 0x09EEB (Elevator Control Panel) - True - Dots
-Inside Mountain Third Layer (Inside Mountain) - Inside Mountain Second Layer Elevator - TrueOneWay - Inside Mountain Bottom Layer - 0x09F89:
+Mountain Third Layer (Mountain Bottom Floor) - Mountain Floor 2 Elevator - TrueOneWay - Mountain Bottom Floor - 0x09F89:
158440 - 0x09FC1 (Giant Puzzle Bottom Left) - True - Shapers & Eraser
158441 - 0x09F8E (Giant Puzzle Bottom Right) - True - Shapers & Eraser
158442 - 0x09F01 (Giant Puzzle Top Right) - True - Rotated Shapers
158443 - 0x09EFF (Giant Puzzle Top Left) - True - Shapers & Eraser
158444 - 0x09FDA (Giant Puzzle) - 0x09FC1 & 0x09F8E & 0x09F01 & 0x09EFF - Shapers & Symmetry
-Door - 0x09F89 (Glass Door) - 0x09FDA
+Door - 0x09F89 (Exit) - 0x09FDA
-Inside Mountain Bottom Layer (Inside Mountain) - Inside Mountain Bottom Layer Rock - 0x17FA2 - Final Room - 0x0C141:
-158614 - 0x17FA2 (Bottom Layer Discard) - 0xFFF00 - Triangles & Environment
-158445 - 0x01983 (Door to Final Room Left) - True - Shapers & Stars
-158446 - 0x01987 (Door to Final Room Right) - True - Squares & Colored Squares & Dots
-Door - 0x0C141 (Door to Final Room) - 0x01983 & 0x01987
+Mountain Bottom Floor (Mountain Bottom Floor) - Mountain Bottom Floor Rock - 0x17FA2 - Final Room - 0x0C141:
+158614 - 0x17FA2 (Discard) - 0xFFF00 - Triangles
+158445 - 0x01983 (Final Room Entry Left) - True - Shapers & Stars
+158446 - 0x01987 (Final Room Entry Right) - True - Colored Squares & Dots
+Door - 0x0C141 (Final Room Entry) - 0x01983 & 0x01987
-Inside Mountain Bottom Layer Rock (Inside Mountain) - Inside Mountain Bottom Layer - 0x17F33 - Inside Mountain Path to Secret Area - 0x17F33:
-Door - 0x17F33 (Bottom Layer Rock Open) - True
+Mountain Bottom Floor Rock (Mountain Bottom Floor) - Mountain Bottom Floor - 0x17F33 - Mountain Path to Caves - 0x17F33:
+Door - 0x17F33 (Rock Open) - True
-Inside Mountain Path to Secret Area (Inside Mountain) - Inside Mountain Bottom Layer Rock - 0x334E1 - Inside Mountain Caves - 0x2D77D:
-158447 - 0x00FF8 (Secret Area Entry Panel) - True - Triangles & Black/White Squares & Squares
-Door - 0x2D77D (Door to Secret Area) - 0x00FF8
+Mountain Path to Caves (Mountain Bottom Floor) - Mountain Bottom Floor Rock - 0x334E1 - Caves - 0x2D77D:
+158447 - 0x00FF8 (Caves Entry Panel) - True - Triangles & Black/White Squares
+Door - 0x2D77D (Caves Entry) - 0x00FF8
158448 - 0x334E1 (Rock Control) - True - True
-Inside Mountain Caves (Inside Mountain Caves) - Main Island - 0x2D73F - Main Island - 0x2D859 - Path to Challenge - 0x019A5:
-158451 - 0x335AB (Elevator Inside Control) - True - Dots & Squares & Black/White Squares
-158452 - 0x335AC (Elevator Upper Outside Control) - 0x335AB - Squares & Black/White Squares
-158453 - 0x3369D (Elevator Lower Outside Control) - 0x335AB - Squares & Black/White Squares & Dots
-158454 - 0x00190 (Dot Grid Triangles 1) - True - Dots & Triangles
-158455 - 0x00558 (Dot Grid Triangles 2) - 0x00190 - Dots & Triangles
-158456 - 0x00567 (Dot Grid Triangles 3) - 0x00558 - Dots & Triangles
-158457 - 0x006FE (Dot Grid Triangles 4) - 0x00567 - Dots & Triangles
-158458 - 0x01A0D (Symmetry Triangles) - True - Symmetry & Triangles
-158459 - 0x008B8 (Squares and Triangles) - True - Squares & Black/White Squares & Triangles
-158460 - 0x00973 (Stars and Triangles) - 0x008B8 - Stars & Triangles
-158461 - 0x0097B (Stars and Triangles of same color) - 0x00973 - Stars & Triangles & Stars and Triangles of same color & Stars + Same Colored Symbol
-158462 - 0x0097D (Stars & Squares and Triangles) - 0x0097B - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol & Triangles
-158463 - 0x0097E (Stars & Squares and Triangles 2) - 0x0097D - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol & Stars and Triangles of same color
-158464 - 0x00994 (Rotated Shapers and Triangles 1) - True - Rotated Shapers & Triangles
-158465 - 0x334D5 (Rotated Shapers and Triangles 2) - 0x00994 - Rotated Shapers & Triangles
-158466 - 0x00995 (Rotated Shapers and Triangles 3) - 0x334D5 - Rotated Shapers & Triangles
-158467 - 0x00996 (Shapers and Triangles 1) - 0x00995 - Shapers & Triangles
-158468 - 0x00998 (Shapers and Triangles 2) - 0x00996 - Shapers & Triangles
-158469 - 0x009A4 (Broken Shapers) - True - Shapers & Broken Shapers
-158470 - 0x018A0 (Symmetry Shapers) - True - Shapers & Symmetry
-158471 - 0x00A72 (Broken and Negative Shapers) - True - Shapers & Broken Shapers & Negative Shapers
-158472 - 0x32962 (Rotated Broken Shapers) - True - Rotated Shapers & Broken Rotated Shapers
-158473 - 0x32966 (Stars and Squares) - True - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
-158474 - 0x01A31 (Rainbow Squares) - True - Color Cycle & RGB & Squares & Colored Squares
-158475 - 0x00B71 (Squares & Stars and Colored Eraser) - True - Colored Eraser & Squares & Colored Squares & Stars & Stars + Same Colored Symbol & Eraser
-158478 - 0x288EA (Wooden Beam Shapers) - True - Environment & Shapers
-158479 - 0x288FC (Wooden Beam Squares and Shapers) - True - Environment & Squares & Black/White Squares & Shapers & Rotated Shapers
-158480 - 0x289E7 (Wooden Beam Stars and Squares) - True - Environment & Stars & Squares & Black/White Squares
-158481 - 0x288AA (Wooden Beam Shapers and Stars) - True - Environment & Stars & Shapers
-158482 - 0x17FB9 (Upstairs Dot Grid Negative Shapers) - True - Shapers & Dots & Negative Shapers
-158483 - 0x0A16B (Upstairs Dot Grid Gap Dots) - True - Dots
-158484 - 0x0A2CE (Upstairs Dot Grid Stars) - 0x0A16B - Stars & Dots
-158485 - 0x0A2D7 (Upstairs Dot Grid Stars & Squares) - 0x0A2CE - Dots & Black/White Squares & Stars + Same Colored Symbol & Stars
-158486 - 0x0A2DD (Upstairs Dot Grid Shapers) - 0x0A2D7 - Shapers & Dots
-158487 - 0x0A2EA (Upstairs Dot Grid Rotated Shapers) - 0x0A2DD - Rotated Shapers & Dots
-158488 - 0x0008F (Upstairs Invisible Dots 1) - True - Dots & Invisible Dots
-158489 - 0x0006B (Upstairs Invisible Dots 2) - 0x0008F - Dots & Invisible Dots
-158490 - 0x0008B (Upstairs Invisible Dots 3) - 0x0006B - Dots & Invisible Dots
-158491 - 0x0008C (Upstairs Invisible Dots 4) - 0x0008B - Dots & Invisible Dots
-158492 - 0x0008A (Upstairs Invisible Dots 5) - 0x0008C - Dots & Invisible Dots
-158493 - 0x00089 (Upstairs Invisible Dots 6) - 0x0008A - Dots & Invisible Dots
-158494 - 0x0006A (Upstairs Invisible Dots 7) - 0x00089 - Dots & Invisible Dots
-158495 - 0x0006C (Upstairs Invisible Dots 8) - 0x0006A - Dots & Invisible Dots
-158496 - 0x00027 (Upstairs Invisible Dot Symmetry 1) - True - Dots & Invisible Dots & Symmetry
-158497 - 0x00028 (Upstairs Invisible Dot Symmetry 2) - 0x00027 - Dots & Invisible Dots & Symmetry
-158498 - 0x00029 (Upstairs Invisible Dot Symmetry 3) - 0x00028 - Dots & Invisible Dots & Symmetry
-158476 - 0x09DD5 (Lone Pillar) - True - Pillar & Triangles
-Door - 0x019A5 (Secret Black Door to Challenge) - 0x09DD5
-158449 - 0x021D7 (Shortcut to Mountain Panel) - True - Triangles & Stars & Stars + Same Colored Symbol & Colored Triangles
-Door - 0x2D73F (Shortcut to Mountain Door) - 0x021D7
-158450 - 0x17CF2 (Shortcut to Swamp Panel) - True - Triangles
-Door - 0x2D859 (Shortcut to Swamp Door) - 0x17CF2
+Caves (Caves) - Main Island - 0x2D73F - Main Island - 0x2D859 - Path to Challenge - 0x019A5:
+158451 - 0x335AB (Elevator Inside Control) - True - Dots & Black/White Squares
+158452 - 0x335AC (Elevator Upper Outside Control) - 0x335AB - Black/White Squares
+158453 - 0x3369D (Elevator Lower Outside Control) - 0x335AB - Black/White Squares & Dots
+158454 - 0x00190 (Blue Tunnel Right First 1) - True - Dots & Triangles
+158455 - 0x00558 (Blue Tunnel Right First 2) - 0x00190 - Dots & Triangles
+158456 - 0x00567 (Blue Tunnel Right First 3) - 0x00558 - Dots & Triangles
+158457 - 0x006FE (Blue Tunnel Right First 4) - 0x00567 - Dots & Triangles
+158458 - 0x01A0D (Blue Tunnel Left First 1) - True - Symmetry & Triangles
+158459 - 0x008B8 (Blue Tunnel Left Second 1) - True - Black/White Squares & Triangles
+158460 - 0x00973 (Blue Tunnel Left Second 2) - 0x008B8 - Stars & Triangles
+158461 - 0x0097B (Blue Tunnel Left Second 3) - 0x00973 - Stars & Triangles & Stars + Same Colored Symbol
+158462 - 0x0097D (Blue Tunnel Left Second 4) - 0x0097B - Stars & Black/White Squares & Stars + Same Colored Symbol & Triangles
+158463 - 0x0097E (Blue Tunnel Left Second 5) - 0x0097D - Stars & Black/White Squares & Stars + Same Colored Symbol
+158464 - 0x00994 (Blue Tunnel Right Second 1) - True - Rotated Shapers & Triangles
+158465 - 0x334D5 (Blue Tunnel Right Second 2) - 0x00994 - Rotated Shapers & Triangles
+158466 - 0x00995 (Blue Tunnel Right Second 3) - 0x334D5 - Rotated Shapers & Triangles
+158467 - 0x00996 (Blue Tunnel Right Second 4) - 0x00995 - Shapers & Triangles
+158468 - 0x00998 (Blue Tunnel Right Second 5) - 0x00996 - Shapers & Triangles
+158469 - 0x009A4 (Blue Tunnel Left Third 1) - True - Shapers
+158470 - 0x018A0 (Blue Tunnel Right Third 1) - True - Shapers & Symmetry
+158471 - 0x00A72 (Blue Tunnel Left Fourth 1) - True - Shapers & Negative Shapers
+158472 - 0x32962 (First Floor Left) - True - Rotated Shapers
+158473 - 0x32966 (First Floor Grounded) - True - Stars & Black/White Squares & Stars + Same Colored Symbol
+158474 - 0x01A31 (First Floor Middle) - True - Colored Squares
+158475 - 0x00B71 (First Floor Right) - True - Colored Squares & Stars & Stars + Same Colored Symbol & Eraser
+158478 - 0x288EA (First Wooden Beam) - True - Shapers
+158479 - 0x288FC (Second Wooden Beam) - True - Black/White Squares & Shapers & Rotated Shapers
+158480 - 0x289E7 (Third Wooden Beam) - True - Stars & Black/White Squares
+158481 - 0x288AA (Fourth Wooden Beam) - True - Stars & Shapers
+158482 - 0x17FB9 (Left Upstairs Single) - True - Shapers & Dots & Negative Shapers
+158483 - 0x0A16B (Left Upstairs Left Row 1) - True - Dots
+158484 - 0x0A2CE (Left Upstairs Left Row 2) - 0x0A16B - Stars & Dots
+158485 - 0x0A2D7 (Left Upstairs Left Row 3) - 0x0A2CE - Dots & Black/White Squares & Stars + Same Colored Symbol & Stars
+158486 - 0x0A2DD (Left Upstairs Left Row 4) - 0x0A2D7 - Shapers & Dots
+158487 - 0x0A2EA (Left Upstairs Left Row 5) - 0x0A2DD - Rotated Shapers & Dots
+158488 - 0x0008F (Right Upstairs Left Row 1) - True - Dots & Invisible Dots
+158489 - 0x0006B (Right Upstairs Left Row 2) - 0x0008F - Dots & Invisible Dots
+158490 - 0x0008B (Right Upstairs Left Row 3) - 0x0006B - Dots & Invisible Dots
+158491 - 0x0008C (Right Upstairs Left Row 4) - 0x0008B - Dots & Invisible Dots
+158492 - 0x0008A (Right Upstairs Left Row 5) - 0x0008C - Dots & Invisible Dots
+158493 - 0x00089 (Right Upstairs Left Row 6) - 0x0008A - Dots & Invisible Dots
+158494 - 0x0006A (Right Upstairs Left Row 7) - 0x00089 - Dots & Invisible Dots
+158495 - 0x0006C (Right Upstairs Left Row 8) - 0x0006A - Dots & Invisible Dots
+158496 - 0x00027 (Right Upstairs Right Row 1) - True - Dots & Invisible Dots & Symmetry
+158497 - 0x00028 (Right Upstairs Right Row 2) - 0x00027 - Dots & Invisible Dots & Symmetry
+158498 - 0x00029 (Right Upstairs Right Row 3) - 0x00028 - Dots & Invisible Dots & Symmetry
+158476 - 0x09DD5 (Lone Pillar) - True - Triangles
+Door - 0x019A5 (Pillar Door) - 0x09DD5
+158449 - 0x021D7 (Mountain Shortcut Panel) - True - Triangles & Stars & Stars + Same Colored Symbol
+Door - 0x2D73F (Mountain Shortcut Door) - 0x021D7
+158450 - 0x17CF2 (Swamp Shortcut Panel) - True - Triangles
+Door - 0x2D859 (Swamp Shortcut Door) - 0x17CF2
-Path to Challenge (Inside Mountain Caves) - Challenge - 0x0A19A:
-158477 - 0x0A16E (Challenge Entry Panel) - True - Stars & Shapers & Colored Shapers & Stars + Same Colored Symbol
-Door - 0x0A19A (Challenge Entry Door) - 0x0A16E
+Path to Challenge (Caves) - Challenge - 0x0A19A:
+158477 - 0x0A16E (Challenge Entry Panel) - True - Stars & Shapers & Stars + Same Colored Symbol
+Door - 0x0A19A (Challenge Entry) - 0x0A16E
-Challenge (Challenge) - Theater Walkway - 0x0348A:
+Challenge (Challenge) - Tunnels - 0x0348A:
158499 - 0x0A332 (Start Timer) - 11 Lasers - True
158500 - 0x0088E (Small Basic) - 0x0A332 - True
158501 - 0x00BAF (Big Basic) - 0x0088E - True
-158502 - 0x00BF3 (Square) - 0x00BAF - Squares & Black/White Squares
+158502 - 0x00BF3 (Square) - 0x00BAF - Black/White Squares
158503 - 0x00C09 (Maze Map) - 0x00BF3 - Dots
158504 - 0x00CDB (Stars and Dots) - 0x00C09 - Stars & Dots
158505 - 0x0051F (Symmetry) - 0x00CDB - Symmetry & Colored Dots & Dots
158506 - 0x00524 (Stars and Shapers) - 0x0051F - Stars & Shapers
158507 - 0x00CD4 (Big Basic 2) - 0x00524 - True
-158508 - 0x00CB9 (Choice Squares Right) - 0x00CD4 - Squares & Black/White Squares
-158509 - 0x00CA1 (Choice Squares Middle) - 0x00CD4 - Squares & Black/White Squares
-158510 - 0x00C80 (Choice Squares Left) - 0x00CD4 - Squares & Black/White Squares
-158511 - 0x00C68 (Choice Squares 2 Right) - 0x00CB9 | 0x00CA1 | 0x00C80 - Squares & Black/White Squares & Colored Squares
-158512 - 0x00C59 (Choice Squares 2 Middle) - 0x00CB9 | 0x00CA1 | 0x00C80 - Squares & Black/White Squares & Colored Squares
-158513 - 0x00C22 (Choice Squares 2 Left) - 0x00CB9 | 0x00CA1 | 0x00C80 - Squares & Black/White Squares & Colored Squares
+158508 - 0x00CB9 (Choice Squares Right) - 0x00CD4 - Black/White Squares
+158509 - 0x00CA1 (Choice Squares Middle) - 0x00CD4 - Black/White Squares
+158510 - 0x00C80 (Choice Squares Left) - 0x00CD4 - Black/White Squares
+158511 - 0x00C68 (Choice Squares 2 Right) - 0x00CB9 | 0x00CA1 | 0x00C80 - Black/White Squares & Colored Squares
+158512 - 0x00C59 (Choice Squares 2 Middle) - 0x00CB9 | 0x00CA1 | 0x00C80 - Black/White Squares & Colored Squares
+158513 - 0x00C22 (Choice Squares 2 Left) - 0x00CB9 | 0x00CA1 | 0x00C80 - Black/White Squares & Colored Squares
158514 - 0x034F4 (Maze Hidden 1) - 0x00C68 | 0x00C59 | 0x00C22 - Triangles
158515 - 0x034EC (Maze Hidden 2) - 0x00C68 | 0x00C59 | 0x00C22 - Triangles
-158516 - 0x1C31A (Dots Pillar) - 0x034F4 & 0x034EC - Dots & Symmetry & Pillar
-158517 - 0x1C319 (Squares Pillar) - 0x034F4 & 0x034EC - Squares & Black/White Squares & Symmetry & Pillar
+158516 - 0x1C31A (Dots Pillar) - 0x034F4 & 0x034EC - Dots & Symmetry
+158517 - 0x1C319 (Squares Pillar) - 0x034F4 & 0x034EC - Black/White Squares & Symmetry
158667 - 0x0356B (Vault Box) - 0x1C31A & 0x1C319 - True
-158518 - 0x039B4 (Door to Theater Walkway Panel) - True - Triangles
-Door - 0x0348A (Door to Theater Walkway) - 0x039B4
+158518 - 0x039B4 (Tunnels Entry Panel) - True - Triangles
+Door - 0x0348A (Tunnels Entry) - 0x039B4
-Theater Walkway (Theater Walkway) - Windmill Interior - 0x27739 - Desert Lowest Level Inbetween Shortcuts - 0x27263 - Town - 0x09E87:
+Tunnels (Tunnels) - Windmill Interior - 0x27739 - Desert Lowest Level Inbetween Shortcuts - 0x27263 - Town - 0x09E87:
158668 - 0x2FAF6 (Vault Box) - True - True
158519 - 0x27732 (Theater Shortcut Panel) - True - True
-Door - 0x27739 (Door to Windmill Interior) - 0x27732
+Door - 0x27739 (Theater Shortcut) - 0x27732
158520 - 0x2773D (Desert Shortcut Panel) - True - True
-Door - 0x27263 (Door to Desert Elevator Room) - 0x2773D
+Door - 0x27263 (Desert Shortcut) - 0x2773D
158521 - 0x09E85 (Town Shortcut Panel) - True - Triangles
-Door - 0x09E87 (Door to Town) - 0x09E85
+Door - 0x09E87 (Town Shortcut) - 0x09E85
-Final Room (Inside Mountain Final Room) - Elevator - 0x339BB & 0x33961:
-158522 - 0x0383A (Right Pillar 1) - True - Stars & Pillar
-158523 - 0x09E56 (Right Pillar 2) - 0x0383A - Stars & Dots & Pillar
-158524 - 0x09E5A (Right Pillar 3) - 0x09E56 - Dots & Pillar
-158525 - 0x33961 (Right Pillar 4) - 0x09E5A - Dots & Symmetry & Pillar
-158526 - 0x0383D (Left Pillar 1) - True - Dots & Pillar
-158527 - 0x0383F (Left Pillar 2) - 0x0383D - Squares & Black/White Squares & Pillar
-158528 - 0x03859 (Left Pillar 3) - 0x0383F - Shapers & Pillar
-158529 - 0x339BB (Left Pillar 4) - 0x03859 - Squares & Black/White Squares & Stars & Symmetry & Pillar
+Final Room (Mountain Final Room) - Elevator - 0x339BB & 0x33961:
+158522 - 0x0383A (Right Pillar 1) - True - Stars
+158523 - 0x09E56 (Right Pillar 2) - 0x0383A - Stars & Dots
+158524 - 0x09E5A (Right Pillar 3) - 0x09E56 - Dots
+158525 - 0x33961 (Right Pillar 4) - 0x09E5A - Dots & Symmetry
+158526 - 0x0383D (Left Pillar 1) - True - Dots
+158527 - 0x0383F (Left Pillar 2) - 0x0383D - Black/White Squares
+158528 - 0x03859 (Left Pillar 3) - 0x0383F - Shapers
+158529 - 0x339BB (Left Pillar 4) - 0x03859 - Black/White Squares & Stars & Symmetry
-Elevator (Inside Mountain Final Room):
+Elevator (Mountain Final Room):
158530 - 0x3D9A6 (Elevator Door Closer Left) - True - True
158531 - 0x3D9A7 (Elevator Door Close Right) - True - True
-158532 - 0x3C113 (Elevator Door Open Left) - 0x3D9A6 | 0x3D9A7 - True
-158533 - 0x3C114 (Elevator Door Open Right) - 0x3D9A6 | 0x3D9A7 - True
+158532 - 0x3C113 (Elevator Entry Left) - 0x3D9A6 | 0x3D9A7 - True
+158533 - 0x3C114 (Elevator Entry Right) - 0x3D9A6 | 0x3D9A7 - True
158534 - 0x3D9AA (Back Wall Left) - 0x3D9A6 | 0x3D9A7 - True
158535 - 0x3D9A8 (Back Wall Right) - 0x3D9A6 | 0x3D9A7 - True
158536 - 0x3D9A9 (Elevator Start) - 0x3D9AA | 0x3D9A8 - True
diff --git a/worlds/witness/__init__.py b/worlds/witness/__init__.py
index a6a9f9f6f8..0f8f0d75c0 100644
--- a/worlds/witness/__init__.py
+++ b/worlds/witness/__init__.py
@@ -36,7 +36,7 @@ class WitnessWorld(World):
"""
game = "The Witness"
topology_present = False
- data_version = 5
+ data_version = 7
static_logic = StaticWitnessLogic()
static_locat = StaticWitnessLocations()
diff --git a/worlds/witness/locations.py b/worlds/witness/locations.py
index 9b7d60ea16..ea0728b16c 100644
--- a/worlds/witness/locations.py
+++ b/worlds/witness/locations.py
@@ -30,17 +30,17 @@ class StaticWitnessLocations:
"Outside Tutorial Vault Box",
"Outside Tutorial Discard",
- "Outside Tutorial Dots Introduction 5",
- "Outside Tutorial Squares Introduction 9",
+ "Outside Tutorial Shed Row 5",
+ "Outside Tutorial Tree Row 9",
"Glass Factory Discard",
- "Glass Factory Vertical Symmetry 5",
- "Glass Factory Rotational Symmetry 3",
+ "Glass Factory Back Wall 5",
+ "Glass Factory Front 3",
"Glass Factory Melting 3",
- "Symmetry Island Black Dots 5",
- "Symmetry Island Colored Dots 6",
- "Symmetry Island Fading Lines 7",
+ "Symmetry Island Right 5",
+ "Symmetry Island Back 6",
+ "Symmetry Island Left 7",
"Symmetry Island Scenery Outlines 5",
"Symmetry Island Laser Panel",
@@ -48,26 +48,28 @@ class StaticWitnessLocations:
"Desert Vault Box",
"Desert Discard",
- "Desert Sun Reflection 8",
- "Desert Artificial Light Reflection 3",
- "Desert Pond Reflection 5",
- "Desert Flood Reflection 6",
+ "Desert Surface 8",
+ "Desert Light Room 3",
+ "Desert Pond Room 5",
+ "Desert Flood Room 6",
+ "Desert Final Bent 3",
+ "Desert Final Hexagonal",
"Desert Laser Panel",
- "Quarry Mill Eraser and Dots 6",
- "Quarry Mill Eraser and Squares 8",
- "Quarry Mill Small Squares & Dots & Eraser",
- "Quarry Boathouse Intro Shapers",
- "Quarry Boathouse Intro Stars",
- "Quarry Boathouse Eraser and Shapers 5",
- "Quarry Boathouse Stars & Eraser & Shapers 2",
- "Quarry Boathouse Stars & Eraser & Shapers 5",
+ "Quarry Mill Lower Row 6",
+ "Quarry Mill Upper Row 8",
+ "Quarry Mill Control Room Right",
+ "Quarry Boathouse Intro Right",
+ "Quarry Boathouse Intro Left",
+ "Quarry Boathouse Front Row 5",
+ "Quarry Boathouse Back First Row 9",
+ "Quarry Boathouse Back Second Row 3",
"Quarry Discard",
"Quarry Laser Panel",
- "Shadows Lower Avoid 8",
- "Shadows Environmental Avoid 8",
- "Shadows Follow 5",
+ "Shadows Intro 8",
+ "Shadows Far 8",
+ "Shadows Near 5",
"Shadows Laser Panel",
"Keep Hedge Maze 4",
@@ -79,44 +81,44 @@ class StaticWitnessLocations:
"Shipwreck Vault Box",
"Shipwreck Discard",
- "Monastery Rhombic Avoid 3",
- "Monastery Branch Follow 2",
+ "Monastery Outside 3",
+ "Monastery Inside 4",
"Monastery Laser Panel",
"Town Cargo Box Discard",
- "Town Hexagonal Reflection",
+ "Town Tall Hexagonal",
"Town Church Lattice",
"Town Rooftop Discard",
- "Town Symmetry Squares 5 + Dots",
- "Town Full Dot Grid Shapers 5",
- "Town Shapers & Dots & Eraser",
+ "Town Red Rooftop 5",
+ "Town Wooden Roof Lower Row 5",
+ "Town Wooden Rooftop",
"Town Laser Panel",
"Theater Discard",
"Jungle Discard",
- "Jungle Waves 3",
- "Jungle Waves 7",
+ "Jungle First Row 3",
+ "Jungle Second Row 4",
"Jungle Popup Wall 6",
"Jungle Laser Panel",
"River Vault Box",
- "Bunker Drawn Squares 5",
- "Bunker Drawn Squares 9",
- "Bunker Drawn Squares through Tinted Glass 3",
- "Bunker Drop-Down Door Squares 2",
+ "Bunker Intro Left 5",
+ "Bunker Intro Back 4",
+ "Bunker Glass Room 3",
+ "Bunker UV Room 2",
"Bunker Laser Panel",
- "Swamp Seperatable Shapers 6",
- "Swamp Combinable Shapers 8",
- "Swamp Broken Shapers 4",
- "Swamp Cyan Underwater Negative Shapers 5",
- "Swamp Platform Shapers 4",
- "Swamp Rotated Shapers 4",
- "Swamp Red Underwater Negative Shapers 4",
- "Swamp More Rotated Shapers 4",
- "Swamp Blue Underwater Negative Shapers 5",
+ "Swamp Intro Front 6",
+ "Swamp Intro Back 8",
+ "Swamp Between Bridges Near Row 4",
+ "Swamp Cyan Underwater 5",
+ "Swamp Platform Row 4",
+ "Swamp Between Bridges Far Row 4",
+ "Swamp Red Underwater 4",
+ "Swamp Beyond Rotating Bridge 4",
+ "Swamp Blue Underwater 5",
"Swamp Laser Panel",
"Treehouse Yellow Bridge 9",
@@ -125,73 +127,77 @@ class StaticWitnessLocations:
"Treehouse Green Bridge 7",
"Treehouse Green Bridge Discard",
"Treehouse Left Orange Bridge 15",
- "Treehouse Burnt House Discard",
+ "Treehouse Laser Discard",
"Treehouse Right Orange Bridge 12",
"Treehouse Laser Panel",
- "Mountaintop Discard",
- "Mountaintop Vault Box",
- }
+ "Mountainside Discard",
+ "Mountainside Vault Box",
- UNCOMMON_LOCATIONS = {
"Mountaintop River Shape",
"Tutorial Patio Floor",
- "Quarry Mill Big Squares & Dots & Eraser",
+ "Quarry Mill Control Room Left",
"Theater Tutorial Video",
"Theater Desert Video",
"Theater Jungle Video",
"Theater Shipwreck Video",
"Theater Mountain Video",
- "Town RGB Squares",
- "Town RGB Stars",
- "Swamp Underwater Back Optional",
+ "Town RGB Room Left",
+ "Town RGB Room Right",
+ "Swamp Purple Underwater",
}
CAVES_LOCATIONS = {
- "Inside Mountain Caves Dot Grid Triangles 4",
- "Inside Mountain Caves Symmetry Triangles",
- "Inside Mountain Caves Stars & Squares and Triangles 2",
- "Inside Mountain Caves Shapers and Triangles 2",
- "Inside Mountain Caves Symmetry Shapers",
- "Inside Mountain Caves Broken and Negative Shapers",
- "Inside Mountain Caves Broken Shapers",
+ "Caves Blue Tunnel Right First 4",
+ "Caves Blue Tunnel Left First 1",
+ "Caves Blue Tunnel Left Second 5",
+ "Caves Blue Tunnel Right Second 5",
+ "Caves Blue Tunnel Right Third 1",
+ "Caves Blue Tunnel Left Fourth 1",
+ "Caves Blue Tunnel Left Third 1",
- "Inside Mountain Caves Rainbow Squares",
- "Inside Mountain Caves Squares & Stars and Colored Eraser",
- "Inside Mountain Caves Rotated Broken Shapers",
- "Inside Mountain Caves Stars and Squares",
- "Inside Mountain Caves Lone Pillar",
- "Inside Mountain Caves Wooden Beam Shapers",
- "Inside Mountain Caves Wooden Beam Squares and Shapers",
- "Inside Mountain Caves Wooden Beam Stars and Squares",
- "Inside Mountain Caves Wooden Beam Shapers and Stars",
- "Inside Mountain Caves Upstairs Invisible Dots 8",
- "Inside Mountain Caves Upstairs Invisible Dot Symmetry 3",
- "Inside Mountain Caves Upstairs Dot Grid Negative Shapers",
- "Inside Mountain Caves Upstairs Dot Grid Rotated Shapers",
+ "Caves First Floor Middle",
+ "Caves First Floor Right",
+ "Caves First Floor Left",
+ "Caves First Floor Grounded",
+ "Caves Lone Pillar",
+ "Caves First Wooden Beam",
+ "Caves Second Wooden Beam",
+ "Caves Third Wooden Beam",
+ "Caves Fourth Wooden Beam",
+ "Caves Right Upstairs Left Row 8",
+ "Caves Right Upstairs Right Row 3",
+ "Caves Left Upstairs Single",
+ "Caves Left Upstairs Left Row 5",
- "Theater Walkway Vault Box",
- "Inside Mountain Bottom Layer Discard",
+ "Tunnels Vault Box",
+ "Mountain Bottom Floor Discard",
"Theater Challenge Video",
}
MOUNTAIN_UNREACHABLE_FROM_BEHIND = {
"Mountaintop Trap Door Triple Exit",
- "Inside Mountain Obscured Vision 5",
- "Inside Mountain Moving Background 7",
- "Inside Mountain Physically Obstructed 3",
- "Inside Mountain Angled Inside Trash 2",
- "Inside Mountain Color Cycle 5",
- "Inside Mountain Same Solution 6",
+ "Mountain Floor 1 Right Row 5",
+ "Mountain Floor 1 Left Row 7",
+ "Mountain Floor 1 Back Row 3",
+ "Mountain Floor 1 Trash Pillar 2",
+ "Mountain Floor 2 Near Row 5",
+ "Mountain Floor 2 Far Row 6",
}
MOUNTAIN_REACHABLE_FROM_BEHIND = {
- "Inside Mountain Elevator Discard",
- "Inside Mountain Giant Puzzle",
+ "Mountain Floor 2 Elevator Discard",
+ "Mountain Bottom Floor Giant Puzzle",
- "Inside Mountain Final Room Left Pillar 4",
- "Inside Mountain Final Room Right Pillar 4",
+ "Mountain Final Room Left Pillar 4",
+ "Mountain Final Room Right Pillar 4",
+ }
+
+ MOUNTAIN_EXTRAS = {
+ "Challenge Vault Box",
+ "Theater Challenge Video",
+ "Mountain Bottom Floor Discard"
}
ALL_LOCATIONS_TO_ID = dict()
@@ -241,37 +247,44 @@ class WitnessPlayerLocations:
StaticWitnessLocations.GENERAL_LOCATIONS
)
- doors = get_option_value(world, player, "shuffle_doors")
+ doors = get_option_value(world, player, "shuffle_doors") >= 2
earlyutm = is_option_enabled(world, player, "early_secret_area")
victory = get_option_value(world, player, "victory_condition")
- lasers = get_option_value(world, player, "challenge_lasers")
+ mount_lasers = get_option_value(world, player, "mountain_lasers")
+ chal_lasers = get_option_value(world, player, "challenge_lasers")
laser_shuffle = get_option_value(world, player, "shuffle_lasers")
postgame = set()
postgame = postgame | StaticWitnessLocations.CAVES_LOCATIONS
postgame = postgame | StaticWitnessLocations.MOUNTAIN_REACHABLE_FROM_BEHIND
postgame = postgame | StaticWitnessLocations.MOUNTAIN_UNREACHABLE_FROM_BEHIND
+ postgame = postgame | StaticWitnessLocations.MOUNTAIN_EXTRAS
self.CHECK_LOCATIONS = self.CHECK_LOCATIONS | postgame
- if earlyutm or doors >= 2 or (victory == 1 and (lasers <= 11 or laser_shuffle)):
+ mountain_enterable_from_top = victory == 0 or victory == 1 or (victory == 3 and chal_lasers > mount_lasers)
+
+ if earlyutm or doors: # in non-doors, there is no way to get symbol-locked by the final pillars (currently)
postgame -= StaticWitnessLocations.CAVES_LOCATIONS
- if doors >= 2:
+ if (doors or earlyutm) and (victory == 0 or (victory == 2 and mount_lasers > chal_lasers)):
+ postgame -= {"Challenge Vault Box", "Theater Challenge Video"}
+
+ if doors or mountain_enterable_from_top:
postgame -= StaticWitnessLocations.MOUNTAIN_REACHABLE_FROM_BEHIND
- if victory != 2:
+ if mountain_enterable_from_top:
postgame -= StaticWitnessLocations.MOUNTAIN_UNREACHABLE_FROM_BEHIND
+ if (victory == 0 and doors) or victory == 1 or (victory == 2 and mount_lasers > chal_lasers and doors):
+ postgame -= {"Mountain Bottom Floor Discard"}
+
if is_option_enabled(world, player, "shuffle_discarded_panels"):
self.PANEL_TYPES_TO_SHUFFLE.add("Discard")
if is_option_enabled(world, player, "shuffle_vault_boxes"):
self.PANEL_TYPES_TO_SHUFFLE.add("Vault")
- if is_option_enabled(world, player, "shuffle_uncommon"):
- self.CHECK_LOCATIONS = self.CHECK_LOCATIONS | StaticWitnessLocations.UNCOMMON_LOCATIONS
-
self.CHECK_LOCATIONS = self.CHECK_LOCATIONS | player_logic.ADDED_CHECKS
if not is_option_enabled(world, player, "shuffle_postgame"):
diff --git a/worlds/witness/player_logic.py b/worlds/witness/player_logic.py
index 6fe45b107f..4840ea0a5d 100644
--- a/worlds/witness/player_logic.py
+++ b/worlds/witness/player_logic.py
@@ -60,7 +60,10 @@ class WitnessPlayerLogic:
for dependentItem in door_items:
all_options.add(items_option.union(dependentItem))
- return frozenset(all_options)
+ if panel_hex != "0x28A0D":
+ return frozenset(all_options)
+ else: # 0x28A0D depends on another entity for *non-power* reasons -> This dependency needs to be preserved
+ these_items = all_options
these_panels = self.DEPENDENT_REQUIREMENTS_BY_HEX[panel_hex]["panels"]
@@ -321,7 +324,7 @@ class WitnessPlayerLogic:
self.VICTORY_LOCATION = "0x0356B"
self.EVENT_ITEM_NAMES = {
"0x01A0F": "Keep Laser Panel (Hedge Mazes) Activates",
- "0x09D9B": "Monastery Overhead Doors Open",
+ "0x09D9B": "Monastery Shutters Open",
"0x193A6": "Monastery Laser Panel Activates",
"0x00037": "Monastery Branch Panels Activate",
"0x0A079": "Access to Bunker Laser",
@@ -332,24 +335,24 @@ class WitnessPlayerLogic:
"0x01D3F": "Keep Laser Panel (Pressure Plates) Activates",
"0x09F7F": "Mountain Access",
"0x0367C": "Quarry Laser Mill Requirement Met",
- "0x009A1": "Swamp Rotated Shapers 1 Activates",
+ "0x009A1": "Swamp Between Bridges Far 1 Activates",
"0x00006": "Swamp Cyan Water Drains",
- "0x00990": "Swamp Broken Shapers 1 Activates",
- "0x0A8DC": "Lower Avoid 6 Activates",
- "0x0000A": "Swamp More Rotated Shapers 1 Access",
- "0x09E86": "Inside Mountain Second Layer Blue Bridge Access",
- "0x09ED8": "Inside Mountain Second Layer Yellow Bridge Access",
+ "0x00990": "Swamp Between Bridges Near Row 1 Activates",
+ "0x0A8DC": "Intro 6 Activates",
+ "0x0000A": "Swamp Beyond Rotating Bridge 1 Access",
+ "0x09E86": "Mountain Floor 2 Blue Bridge Access",
+ "0x09ED8": "Mountain Floor 2 Yellow Bridge Access",
"0x0A3D0": "Quarry Laser Boathouse Requirement Met",
"0x00596": "Swamp Red Water Drains",
"0x00E3A": "Swamp Purple Water Drains",
"0x0343A": "Door to Symmetry Island Powers On",
- "0xFFF00": "Inside Mountain Bottom Layer Discard Turns On",
+ "0xFFF00": "Mountain Bottom Floor Discard Turns On",
"0x17CA6": "All Boat Panels Turn On",
"0x17CDF": "All Boat Panels Turn On",
"0x09DB8": "All Boat Panels Turn On",
"0x17C95": "All Boat Panels Turn On",
"0x03BB0": "Town Church Lattice Vision From Outside",
- "0x28AC1": "Town Shapers & Dots & Eraser Turns On",
+ "0x28AC1": "Town Wooden Rooftop Turns On",
"0x28A69": "Town Tower 1st Door Opens",
"0x28ACC": "Town Tower 2nd Door Opens",
"0x28AD9": "Town Tower 3rd Door Opens",
@@ -357,9 +360,9 @@ class WitnessPlayerLogic:
"0x03675": "Quarry Mill Ramp Activation From Above",
"0x03679": "Quarry Mill Lift Lowering While Standing On It",
"0x2FAF6": "Tutorial Gate Secret Solution Knowledge",
- "0x079DF": "Town Hexagonal Reflection Turns On",
+ "0x079DF": "Town Tall Hexagonal Turns On",
"0x17DA2": "Right Orange Bridge Fully Extended",
- "0x19B24": "Shadows Lower Avoid Patterns Visible",
+ "0x19B24": "Shadows Intro Patterns Visible",
"0x2700B": "Open Door to Treehouse Laser House",
"0x00055": "Orchard Apple Trees 4 Turns On",
"0x17DDB": "Left Orange Bridge Fully Extended",
@@ -369,6 +372,8 @@ class WitnessPlayerLogic:
"0x03481": "Tutorial Video Pattern Knowledge",
"0x03702": "Jungle Video Pattern Knowledge",
"0x0356B": "Challenge Video Pattern Knowledge",
+ "0x0A15F": "Desert Laser Panel Shutters Open (1)",
+ "0x012D7": "Desert Laser Panel Shutters Open (2)",
}
self.ALWAYS_EVENT_NAMES_BY_HEX = {
diff --git a/worlds/witness/regions.py b/worlds/witness/regions.py
index b5ee31b8ca..143f3e77e5 100644
--- a/worlds/witness/regions.py
+++ b/worlds/witness/regions.py
@@ -73,7 +73,7 @@ class WitnessRegions:
all_locations = all_locations | set(locations_for_this_region)
world.regions += [
- create_region(world, player, region_name, self.locat,locations_for_this_region)
+ create_region(world, player, region_name, self.locat, locations_for_this_region)
]
for region_name, region in StaticWitnessLogic.ALL_REGIONS_BY_NAME.items():
diff --git a/worlds/witness/settings/Disable_Unrandomized.txt b/worlds/witness/settings/Disable_Unrandomized.txt
index f03f5496c2..4f26e3136a 100644
--- a/worlds/witness/settings/Disable_Unrandomized.txt
+++ b/worlds/witness/settings/Disable_Unrandomized.txt
@@ -25,84 +25,84 @@ Disabled Locations:
0x00055 (Orchard Apple Tree 3)
0x032F7 (Orchard Apple Tree 4)
0x032FF (Orchard Apple Tree 5)
-0x198B5 (Shadows Lower Avoid 1)
-0x198BD (Shadows Lower Avoid 2)
-0x198BF (Shadows Lower Avoid 3)
-0x19771 (Shadows Lower Avoid 4)
-0x0A8DC (Shadows Lower Avoid 5)
-0x0AC74 (Shadows Lower Avoid 6)
-0x0AC7A (Shadows Lower Avoid 7)
-0x0A8E0 (Shadows Lower Avoid 8)
-0x386FA (Shadows Environmental Avoid 1)
-0x1C33F (Shadows Environmental Avoid 2)
-0x196E2 (Shadows Environmental Avoid 3)
-0x1972A (Shadows Environmental Avoid 4)
-0x19809 (Shadows Environmental Avoid 5)
-0x19806 (Shadows Environmental Avoid 6)
-0x196F8 (Shadows Environmental Avoid 7)
-0x1972F (Shadows Environmental Avoid 8)
-0x19797 (Shadows Follow 1)
-0x1979A (Shadows Follow 2)
-0x197E0 (Shadows Follow 3)
-0x197E8 (Shadows Follow 4)
-0x197E5 (Shadows Follow 5)
+0x198B5 (Shadows Intro 1)
+0x198BD (Shadows Intro 2)
+0x198BF (Shadows Intro 3)
+0x19771 (Shadows Intro 4)
+0x0A8DC (Shadows Intro 5)
+0x0AC74 (Shadows Intro 6)
+0x0AC7A (Shadows Intro 7)
+0x0A8E0 (Shadows Intro 8)
+0x386FA (Shadows Far 1)
+0x1C33F (Shadows Far 2)
+0x196E2 (Shadows Far 3)
+0x1972A (Shadows Far 4)
+0x19809 (Shadows Far 5)
+0x19806 (Shadows Far 6)
+0x196F8 (Shadows Far 7)
+0x1972F (Shadows Far 8)
+0x19797 (Shadows Near 1)
+0x1979A (Shadows Near 2)
+0x197E0 (Shadows Near 3)
+0x197E8 (Shadows Near 4)
+0x197E5 (Shadows Near 5)
0x19650 (Shadows Laser)
0x00139 (Keep Hedge Maze 1)
0x019DC (Keep Hedge Maze 2)
0x019E7 (Keep Hedge Maze 3)
0x01A0F (Keep Hedge Maze 4)
0x0360E (Laser Hedges)
-0x00B10 (Monastery Door Open Left)
-0x00C92 (Monastery Door Open Right)
-0x00290 (Monastery Rhombic Avoid 1)
-0x00038 (Monastery Rhombic Avoid 2)
-0x00037 (Monastery Rhombic Avoid 3)
-0x193A7 (Monastery Branch Avoid 1)
-0x193AA (Monastery Branch Avoid 2)
-0x193AB (Monastery Branch Follow 1)
-0x193A6 (Monastery Branch Follow 2)
+0x00B10 (Monastery Entry Left)
+0x00C92 (Monastery Entry Right)
+0x00290 (Monastery Outside 1)
+0x00038 (Monastery Outside 2)
+0x00037 (Monastery Outside 3)
+0x193A7 (Monastery Inside 1)
+0x193AA (Monastery Inside 2)
+0x193AB (Monastery Inside 3)
+0x193A6 (Monastery Inside 4)
0x17CA4 (Monastery Laser)
-0x18590 (Tree Outlines) - True - Symmetry & Environment
-0x28AE3 (Vines Shadows Follow) - 0x18590 - Shadows Follow & Environment
-0x28938 (Four-way Apple Tree) - 0x28AE3 - Environment
-0x079DF (Triple Environmental Puzzle) - 0x28938 - Shadows Avoid & Environment & Reflection
-0x28B39 (Hexagonal Reflection) - 0x079DF & 0x2896A - Reflection
+0x18590 (Transparent) - True - Symmetry & Environment
+0x28AE3 (Vines) - 0x18590 - Shadows Follow & Environment
+0x28938 (Apple Tree) - 0x28AE3 - Environment
+0x079DF (Triple Exit) - 0x28938 - Shadows Avoid & Environment & Reflection
+0x28B39 (Tall Hexagonal) - 0x079DF & 0x2896A - Reflection
0x03553 (Theater Tutorial Video)
0x03552 (Theater Desert Video)
0x0354E (Theater Jungle Video)
0x03549 (Theater Challenge Video)
0x0354F (Theater Shipwreck Video)
0x03545 (Theater Mountain Video)
-0x002C4 (Waves 1)
-0x00767 (Waves 2)
-0x002C6 (Waves 3)
-0x0070E (Waves 4)
-0x0070F (Waves 5)
-0x0087D (Waves 6)
-0x002C7 (Waves 7)
-0x15ADD (River Rhombic Avoid Vault)
+0x002C4 (First Row 1)
+0x00767 (First Row 2)
+0x002C6 (First Row 3)
+0x0070E (Second Row 1)
+0x0070F (Second Row 2)
+0x0087D (Second Row 3)
+0x002C7 (Second Row 4)
+0x15ADD (River Outside Vault)
0x03702 (River Vault Box)
-0x17CAA (Rhombic Avoid to Monastery Garden)
+0x17CAA (Monastery Shortcut Panel)
0x17C2E (Door to Bunker)
-0x09F7D (Bunker Drawn Squares 1)
-0x09FDC (Bunker Drawn Squares 2)
-0x09FF7 (Bunker Drawn Squares 3)
-0x09F82 (Bunker Drawn Squares 4)
-0x09FF8 (Bunker Drawn Squares 5)
-0x09D9F (Bunker Drawn Squares 6)
-0x09DA1 (Bunker Drawn Squares 7)
-0x09DA2 (Bunker Drawn Squares 8)
-0x09DAF (Bunker Drawn Squares 9)
-0x0A010 (Bunker Drawn Squares through Tinted Glass 1)
-0x0A01B (Bunker Drawn Squares through Tinted Glass 2)
-0x0A01F (Bunker Drawn Squares through Tinted Glass 3)
-0x0A099 (Door to Bunker Proper)
+0x09F7D (Bunker Intro Left 1)
+0x09FDC (Bunker Intro Left 2)
+0x09FF7 (Bunker Intro Left 3)
+0x09F82 (Bunker Intro Left 4)
+0x09FF8 (Bunker Intro Left 5)
+0x09D9F (Bunker Intro Back 1)
+0x09DA1 (Bunker Intro Back 2)
+0x09DA2 (Bunker Intro Back 3)
+0x09DAF (Bunker Intro Back 4)
+0x0A010 (Bunker Glass Room 1)
+0x0A01B (Bunker Glass Room 2)
+0x0A01F (Bunker Glass Room 3)
+0x0A099 (Tinted Glass Door)
0x34BC5 (Bunker Drop-Down Door Open)
0x34BC6 (Bunker Drop-Down Door Close)
-0x17E63 (Bunker Drop-Down Door Squares 1)
-0x17E67 (Bunker Drop-Down Door Squares 2)
+0x17E63 (Bunker UV Room 1)
+0x17E67 (Bunker UV Room 2)
0x09DE0 (Bunker Laser)
0x0A079 (Bunker Elevator Control)
0x0042D (Mountaintop River Shape)
-0x17CAA (River Door to Garden Panel)
\ No newline at end of file
+0x17CAA (River Garden Entry Panel)
diff --git a/worlds/witness/settings/Door_Panel_Shuffle.txt b/worlds/witness/settings/Door_Panel_Shuffle.txt
index d6982f52e3..745c0b4a45 100644
--- a/worlds/witness/settings/Door_Panel_Shuffle.txt
+++ b/worlds/witness/settings/Door_Panel_Shuffle.txt
@@ -1,31 +1,31 @@
Items:
-Glass Factory Entry Door (Panel)
-Door to Symmetry Island Lower (Panel)
-Door to Symmetry Island Upper (Panel)
-Door to Desert Flood Light Room (Panel)
-Desert Flood Room Flood Controls (Panel)
-Quarry Door to Mill (Panel)
+Glass Factory Entry (Panel)
+Symmetry Island Lower (Panel)
+Symmetry Island Upper (Panel)
+Desert Light Room Entry (Panel)
+Desert Flood Controls (Panel)
+Quarry Mill Entry (Panel)
Quarry Mill Ramp Controls (Panel)
-Quarry Mill Elevator Controls (Panel)
+Quarry Mill Lift Controls (Panel)
Quarry Boathouse Ramp Height Control (Panel)
Quarry Boathouse Ramp Horizontal Control (Panel)
Shadows Door Timer (Panel)
-Monastery Entry Door Left (Panel)
-Monastery Entry Door Right (Panel)
-Town Door to RGB House (Panel)
-Town Door to Church (Panel)
+Monastery Entry Left (Panel)
+Monastery Entry Right (Panel)
+Town Tinted Glass Door (Panel)
+Town Church Entry (Panel)
Town Maze Panel (Drop-Down Staircase) (Panel)
-Windmill Door (Panel)
+Windmill Entry (Panel)
Treehouse First & Second Doors (Panel)
Treehouse Third Door (Panel)
Treehouse Laser House Door Timer (Panel)
-Treehouse Shortcut Drop-Down Bridge (Panel)
+Treehouse Drawbridge (Panel)
Jungle Popup Wall (Panel)
-Bunker Entry Door (Panel)
-Inside Bunker Door to Bunker Proper (Panel)
+Bunker Entry (Panel)
+Bunker Tinted Glass Door (Panel)
Bunker Elevator Control (Panel)
-Swamp Entry Door (Panel)
+Swamp Entry (Panel)
Swamp Sliding Bridge (Panel)
Swamp Rotating Bridge (Panel)
Swamp Maze Control (Panel)
-Boat
+Boat
\ No newline at end of file
diff --git a/worlds/witness/settings/Doors_Complex.txt b/worlds/witness/settings/Doors_Complex.txt
index c62562e32a..9d883cad2f 100644
--- a/worlds/witness/settings/Doors_Complex.txt
+++ b/worlds/witness/settings/Doors_Complex.txt
@@ -1,128 +1,128 @@
Items:
-Outside Tutorial Optional Door
-Outside Tutorial Outpost Entry Door
-Outside Tutorial Outpost Exit Door
-Glass Factory Entry Door
-Glass Factory Back Wall
-Symmetry Island Lower Door
-Symmetry Island Upper Door
-Orchard Middle Gate
-Orchard Final Gate
-Desert Door to Flood Light Room
-Desert Door to Pond Room
-Desert Door to Water Levels Room
-Desert Door to Elevator Room
-Quarry Main Entry 1
-Quarry Main Entry 2
-Quarry Door to Mill
-Quarry Mill Side Door
-Quarry Mill Rooftop Shortcut
-Quarry Mill Stairs
-Quarry Boathouse Boat Staircase
-Quarry Boathouse First Barrier
-Quarry Boathouse Shortcut
-Shadows Timed Door
-Shadows Laser Room Right Door
-Shadows Laser Room Left Door
-Shadows Barrier to Quarry
-Shadows Barrier to Ledge
-Keep Hedge Maze 1 Exit Door
-Keep Pressure Plates 1 Exit Door
-Keep Hedge Maze 2 Shortcut
-Keep Hedge Maze 2 Exit Door
-Keep Hedge Maze 3 Shortcut
-Keep Hedge Maze 3 Exit Door
-Keep Hedge Maze 4 Shortcut
-Keep Hedge Maze 4 Exit Door
-Keep Pressure Plates 2 Exit Door
-Keep Pressure Plates 3 Exit Door
-Keep Pressure Plates 4 Exit Door
-Keep Shortcut to Shadows
-Keep Tower Shortcut
-Monastery Shortcut
-Monastery Inner Door
-Monastery Outer Door
-Monastery Door to Garden
-Town Cargo Box Door
-Town Wooden Roof Staircase
-Town Tinted Door to RGB House
-Town Door to Church
-Town Maze Staircase
-Town Windmill Door
-Town RGB House Staircase
-Town Tower Blue Panels Door
-Town Tower Lattice Door
-Town Tower Environmental Set Door
-Town Tower Wooden Roof Set Door
-Theater Entry Door
-Theater Exit Door Left
-Theater Exit Door Right
-Jungle Bamboo Shortcut to River
-Jungle Popup Wall
-River Shortcut to Monastery Garden
-Bunker Bunker Entry Door
-Bunker Tinted Glass Door
-Bunker Door to Ultraviolet Room
-Bunker Door to Elevator
-Swamp Entry Door
-Swamp Door to Broken Shapers
+Outside Tutorial Outpost Path (Door)
+Outside Tutorial Outpost Entry (Door)
+Outside Tutorial Outpost Exit (Door)
+Glass Factory Entry (Door)
+Glass Factory Back Wall (Door)
+Symmetry Island Lower (Door)
+Symmetry Island Upper (Door)
+Orchard First Gate (Door)
+Orchard Second Gate (Door)
+Desert Light Room Entry (Door)
+Desert Pond Room Entry (Door)
+Desert Flood Room Entry (Door)
+Desert Elevator Room Entry (Door)
+Quarry Entry 1 (Door)
+Quarry Entry 2 (Door)
+Quarry Mill Entry (Door)
+Quarry Mill Side Exit (Door)
+Quarry Mill Roof Exit (Door)
+Quarry Mill Stairs (Door)
+Quarry Boathouse Dock (Door)
+Quarry Boathouse First Barrier (Door)
+Quarry Boathouse Second Barrier (Door)
+Shadows Timed Door (Door)
+Shadows Laser Entry Right (Door)
+Shadows Laser Entry Left (Door)
+Shadows Quarry Barrier (Door)
+Shadows Ledge Barrier (Door)
+Keep Hedge Maze 1 Exit (Door)
+Keep Pressure Plates 1 Exit (Door)
+Keep Hedge Maze 2 Shortcut (Door)
+Keep Hedge Maze 2 Exit (Door)
+Keep Hedge Maze 3 Shortcut (Door)
+Keep Hedge Maze 3 Exit (Door)
+Keep Hedge Maze 4 Shortcut (Door)
+Keep Hedge Maze 4 Exit (Door)
+Keep Pressure Plates 2 Exit (Door)
+Keep Pressure Plates 3 Exit (Door)
+Keep Pressure Plates 4 Exit (Door)
+Keep Shadows Shortcut (Door)
+Keep Tower Shortcut (Door)
+Monastery Shortcut (Door)
+Monastery Entry Inner (Door)
+Monastery Entry Outer (Door)
+Monastery Garden Entry (Door)
+Town Cargo Box Entry (Door)
+Town Wooden Roof Stairs (Door)
+Town Tinted Glass Door (Door)
+Town Church Entry (Door)
+Town Maze Stairs (Door)
+Town Windmill Entry (Door)
+Town RGB House Stairs (Door)
+Town Tower First Door (Door)
+Town Tower Third Door (Door)
+Town Tower Fourth Door (Door)
+Town Tower Second Door (Door)
+Theater Entry (Door)
+Theater Exit Left (Door)
+Theater Exit Right (Door)
+Jungle Bamboo Laser Shortcut (Door)
+Jungle Popup Wall (Door)
+River Monastery Shortcut (Door)
+Bunker Entry (Door)
+Bunker Tinted Glass Door (Door)
+Bunker UV Room Entry (Door)
+Bunker Elevator Room Entry (Door)
+Swamp Entry (Door)
+Swamp Between Bridges First Door
Swamp Platform Shortcut Door
-Swamp Cyan Water Pump
-Swamp Door to Rotated Shapers
-Swamp Red Water Pump
-Swamp Red Underwater Exit
-Swamp Blue Water Pump
-Swamp Purple Water Pump
-Swamp Near Laser Shortcut
-Treehouse First Door
-Treehouse Second Door
-Treehouse Beyond Yellow Bridge Door
-Treehouse Drawbridge
-Treehouse Timed Door to Laser House
-Inside Mountain First Layer Exit Door
-Inside Mountain Second Layer Staircase Near
-Inside Mountain Second Layer Exit Door
-Inside Mountain Second Layer Staircase Far
-Inside Mountain Giant Puzzle Exit Door
-Inside Mountain Door to Final Room
-Inside Mountain Bottom Layer Rock
-Inside Mountain Door to Secret Area
-Caves Pillar Door
-Caves Mountain Shortcut
-Caves Swamp Shortcut
-Challenge Entry Door
-Challenge Door to Theater Walkway
-Theater Walkway Door to Windmill Interior
-Theater Walkway Door to Desert Elevator Room
-Theater Walkway Door to Town
+Swamp Cyan Water Pump (Door)
+Swamp Between Bridges Second Door
+Swamp Red Water Pump (Door)
+Swamp Red Underwater Exit (Door)
+Swamp Blue Water Pump (Door)
+Swamp Purple Water Pump (Door)
+Swamp Laser Shortcut (Door)
+Treehouse First Door (Door)
+Treehouse Second Door (Door)
+Treehouse Third Door (Door)
+Treehouse Drawbridge (Door)
+Treehouse Laser House Entry (Door)
+Mountain Floor 1 Exit (Door)
+Mountain Floor 2 Staircase Near (Door)
+Mountain Floor 2 Exit (Door)
+Mountain Floor 2 Staircase Far (Door)
+Mountain Bottom Floor Giant Puzzle Exit (Door)
+Mountain Bottom Floor Final Room Entry (Door)
+Mountain Bottom Floor Rock (Door)
+Caves Entry (Door)
+Caves Pillar Door (Door)
+Caves Mountain Shortcut (Door)
+Caves Swamp Shortcut (Door)
+Challenge Entry (Door)
+Challenge Tunnels Entry (Door)
+Tunnels Theater Shortcut (Door)
+Tunnels Desert Shortcut (Door)
+Tunnels Town Shortcut (Door)
Added Locations:
-Outside Tutorial Door to Outpost Panel
-Outside Tutorial Exit Door from Outpost Panel
-Glass Factory Entry Door Panel
-Glass Factory Vertical Symmetry 5
-Symmetry Island Door to Symmetry Island Lower Panel
-Symmetry Island Door to Symmetry Island Upper Panel
+Outside Tutorial Outpost Entry Panel
+Outside Tutorial Outpost Exit Panel
+Glass Factory Entry Panel
+Glass Factory Back Wall 5
+Symmetry Island Lower Panel
+Symmetry Island Upper Panel
Orchard Apple Tree 3
Orchard Apple Tree 5
-Desert Door to Desert Flood Light Room Panel
-Desert Artificial Light Reflection 3
-Desert Door to Water Levels Room Panel
-Desert Flood Reflection 6
-Quarry Door to Quarry 1 Panel
-Quarry Door to Quarry 2 Panel
-Quarry Door to Mill Right
-Quarry Door to Mill Left
-Quarry Mill Ground Floor Shortcut Door Panel
-Quarry Mill Door to Outside Quarry Stairs Panel
+Desert Light Room Entry Panel
+Desert Light Room 3
+Desert Flood Room Entry Panel
+Desert Flood Room 6
+Quarry Entry 1 Panel
+Quarry Entry 2 Panel
+Quarry Mill Entry Right Panel
+Quarry Mill Entry Left Panel
+Quarry Mill Side Exit Panel
+Quarry Mill Roof Exit Panel
Quarry Mill Stair Control
-Quarry Boathouse Shortcut Door Panel
+Quarry Boathouse Second Barrier Panel
Shadows Door Timer Inside
Shadows Door Timer Outside
-Shadows Environmental Avoid 8
-Shadows Follow 5
-Shadows Lower Avoid 3
-Shadows Lower Avoid 5
+Shadows Far 8
+Shadows Near 5
+Shadows Intro 3
+Shadows Intro 5
Keep Hedge Maze 1
Keep Pressure Plates 1
Keep Hedge Maze 2
@@ -131,71 +131,70 @@ Keep Hedge Maze 4
Keep Pressure Plates 2
Keep Pressure Plates 3
Keep Pressure Plates 4
-Keep Shortcut to Shadows Panel
-Keep Tower Shortcut to Keep Panel
-Monastery Shortcut Door Panel
-Monastery Door Open Left
-Monastery Door Open Right
-Monastery Rhombic Avoid 3
-Town Cargo Box Panel
-Town Full Dot Grid Shapers 5
-Town Tinted Door Panel
-Town Door to Church Stars Panel
+Keep Shadows Shortcut Panel
+Keep Tower Shortcut Panel
+Monastery Shortcut Panel
+Monastery Entry Left
+Monastery Entry Right
+Monastery Outside 3
+Town Cargo Box Entry Panel
+Town Wooden Roof Lower Row 5
+Town Tinted Glass Door Panel
+Town Church Entry Panel
Town Maze Stair Control
-Town Windmill Door Panel
-Town Sound Room Left
+Town Windmill Entry Panel
Town Sound Room Right
-Town Symmetry Squares 5 + Dots
+Town Red Rooftop 5
Town Church Lattice
-Town Hexagonal Reflection
-Town Shapers & Dots & Eraser
-Windmill Door to Front of Theater Panel
-Theater Door to Cargo Box Left Panel
-Theater Door to Cargo Box Right Panel
-Jungle Shortcut to River Panel
+Town Tall Hexagonal
+Town Wooden Rooftop
+Windmill Theater Entry Panel
+Theater Exit Left Panel
+Theater Exit Right Panel
+Jungle Laser Shortcut Panel
Jungle Popup Wall Control
-River Rhombic Avoid to Monastery Garden
-Bunker Bunker Entry Panel
-Bunker Door to Bunker Proper Panel
-Bunker Drawn Squares through Tinted Glass 3
-Bunker Drop-Down Door Squares 2
+River Monastery Shortcut Panel
+Bunker Entry Panel
+Bunker Tinted Glass Door Panel
+Bunker Glass Room 3
+Bunker UV Room 2
Swamp Entry Panel
-Swamp Platform Shapers 4
+Swamp Platform Row 4
Swamp Platform Shortcut Right Panel
-Swamp Blue Underwater Negative Shapers 5
-Swamp Broken Shapers 4
-Swamp Cyan Underwater Negative Shapers 5
-Swamp Red Underwater Negative Shapers 4
-Swamp More Rotated Shapers 4
-Swamp More Rotated Shapers 4
-Swamp Near Laser Shortcut Right Panel
+Swamp Blue Underwater 5
+Swamp Between Bridges Near Row 4
+Swamp Cyan Underwater 5
+Swamp Red Underwater 4
+Swamp Beyond Rotating Bridge 4
+Swamp Beyond Rotating Bridge 4
+Swamp Laser Shortcut Right Panel
Treehouse First Door Panel
Treehouse Second Door Panel
-Treehouse Beyond Yellow Bridge Door Panel
+Treehouse Third Door Panel
Treehouse Bridge Control
Treehouse Left Orange Bridge 15
Treehouse Right Orange Bridge 12
Treehouse Laser House Door Timer Outside Control
-Treehouse Laser House Door Timer Inside Control
-Inside Mountain Moving Background 7
-Inside Mountain Obscured Vision 5
-Inside Mountain Physically Obstructed 3
-Inside Mountain Angled Inside Trash 2
-Inside Mountain Color Cycle 5
-Inside Mountain Light Bridge Controller 2
-Inside Mountain Light Bridge Controller 3
-Inside Mountain Same Solution 6
-Inside Mountain Giant Puzzle
-Inside Mountain Door to Final Room Left
-Inside Mountain Door to Final Room Right
-Inside Mountain Bottom Layer Discard
-Inside Mountain Rock Control
-Inside Mountain Secret Area Entry Panel
-Inside Mountain Caves Lone Pillar
-Inside Mountain Caves Shortcut to Mountain Panel
-Inside Mountain Caves Shortcut to Swamp Panel
-Inside Mountain Caves Challenge Entry Panel
-Challenge Door to Theater Walkway Panel
-Theater Walkway Theater Shortcut Panel
-Theater Walkway Desert Shortcut Panel
-Theater Walkway Town Shortcut Panel
\ No newline at end of file
+Treehouse Laser House Door Timer Inside
+Mountain Floor 1 Left Row 7
+Mountain Floor 1 Right Row 5
+Mountain Floor 1 Back Row 3
+Mountain Floor 1 Trash Pillar 2
+Mountain Floor 2 Near Row 5
+Mountain Floor 2 Light Bridge Controller Near
+Mountain Floor 2 Light Bridge Controller Far
+Mountain Floor 2 Far Row 6
+Mountain Bottom Floor Giant Puzzle
+Mountain Bottom Floor Final Room Entry Left
+Mountain Bottom Floor Final Room Entry Right
+Mountain Bottom Floor Discard
+Mountain Bottom Floor Rock Control
+Mountain Bottom Floor Caves Entry Panel
+Caves Lone Pillar
+Caves Mountain Shortcut Panel
+Caves Swamp Shortcut Panel
+Caves Challenge Entry Panel
+Challenge Tunnels Entry Panel
+Tunnels Theater Shortcut Panel
+Tunnels Desert Shortcut Panel
+Tunnels Town Shortcut Panel
\ No newline at end of file
diff --git a/worlds/witness/settings/Doors_Max.txt b/worlds/witness/settings/Doors_Max.txt
index ec0a56a597..739000426c 100644
--- a/worlds/witness/settings/Doors_Max.txt
+++ b/worlds/witness/settings/Doors_Max.txt
@@ -1,104 +1,104 @@
Items:
-Outside Tutorial Optional Door
-Outside Tutorial Outpost Entry Door
-Outside Tutorial Outpost Exit Door
-Glass Factory Entry Door
-Glass Factory Back Wall
-Symmetry Island Lower Door
-Symmetry Island Upper Door
-Orchard Middle Gate
-Orchard Final Gate
-Desert Door to Flood Light Room
-Desert Door to Pond Room
-Desert Door to Water Levels Room
-Desert Door to Elevator Room
-Quarry Main Entry 1
-Quarry Main Entry 2
-Quarry Door to Mill
-Quarry Mill Side Door
-Quarry Mill Rooftop Shortcut
-Quarry Mill Stairs
-Quarry Boathouse Boat Staircase
-Quarry Boathouse First Barrier
-Quarry Boathouse Shortcut
-Shadows Timed Door
-Shadows Laser Room Right Door
-Shadows Laser Room Left Door
-Shadows Barrier to Quarry
-Shadows Barrier to Ledge
-Keep Hedge Maze 1 Exit Door
-Keep Pressure Plates 1 Exit Door
-Keep Hedge Maze 2 Shortcut
-Keep Hedge Maze 2 Exit Door
-Keep Hedge Maze 3 Shortcut
-Keep Hedge Maze 3 Exit Door
-Keep Hedge Maze 4 Shortcut
-Keep Hedge Maze 4 Exit Door
-Keep Pressure Plates 2 Exit Door
-Keep Pressure Plates 3 Exit Door
-Keep Pressure Plates 4 Exit Door
-Keep Shortcut to Shadows
-Keep Tower Shortcut
-Monastery Shortcut
-Monastery Inner Door
-Monastery Outer Door
-Monastery Door to Garden
-Town Cargo Box Door
-Town Wooden Roof Staircase
-Town Tinted Door to RGB House
-Town Door to Church
-Town Maze Staircase
-Town Windmill Door
-Town RGB House Staircase
-Town Tower Blue Panels Door
-Town Tower Lattice Door
-Town Tower Environmental Set Door
-Town Tower Wooden Roof Set Door
-Theater Entry Door
-Theater Exit Door Left
-Theater Exit Door Right
-Jungle Bamboo Shortcut to River
-Jungle Popup Wall
-River Shortcut to Monastery Garden
-Bunker Bunker Entry Door
-Bunker Tinted Glass Door
-Bunker Door to Ultraviolet Room
-Bunker Door to Elevator
-Swamp Entry Door
-Swamp Door to Broken Shapers
+Outside Tutorial Outpost Path (Door)
+Outside Tutorial Outpost Entry (Door)
+Outside Tutorial Outpost Exit (Door)
+Glass Factory Entry (Door)
+Glass Factory Back Wall (Door)
+Symmetry Island Lower (Door)
+Symmetry Island Upper (Door)
+Orchard First Gate (Door)
+Orchard Second Gate (Door)
+Desert Light Room Entry (Door)
+Desert Pond Room Entry (Door)
+Desert Flood Room Entry (Door)
+Desert Elevator Room Entry (Door)
+Quarry Entry 1 (Door)
+Quarry Entry 2 (Door)
+Quarry Mill Entry (Door)
+Quarry Mill Side Exit (Door)
+Quarry Mill Roof Exit (Door)
+Quarry Mill Stairs (Door)
+Quarry Boathouse Dock (Door)
+Quarry Boathouse First Barrier (Door)
+Quarry Boathouse Second Barrier (Door)
+Shadows Timed Door (Door)
+Shadows Laser Entry Right (Door)
+Shadows Laser Entry Left (Door)
+Shadows Quarry Barrier (Door)
+Shadows Ledge Barrier (Door)
+Keep Hedge Maze 1 Exit (Door)
+Keep Pressure Plates 1 Exit (Door)
+Keep Hedge Maze 2 Shortcut (Door)
+Keep Hedge Maze 2 Exit (Door)
+Keep Hedge Maze 3 Shortcut (Door)
+Keep Hedge Maze 3 Exit (Door)
+Keep Hedge Maze 4 Shortcut (Door)
+Keep Hedge Maze 4 Exit (Door)
+Keep Pressure Plates 2 Exit (Door)
+Keep Pressure Plates 3 Exit (Door)
+Keep Pressure Plates 4 Exit (Door)
+Keep Shadows Shortcut (Door)
+Keep Tower Shortcut (Door)
+Monastery Shortcut (Door)
+Monastery Entry Inner (Door)
+Monastery Entry Outer (Door)
+Monastery Garden Entry (Door)
+Town Cargo Box Entry (Door)
+Town Wooden Roof Stairs (Door)
+Town Tinted Glass Door (Door)
+Town Church Entry (Door)
+Town Maze Stairs (Door)
+Town Windmill Entry (Door)
+Town RGB House Stairs (Door)
+Town Tower First Door (Door)
+Town Tower Third Door (Door)
+Town Tower Fourth Door (Door)
+Town Tower Second Door (Door)
+Theater Entry (Door)
+Theater Exit Left (Door)
+Theater Exit Right (Door)
+Jungle Bamboo Laser Shortcut (Door)
+Jungle Popup Wall (Door)
+River Monastery Shortcut (Door)
+Bunker Entry (Door)
+Bunker Tinted Glass Door (Door)
+Bunker UV Room Entry (Door)
+Bunker Elevator Room Entry (Door)
+Swamp Entry (Door)
+Swamp Between Bridges First Door
Swamp Platform Shortcut Door
-Swamp Cyan Water Pump
-Swamp Door to Rotated Shapers
-Swamp Red Water Pump
-Swamp Red Underwater Exit
-Swamp Blue Water Pump
-Swamp Purple Water Pump
-Swamp Near Laser Shortcut
-Treehouse First Door
-Treehouse Second Door
-Treehouse Beyond Yellow Bridge Door
-Treehouse Drawbridge
-Treehouse Timed Door to Laser House
-Inside Mountain First Layer Exit Door
-Inside Mountain Second Layer Staircase Near
-Inside Mountain Second Layer Exit Door
-Inside Mountain Second Layer Staircase Far
-Inside Mountain Giant Puzzle Exit Door
-Inside Mountain Door to Final Room
-Inside Mountain Bottom Layer Rock
-Inside Mountain Door to Secret Area
-Caves Pillar Door
-Caves Mountain Shortcut
-Caves Swamp Shortcut
-Challenge Entry Door
-Challenge Door to Theater Walkway
-Theater Walkway Door to Windmill Interior
-Theater Walkway Door to Desert Elevator Room
-Theater Walkway Door to Town
+Swamp Cyan Water Pump (Door)
+Swamp Between Bridges Second Door
+Swamp Red Water Pump (Door)
+Swamp Red Underwater Exit (Door)
+Swamp Blue Water Pump (Door)
+Swamp Purple Water Pump (Door)
+Swamp Laser Shortcut (Door)
+Treehouse First Door (Door)
+Treehouse Second Door (Door)
+Treehouse Third Door (Door)
+Treehouse Drawbridge (Door)
+Treehouse Laser House Entry (Door)
+Mountain Floor 1 Exit (Door)
+Mountain Floor 2 Staircase Near (Door)
+Mountain Floor 2 Exit (Door)
+Mountain Floor 2 Staircase Far (Door)
+Mountain Bottom Floor Giant Puzzle Exit (Door)
+Mountain Bottom Floor Final Room Entry (Door)
+Mountain Bottom Floor Rock (Door)
+Caves Entry (Door)
+Caves Pillar Door (Door)
+Caves Mountain Shortcut (Door)
+Caves Swamp Shortcut (Door)
+Challenge Entry (Door)
+Challenge Tunnels Entry (Door)
+Tunnels Theater Shortcut (Door)
+Tunnels Desert Shortcut (Door)
+Tunnels Town Shortcut (Door)
-Desert Flood Room Flood Controls (Panel)
+Desert Flood Controls (Panel)
Quarry Mill Ramp Controls (Panel)
-Quarry Mill Elevator Controls (Panel)
+Quarry Mill Lift Controls (Panel)
Quarry Boathouse Ramp Height Control (Panel)
Quarry Boathouse Ramp Horizontal Control (Panel)
Bunker Elevator Control (Panel)
@@ -108,32 +108,32 @@ Swamp Maze Control (Panel)
Boat
Added Locations:
-Outside Tutorial Door to Outpost Panel
-Outside Tutorial Exit Door from Outpost Panel
-Glass Factory Entry Door Panel
-Glass Factory Vertical Symmetry 5
-Symmetry Island Door to Symmetry Island Lower Panel
-Symmetry Island Door to Symmetry Island Upper Panel
+Outside Tutorial Outpost Entry Panel
+Outside Tutorial Outpost Exit Panel
+Glass Factory Entry Panel
+Glass Factory Back Wall 5
+Symmetry Island Lower Panel
+Symmetry Island Upper Panel
Orchard Apple Tree 3
Orchard Apple Tree 5
-Desert Door to Desert Flood Light Room Panel
-Desert Artificial Light Reflection 3
-Desert Door to Water Levels Room Panel
-Desert Flood Reflection 6
-Quarry Door to Quarry 1 Panel
-Quarry Door to Quarry 2 Panel
-Quarry Door to Mill Right
-Quarry Door to Mill Left
-Quarry Mill Ground Floor Shortcut Door Panel
-Quarry Mill Door to Outside Quarry Stairs Panel
+Desert Light Room Entry Panel
+Desert Light Room 3
+Desert Flood Room Entry Panel
+Desert Flood Room 6
+Quarry Entry 1 Panel
+Quarry Entry 2 Panel
+Quarry Mill Entry Right Panel
+Quarry Mill Entry Left Panel
+Quarry Mill Side Exit Panel
+Quarry Mill Roof Exit Panel
Quarry Mill Stair Control
-Quarry Boathouse Shortcut Door Panel
+Quarry Boathouse Second Barrier Panel
Shadows Door Timer Inside
Shadows Door Timer Outside
-Shadows Environmental Avoid 8
-Shadows Follow 5
-Shadows Lower Avoid 3
-Shadows Lower Avoid 5
+Shadows Far 8
+Shadows Near 5
+Shadows Intro 3
+Shadows Intro 5
Keep Hedge Maze 1
Keep Pressure Plates 1
Keep Hedge Maze 2
@@ -142,71 +142,70 @@ Keep Hedge Maze 4
Keep Pressure Plates 2
Keep Pressure Plates 3
Keep Pressure Plates 4
-Keep Shortcut to Shadows Panel
-Keep Tower Shortcut to Keep Panel
-Monastery Shortcut Door Panel
-Monastery Door Open Left
-Monastery Door Open Right
-Monastery Rhombic Avoid 3
-Town Cargo Box Panel
-Town Full Dot Grid Shapers 5
-Town Tinted Door Panel
-Town Door to Church Stars Panel
+Keep Shadows Shortcut Panel
+Keep Tower Shortcut Panel
+Monastery Shortcut Panel
+Monastery Entry Left
+Monastery Entry Right
+Monastery Outside 3
+Town Cargo Box Entry Panel
+Town Wooden Roof Lower Row 5
+Town Tinted Glass Door Panel
+Town Church Entry Panel
Town Maze Stair Control
-Town Windmill Door Panel
-Town Sound Room Left
+Town Windmill Entry Panel
Town Sound Room Right
-Town Symmetry Squares 5 + Dots
+Town Red Rooftop 5
Town Church Lattice
-Town Hexagonal Reflection
-Town Shapers & Dots & Eraser
-Windmill Door to Front of Theater Panel
-Theater Door to Cargo Box Left Panel
-Theater Door to Cargo Box Right Panel
-Jungle Shortcut to River Panel
+Town Tall Hexagonal
+Town Wooden Rooftop
+Windmill Theater Entry Panel
+Theater Exit Left Panel
+Theater Exit Right Panel
+Jungle Laser Shortcut Panel
Jungle Popup Wall Control
-River Rhombic Avoid to Monastery Garden
-Bunker Bunker Entry Panel
-Bunker Door to Bunker Proper Panel
-Bunker Drawn Squares through Tinted Glass 3
-Bunker Drop-Down Door Squares 2
+River Monastery Shortcut Panel
+Bunker Entry Panel
+Bunker Tinted Glass Door Panel
+Bunker Glass Room 3
+Bunker UV Room 2
Swamp Entry Panel
-Swamp Platform Shapers 4
+Swamp Platform Row 4
Swamp Platform Shortcut Right Panel
-Swamp Blue Underwater Negative Shapers 5
-Swamp Broken Shapers 4
-Swamp Cyan Underwater Negative Shapers 5
-Swamp Red Underwater Negative Shapers 4
-Swamp More Rotated Shapers 4
-Swamp More Rotated Shapers 4
-Swamp Near Laser Shortcut Right Panel
+Swamp Blue Underwater 5
+Swamp Between Bridges Near Row 4
+Swamp Cyan Underwater 5
+Swamp Red Underwater 4
+Swamp Beyond Rotating Bridge 4
+Swamp Beyond Rotating Bridge 4
+Swamp Laser Shortcut Right Panel
Treehouse First Door Panel
Treehouse Second Door Panel
-Treehouse Beyond Yellow Bridge Door Panel
+Treehouse Third Door Panel
Treehouse Bridge Control
Treehouse Left Orange Bridge 15
Treehouse Right Orange Bridge 12
Treehouse Laser House Door Timer Outside Control
-Treehouse Laser House Door Timer Inside Control
-Inside Mountain Moving Background 7
-Inside Mountain Obscured Vision 5
-Inside Mountain Physically Obstructed 3
-Inside Mountain Angled Inside Trash 2
-Inside Mountain Color Cycle 5
-Inside Mountain Light Bridge Controller 2
-Inside Mountain Light Bridge Controller 3
-Inside Mountain Same Solution 6
-Inside Mountain Giant Puzzle
-Inside Mountain Door to Final Room Left
-Inside Mountain Door to Final Room Right
-Inside Mountain Bottom Layer Discard
-Inside Mountain Rock Control
-Inside Mountain Secret Area Entry Panel
-Inside Mountain Caves Lone Pillar
-Inside Mountain Caves Shortcut to Mountain Panel
-Inside Mountain Caves Shortcut to Swamp Panel
-Inside Mountain Caves Challenge Entry Panel
-Challenge Door to Theater Walkway Panel
-Theater Walkway Theater Shortcut Panel
-Theater Walkway Desert Shortcut Panel
-Theater Walkway Town Shortcut Panel
\ No newline at end of file
+Treehouse Laser House Door Timer Inside
+Mountain Floor 1 Left Row 7
+Mountain Floor 1 Right Row 5
+Mountain Floor 1 Back Row 3
+Mountain Floor 1 Trash Pillar 2
+Mountain Floor 2 Near Row 5
+Mountain Floor 2 Light Bridge Controller Near
+Mountain Floor 2 Light Bridge Controller Far
+Mountain Floor 2 Far Row 6
+Mountain Bottom Floor Giant Puzzle
+Mountain Bottom Floor Final Room Entry Left
+Mountain Bottom Floor Final Room Entry Right
+Mountain Bottom Floor Discard
+Mountain Bottom Floor Rock Control
+Mountain Bottom Floor Caves Entry Panel
+Caves Lone Pillar
+Caves Mountain Shortcut Panel
+Caves Swamp Shortcut Panel
+Caves Challenge Entry Panel
+Challenge Tunnels Entry Panel
+Tunnels Theater Shortcut Panel
+Tunnels Desert Shortcut Panel
+Tunnels Town Shortcut Panel
\ No newline at end of file
diff --git a/worlds/witness/settings/Doors_Simple.txt b/worlds/witness/settings/Doors_Simple.txt
index 1335456d95..8cda2ee64b 100644
--- a/worlds/witness/settings/Doors_Simple.txt
+++ b/worlds/witness/settings/Doors_Simple.txt
@@ -1,73 +1,73 @@
Items:
-Glass Factory Back Wall
-Quarry Boathouse Boat Staircase
+Glass Factory Back Wall (Door)
+Quarry Boathouse Dock (Door)
Outside Tutorial Outpost Doors
-Glass Factory Entry Door
+Glass Factory Entry (Door)
Symmetry Island Doors
Orchard Gates
Desert Doors
Quarry Main Entry
-Quarry Door to Mill
+Quarry Mill Entry (Door)
Quarry Mill Shortcuts
Quarry Boathouse Barriers
-Shadows Timed Door
+Shadows Timed Door (Door)
Shadows Laser Room Door
Shadows Barriers
Keep Hedge Maze Doors
Keep Pressure Plates Doors
Keep Shortcuts
-Monastery Entry Door
+Monastery Entry
Monastery Shortcuts
Town Doors
Town Tower Doors
-Theater Entry Door
-Theater Exit Door
+Theater Entry (Door)
+Theater Exit
Jungle & River Shortcuts
-Jungle Popup Wall
+Jungle Popup Wall (Door)
Bunker Doors
Swamp Doors
-Swamp Near Laser Shortcut
+Swamp Laser Shortcut (Door)
Swamp Water Pumps
Treehouse Entry Doors
-Treehouse Drawbridge
-Treehouse Timed Door to Laser House
-Inside Mountain First Layer Exit Door
-Inside Mountain Second Layer Stairs & Doors
-Inside Mountain Giant Puzzle Exit Door
-Inside Mountain Door to Final Room
-Inside Mountain Bottom Layer Doors to Caves
+Treehouse Drawbridge (Door)
+Treehouse Laser House Entry (Door)
+Mountain Floor 1 Exit (Door)
+Mountain Floor 2 Stairs & Doors
+Mountain Bottom Floor Giant Puzzle Exit (Door)
+Mountain Bottom Floor Final Room Entry (Door)
+Mountain Bottom Floor Doors to Caves
Caves Doors to Challenge
Caves Exits to Main Island
-Challenge Door to Theater Walkway
-Theater Walkway Doors
+Challenge Tunnels Entry (Door)
+Tunnels Doors
Added Locations:
-Outside Tutorial Door to Outpost Panel
-Outside Tutorial Exit Door from Outpost Panel
-Glass Factory Entry Door Panel
-Glass Factory Vertical Symmetry 5
-Symmetry Island Door to Symmetry Island Lower Panel
-Symmetry Island Door to Symmetry Island Upper Panel
+Outside Tutorial Outpost Entry Panel
+Outside Tutorial Outpost Exit Panel
+Glass Factory Entry Panel
+Glass Factory Back Wall 5
+Symmetry Island Lower Panel
+Symmetry Island Upper Panel
Orchard Apple Tree 3
Orchard Apple Tree 5
-Desert Door to Desert Flood Light Room Panel
-Desert Artificial Light Reflection 3
-Desert Door to Water Levels Room Panel
-Desert Flood Reflection 6
-Quarry Door to Quarry 1 Panel
-Quarry Door to Quarry 2 Panel
-Quarry Door to Mill Right
-Quarry Door to Mill Left
-Quarry Mill Ground Floor Shortcut Door Panel
-Quarry Mill Door to Outside Quarry Stairs Panel
+Desert Light Room Entry Panel
+Desert Light Room 3
+Desert Flood Room Entry Panel
+Desert Flood Room 6
+Quarry Entry 1 Panel
+Quarry Entry 2 Panel
+Quarry Mill Entry Right Panel
+Quarry Mill Entry Left Panel
+Quarry Mill Side Exit Panel
+Quarry Mill Roof Exit Panel
Quarry Mill Stair Control
-Quarry Boathouse Shortcut Door Panel
+Quarry Boathouse Second Barrier Panel
Shadows Door Timer Inside
Shadows Door Timer Outside
-Shadows Environmental Avoid 8
-Shadows Follow 5
-Shadows Lower Avoid 3
-Shadows Lower Avoid 5
+Shadows Far 8
+Shadows Near 5
+Shadows Intro 3
+Shadows Intro 5
Keep Hedge Maze 1
Keep Pressure Plates 1
Keep Hedge Maze 2
@@ -76,71 +76,70 @@ Keep Hedge Maze 4
Keep Pressure Plates 2
Keep Pressure Plates 3
Keep Pressure Plates 4
-Keep Shortcut to Shadows Panel
-Keep Tower Shortcut to Keep Panel
-Monastery Shortcut Door Panel
-Monastery Door Open Left
-Monastery Door Open Right
-Monastery Rhombic Avoid 3
-Town Cargo Box Panel
-Town Full Dot Grid Shapers 5
-Town Tinted Door Panel
-Town Door to Church Stars Panel
+Keep Shadows Shortcut Panel
+Keep Tower Shortcut Panel
+Monastery Shortcut Panel
+Monastery Entry Left
+Monastery Entry Right
+Monastery Outside 3
+Town Cargo Box Entry Panel
+Town Wooden Roof Lower Row 5
+Town Tinted Glass Door Panel
+Town Church Entry Panel
Town Maze Stair Control
-Town Windmill Door Panel
-Town Sound Room Left
+Town Windmill Entry Panel
Town Sound Room Right
-Town Symmetry Squares 5 + Dots
+Town Red Rooftop 5
Town Church Lattice
-Town Hexagonal Reflection
-Town Shapers & Dots & Eraser
-Windmill Door to Front of Theater Panel
-Theater Door to Cargo Box Left Panel
-Theater Door to Cargo Box Right Panel
-Jungle Shortcut to River Panel
+Town Tall Hexagonal
+Town Wooden Rooftop
+Windmill Theater Entry Panel
+Theater Exit Left Panel
+Theater Exit Right Panel
+Jungle Laser Shortcut Panel
Jungle Popup Wall Control
-River Rhombic Avoid to Monastery Garden
-Bunker Bunker Entry Panel
-Bunker Door to Bunker Proper Panel
-Bunker Drawn Squares through Tinted Glass 3
-Bunker Drop-Down Door Squares 2
+River Monastery Shortcut Panel
+Bunker Entry Panel
+Bunker Tinted Glass Door Panel
+Bunker Glass Room 3
+Bunker UV Room 2
Swamp Entry Panel
-Swamp Platform Shapers 4
+Swamp Platform Row 4
Swamp Platform Shortcut Right Panel
-Swamp Blue Underwater Negative Shapers 5
-Swamp Broken Shapers 4
-Swamp Cyan Underwater Negative Shapers 5
-Swamp Red Underwater Negative Shapers 4
-Swamp More Rotated Shapers 4
-Swamp More Rotated Shapers 4
-Swamp Near Laser Shortcut Right Panel
+Swamp Blue Underwater 5
+Swamp Between Bridges Near Row 4
+Swamp Cyan Underwater 5
+Swamp Red Underwater 4
+Swamp Beyond Rotating Bridge 4
+Swamp Beyond Rotating Bridge 4
+Swamp Laser Shortcut Right Panel
Treehouse First Door Panel
Treehouse Second Door Panel
-Treehouse Beyond Yellow Bridge Door Panel
+Treehouse Third Door Panel
Treehouse Bridge Control
Treehouse Left Orange Bridge 15
Treehouse Right Orange Bridge 12
Treehouse Laser House Door Timer Outside Control
-Treehouse Laser House Door Timer Inside Control
-Inside Mountain Moving Background 7
-Inside Mountain Obscured Vision 5
-Inside Mountain Physically Obstructed 3
-Inside Mountain Angled Inside Trash 2
-Inside Mountain Color Cycle 5
-Inside Mountain Light Bridge Controller 2
-Inside Mountain Light Bridge Controller 3
-Inside Mountain Same Solution 6
-Inside Mountain Giant Puzzle
-Inside Mountain Door to Final Room Left
-Inside Mountain Door to Final Room Right
-Inside Mountain Bottom Layer Discard
-Inside Mountain Rock Control
-Inside Mountain Secret Area Entry Panel
-Inside Mountain Caves Lone Pillar
-Inside Mountain Caves Shortcut to Mountain Panel
-Inside Mountain Caves Shortcut to Swamp Panel
-Inside Mountain Caves Challenge Entry Panel
-Challenge Door to Theater Walkway Panel
-Theater Walkway Theater Shortcut Panel
-Theater Walkway Desert Shortcut Panel
-Theater Walkway Town Shortcut Panel
\ No newline at end of file
+Treehouse Laser House Door Timer Inside
+Mountain Floor 1 Left Row 7
+Mountain Floor 1 Right Row 5
+Mountain Floor 1 Back Row 3
+Mountain Floor 1 Trash Pillar 2
+Mountain Floor 2 Near Row 5
+Mountain Floor 2 Light Bridge Controller Near
+Mountain Floor 2 Light Bridge Controller Far
+Mountain Floor 2 Far Row 6
+Mountain Bottom Floor Giant Puzzle
+Mountain Bottom Floor Final Room Entry Left
+Mountain Bottom Floor Final Room Entry Right
+Mountain Bottom Floor Discard
+Mountain Bottom Floor Rock Control
+Mountain Bottom Floor Caves Entry Panel
+Caves Lone Pillar
+Caves Mountain Shortcut Panel
+Caves Swamp Shortcut Panel
+Caves Challenge Entry Panel
+Challenge Tunnels Entry Panel
+Tunnels Theater Shortcut Panel
+Tunnels Desert Shortcut Panel
+Tunnels Town Shortcut Panel
\ No newline at end of file
diff --git a/worlds/witness/settings/Early_UTM.txt b/worlds/witness/settings/Early_UTM.txt
index 893f29d8bb..b04aa3d339 100644
--- a/worlds/witness/settings/Early_UTM.txt
+++ b/worlds/witness/settings/Early_UTM.txt
@@ -5,5 +5,5 @@ Starting Inventory:
Caves Exits to Main Island
Remove Items:
-Caves Mountain Shortcut
-Caves Swamp Shortcut
\ No newline at end of file
+Caves Mountain Shortcut (Door)
+Caves Swamp Shortcut (Door)
\ No newline at end of file