Add The Witness (#467)
* Added The Witness Co-authored-by: metzner <unconfigured@null.spigotmc.org> Co-authored-by: Jarno Westhof <jarnowesthof@gmail.com> Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com>
This commit is contained in:
parent
50eaf712a9
commit
3e8c821c02
|
@ -23,6 +23,7 @@ Currently, the following games are supported:
|
|||
* ChecksFinder
|
||||
* ArchipIDLE
|
||||
* Hollow Knight
|
||||
* The Witness
|
||||
|
||||
For setup and instructions check out our [tutorials page](https://archipelago.gg/tutorial/).
|
||||
Downloads can be found at [Releases](https://github.com/ArchipelagoMW/Archipelago/releases), including compiled
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# The Witness
|
||||
|
||||
## Where is the settings page?
|
||||
|
||||
The [player settings page for this game](../player-settings) contains all the options you need to configure and export a
|
||||
config file.
|
||||
|
||||
## What does randomization do to this game?
|
||||
|
||||
Puzzles are randomly generated using the popular [Sigma Rando](https://github.com/sigma144/witness-randomizer).
|
||||
They are made to be similar to the original game, but with different solutions.
|
||||
|
||||
Ontop of that each puzzle symbol (Squares, Stars, Dots, etc.) is now an item.
|
||||
Panels with puzzle symbols on them are now locked initially.
|
||||
|
||||
## What is a "check" in The Witness?
|
||||
|
||||
Solving the last panel in a row of panels or an important standalone panel will count as a check, and send out an item.
|
||||
|
||||
## What "items" can you unlock in The Witness?
|
||||
|
||||
Every puzzle symbol and many other puzzle mechanics are items.
|
||||
This includes symbols such as "Dots", "Black/White Squares", "Colored Squares", "Stars", "Symmetry", "Shapers" (coll. "Tetris Pieces"), "Erasers" and many more.
|
||||
|
||||
## The Jungle, Orchard, Forest and Color House aren't randomized. What gives?
|
||||
|
||||
There are limitations to what can currently be randomized in The Witness.
|
||||
There is an option to turn these non-randomized panels off, called "disable_non_randomized" in your yaml file. This will also slightly change the activation requirement of certain panels, detailed [here](https://github.com/sigma144/witness-randomizer/wiki/Activation-Triggers).
|
|
@ -0,0 +1,26 @@
|
|||
# The Witness Randomizer Setup
|
||||
|
||||
## Required Software
|
||||
|
||||
- [The Witness (Steam)](https://store.steampowered.com/app/210970/The_Witness/)
|
||||
- [The Witness Archipalego Randomizer](https://github.com/JarnoWesthof/The-Witness-Randomizer-for-Archipelago)
|
||||
- [ArchipelagoTextClient](https://github.com/ArchipelagoMW/Archipelago/releases)
|
||||
|
||||
## Joining a MultiWorld Game
|
||||
|
||||
This Randomizer can be very "moody" if you don't do everything in the correct order.
|
||||
It is recommended to do every single one of these steps when you connect to a world.
|
||||
|
||||
1. Launch The Witness
|
||||
2. Start a fresh save (unless you have absolutely no other choice)
|
||||
3. Do not move
|
||||
4. Launch [The Witness Archipalego Randomizer](https://github.com/JarnoWesthof/The-Witness-Randomizer-for-Archipelago)
|
||||
5. Enter the Archipelago Adress, Slot Name and Password
|
||||
6. Press "Randomize"
|
||||
7. Wait for the randomization to fully finish before moving in-game
|
||||
|
||||
That's it! Have fun!
|
||||
|
||||
## ArchipelagoTextClient
|
||||
|
||||
Its recommended to have Archipelago's Text Client open on the side to keep track of what item you receive and send as The Witness has no in-game messages.
|
|
@ -574,5 +574,24 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"gameTitle": "The Witness",
|
||||
"tutorials": [
|
||||
{
|
||||
"name": "Multiworld Setup Guide",
|
||||
"description": "A guide to playing The Witness with Archipelago.",
|
||||
"files": [
|
||||
{
|
||||
"language": "English",
|
||||
"filename": "The Witness/setup_en.md",
|
||||
"link": "The Witness/setup/en",
|
||||
"authors": [
|
||||
"NewSoupVi", "Jarno"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 374 KiB |
|
@ -71,9 +71,11 @@ flowchart LR
|
|||
SM64[Super Mario 64 Ex]
|
||||
V6[VVVVVV]
|
||||
MT[Meritous]
|
||||
TW[The Witness]
|
||||
|
||||
APCLIENTPP <--> SOE
|
||||
APCLIENTPP <--> MT
|
||||
APCLIENTPP <-- The Witness Randomizer --> TW
|
||||
APCPP <--> SM64
|
||||
APCPP <--> V6
|
||||
end
|
||||
|
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 82 KiB |
|
@ -0,0 +1,104 @@
|
|||
Event Items:
|
||||
Shadows Laser Activation - 0x00021,0x17D28,0x17C71
|
||||
Bunker Laser Activation - 0x00061,0x17D01,0x17C42
|
||||
Monastery Laser Activation - 0x00A5B,0x17CE7,0x17FA9,0x17CA4
|
||||
Town Tower 4th Door Opens - 0x17CFB,0x3C12B,0x00B8D,0x17CF7
|
||||
|
||||
Requirement Changes:
|
||||
0x17CA4 - True - True
|
||||
0x28B39 - 0x2896A - Reflection
|
||||
0x17CAB - True - True
|
||||
|
||||
Region Changes:
|
||||
Quarry (Quarry) - Outside Quarry - 0x17C09 - Quarry Mill - 0x275ED - Quarry Mill - 0x17CAC
|
||||
|
||||
Disabled Locations:
|
||||
0x03505 (Tutorial Gate Close)
|
||||
0x0C335 (Tutorial Pillar)
|
||||
0x0C373 (Tutorial Patio Floor)
|
||||
0x009B8 (Symmetry Island Scenery Outlines 1)
|
||||
0x003E8 (Symmetry Island Scenery Outlines 2)
|
||||
0x00A15 (Symmetry Island Scenery Outlines 3)
|
||||
0x00B53 (Symmetry Island Scenery Outlines 4)
|
||||
0x00B8D (Symmetry Island Scenery Outlines 5)
|
||||
0x00143 (Orchard Apple Tree 1)
|
||||
0x0003B (Orchard Apple Tree 2)
|
||||
0x00055 (Orchard Apple Tree 3)
|
||||
0x032F7 (Orchard Apple Tree 4)
|
||||
0x032FF (Orchard Apple Tree 5)
|
||||
0x168B5 (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)
|
||||
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)
|
||||
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)
|
||||
0x17CA4 (Monastery Laser) - 0x193A6 - True
|
||||
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
|
||||
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)
|
||||
0x03702 (River Vault Box)
|
||||
0x17C2E (Door to Bunker) - True - Squares & Black/White Squares
|
||||
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)
|
||||
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)
|
||||
0x09DE0 (Bunker Laser)
|
||||
0x0A079 (Bunker Elevator Control)
|
||||
0x0042D (Mountaintop River Shape)
|
|
@ -0,0 +1,71 @@
|
|||
from typing import Dict
|
||||
from BaseClasses import MultiWorld
|
||||
from Options import Toggle, DefaultOnToggle, Option
|
||||
|
||||
|
||||
# class HardMode(Toggle):
|
||||
# "Play the randomizer in hardmode"
|
||||
# display_name = "Hard Mode"
|
||||
|
||||
# class UnlockSymbols(DefaultOnToggle):
|
||||
# "All Puzzle symbols of a specific panel need to be unlocked before the panel can be used"
|
||||
# display_name = "Unlock Symbols"
|
||||
|
||||
class DisableNonRandomizedPuzzles(DefaultOnToggle):
|
||||
"""Disable puzzles that cannot be randomized.
|
||||
Non randomized puzzles are Shadows, Monastery, and Greenhouse.
|
||||
The lasers for those areas will be activated as you solve optional puzzles throughout the island."""
|
||||
display_name = "Disable non randomized puzzles"
|
||||
|
||||
|
||||
class ShuffleDiscardedPanels(Toggle):
|
||||
"""Discarded Panels will have items on them.
|
||||
Solving certain Discarded Panels may still be necessary!"""
|
||||
display_name = "Shuffle Discarded Panels"
|
||||
|
||||
|
||||
class ShuffleVaultBoxes(Toggle):
|
||||
"""Vault Boxes will have items on them."""
|
||||
display_name = "Shuffle Vault Boxes"
|
||||
|
||||
|
||||
class ShuffleUncommonLocations(Toggle):
|
||||
"""Adds the following checks to the pool:
|
||||
Mountaintop River Shape, Tutorial Patio Floor, Theater Videos"""
|
||||
display_name = "Shuffle Uncommon Locations"
|
||||
|
||||
|
||||
class ShuffleHardLocations(Toggle):
|
||||
"""Adds some harder locations into the game, e.g. Mountain Secret Area panels"""
|
||||
display_name = "Shuffle Hard Locations"
|
||||
|
||||
|
||||
class ChallengeVictoryCondition(Toggle):
|
||||
"""The victory condition now becomes beating the Challenge area,
|
||||
instead of the final elevator."""
|
||||
display_name = "Victory on beating the Challenge"
|
||||
|
||||
|
||||
the_witness_options: Dict[str, Option] = {
|
||||
# "hard_mode": HardMode,
|
||||
# "unlock_symbols": UnlockSymbols,
|
||||
"disable_non_randomized_puzzles": DisableNonRandomizedPuzzles,
|
||||
"shuffle_discarded_panels": ShuffleDiscardedPanels,
|
||||
"shuffle_vault_boxes": ShuffleVaultBoxes,
|
||||
"shuffle_uncommon": ShuffleUncommonLocations,
|
||||
"shuffle_hard": ShuffleHardLocations,
|
||||
"challenge_victory": ChallengeVictoryCondition
|
||||
}
|
||||
|
||||
|
||||
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) -> int:
|
||||
option = getattr(world, name, None)
|
||||
|
||||
if option is None:
|
||||
return 0
|
||||
|
||||
return int(option[player].value)
|
|
@ -0,0 +1,21 @@
|
|||
Progression:
|
||||
0 - Dots
|
||||
1 - Colored Dots
|
||||
5 - Sound Dots
|
||||
10 - Symmetry
|
||||
20 - Triangles
|
||||
30 - Eraser
|
||||
40 - Shapers
|
||||
41 - Rotated Shapers
|
||||
50 - Negative Shapers
|
||||
60 - Stars
|
||||
61 - Stars + Same Colored Symbol
|
||||
71 - Black/White Squares
|
||||
72 - Colored Squares
|
||||
|
||||
Boosts:
|
||||
500 - Speed Boost
|
||||
|
||||
Traps:
|
||||
600 - Slowness Trap
|
||||
610 - Power Surge Trap
|
|
@ -0,0 +1,712 @@
|
|||
First Hallway (First Hallway) - Entry - True:
|
||||
0x00064 (Straight) - True - True
|
||||
0x00182 (Bend) - 0x00064 - True
|
||||
|
||||
Tutorial (Tutorial) - First Hallway - 0x00182:
|
||||
0x00293 (Front Center) - True - True
|
||||
0x00295 (Center Left) - 0x00293 - True
|
||||
0x002C2 (Front Left) - 0x00295 - True
|
||||
0x0A3B5 (Back Left) - True - True
|
||||
0x0A3B2 (Back Right) - True - True
|
||||
0x03629 (Gate Open) - 0x002C2 & 0x0A3B5 & 0x0A3B2 - True
|
||||
0x03505 (Gate Close) - 0x2FAF6 - True
|
||||
0x0C335 (Pillar) - True - Triangles - True
|
||||
0x0C373 (Patio Floor) - 0x0C335 - True
|
||||
|
||||
Outside Tutorial (Outside Tutorial) - Tutorial - 0x03629:
|
||||
0x033D4 (Vault) - True - Dots & Squares & Black/White Squares
|
||||
0x03481 (Vault Box) - 0x033D4 - True
|
||||
0x0A171 (Optional Door 1) - 0x0A3B5 - Dots
|
||||
0x17CFB (Discard) - 0x0A171 - Triangles
|
||||
0x04CA4 (Optional Door 2) - 0x0A171 - Dots & Squares & Black/White Squares
|
||||
0x0005D (Dots Introduction 1) - True - Dots
|
||||
0x0005E (Dots Introduction 2) - 0x0005D - Dots
|
||||
0x0005F (Dots Introduction 3) - 0x0005E - Dots
|
||||
0x00060 (Dots Introduction 4) - 0x0005F - Dots
|
||||
0x00061 (Dots Introduction 5) - 0x00060 - Dots
|
||||
0x018AF (Squares Introduction 1) - True - Squares & Black/White Squares
|
||||
0x0001B (Squares Introduction 2) - 0x018AF - Squares & Black/White Squares
|
||||
0x012C9 (Squares Introduction 3) - 0x0001B - Squares & Black/White Squares
|
||||
0x0001C (Squares Introduction 4) - 0x012C9 - Squares & Black/White Squares
|
||||
0x0001D (Squares Introduction 5) - 0x0001C - Squares & Black/White Squares
|
||||
0x0001E (Squares Introduction 6) - 0x0001D - Squares & Black/White Squares
|
||||
0x0001F (Squares Introduction 7) - 0x0001E - Squares & Black/White Squares
|
||||
0x00020 (Squares Introduction 8) - 0x0001F - Squares & Black/White Squares
|
||||
0x00021 (Squares Introduction 9) - 0x00020 - Squares & Black/White Squares
|
||||
|
||||
Main Island () - Outside Tutorial - True:
|
||||
|
||||
Outside Glass Factory (Glass Factory) - Main Island - True:
|
||||
0x01A54 (Entry Door) - True - Symmetry
|
||||
0x3C12B (Discard) - True - Triangles
|
||||
|
||||
Inside Glass Factory (Glass Factory) - Outside Glass Factory - 0x01A54:
|
||||
0x00086 (Vertical Symmetry 1) - True - Symmetry
|
||||
0x00087 (Vertical Symmetry 2) - 0x00086 - Symmetry
|
||||
0x00059 (Vertical Symmetry 3) - 0x00087 - Symmetry
|
||||
0x00062 (Vertical Symmetry 4) - 0x00059 - Symmetry
|
||||
0x0005C (Vertical Symmetry 5) - 0x00062 - Symmetry
|
||||
0x0008D (Rotational Symmetry 1) - 0x0005C - Symmetry
|
||||
0x00081 (Rotational Symmetry 2) - 0x0008D - Symmetry
|
||||
0x00083 (Rotational Symmetry 3) - 0x00081 - Symmetry
|
||||
0x00084 (Melting 1) - 0x00083 - Symmetry
|
||||
0x00082 (Melting 2) - 0x00084 - Symmetry
|
||||
0x0343A (Melting 3) - 0x00082 - Symmetry
|
||||
0x17CC8 (Boat Spawn) - True - Boat
|
||||
|
||||
Outside Symmetry Island (Symmetry Island) - Main Island - True:
|
||||
0x000B0 (Door to Symmetry Island Lower) - True - Dots
|
||||
|
||||
Symmetry Island Lower (Symmetry Island) - Outside Symmetry Island - 0x000B0:
|
||||
0x00022 (Black Dots 1) - True - Symmetry & Dots
|
||||
0x00023 (Black Dots 2) - 0x00022 - Symmetry & Dots
|
||||
0x00024 (Black Dots 3) - 0x00023 - Symmetry & Dots
|
||||
0x00025 (Black Dots 4) - 0x00024 - Symmetry & Dots
|
||||
0x00026 (Black Dots 5) - 0x00025 - Symmetry & Dots
|
||||
0x0007C (Colored Dots 1) - 0x00026 - Symmetry & Colored Dots
|
||||
0x0007E (Colored Dots 2) - 0x0007C - Symmetry & Colored Dots
|
||||
0x00075 (Colored Dots 3) - 0x0007E - Symmetry & Colored Dots
|
||||
0x00073 (Colored Dots 4) - 0x00075 - Symmetry & Colored Dots
|
||||
0x00077 (Colored Dots 5) - 0x00073 - Symmetry & Colored Dots
|
||||
0x00079 (Colored Dots 6) - 0x00077 - Symmetry & Colored Dots
|
||||
0x00065 (Fading Lines 1) - 0x00079 - Symmetry & Colored Dots
|
||||
0x0006D (Fading Lines 2) - 0x00065 - Symmetry & Colored Dots
|
||||
0x00072 (Fading Lines 3) - 0x0006D - Symmetry & Colored Dots
|
||||
0x0006F (Fading Lines 4) - 0x00072 - Symmetry & Colored Dots
|
||||
0x00070 (Fading Lines 5) - 0x0006F - Symmetry & Colored Dots
|
||||
0x00071 (Fading Lines 6) - 0x00070 - Symmetry & Colored Dots
|
||||
0x00076 (Fading Lines 7) - 0x00071 - Symmetry & Colored Dots
|
||||
0x009B8 (Scenery Outlines 1) - True - Symmetry & Environment
|
||||
0x003E8 (Scenery Outlines 2) - 0x009B8 - Symmetry & Environment
|
||||
0x00A15 (Scenery Outlines 3) - 0x003E8 - Symmetry & Environment
|
||||
0x00B53 (Scenery Outlines 4) - 0x00A15 - Symmetry & Environment
|
||||
0x00B8D (Scenery Outlines 5) - 0x00B53 - Symmetry & Environment
|
||||
0x1C349 (Door to Symmetry Island Upper) - 0x00076 - Symmetry & Dots
|
||||
|
||||
Symmetry Island Upper (Symmetry Island) - Symmetry Island Lower - 0x1C349:
|
||||
0x00A52 (Yellow 1) - True - Symmetry & Colored Dots
|
||||
0x00A57 (Yellow 2) - 0x00A52 - Symmetry & Colored Dots
|
||||
0x00A5B (Yellow 3) - 0x00A57 - Symmetry & Colored Dots
|
||||
0x00A61 (Blue 1) - 0x00A52 - Symmetry & Colored Dots
|
||||
0x00A64 (Blue 2) - 0x00A61 & 0x00A52 - Symmetry & Colored Dots
|
||||
0x00A68 (Blue 3) - 0x00A64 & 0x00A57 - Symmetry & Colored Dots
|
||||
0x0360D (Laser) - 0x00A68 - True
|
||||
|
||||
Orchard (Orchard) - Main Island - True:
|
||||
0x00143 (Apple Tree 1) - True - Environment
|
||||
0x0003B (Apple Tree 2) - 0x00143 - Environment
|
||||
0x00055 (Apple Tree 3) - 0x0003B - Environment
|
||||
0x032F7 (Apple Tree 4) - 0x00055 - Environment
|
||||
0x032FF (Apple Tree 5) - 0x032F7 - Environment
|
||||
|
||||
Desert Outside (Desert) - Main Island - True:
|
||||
0x0CC7B (Vault) - True - Dots & Shapers & Rotated Shapers & Negative Shapers
|
||||
0x0339E (Vault Box) - 0x0CC7B - True
|
||||
0x17CE7 (Discard) - True - Triangles
|
||||
0x00698 (Sun Reflection 1) - True - Reflection
|
||||
0x0048F (Sun Reflection 2) - 0x00698 - Reflection
|
||||
0x09F92 (Sun Reflection 3) - 0x0048F & 0x09FA0 - Reflection
|
||||
0x09FA0 (Reflection 3 Control) - 0x0048F - True
|
||||
0x0A036 (Sun Reflection 4) - 0x09F92 - Reflection
|
||||
0x09DA6 (Sun Reflection 5) - 0x09F92 - Reflection
|
||||
0x0A049 (Sun Reflection 6) - 0x09F92 - Reflection
|
||||
0x0A053 (Sun Reflection 7) - 0x0A036 & 0x09DA6 & 0x0A049 - Reflection
|
||||
0x09F94 (Sun Reflection 8) - 0x0A053 & 0x09F86 - Reflection
|
||||
0x09F86 (Reflection 8 Control) - 0x0A053 - True
|
||||
0x0C339 (Door to Desert Flood Light Room) - 0x09F94 - True
|
||||
|
||||
Desert Floodlight Room (Desert) - Desert Outside - 0x0C339:
|
||||
0x09FAA (Light Control) - True - True
|
||||
0x00422 (Artificial Light Reflection 1) - 0x09FAA - Reflection
|
||||
0x006E3 (Artificial Light Reflection 2) - 0x09FAA - Reflection
|
||||
0x0A02D (Artificial Light Reflection 3) - 0x09FAA & 0x00422 & 0x006E3 - Reflection
|
||||
|
||||
Desert Pond Room (Desert) - Desert Floodlight Room - 0x0A02D:
|
||||
0x00C72 (Pond Reflection 1) - True - Reflection
|
||||
0x0129D (Pond Reflection 2) - 0x00C72 - Reflection
|
||||
0x008BB (Pond Reflection 3) - 0x0129D - Reflection
|
||||
0x0078D (Pond Reflection 4) - 0x008BB - Reflection
|
||||
0x18313 (Pond Reflection 5) - 0x0078D - Reflection
|
||||
0x0A249 (Door to Desert Water Levels Room) - 0x18313 - Reflection
|
||||
|
||||
Desert Water Levels Room (Desert) - Desert Pond Room - 0x0A249:
|
||||
0x1C2DF (Reduce Water Level Far Left) - True - True
|
||||
0x1831E (Reduce Water Level Far Right) - True - True
|
||||
0x1C260 (Reduce Water Level Near Left) - True - True
|
||||
0x1831C (Reduce Water Level Near Right) - True - True
|
||||
0x1C2F3 (Raise Water Level Far Left) - True - True
|
||||
0x1831D (Raise Water Level Far Right) - True - True
|
||||
0x1C2B1 (Raise Water Level Near Left) - True - True
|
||||
0x1831B (Raise Water Level Near Right) - True - True
|
||||
0x04D18 (Flood Reflection 1) - True - Reflection
|
||||
0x01205 (Flood Reflection 2) - 0x04D18 - Reflection
|
||||
0x181AB (Flood Reflection 3) - 0x01205 - Reflection
|
||||
0x0117A (Flood Reflection 4) - 0x181AB - Reflection
|
||||
0x17ECA (Flood Reflection 5) - 0x0117A - Reflection
|
||||
0x18076 (Flood Reflection 6) - 0x17ECA - Reflection
|
||||
|
||||
Desert Elevator Room (Desert) - Desert Water Levels Room - 0x18076:
|
||||
0x17C31 (Final Transparent Reflection) - True - Reflection
|
||||
0x012D7 (Final Reflection) - 0x17C31 & 0x0A015 - Reflection
|
||||
0x012D7 (Final Reflection) - 0x17C31 & 0x0A015 - Reflection
|
||||
0x0A015 (Final Reflection Control) - 0x17C31 - True
|
||||
0x0A15C (Final Bent Reflection 1) - True - Reflection
|
||||
0x09FFF (Final Bent Reflection 2) - 0x0A15C - Reflection
|
||||
0x0A15F (Final Bent Reflection 3) - 0x09FFF - Reflection
|
||||
0x03608 (Laser) - 0x012D7 & 0x0A15F - True
|
||||
|
||||
Outside Quarry (Quarry) - Main Island - True:
|
||||
0x09E57 (Door to Quarry 1) - True - Squares & Black/White Squares
|
||||
0x17C09 (Door to Quarry 2) - 0x09E57 - Shapers
|
||||
0x17CC4 (Elevator Control) - 0x0367C - Dots & Eraser
|
||||
|
||||
Quarry (Quarry) - Outside Quarry - 0x17C09 - Quarry Mill - 0x275ED - Quarry Mill - 0x17CAC - Shadows Ledge - 0x198BF:
|
||||
0x01E5A (Door to Mill Left) - True - Squares & Black/White Squares
|
||||
0x01E59 (Door to Mill Right) - True - Dots
|
||||
0x17CF0 (Discard) - True - Triangles
|
||||
0x03612 (Laser) - 0x0A3D0 & 0x0367C - Eraser & Shapers
|
||||
|
||||
Quarry Mill (Quarry Mill) - Quarry - 0x01E59 & 0x01E5A:
|
||||
0x275ED (Ground Floor Shortcut Door) - True - True
|
||||
0x03678 (Lower Ramp Control) - True - Dots & Eraser
|
||||
0x00E0C (Eraser and Dots 1) - 0x03678 - Dots & Eraser
|
||||
0x01489 (Eraser and Dots 2) - 0x00E0C - Dots & Eraser
|
||||
0x0148A (Eraser and Dots 3) - 0x01489 - Dots & Eraser
|
||||
0x014D9 (Eraser and Dots 4) - 0x0148A - Dots & Eraser
|
||||
0x014E7 (Eraser and Dots 5) - 0x014D9 - Dots & Eraser
|
||||
0x014E8 (Eraser and Dots 6) - 0x014E7 - Dots & Eraser
|
||||
0x03679 (Lower Lift Control) - 0x014E8 - Dots & Eraser
|
||||
0x03675 (Upper Ramp Control) - 0x03679 - Dots & Eraser
|
||||
0x03676 (Upper Lift Control) - 0x03679 - Dots & Eraser
|
||||
0x00557 (Eraser and Squares 1) - 0x03679 - Squares & Colored Squares & Eraser
|
||||
0x005F1 (Eraser and Squares 2) - 0x00557 - Squares & Colored Squares & Eraser
|
||||
0x00620 (Eraser and Squares 3) - 0x005F1 - Squares & Colored Squares & Eraser
|
||||
0x009F5 (Eraser and Squares 4) - 0x00620 - Squares & Colored Squares & Eraser
|
||||
0x0146C (Eraser and Squares 5) - 0x009F5 - Squares & Colored Squares & Eraser
|
||||
0x3C12D (Eraser and Squares 6) - 0x0146C - Squares & Colored Squares & Eraser
|
||||
0x03686 (Eraser and Squares 7) - 0x3C12D - Squares & Colored Squares & Eraser
|
||||
0x014E9 (Eraser and Squares 8) - 0x03686 - Squares & Colored Squares & Eraser
|
||||
0x03677 (Stair Control) - 0x014E8 - Squares & Colored Squares & Eraser
|
||||
0x3C125 (Big Squares & Dots & and Eraser) - 0x0367C - Squares & Black/White Squares & Dots & Eraser
|
||||
0x0367C (Small Squares & Dots & and Eraser) - 0x014E9 - Squares & Colored Squares & Dots & Eraser
|
||||
0x17CAC (Door to Outside Quarry Stairs) - True - True
|
||||
|
||||
Quarry Boathouse (Quarry Boathouse) - Quarry - True:
|
||||
0x034D4 (Intro Stars) - True - Stars
|
||||
0x021D5 (Intro Shapers) - True - Shapers & Rotated Shapers
|
||||
0x03852 (Ramp Height Control) - 0x034D4 & 0x021D5 - Rotated Shapers
|
||||
0x021B3 (Eraser and Shapers 1) - 0x03852 - Shapers & Eraser
|
||||
0x021B4 (Eraser and Shapers 2) - 0x021B3 - Shapers & Eraser
|
||||
0x021B0 (Eraser and Shapers 3) - 0x021B4 - Shapers & Eraser
|
||||
0x021AF (Eraser and Shapers 4) - 0x021B0 - Shapers & Eraser
|
||||
0x021AE (Eraser and Shapers 5) - 0x021AF - Shapers & Eraser & Broken Shapers
|
||||
0x03858 (Ramp Horizontal Control) - 0x021AE - Shapers & Eraser
|
||||
0x38663 (Shortcut Door) - 0x03858 - True
|
||||
0x021B5 (Stars and Colored Eraser 1) - 0x03858 - Stars & Stars + Same Colored Symbol & Eraser
|
||||
0x021B6 (Stars and Colored Eraser 2) - 0x021B5 - Stars & Stars + Same Colored Symbol & Eraser
|
||||
0x021B7 (Stars and Colored Eraser 3) - 0x021B6 - Stars & Stars + Same Colored Symbol & Eraser
|
||||
0x021BB (Stars and Colored Eraser 4) - 0x021B7 - Stars & Stars + Same Colored Symbol & Eraser
|
||||
0x09DB5 (Stars and Colored Eraser 5) - 0x021BB - Stars & Stars + Same Colored Symbol & Eraser
|
||||
0x09DB1 (Stars and Colored Eraser 6) - 0x09DB5 - Stars & Stars + Same Colored Symbol & Eraser
|
||||
0x3C124 (Stars and Colored Eraser 7) - 0x09DB1 - Stars & Stars + Same Colored Symbol & Eraser
|
||||
0x09DB3 (Stars & Eraser & and Shapers 1) - 0x3C124 - Stars & Eraser & Shapers
|
||||
0x09DB4 (Stars & Eraser & and Shapers 2) - 0x09DB3 - Stars & Eraser & Shapers
|
||||
0x275FA (Hook Control) - 0x03858 - Shapers & Eraser
|
||||
0x17CA6 (Boat Spawn) - True - Boat
|
||||
0x0A3CB (Stars & Eraser & and Shapers 3) - 0x09DB4 - Stars & Eraser & Shapers
|
||||
0x0A3CC (Stars & Eraser & and Shapers 4) - 0x0A3CB - Stars & Eraser & Shapers
|
||||
0x0A3D0 (Stars & Eraser & and Shapers 5) - 0x0A3CC - Stars & Eraser & Shapers
|
||||
|
||||
Shadows (Shadows) - Main Island - True - Keep Glass Plates - 0x09E49:
|
||||
0x334DB (Door Timer Outside) - True - True
|
||||
0x0AC74 (Lower Avoid 6) - 0x0A8DC - Shadows Avoid
|
||||
0x0AC7A (Lower Avoid 7) - 0x0AC74 - Shadows Avoid
|
||||
0x0A8E0 (Lower Avoid 8) - 0x0AC7A - Shadows Avoid
|
||||
0x386FA (Environmental Avoid 1) - 0x0A8E0 - Shadows Avoid & Environment
|
||||
0x1C33F (Environmental Avoid 2) - 0x386FA - Shadows Avoid & Environment
|
||||
0x196E2 (Environmental Avoid 3) - 0x1C33F - Shadows Avoid & Environment
|
||||
0x1972A (Environmental Avoid 4) - 0x196E2 - Shadows Avoid & Environment
|
||||
0x19809 (Environmental Avoid 5) - 0x1972A - Shadows Avoid & Environment
|
||||
0x19806 (Environmental Avoid 6) - 0x19809 - Shadows Avoid & Environment
|
||||
0x196F8 (Environmental Avoid 7) - 0x19806 - Shadows Avoid & Environment
|
||||
0x1972F (Environmental Avoid 8) - 0x196F8 - Shadows Avoid & Environment
|
||||
0x19797 (Follow 1) - 0x0A8E0 - Shadows Follow
|
||||
0x1979A (Follow 2) - 0x19797 - Shadows Follow
|
||||
0x197E0 (Follow 3) - 0x1979A - Shadows Follow
|
||||
0x197E8 (Follow 4) - 0x197E0 - Shadows Follow
|
||||
0x197E5 (Follow 5) - 0x197E8 - Shadows Follow
|
||||
0x19650 (Laser) - 0x197E5 & 0x196F8 - Shadows Avoid & Shadows Follow
|
||||
|
||||
Shadows Ledge (Shadows) - Shadows - 0x334DB | 0x334DC | 0x0A8DC:
|
||||
0x334DC (Door Timer Inside) - True - True
|
||||
0x168B5 (Lower Avoid 1) - True - Shadows Avoid
|
||||
0x198BD (Lower Avoid 2) - 0x168B5 - Shadows Avoid
|
||||
0x198BF (Lower Avoid 3) - 0x198BD & 0x334DC - Shadows Avoid
|
||||
0x19771 (Lower Avoid 4) - 0x198BF - Shadows Avoid
|
||||
0x0A8DC (Lower Avoid 5) - 0x19771 - Shadows Avoid
|
||||
|
||||
Keep (Keep) - Main Island - True:
|
||||
|
||||
Keep Hedges (Keep) - Keep - True:
|
||||
0x00139 (Hedge Maze 1) - True - Environment
|
||||
0x019DC (Hedge Maze 2) - 0x00139 - Environment
|
||||
0x019E7 (Hedge Maze 3) - 0x019DC - Environment & Sound
|
||||
0x01A0F (Hedge Maze 4) - 0x019E7 - Environment
|
||||
|
||||
Keep Glass Plates (Keep) - Keep - True - Keep Tower - 0x0361B:
|
||||
0x0A3A8 (Reset Pressure Plates 1) - True - True
|
||||
0x033EA (Pressure Plates 1) - 0x0A3A8 - Pressure Plates & Dots
|
||||
0x0A3B9 (Reset Pressure Plates 2) - 0x033EA - True
|
||||
0x01BE9 (Pressure Plates 2) - 0x033EA & 0x0A3B9 - Pressure Plates & Stars & Stars + Same Colored Symbol & Squares & Black/White Squares
|
||||
0x0A3BB (Reset Pressure Plates 3) - 0x0A3A8 - True
|
||||
0x01CD3 (Pressure Plates 3) - 0x0A3A8 & 0x0A3BB - Pressure Plates & Shapers & Squares & Black/White Squares & Colored Squares
|
||||
0x0A3AD (Reset Pressure Plates 4) - 0x01CD3 - True
|
||||
0x01D3F (Pressure Plates 4) - 0x01CD3 & 0x0A3AD - Pressure Plates & Shapers & Dots & Symmetry
|
||||
0x17D27 (Discard) - 0x01CD3 - Triangles
|
||||
0x09E49 (Shortcut to Shadows) - 0x01CD3 - True
|
||||
|
||||
Shipwreck (Shipwreck) - Keep Glass Plates - 0x033EA:
|
||||
0x00AFB (Vault) - True - Symmetry & Sound & Sound Dots & Colored Dots
|
||||
0x03535 (Vault Box) - 0x00AFB - True
|
||||
0x17D28 (Discard) - True - Triangles
|
||||
|
||||
Keep Tower (Keep) - Keep Hedges - 0x01A0F - Keep Glass Plates - 0x01D3F:
|
||||
0x0361B (Shortcut to Keep Glass Plates) - True - True
|
||||
0x0360E (Laser Hedges) - 0x01A0F - Environment & Sound
|
||||
0x03317 (Laser Pressure Plates) - 0x01D3F - Shapers & Squares & Black/White Squares & Colored Squares & Stars & Stars + Same Colored Symbol & Dots
|
||||
|
||||
Outside Monastery (Monastery) - Main Island - True:
|
||||
0x03713 (Shortcut) - True - True
|
||||
0x00B10 (Door Open Left) - True - True
|
||||
0x00C92 (Door Open Right) - True - True
|
||||
0x00290 (Rhombic Avoid 1) - 0x09D9B - Environment
|
||||
0x00038 (Rhombic Avoid 2) - 0x09D9B & 0x00290 - Environment
|
||||
0x00037 (Rhombic Avoid 3) - 0x09D9B & 0x00038 - Environment
|
||||
0x17CA4 (Laser) - 0x193A6 - True
|
||||
|
||||
Inside Monastery (Monastery) - Outside Monastery - 0x00B10 & 0x00C92:
|
||||
0x09D9B (Overhead Door Control) - True - Dots
|
||||
0x193A7 (Branch Avoid 1) - 0x00037 - Environment
|
||||
0x193AA (Branch Avoid 2) - 0x193A7 - Environment
|
||||
0x193AB (Branch Follow 1) - 0x193AA - Environment
|
||||
0x193A6 (Branch Follow 2) - 0x193AB - Environment
|
||||
|
||||
Monastery Garden (Monastery) - Outside Monastery - 0x00037 - Outside Jungle River - 0x17CAA:
|
||||
|
||||
Town (Town) - Main Island - True - Theater - 0x0A168 | 0x33AB2:
|
||||
0x0A054 (Boat Summon) - True - Boat
|
||||
0x0A0C8 (Cargo Box) - True - Squares & Black/White Squares & Shapers
|
||||
0x17D01 (Cargo Box Discard) - 0x0A0C8 - Triangles
|
||||
0x09F98 (Desert Laser Redirect) - True - True
|
||||
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
|
||||
0x28998 (Tinted Door to RGB House) - True - Stars & Rotated Shapers
|
||||
0x28A0D (Door to Church) - 0x28998 - Stars & RGB & Environment
|
||||
0x28A69 (Square Avoid) - 0x28A0D - Environment
|
||||
0x28A79 (Maze Stair Control) - True - Environment
|
||||
0x2896A (Maze Rooftop Bridge Control) - 0x28A79 - Shapers
|
||||
0x17C71 (Rooftop Discard) - 0x2896A - Triangles
|
||||
0x28AC7 (Symmetry Squares 1) - 0x2896A - Symmetry & Squares & Black/White Squares
|
||||
0x28AC8 (Symmetry Squares 2) - 0x28AC7 - Symmetry & Squares & Black/White Squares
|
||||
0x28ACA (Symmetry Squares 3 + Dots) - 0x28AC8 - Symmetry & Squares & Black/White Squares & Dots
|
||||
0x28ACB (Symmetry Squares 4 + Dots) - 0x28ACA - Symmetry & Squares & Black/White Squares & Dots
|
||||
0x28ACC (Symmetry Squares 5 + Dots) - 0x28ACB - Symmetry & Squares & Black/White Squares & Dots
|
||||
0x2899C (Full Dot Grid Shapers 1) - True - Rotated Shapers & Dots
|
||||
0x28A33 (Full Dot Grid Shapers 2) - 0x2899C - Shapers & Dots
|
||||
0x28ABF (Full Dot Grid Shapers 3) - 0x28A33 - Shapers & Rotated Shapers & Dots
|
||||
0x28AC0 (Full Dot Grid Shapers 4) - 0x28ABF - Rotated Shapers & Dots
|
||||
0x28AC1 (Full Dot Grid Shapers 5) - 0x28AC0 - Rotated Shapers & Dots
|
||||
0x28AD9 (Shapers & Dots & and Eraser) - 0x28AC1 - Rotated Shapers & Dots & Eraser
|
||||
0x17F5F (Windmill Door) - True - Dots
|
||||
|
||||
RGB House (Town) - Town - 0x28998:
|
||||
0x034E4 (Sound Room Left) - True - Sound & Sound Waves
|
||||
0x034E3 (Sound Room Right) - True - Sound & Sound Dots
|
||||
0x334D8 (RGB Control) - 0x034E4 & 0x034E3 - Rotated Shapers & RGB & Squares & Colored Squares
|
||||
0x03C0C (RGB Squares) - 0x334D8 - RGB & Squares & Colored Squares & Black/White Squares
|
||||
0x03C08 (RGB Stars) - 0x334D8 - RGB & Stars
|
||||
|
||||
Town Tower Top (Town) - Town - 0x28A69 & 0x28B39 & 0x28ACC & 0x28AD9:
|
||||
0x032F5 (Laser) - True - True
|
||||
|
||||
Windmill Interior (Windmill) - Town - 0x17F5F:
|
||||
0x17D02 (Turn Control) - True - Dots
|
||||
0x17F89 (Door to Front of Theater) - True - Squares & Black/White Squares
|
||||
|
||||
Theater (Theater) - Windmill Interior - 0x17F89:
|
||||
0x00815 (Video Input) - True - True
|
||||
0x03553 (Tutorial Video) - 0x00815 & 0x03481 - True
|
||||
0x03552 (Desert Video) - 0x00815 & 0x0339E - True
|
||||
0x0354E (Jungle Video) - 0x00815 & 0x03702 - True
|
||||
0x03549 (Challenge Video) - 0x00815 & 0x2FAF6 - True
|
||||
0x0354F (Shipwreck Video) - 0x00815 & 0x03535 - True
|
||||
0x03545 (Mountain Video) - 0x00815 & 0x03542 - True
|
||||
0x0A168 (Door to Cargo Box Left) - True - Squares & Black/White Squares & Eraser
|
||||
0x33AB2 (Door to Cargo Box Right) - True - Squares & Black/White Squares & Shapers
|
||||
0x17CF7 (Discard) - True - Triangles
|
||||
|
||||
Jungle (Jungle) - Main Island - True:
|
||||
0x17CDF (Shore Boat Spawn) - True - Boat
|
||||
0x17F9B (Discard) - True - Triangles
|
||||
0x002C4 (Waves 1) - True - Sound & Sound Waves
|
||||
0x00767 (Waves 2) - 0x002C4 - Sound & Sound Waves
|
||||
0x002C6 (Waves 3) - 0x00767 - Sound & Sound Waves
|
||||
0x0070E (Waves 4) - 0x002C6 - Sound & Sound Waves
|
||||
0x0070F (Waves 5) - 0x0070E - Sound & Sound Waves
|
||||
0x0087D (Waves 6) - 0x0070F - Sound & Sound Waves
|
||||
0x002C7 (Waves 7) - 0x0087D - Sound & Sound Waves
|
||||
0x17CAB (Popup Wall Control) - 0x002C7 - True
|
||||
0x0026D (Popup Wall 1) - 0x17CAB - Sound & Sound Dots
|
||||
0x0026E (Popup Wall 2) - 0x0026D - Sound & Sound Dots
|
||||
0x0026F (Popup Wall 3) - 0x0026E - Sound & Sound Dots
|
||||
0x00C3F (Popup Wall 4) - 0x0026F - Sound & Sound Dots
|
||||
0x00C41 (Popup Wall 5) - 0x00C3F - Sound & Sound Dots
|
||||
0x014B2 (Popup Wall 6) - 0x00C41 - Sound & Sound Dots
|
||||
0x03616 (Laser) - 0x014B2 - True
|
||||
0x337FA (Shortcut to River) - True - True
|
||||
|
||||
Outside Jungle River (River) - Main Island - True - Jungle - 0x337FA:
|
||||
0x17CAA (Rhombic Avoid to Monastery Garden) - True - Environment
|
||||
0x15ADD (Rhombic Avoid Vault) - True - Environment
|
||||
0x03702 (Vault Box) - 0x15ADD - True
|
||||
|
||||
Outside Bunker (Bunker) - Main Island - True - Inside Bunker - 0x0A079:
|
||||
0x17C2E (Door to Bunker) - True - Squares & Black/White Squares
|
||||
0x09DE0 (Laser) - 0x0A079 - True
|
||||
|
||||
Inside Bunker (Bunker) - Outside Bunker - 0x17C2E:
|
||||
0x09F7D (Drawn Squares 1) - True - Squares & Colored Squares
|
||||
0x09FDC (Drawn Squares 2) - 0x09F7D - Squares & Colored Squares & Black/White Squares
|
||||
0x09FF7 (Drawn Squares 3) - 0x09FDC - Squares & Colored Squares & Black/White Squares
|
||||
0x09F82 (Drawn Squares 4) - 0x09FF7 - Squares & Colored Squares & Black/White Squares
|
||||
0x09FF8 (Drawn Squares 5) - 0x09F82 - Squares & Colored Squares & Black/White Squares
|
||||
0x09D9F (Drawn Squares 6) - 0x09FF8 - Squares & Colored Squares & Black/White Squares
|
||||
0x09DA1 (Drawn Squares 7) - 0x09D9F - Squares & Colored Squares
|
||||
0x09DA2 (Drawn Squares 8) - 0x09DA1 - Squares & Colored Squares
|
||||
0x09DAF (Drawn Squares 9) - 0x09DA2 - Squares & Colored Squares
|
||||
0x0A099 (Door to Bunker Proper) - 0x09DAF - True
|
||||
0x0A010 (Drawn Squares through Tinted Glass 1) - 0x0A099 - Squares & Colored Squares & RGB & Environment
|
||||
0x0A01B (Drawn Squares through Tinted Glass 2) - 0x0A010 - Squares & Colored Squares & Black/White Squares & RGB & Environment
|
||||
0x0A01F (Drawn Squares through Tinted Glass 3) - 0x0A01B - Squares & Colored Squares & Black/White Squares & RGB & Environment
|
||||
0x34BC5 (Drop-Down Door Open) - 0x0A01F - True
|
||||
0x34BC6 (Drop-Down Door Close) - 0x34BC5 - True
|
||||
0x17E63 (Drop-Down Door Squares 1) - 0x0A01F & 0x34BC5 - Squares & Colored Squares & RGB & Environment
|
||||
0x17E67 (Drop-Down Door Squares 2) - 0x17E63 & 0x34BC6 - Squares & Colored Squares & Black/White Squares & RGB
|
||||
0x0A079 (Elevator Control) - 0x17E67 - Squares & Colored Squares & Black/White Squares & RGB
|
||||
|
||||
Outside Swamp (Swamp) - Main Island - True:
|
||||
0x0056E (Entry Door) - True - Shapers
|
||||
|
||||
Swamp Entry Area (Swamp) - Outside Swamp - 0x0056E:
|
||||
0x00469 (Seperatable Shapers 1) - True - Shapers
|
||||
0x00472 (Seperatable Shapers 2) - 0x00469 - Shapers
|
||||
0x00262 (Seperatable Shapers 3) - 0x00472 - Shapers
|
||||
0x00474 (Seperatable Shapers 4) - 0x00262 - Shapers
|
||||
0x00553 (Seperatable Shapers 5) - 0x00474 - Shapers
|
||||
0x0056F (Seperatable Shapers 6) - 0x00553 - Shapers
|
||||
0x00390 (Combinable Shapers 1) - 0x0056F - Shapers
|
||||
0x010CA (Combinable Shapers 2) - 0x00390 - Shapers
|
||||
0x00983 (Combinable Shapers 3) - 0x010CA - Shapers
|
||||
0x00984 (Combinable Shapers 4) - 0x00983 - Shapers
|
||||
0x00986 (Combinable Shapers 5) - 0x00984 - Shapers
|
||||
0x00985 (Combinable Shapers 6) - 0x00986 - Shapers
|
||||
0x00987 (Combinable Shapers 7) - 0x00985 - Shapers
|
||||
0x181A9 (Combinable Shapers 8) - 0x00987 - Shapers
|
||||
0x00609 (Slide Bridge) - 0x181A9 - Shapers
|
||||
|
||||
Swamp Near Platform (Swamp) - Swamp Entry Area - 0x00609 | 0x18488:
|
||||
0x00999 (Broken Shapers 1) - 0x00990 - Broken Shapers
|
||||
0x0099D (Broken Shapers 2) - 0x00999 - Broken Shapers
|
||||
0x009A0 (Broken Shapers 3) - 0x0099D - Broken Shapers
|
||||
0x009A1 (Broken Shapers 4) - 0x009A0 - Broken Shapers
|
||||
0x00002 (Cyan Underwater Negative Shapers 1) - 0x00006 - Shapers & Negative Shapers
|
||||
0x00004 (Cyan Underwater Negative Shapers 2) - 0x00002 - Shapers & Negative Shapers
|
||||
0x00005 (Cyan Underwater Negative Shapers 3) - 0x00004 - Shapers & Negative Shapers
|
||||
0x013E6 (Cyan Underwater Negative Shapers 4) - 0x00005 - Shapers & Negative Shapers
|
||||
0x00596 (Cyan Underwater Negative Shapers 5) - 0x013E6 - Shapers & Negative Shapers
|
||||
0x18488 (Cyan Underwater Sliding Bridge Control) - 0x00006 - Shapers
|
||||
|
||||
Swamp Platform (Swamp) - Swamp Near Platform - True:
|
||||
0x00982 (Platform Shapers 1) - True - Shapers
|
||||
0x0097F (Platform Shapers 2) - 0x00982 - Shapers
|
||||
0x0098F (Platform Shapers 3) - 0x0097F - Shapers
|
||||
0x00990 (Platform Shapers 4) - 0x0098F - Shapers
|
||||
0x17C0D (Platform Shortcut Door Left) - True - Shapers
|
||||
0x17C0E (Platform Shortcut Door Right) - True - Shapers
|
||||
|
||||
Swamp Rotating Bridge Near Side (Swamp) - Swamp Near Platform - 0x009A1:
|
||||
0x00007 (Rotated Shapers 1) - 0x009A1 - Rotated Shapers
|
||||
0x00008 (Rotated Shapers 2) - 0x00007 - Rotated Shapers & Shapers
|
||||
0x00009 (Rotated Shapers 3) - 0x00008 - Rotated Shapers
|
||||
0x0000A (Rotated Shapers 4) - 0x00009 - Rotated Shapers
|
||||
0x00001 (Red Underwater Negative Shapers 1) - 0x00596 - Shapers & Negative Shapers
|
||||
0x014D2 (Red Underwater Negative Shapers 2) - 0x00596 - Shapers & Negative Shapers
|
||||
0x014D4 (Red Underwater Negative Shapers 3) - 0x00596 - Shapers & Negative Shapers
|
||||
0x014D1 (Red Underwater Negative Shapers 4) - 0x00596 - Shapers & Negative Shapers
|
||||
|
||||
Swamp Near Boat (Swamp) - Swamp Rotating Bridge Near Side - 0x009A1 - Swamp Platform - 0x17C0D & 0x17C0E:
|
||||
0x181F5 (Rotating Bridge) - True - Rotated Shapers, Shapers
|
||||
0x09DB8 (Boat Spawn) - True - Boat
|
||||
0x003B2 (More Rotated Shapers 1) - 0x0000A - Rotated Shapers
|
||||
0x00A1E (More Rotated Shapers 2) - 0x003B2 - Rotated Shapers
|
||||
0x00C2E (More Rotated Shapers 3) - 0x00A1E - Rotated Shapers
|
||||
0x00E3A (More Rotated Shapers 4) - 0x00C2E - Rotated Shapers
|
||||
0x009A6 (Underwater Back Optional) - 0x00E3A - Shapers
|
||||
0x009AB (Blue Underwater Negative Shapers 1) - 0x00E3A - Shapers & Negative Shapers
|
||||
0x009AD (Blue Underwater Negative Shapers 2) - 0x009AB - Shapers & Negative Shapers
|
||||
0x009AE (Blue Underwater Negetive Shapers 3) - 0x009AD - Shapers & Negative Shapers
|
||||
0x009AF (Blue Underwater Negative Shapers 4) - 0x009AE - Shapers & Negative Shapers
|
||||
0x00006 (Blue Underwater Negative Shapers 5) - 0x009AF - Shapers & Negative Shapers & Broken Negative Shapers
|
||||
0x17E2B (Long Bridge Control) - True - Rotated Shapers
|
||||
|
||||
Swamp Maze (Swamp) - Swamp Rotating Bridge Near Side - 0x00001 & 0x014D2 & 0x014D4 & 0x014D1 - Outside Swamp - 0x17C05 & 0x17C02:
|
||||
0x17C04 (Maze Control) - True - Shapers & Negative Shapers & Rotated Shapers & Environment
|
||||
0x03615 (Laser) - 0x17C04 - True
|
||||
0x17C05 (Near Laser Shortcut Door Left) - True - Rotated Shapers
|
||||
0x17C02 (Near Laser Shortcut Door Right) - 0x17C05 - Shapers & Negative Shapers & Rotated Shapers
|
||||
|
||||
Treehouse Entry Area (Treehouse):
|
||||
0x17C95 (Boat Spawn) - True - Boat
|
||||
0x0288C (First Door) - True - Stars
|
||||
0x02886 (Second Door) - 0x0288C - Stars
|
||||
0x17D72 (Yellow Bridge 1) - 0x02886 - Stars
|
||||
0x17D8F (Yellow Bridge 2) - 0x17D72 - Stars
|
||||
0x17D74 (Yellow Bridge 3) - 0x17D8F - Stars
|
||||
0x17DAC (Yellow Bridge 4) - 0x17D74 - Stars
|
||||
0x17D9E (Yellow Bridge 5) - 0x17DAC - Stars
|
||||
0x17DB9 (Yellow Bridge 6) - 0x17D9E - Stars
|
||||
0x17D9C (Yellow Bridge 7) - 0x17DB9 - Stars
|
||||
0x17DC2 (Yellow Bridge 8) - 0x17D9C - Stars
|
||||
0x17DC4 (Yellow Bridge 9) - 0x17DC2 - Stars
|
||||
0x0A182 (Beyond Yellow Bridge Door) - 0x17DC4 - Stars
|
||||
|
||||
Treehouse Beyond Yellow Bridge (Treehouse) - Treehouse Entry Area - 0x0A182:
|
||||
0x2700B (Laser House Door Timer Outside Control) - True - True
|
||||
0x17DC8 (First Purple Bridge 1) - True - Stars & Dots
|
||||
0x17DC7 (First Purple Bridge 2) - 0x17DC8 - Stars & Dots
|
||||
0x17CE4 (First Purple Bridge 3) - 0x17DC7 - Stars & Dots
|
||||
0x17D2D (First Purple Bridge 4) - 0x17CE4 - Stars & Dots
|
||||
0x17D6C (First Purple Bridge 5) - 0x17D2D - Stars & Dots
|
||||
0x17D9B (Second Purple Bridge 1) - 0x17D6C - Stars & Squares & Black/White Squares
|
||||
0x17D99 (Second Purple Bridge 2) - 0x17D9B - Stars & Squares & Black/White Squares
|
||||
0x17DAA (Second Purple Bridge 3) - 0x17D99 - Stars & Squares & Black/White Squares
|
||||
0x17D97 (Second Purple Bridge 4) - 0x17DAA - Stars & Squares & Black/White Squares & Colored Squares
|
||||
0x17BDF (Second Purple Bridge 5) - 0x17D97 - Stars & Squares & Colored Squares
|
||||
0x17D91 (Second Purple Bridge 6) - 0x17BDF - Stars & Squares & Colored Squares
|
||||
0x17DC6 (Second Purple Bridge 7) - 0x17D91 - Stars & Squares & Colored Squares
|
||||
0x17E3C (Green Bridge 1) - True - Stars & Shapers
|
||||
0x17E4D (Green Bridge 2) - 0x17E3C - Stars & Shapers
|
||||
0x17E4F (Green Bridge 3) - 0x17E4D - Stars & Shapers & Rotated Shapers
|
||||
0x17E52 (Green Bridge 4 & Directional) - 0x17E4F - Stars & Rotated Shapers & Environment
|
||||
0x17E5B (Green Bridge 5) - 0x17E52 - Stars & Shapers & Colored Shapers & Stars + Same Colored Symbol
|
||||
0x17E5F (Green Bridge 6) - 0x17E5B - Stars & Shapers & Colored Shapers & Negative Shapers & Colored Negative Shapers & Stars + Same Colored Symbol
|
||||
0x17E61 (Green Bridge 7) - 0x17E5F - Stars & Shapers & Rotated Shapers
|
||||
0x17FA9 (Green Bridge Discard) - 0x17E61 - Triangles
|
||||
0x17DB3 (Left Orange Bridge 1) - 0x17DC6 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x17DB5 (Left Orange Bridge 2) - 0x17DB3 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x17DB6 (Left Orange Bridge 3) - 0x17DB5 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x17DC0 (Left Orange Bridge 4) - 0x17DB6 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x17DD7 (Left Orange Bridge 5) - 0x17DC0 - Stars & Squares & Black/White Squares & Colored Squares & Stars + Same Colored Symbol
|
||||
0x17DD9 (Left Orange Bridge 6) - 0x17DD7 - Stars & Squares & Black/White Squares & Colored Squares & Stars + Same Colored Symbol
|
||||
0x17DB8 (Left Orange Bridge 7) - 0x17DD9 - Stars & Squares & Black/White Squares & Colored Squares & Stars + Same Colored Symbol
|
||||
0x17DDC (Left Orange Bridge 8) - 0x17DB8 - Stars & Squares & Colored Squares & Stars + Same Colored Symbol
|
||||
0x17DD1 (Left Orange Bridge 9 & Directional) - 0x17DDC - Stars & Squares & Colored Squares & Stars + Same Colored Symbol & Environment
|
||||
0x17DDE (Left Orange Bridge 10) - 0x17DD1 - Stars & Squares & Colored Squares & Stars + Same Colored Symbol
|
||||
0x17DE3 (Left Orange Bridge 11) - 0x17DDE - Stars & Squares & Colored Squares & Stars + Same Colored Symbol
|
||||
0x17DEC (Left Orange Bridge 12) - 0x17DE3 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x17DAE (Left Orange Bridge 13) - 0x17DEC - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x17DB0 (Left Orange Bridge 14) - 0x17DAE - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x17DDB (Left Orange Bridge 15) - 0x17DB0 - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x17FA0 (Burned House Discard) - 0x17DDB - Triangles
|
||||
0x17D88 (Right Orange Bridge 1) - True - Stars
|
||||
0x17DB4 (Right Orange Bridge 2) - 0x17D88 - Stars
|
||||
0x17D8C (Right Orange Bridge 3) - 0x17DB4 - Stars
|
||||
0x17CE3 (Right Orange Bridge 4 & Directional) - 0x17D8C - Stars & Environment
|
||||
0x17DCD (Right Orange Bridge 5) - 0x17CE3 - Stars
|
||||
0x17DB2 (Right Orange Bridge 6) - 0x17DCD - Stars
|
||||
0x17DCC (Right Orange Bridge 7) - 0x17DB2 - Stars
|
||||
0x17DCA (Right Orange Bridge 8) - 0x17DCC - Stars
|
||||
0x17D8E (Right Orange Bridge 9) - 0x17DCA - Stars
|
||||
0x17DB7 (Right Orange Bridge 10 & Directional) - 0x17D8E - Stars
|
||||
0x17DB1 (Right Orange Bridge 11) - 0x17DB7 - Stars
|
||||
0x17DA2 (Right Orange Bridge 12) - 0x17DB1 - Stars
|
||||
|
||||
Treehouse Laser Room (Treehouse) - Treehouse Beyond Yellow Bridge - 0x2700B & 0x17DA2 & 0x17DDB:
|
||||
0x03613 (Laser) - True - True
|
||||
0x17CBC (Laser House Door Timer Inside Control) - True - True
|
||||
|
||||
Treehouse Bridge Platform (Treehouse) - Treehouse Beyond Yellow Bridge - 0x17DA2 - Main Island - 0x037FF:
|
||||
0x037FF (Bridge Control) - True - Stars
|
||||
|
||||
Mountaintop (Mountaintop) - Main Island - True:
|
||||
0x0042D (River Shape) - True - True
|
||||
0x09F7F (Box Open) - 7 Lasers - True
|
||||
0x17C34 (Trap Door Triple Exit) - 0x09F7F - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x17C42 (Discard) - True - Triangles
|
||||
0x002A6 (Vault) - True - Symmetry & Colored Dots & Squares & Black/White Squares & Dots
|
||||
0x03542 (Vault Box) - 0x002A6 - True
|
||||
|
||||
Inside Mountain Top Layer (Inside Mountain) - Mountaintop - 0x17C34:
|
||||
0x09E39 (Light Bridge Controller) - True - Squares & Black/White Squares & Colored Squares & Eraser & Colored Eraser
|
||||
|
||||
Inside Mountain Top Layer Bridge (Inside Mountain) - Inside Mountain Top Layer - 0x09E39:
|
||||
0x09E7A (Obscured Vision 1) - True - Obscured & Squares & Black/White Squares & Dots
|
||||
0x09E71 (Obscured Vision 2) - 0x09E7A - Obscured & Squares & Black/White Squares & Dots
|
||||
0x09E72 (Obscured Vision 3) - 0x09E71 - Obscured & Squares & Black/White Squares & Rotated Shapers & Dots
|
||||
0x09E69 (Obscured Vision 4) - 0x09E72 - Obscured & Squares & Black/White Squares & Dots
|
||||
0x09E7B (Obscured Vision 5) - 0x09E69 - Obscured & Squares & Black/White Squares & Dots
|
||||
0x09E73 (Moving Background 1) - True - Moving & Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x09E75 (Moving Background 2) - 0x09E73 - Moving & Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x09E78 (Moving Background 3) - 0x09E75 - Moving & Shapers
|
||||
0x09E79 (Moving Background 4) - 0x09E78 - Moving & Shapers & Rotated Shapers
|
||||
0x09E6C (Moving Background 5) - 0x09E79 - Moving & Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x09E6F (Moving Background 6) - 0x09E6C - Moving & Stars & Rotated Shapers & Shapers
|
||||
0x09E6B (Moving Background 7) - 0x09E6F - Moving & Stars & Dots
|
||||
0x33AF5 (Physically Obstructed 1) - True - Squares & Black/White Squares & Environment & Symmetry
|
||||
0x33AF7 (Physically Obstructed 2) - 0x33AF5 - Squares & Black/White Squares & Stars & Environment
|
||||
0x09F6E (Physically Obstructed 3) - 0x33AF7 - Symmetry & Dots & Environment
|
||||
0x09EAD (Angled Inside Trash 1) - True - Squares & Black/White Squares & Shapers & Angled
|
||||
0x09EAF (Angled Inside Trash 2) - 0x09EAD - Squares & Black/White Squares & Shapers & Angled
|
||||
|
||||
Inside Mountain Second Layer (Inside Mountain) - Inside Mountain Top Layer Bridge - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B:
|
||||
0x09FD3 (Color Cycle 1) - True - Color Cycle & RGB & Stars & Squares & Colored Squares & Stars + Same Colored Symbol
|
||||
0x09FD4 (Color Cycle 2) - 0x09FD3 - Color Cycle & RGB & Stars & Squares & Colored Squares & Stars + Same Colored Symbol
|
||||
0x09FD6 (Color Cycle 3) - 0x09FD4 - Color Cycle & RGB & Stars & Squares & Colored Squares & Stars + Same Colored Symbol
|
||||
0x09FD7 (Color Cycle 4) - 0x09FD6 - Color Cycle & RGB & Stars & Squares & Colored Squares & Stars + Same Colored Symbol & Shapers & Colored Shapers
|
||||
0x09FD8 (Color Cycle 5) - 0x09FD7 - Color Cycle & RGB & Squares & Colored Squares & Symmetry & Colored Dots
|
||||
0x09E86 (Light Bridge Controller 2) - 0x09FD7 - Stars & Stars + Same Colored Symbol & Colored Rotated Shapers & Eraser & Two Lines
|
||||
|
||||
Inside Mountain Second Layer Beyond Bridge (Inside Mountain) - Inside Mountain Second Layer - 0x09E86:
|
||||
0x09FCC (Same Solution 1) - True - Dots & Same Solution
|
||||
0x09FCE (Same Solution 2) - 0x09FCC - Squares & Black/White Squares & Same Solution
|
||||
0x09FCF (Same Solution 3) - 0x09FCE - Stars & Same Solution
|
||||
0x09FD0 (Same Solution 4) - 0x09FCF - Rotated Shapers & Same Solution
|
||||
0x09FD1 (Same Solution 5) - 0x09FD0 - Stars & Squares & Colored Squares & Stars + Same Colored Symbol & Same Solution
|
||||
0x09FD2 (Same Solution 6) - 0x09FD1 - Shapers & Same Solution
|
||||
0x09ED8 (Light Bridge Controller 3) - 0x09FD2 - Stars & Stars + Same Colored Symbol & Colored Rotated Shapers & Eraser & Two Lines
|
||||
|
||||
Inside Mountain Second Layer Elevator (Inside Mountain) - Inside Mountain Second Layer - 0x09ED8 & 0x09E86:
|
||||
0x09EEB (Elevator Control Panel) - True - Dots
|
||||
0x17F93 (Elevator Discard) - True - Triangles
|
||||
|
||||
Inside Mountain Third Layer (Inside Mountain) - Inside Mountain Second Layer Elevator - 0x09EEB:
|
||||
0x09FC1 (Giant Puzzle Bottom Left) - True - Shapers & Eraser
|
||||
0x09F8E (Giant Puzzle Bottom Right) - True - Shapers & Eraser
|
||||
0x09F01 (Giant Puzzle Top Right) - True - Rotated Shapers
|
||||
0x09EFF (Giant Puzzle Top Left) - True - Shapers & Eraser
|
||||
0x09FDA (Giant Puzzle) - 0x09FC1 & 0x09F8E & 0x09F01 & 0x09EFF - Shapers & Symmetry
|
||||
|
||||
Inside Mountain Bottom Layer (Inside Mountain) - Inside Mountain Third Layer - 0x09FDA - Inside Mountain Path to Secret Area - 0x334E1:
|
||||
0x17FA2 (Bottom Layer Discard) - 11 Lasers & 0x09F7F - Triangles & Environment
|
||||
0x01983 (Door to Final Room Left) - True - Shapers & Stars
|
||||
0x01987 (Door to Final Room Right) - True - Squares & Colored Squares
|
||||
|
||||
|
||||
Inside Mountain Path to Secret Area (Inside Mountain) - Inside Mountain Bottom Layer - 0x17FA2:
|
||||
0x00FF8 (Door to Secret Area) - True - Triangles & Black/White Squares & Squares
|
||||
0x334E1 (Rock Control) - True - True
|
||||
|
||||
Inside Mountain Secret Area (Inside Mountain Secret Area) - Inside Mountain Path to Secret Area - 0x00FF8 - Main Island - 0x021D7 - Main Island - 0x17CF2:
|
||||
0x021D7 (Shortcut to Mountain) - True - Triangles & Stars & Stars + Same Colored Symbol & Colored Triangles
|
||||
0x17CF2 (Shortcut to Swamp) - True - Triangles
|
||||
0x335AB (Elevator Inside Control) - True - Dots & Squares & Black/White Squares
|
||||
0x335AC (Elevator Upper Outside Control) - 0x335AB - Squares & Black/White Squares
|
||||
0x3369D (Elevator Lower Outside Control) - 0x335AB - Squares & Black/White Squares & Dots
|
||||
0x00190 (Dot Grid Triangles 1) - True - Dots & Triangles
|
||||
0x00558 (Dot Grid Triangles 2) - 0x00190 - Dots & Triangles
|
||||
0x00567 (Dot Grid Triangles 3) - 0x00558 - Dots & Triangles
|
||||
0x006FE (Dot Grid Triangles 4) - 0x00567 - Dots & Triangles
|
||||
0x01A0D (Symmetry Triangles) - True - Symmetry & Triangles
|
||||
0x008B8 (Squares and Triangles) - True - Squares & Black/White Squares & Triangles
|
||||
0x00973 (Stars and Triangles) - 0x008B8 - Stars & Triangles
|
||||
0x0097B (Stars and Triangles of same color) - 0x00973 - Stars & Triangles & Stars and Triangles of same color & Stars + Same Colored Symbol
|
||||
0x0097D (Stars & Squares and Triangles) - 0x0097B - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol & Triangles
|
||||
0x0097E (Stars & Squares and Triangles 2) - 0x0097D - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol & Stars and Triangles of same color
|
||||
0x00994 (Rotated Shapers and Triangles 1) - True - Rotated Shapers & Triangles
|
||||
0x334D5 (Rotated Shapers and Triangles 2) - 0x00994 - Rotated Shapers & Triangles
|
||||
0x00995 (Rotated Shapers and Triangles 3) - 0x334D5 - Rotated Shapers & Triangles
|
||||
0x00996 (Shapers and Triangles 1) - 0x00995 - Shapers & Triangles
|
||||
0x00998 (Shapers and Triangles 2) - 0x00996 - Shapers & Triangles
|
||||
0x009A4 (Broken Shapers) - True - Shapers & Broken Shapers
|
||||
0x018A0 (Symmetry Shapers) - True - Shapers & Symmetry
|
||||
0x00A72 (Broken and Negative Shapers) - True - Shapers & Broken Shapers & Negative Shapers
|
||||
0x32962 (Rotated Broken Shapers) - True - Rotated Shapers & Broken Rotated Shapers
|
||||
0x32966 (Stars and Squares) - True - Stars & Squares & Black/White Squares & Stars + Same Colored Symbol
|
||||
0x01A31 (Rainbow Squares) - True - Color Cycle & RGB & Squares & Colored Squares
|
||||
0x00B71 (Squares & Stars and Colored Eraser) - True - Colored Eraser & Squares & Colored Squares & Stars & Stars + Same Colored Symbol
|
||||
0x09DD5 (Lone Pillar) - True - Pillar & Triangles
|
||||
0x0A16E (Door to Challenge) - 0x09DD5 - Stars & Shapers & Colored Shapers & Stars + Same Colored Symbol
|
||||
0x288EA (Wooden Beam Shapers) - True - Environment & Shapers
|
||||
0x288FC (Wooden Beam Squares and Shapers) - True - Environment & Squares & Black/White Squares & Shapers & Rotated Shapers
|
||||
0x289E7 (Wooden Beam Shapers and Squares) - True - Environment & Stars & Squares & Black/White Squares
|
||||
0x288AA (Wooden Beam Shapers and Stars) - True - Environment & Stars & Shapers
|
||||
0x17FB9 (Upstairs Dot Grid Negative Shapers) - True - Shapers & Dots & Negative Shapers
|
||||
0x0A16B (Upstairs Dot Grid Squares) - True - Squares & Black/White Squares & Colored Squares & Dots
|
||||
0x0A2CE (Upstairs Dot Grid Stars) - 0x0A16B - Stars & Dots
|
||||
0x0A2D7 (Upstairs Dot Grid Triangles) - 0x0A2CE - Triangles & Dots
|
||||
0x0A2DD (Upstairs Dot Grid Shapers) - 0x0A2D7 - Shapers & Dots
|
||||
0x0A2EA (Upstairs Dot Grid Rotated Shapers) - 0x0A2DD - Rotated Shapers & Dots
|
||||
0x0008F (Upstairs Invisible Dots 1) - True - Dots & Invisible Dots
|
||||
0x0006B (Upstairs Invisible Dots 2) - 0x0008F - Dots & Invisible Dots
|
||||
0x0008B (Upstairs Invisible Dots 3) - 0x0006B - Dots & Invisible Dots
|
||||
0x0008C (Upstairs Invisible Dots 4) - 0x0008B - Dots & Invisible Dots
|
||||
0x0008A (Upstairs Invisible Dots 5) - 0x0008C - Dots & Invisible Dots
|
||||
0x00089 (Upstairs Invisible Dots 6) - 0x0008A - Dots & Invisible Dots
|
||||
0x0006A (Upstairs Invisible Dots 7) - 0x00089 - Dots & Invisible Dots
|
||||
0x0006C (Upstairs Invisible Dots 8) - 0x0006A - Dots & Invisible Dots
|
||||
0x00027 (Upstairs Invisible Dot Symmetry 1) - True - Dots & Invisible Dots & Symmetry
|
||||
0x00028 (Upstairs Invisible Dot Symmetry 2) - 0x00027 - Dots & Invisible Dots & Symmetry
|
||||
0x00029 (Upstairs Invisible Dot Symmetry 3) - 0x00028 - Dots & Invisible Dots & Symmetry
|
||||
|
||||
Challenge (Challenge) - Inside Mountain Secret Area - 0x0A16E:
|
||||
0x0A332 (Start Timer) - True - True
|
||||
0x0088E (Small Basic) - 0x0A332 - True
|
||||
0x00BAF (Big Basic) - 0x0088E - True
|
||||
0x00BF3 (Square) - 0x00BAF - Squares & Black/White Squares
|
||||
0x00C09 (Maze Map) - 0x00BF3 - Dots
|
||||
0x00CDB (Stars and Dots) - 0x00C09 - Stars & Dots
|
||||
0x0051F (Symmetry) - 0x00CDB - Symmetry & Colored Dots & Dots
|
||||
0x00524 (Stars and Shapers) - 0x0051F - Stars & Shapers
|
||||
0x00CD4 (Big Basic 2) - 0x00524 - True
|
||||
0x00CB9 (Choice Squares Right) - 0x00CD4 - Squares & Black/White Squares
|
||||
0x00CA1 (Choice Squares Middle) - 0x00CD4 - Squares & Black/White Squares
|
||||
0x00C80 (Choice Squares Left) - 0x00CD4 - Squares & Black/White Squares
|
||||
0x00C68 (Choice Squares 2 Right) - 0x00CB9 | 0x00CA1 | 0x00C80 - Squares & Black/White Squares & Colored Squares
|
||||
0x00C59 (Choice Squares 2 Middle) - 0x00CB9 | 0x00CA1 | 0x00C80 - Squares & Black/White Squares & Colored Squares
|
||||
0x00C22 (Choice Squares 2 Left) - 0x00CB9 | 0x00CA1 | 0x00C80 - Squares & Black/White Squares & Colored Squares
|
||||
0x034F4 (Maze Hidden 1) - 0x00C68 | 0x00C59 | 0x00C22 - Triangles
|
||||
0x034EC (Maze Hidden 2) - 0x00C68 | 0x00C59 | 0x00C22 - Triangles
|
||||
0x1C31A (Dots Pillar) - 0x034F4 & 0x034EC - Dots & Symmetry & Pillar
|
||||
0x1C319 (Squares Pillar) - 0x034F4 & 0x034EC - Squares & Black/White Squares & Symmetry & Pillar
|
||||
0x0356B (Vault Box) - 0x1C31A & 0x1C319 - True
|
||||
0x039B4 (Door to Theater Walkway) - True - Triangles
|
||||
|
||||
Theater Walkway (Theater Walkway) - Challenge - 0x039B4 - Theater - 0x27732 - Desert Elevator Room - 0x2773D & 0x03608 - Town - 0x09E85:
|
||||
0x2FAF6 (Vault Box) - True - True
|
||||
0x27732 (Door to Back of Theater) - True - True
|
||||
0x2773D (Door to Desert Elevator Room) - True - True
|
||||
0x09E85 (Door to Town) - True - Triangles
|
||||
|
||||
Final Room (Inside Mountain Final Room) - Inside Mountain Bottom Layer - 0x01983 & 0x01987:
|
||||
0x0383A (Stars Pillar) - True - Stars & Pillar
|
||||
0x09E56 (Stars and Dots Pillar) - 0x0383A - Stars & Dots & Pillar
|
||||
0x09E5A (Dot Grid Pillar) - 0x09E56 - Dots & Pillar
|
||||
0x33961 (Sparse Dots Pillar) - 0x09E5A - Dots & Pillar
|
||||
0x0383D (Dot Maze Pillar) - True - Dots & Pillar
|
||||
0x0383F (Squares Pillar) - 0x0383D - Squares & Black/White Squares & Pillar
|
||||
0x03859 (Shapers Pillar) - 0x0383F - Shapers & Pillar
|
||||
0x339BB (Squares and Stars) - 0x03859 - Squares & Black/White Squares & Stars & Pillar
|
||||
|
||||
Elevator (Inside Mountain Final Room) - Final Room - 0x339BB & 0x33961:
|
||||
0x3D9A6 (Elevator Door Closer Left) - True - True
|
||||
0x3D9A7 (Elevator Door Close Right) - True - True
|
||||
0x3C113 (Elevator Door Open Left) - 0x3D9A6 | 0x3D9A7 - True
|
||||
0x3C114 (Elevator Door Open Right) - 0x3D9A6 | 0x3D9A7 - True
|
||||
0x3D9AA (Back Wall Left) - 0x3D9A6 | 0x3D9A7 - True
|
||||
0x3D9A8 (Back Wall Right) - 0x3D9A6 | 0x3D9A7 - True
|
||||
0x3D9A9 (Elevator Start) - 0x3D9AA | 0x3D9A8 - True
|
||||
|
||||
Boat (Boat) - Main Island - 0x17CDF | 0x17CC8 | 0x17CA6 | 0x09DB8 | 0x17C95 - Inside Glass Factory - 0x17CDF | 0x17CC8 | 0x17CA6 | 0x09DB8 | 0x17C95 - Quarry Boathouse - 0x17CDF | 0x17CC8 | 0x17CA6 | 0x09DB8 | 0x17C95 - Swamp Near Boat - 0x17CDF | 0x17CC8 | 0x17CA6 | 0x09DB8 | 0x17C95 - Treehouse Entry Area - 0x17CDF | 0x17CC8 | 0x17CA6 | 0x09DB8 | 0x17C95:
|
|
@ -0,0 +1,165 @@
|
|||
"""
|
||||
Archipelago init file for The Witness
|
||||
"""
|
||||
|
||||
import typing
|
||||
|
||||
from BaseClasses import Region, RegionType, Location, MultiWorld, Item, Entrance
|
||||
from ..AutoWorld import World, WebWorld
|
||||
from .player_logic import StaticWitnessLogic, WitnessPlayerLogic
|
||||
from .locations import WitnessPlayerLocations, StaticWitnessLocations
|
||||
from .items import WitnessItem, StaticWitnessItems, WitnessPlayerItems
|
||||
from .rules import set_rules
|
||||
from .regions import WitnessRegions
|
||||
from .Options import is_option_enabled, the_witness_options
|
||||
|
||||
|
||||
class WitnessWebWorld(WebWorld):
|
||||
theme = "jungle"
|
||||
|
||||
|
||||
class WitnessWorld(World):
|
||||
"""
|
||||
The Witness is an open-world puzzle game with dozens of locations
|
||||
to explore and over 500 puzzles. Play the popular puzzle randomizer
|
||||
by sigma144, with an added layer of progression randomization!
|
||||
"""
|
||||
game = "The Witness"
|
||||
topology_present = False
|
||||
static_logic = StaticWitnessLogic()
|
||||
static_locat = StaticWitnessLocations()
|
||||
static_items = StaticWitnessItems()
|
||||
web = WitnessWebWorld()
|
||||
options = the_witness_options
|
||||
|
||||
item_name_to_id = {
|
||||
name: data.code for name, data in static_items.ALL_ITEM_TABLE.items()
|
||||
}
|
||||
location_name_to_id = StaticWitnessLocations.ALL_LOCATIONS_TO_ID
|
||||
|
||||
def _get_slot_data(self):
|
||||
return {
|
||||
'seed': self.world.random.randint(0, 1000000),
|
||||
'victory_location': int(self.player_logic.VICTORY_LOCATION, 16),
|
||||
'panelhex_to_id': self.locat.CHECK_PANELHEX_TO_ID
|
||||
}
|
||||
|
||||
def generate_early(self):
|
||||
self.player_logic = WitnessPlayerLogic(self.world, self.player)
|
||||
self.locat = WitnessPlayerLocations(self.world, self.player, self.player_logic)
|
||||
self.items = WitnessPlayerItems(self.locat, self.world, self.player, self.player_logic)
|
||||
self.regio = WitnessRegions(self.locat)
|
||||
|
||||
def generate_basic(self):
|
||||
# Generate item pool
|
||||
pool = []
|
||||
items_by_name = dict()
|
||||
for item in self.items.ITEM_TABLE:
|
||||
witness_item = self.create_item(item)
|
||||
if item not in self.items.EVENT_ITEM_TABLE:
|
||||
pool.append(witness_item)
|
||||
items_by_name[item] = witness_item
|
||||
|
||||
# Put good item on first check
|
||||
random_good_item = self.world.random.choice(self.items.GOOD_ITEMS)
|
||||
first_check = self.world.get_location(
|
||||
"Tutorial Gate Open", self.player
|
||||
)
|
||||
first_check.place_locked_item(items_by_name[random_good_item])
|
||||
pool.remove(items_by_name[random_good_item])
|
||||
|
||||
# Put in junk items to fill the rest
|
||||
junk_pool = self.items.JUNK_WEIGHTS.copy()
|
||||
junk_pool = self.world.random.choices(
|
||||
list(junk_pool.keys()), weights=list(junk_pool.values()),
|
||||
k=len(self.locat.CHECK_LOCATION_TABLE) - len(pool) - len(self.locat.EVENT_LOCATION_TABLE) - 1
|
||||
)
|
||||
|
||||
pool += [self.create_item(junk) for junk in junk_pool]
|
||||
|
||||
# Tie Event Items to Event Locations (e.g. Laser Activations)
|
||||
for event_location in self.locat.EVENT_LOCATION_TABLE:
|
||||
item_obj = self.create_item(
|
||||
self.player_logic.EVENT_ITEM_PAIRS[event_location]
|
||||
)
|
||||
location_obj = self.world.get_location(event_location, self.player)
|
||||
location_obj.place_locked_item(item_obj)
|
||||
|
||||
self.world.itempool += pool
|
||||
|
||||
def create_regions(self):
|
||||
self.regio.create_regions(self.world, self.player, self.player_logic)
|
||||
|
||||
def set_rules(self):
|
||||
set_rules(self.world, self.player, self.player_logic, self.locat)
|
||||
|
||||
def fill_slot_data(self) -> dict:
|
||||
slot_data = self._get_slot_data()
|
||||
|
||||
slot_data["hard_mode"] = False
|
||||
|
||||
for option_name in the_witness_options:
|
||||
slot_data[option_name] = is_option_enabled(
|
||||
self.world, self.player, option_name
|
||||
)
|
||||
|
||||
return slot_data
|
||||
|
||||
def create_item(self, name: str) -> Item:
|
||||
# this conditional is purely for unit tests, which need to be able to create an item before generate_early
|
||||
if hasattr(self, 'items'):
|
||||
item = self.items.ITEM_TABLE[name]
|
||||
else:
|
||||
item = StaticWitnessItems.ALL_ITEM_TABLE[name]
|
||||
|
||||
new_item = WitnessItem(
|
||||
name, item.progression, item.code, player=self.player
|
||||
)
|
||||
new_item.trap = item.trap
|
||||
return new_item
|
||||
|
||||
def get_filler_item_name(self) -> str: # Used ny itemlinks
|
||||
junk_pool = self.items.JUNK_WEIGHTS.copy()
|
||||
|
||||
return self.world.random.choices(list(junk_pool.keys()), weights=list(junk_pool.values()))[0]
|
||||
|
||||
|
||||
class WitnessLocation(Location):
|
||||
"""
|
||||
Archipelago Location for The Witness
|
||||
"""
|
||||
game: str = "The Witness"
|
||||
check_hex: int = -1
|
||||
|
||||
def __init__(self, player: int, name: str, address: typing.Optional[int], parent, ch_hex: int = -1):
|
||||
super().__init__(player, name, address, parent)
|
||||
self.check_hex = ch_hex
|
||||
|
||||
|
||||
def create_region(world: MultiWorld, player: int, name: str,
|
||||
locat: WitnessPlayerLocations, region_locations=None, exits=None):
|
||||
"""
|
||||
Create an Archipelago Region for The Witness
|
||||
"""
|
||||
|
||||
ret = Region(name, RegionType.Generic, name, player)
|
||||
ret.world = world
|
||||
if region_locations:
|
||||
for location in region_locations:
|
||||
loc_id = locat.CHECK_LOCATION_TABLE[location]
|
||||
|
||||
check_hex = -1
|
||||
if location in StaticWitnessLogic.CHECKS_BY_NAME:
|
||||
check_hex = int(
|
||||
StaticWitnessLogic.CHECKS_BY_NAME[location]["checkHex"], 0
|
||||
)
|
||||
location = WitnessLocation(
|
||||
player, location, loc_id, ret, check_hex
|
||||
)
|
||||
|
||||
ret.locations.append(location)
|
||||
if exits:
|
||||
for single_exit in exits:
|
||||
ret.exits.append(Entrance(player, single_exit, ret))
|
||||
|
||||
return ret
|
|
@ -0,0 +1,98 @@
|
|||
"""
|
||||
Defines progression, junk and event items for The Witness
|
||||
"""
|
||||
import copy
|
||||
from typing import Dict, NamedTuple, Optional
|
||||
|
||||
from BaseClasses import Item, MultiWorld
|
||||
from . import StaticWitnessLogic, WitnessPlayerLocations, WitnessPlayerLogic
|
||||
from .Options import is_option_enabled
|
||||
|
||||
|
||||
class ItemData(NamedTuple):
|
||||
"""
|
||||
ItemData for an item in The Witness
|
||||
"""
|
||||
code: Optional[int]
|
||||
progression: bool
|
||||
event: bool = False
|
||||
trap: bool = False
|
||||
|
||||
|
||||
class WitnessItem(Item):
|
||||
"""
|
||||
Item from the game The Witness
|
||||
"""
|
||||
game: str = "The Witness"
|
||||
|
||||
|
||||
class StaticWitnessItems:
|
||||
"""
|
||||
Class that handles Witness items independent of world settings
|
||||
"""
|
||||
|
||||
ALL_ITEM_TABLE: Dict[str, ItemData] = {}
|
||||
|
||||
JUNK_WEIGHTS = {
|
||||
"Speed Boost": 1,
|
||||
"Slowness": 0.8,
|
||||
"Power Surge": 0.2,
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
item_tab = dict()
|
||||
|
||||
for item in StaticWitnessLogic.ALL_ITEMS:
|
||||
if item[0] == "11 Lasers" or item == "7 Lasers":
|
||||
continue
|
||||
|
||||
item_tab[item[0]] = ItemData(158000 + item[1], True, False)
|
||||
|
||||
for item in StaticWitnessLogic.ALL_TRAPS:
|
||||
item_tab[item[0]] = ItemData(
|
||||
158000 + item[1], False, False, True
|
||||
)
|
||||
|
||||
for item in StaticWitnessLogic.ALL_BOOSTS:
|
||||
item_tab[item[0]] = ItemData(158000 + item[1], False, False)
|
||||
|
||||
item_tab = dict(sorted(
|
||||
item_tab.items(),
|
||||
key=lambda single_item: single_item[1].code
|
||||
if isinstance(single_item[1].code, int) else 0)
|
||||
)
|
||||
|
||||
for key, item in item_tab.items():
|
||||
self.ALL_ITEM_TABLE[key] = item
|
||||
|
||||
|
||||
class WitnessPlayerItems:
|
||||
"""
|
||||
Class that defines Items for a single world
|
||||
"""
|
||||
|
||||
def __init__(self, locat: WitnessPlayerLocations, world: MultiWorld, player: int, player_logic: WitnessPlayerLogic):
|
||||
"""Adds event items after logic changes due to options"""
|
||||
self.EVENT_ITEM_TABLE = dict()
|
||||
self.ITEM_TABLE = copy.copy(StaticWitnessItems.ALL_ITEM_TABLE)
|
||||
|
||||
self.GOOD_ITEMS = [
|
||||
"Dots", "Black/White Squares", "Stars",
|
||||
"Shapers", "Symmetry"
|
||||
]
|
||||
|
||||
if is_option_enabled(world, player, "shuffle_discarded_panels"):
|
||||
self.GOOD_ITEMS.append("Triangles")
|
||||
if not is_option_enabled(world, player, "disable_non_randomized_puzzles"):
|
||||
self.GOOD_ITEMS.append("Colored Squares")
|
||||
|
||||
for event_location in locat.EVENT_LOCATION_TABLE:
|
||||
location = player_logic.EVENT_ITEM_PAIRS[event_location]
|
||||
self.EVENT_ITEM_TABLE[location] = ItemData(None, True, True)
|
||||
self.ITEM_TABLE[location] = ItemData(None, True, True)
|
||||
|
||||
self.JUNK_WEIGHTS = {
|
||||
key: value for (key, value)
|
||||
in StaticWitnessItems.JUNK_WEIGHTS.items()
|
||||
if key in self.ITEM_TABLE.keys()
|
||||
}
|
|
@ -0,0 +1,281 @@
|
|||
"""
|
||||
Defines constants for different types of locations in the game
|
||||
"""
|
||||
|
||||
from .Options import is_option_enabled
|
||||
from .player_logic import StaticWitnessLogic, WitnessPlayerLogic
|
||||
|
||||
|
||||
class StaticWitnessLocations:
|
||||
"""
|
||||
Witness Location Constants that stay consistent across worlds
|
||||
"""
|
||||
ID_START = 158000
|
||||
|
||||
TYPE_OFFSETS = {
|
||||
"General": 0,
|
||||
"Discard": 600,
|
||||
"Vault": 650,
|
||||
"Laser": 700,
|
||||
}
|
||||
|
||||
GENERAL_LOCATIONS = {
|
||||
"Tutorial Gate Open",
|
||||
|
||||
"Outside Tutorial Vault Box",
|
||||
"Outside Tutorial Discard",
|
||||
"Outside Tutorial Dots Introduction 5",
|
||||
"Outside Tutorial Squares Introduction 9",
|
||||
|
||||
"Glass Factory Discard",
|
||||
"Glass Factory Vertical Symmetry 5",
|
||||
"Glass Factory Rotational Symmetry 3",
|
||||
"Glass Factory Melting 3",
|
||||
|
||||
"Symmetry Island Black Dots 5",
|
||||
"Symmetry Island Colored Dots 6",
|
||||
"Symmetry Island Fading Lines 7",
|
||||
"Symmetry Island Scenery Outlines 5",
|
||||
"Symmetry Island Laser",
|
||||
|
||||
"Orchard Apple Tree 5",
|
||||
|
||||
"Desert Vault Box",
|
||||
"Desert Discard",
|
||||
"Desert Sun Reflection 8",
|
||||
"Desert Artificial Light Reflection 3",
|
||||
"Desert Pond Reflection 5",
|
||||
"Desert Flood Reflection 6",
|
||||
"Desert Laser",
|
||||
|
||||
"Quarry Mill Eraser and Dots 6",
|
||||
"Quarry Mill Eraser and Squares 8",
|
||||
"Quarry Mill Small Squares & Dots & and Eraser",
|
||||
"Quarry Mill Big Squares & Dots & and Eraser",
|
||||
"Quarry Boathouse Intro Shapers",
|
||||
"Quarry Boathouse Eraser and Shapers 5",
|
||||
"Quarry Boathouse Stars & Eraser & and Shapers 2",
|
||||
"Quarry Boathouse Stars & Eraser & and Shapers 5",
|
||||
"Quarry Discard",
|
||||
"Quarry Laser",
|
||||
|
||||
"Shadows Lower Avoid 8",
|
||||
"Shadows Environmental Avoid 8",
|
||||
"Shadows Follow 5",
|
||||
"Shadows Laser",
|
||||
|
||||
"Keep Hedge Maze 4",
|
||||
"Keep Pressure Plates 4",
|
||||
"Keep Discard",
|
||||
"Keep Laser Hedges",
|
||||
"Keep Laser Pressure Plates",
|
||||
|
||||
"Shipwreck Vault Box",
|
||||
"Shipwreck Discard",
|
||||
|
||||
"Monastery Rhombic Avoid 3",
|
||||
"Monastery Branch Follow 2",
|
||||
"Monastery Laser",
|
||||
|
||||
"Town Cargo Box Discard",
|
||||
"Town Hexagonal Reflection",
|
||||
"Town Square Avoid",
|
||||
"Town Rooftop Discard",
|
||||
"Town Symmetry Squares 5 + Dots",
|
||||
"Town Full Dot Grid Shapers 5",
|
||||
"Town Shapers & Dots & and Eraser",
|
||||
"Town Laser",
|
||||
|
||||
"Theater Discard",
|
||||
|
||||
"Jungle Discard",
|
||||
"Jungle Waves 3",
|
||||
"Jungle Waves 7",
|
||||
"Jungle Popup Wall 6",
|
||||
"Jungle Laser",
|
||||
|
||||
"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 Laser",
|
||||
|
||||
"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 Laser",
|
||||
|
||||
"Treehouse Yellow Bridge 9",
|
||||
"Treehouse First Purple Bridge 5",
|
||||
"Treehouse Second Purple Bridge 7",
|
||||
"Treehouse Green Bridge 7",
|
||||
"Treehouse Green Bridge Discard",
|
||||
"Treehouse Left Orange Bridge 15",
|
||||
"Treehouse Burned House Discard",
|
||||
"Treehouse Right Orange Bridge 12",
|
||||
"Treehouse Laser",
|
||||
|
||||
"Mountaintop Trap Door Triple Exit",
|
||||
"Mountaintop Discard",
|
||||
"Mountaintop Vault Box",
|
||||
|
||||
"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",
|
||||
"Inside Mountain Elevator Discard",
|
||||
"Inside Mountain Giant Puzzle",
|
||||
}
|
||||
|
||||
UNCOMMON_LOCATIONS = {
|
||||
"Mountaintop River Shape",
|
||||
"Tutorial Patio Floor",
|
||||
"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",
|
||||
}
|
||||
|
||||
HARD_LOCATIONS = {
|
||||
"Tutorial Gate Close",
|
||||
|
||||
"Inside Mountain Secret Area Dot Grid Triangles 4",
|
||||
"Inside Mountain Secret Area Symmetry Triangles",
|
||||
"Inside Mountain Secret Area Stars & Squares and Triangles 2",
|
||||
"Inside Mountain Secret Area Shapers and Triangles 2",
|
||||
"Inside Mountain Secret Area Symmetry Shapers",
|
||||
"Inside Mountain Secret Area Broken and Negative Shapers",
|
||||
"Inside Mountain Secret Area Broken Shapers",
|
||||
|
||||
"Inside Mountain Secret Area Rainbow Squares",
|
||||
"Inside Mountain Secret Area Squares & Stars and Colored Eraser",
|
||||
"Inside Mountain Secret Area Rotated Broken Shapers",
|
||||
"Inside Mountain Secret Area Stars and Squares",
|
||||
"Inside Mountain Secret Area Lone Pillar",
|
||||
"Inside Mountain Secret Area Wooden Beam Shapers",
|
||||
"Inside Mountain Secret Area Wooden Beam Squares and Shapers",
|
||||
"Inside Mountain Secret Area Wooden Beam Shapers and Squares",
|
||||
"Inside Mountain Secret Area Wooden Beam Shapers and Stars",
|
||||
"Inside Mountain Secret Area Upstairs Invisible Dots 8",
|
||||
"Inside Mountain Secret Area Upstairs Invisible Dot Symmetry 3",
|
||||
"Inside Mountain Secret Area Upstairs Dot Grid Shapers",
|
||||
"Inside Mountain Secret Area Upstairs Dot Grid Rotated Shapers",
|
||||
|
||||
"Challenge Vault Box",
|
||||
"Theater Walkway Vault Box",
|
||||
"Inside Mountain Bottom Layer Discard",
|
||||
"Theater Challenge Video",
|
||||
}
|
||||
|
||||
ALL_LOCATIONS_TO_ID = dict()
|
||||
|
||||
@staticmethod
|
||||
def get_id(chex):
|
||||
"""
|
||||
Calculates the location ID for any given location
|
||||
"""
|
||||
|
||||
panel_offset = StaticWitnessLogic.CHECKS_BY_HEX[chex]["idOffset"]
|
||||
type_offset = StaticWitnessLocations.TYPE_OFFSETS[
|
||||
StaticWitnessLogic.CHECKS_BY_HEX[chex]["panelType"]
|
||||
]
|
||||
|
||||
return StaticWitnessLocations.ID_START + panel_offset + type_offset
|
||||
|
||||
@staticmethod
|
||||
def get_event_name(panel_hex):
|
||||
"""
|
||||
Returns the event name of any given panel.
|
||||
Currently this is always "Panelname Solved"
|
||||
"""
|
||||
|
||||
return StaticWitnessLogic.CHECKS_BY_HEX[panel_hex]["checkName"] + " Solved"
|
||||
|
||||
def __init__(self):
|
||||
all_loc_to_id = {
|
||||
panel_obj["checkName"]: self.get_id(chex)
|
||||
for chex, panel_obj in StaticWitnessLogic.CHECKS_BY_HEX.items()
|
||||
}
|
||||
|
||||
all_loc_to_id = dict(
|
||||
sorted(all_loc_to_id.items(), key=lambda loc: loc[1])
|
||||
)
|
||||
|
||||
for key, item in all_loc_to_id.items():
|
||||
self.ALL_LOCATIONS_TO_ID[key] = item
|
||||
|
||||
|
||||
class WitnessPlayerLocations:
|
||||
"""
|
||||
Class that defines locations for a single player
|
||||
"""
|
||||
|
||||
def __init__(self, world, player, player_logic: WitnessPlayerLogic):
|
||||
self.PANEL_TYPES_TO_SHUFFLE = {"General", "Laser"}
|
||||
self.CHECK_LOCATIONS = (
|
||||
StaticWitnessLocations.GENERAL_LOCATIONS
|
||||
)
|
||||
|
||||
"""Defines locations AFTER logic changes due to options"""
|
||||
|
||||
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
|
||||
|
||||
if is_option_enabled(world, player, "shuffle_hard"):
|
||||
self.CHECK_LOCATIONS = self.CHECK_LOCATIONS | StaticWitnessLocations.HARD_LOCATIONS
|
||||
|
||||
self.CHECK_LOCATIONS = self.CHECK_LOCATIONS | player_logic.ADDED_CHECKS
|
||||
|
||||
self.CHECK_LOCATIONS = self.CHECK_LOCATIONS - {
|
||||
StaticWitnessLogic.CHECKS_BY_HEX[check_hex]["checkName"]
|
||||
for check_hex in player_logic.COMPLETELY_DISABLED_CHECKS
|
||||
}
|
||||
|
||||
self.CHECK_PANELHEX_TO_ID = {
|
||||
StaticWitnessLogic.CHECKS_BY_NAME[ch]["checkHex"]: StaticWitnessLocations.ALL_LOCATIONS_TO_ID[ch]
|
||||
for ch in self.CHECK_LOCATIONS
|
||||
}
|
||||
|
||||
self.CHECK_PANELHEX_TO_ID = dict(
|
||||
sorted(self.CHECK_PANELHEX_TO_ID.items(), key=lambda item: item[1])
|
||||
)
|
||||
|
||||
event_locations = {
|
||||
p for p in player_logic.NECESSARY_EVENT_PANELS
|
||||
if StaticWitnessLogic.CHECKS_BY_HEX[p]["checkName"]
|
||||
not in self.CHECK_LOCATIONS
|
||||
or p in player_logic.ALWAYS_EVENT_HEX_CODES
|
||||
}
|
||||
|
||||
self.EVENT_LOCATION_TABLE = {
|
||||
StaticWitnessLocations.get_event_name(panel_hex): None
|
||||
for panel_hex in event_locations
|
||||
}
|
||||
|
||||
check_dict = {
|
||||
location: StaticWitnessLocations.get_id(StaticWitnessLogic.CHECKS_BY_NAME[location]["checkHex"])
|
||||
for location in self.CHECK_LOCATIONS
|
||||
if StaticWitnessLogic.CHECKS_BY_NAME[location]["panelType"] in self.PANEL_TYPES_TO_SHUFFLE
|
||||
}
|
||||
|
||||
self.CHECK_LOCATION_TABLE = {**self.EVENT_LOCATION_TABLE, **check_dict}
|
|
@ -0,0 +1,287 @@
|
|||
"""
|
||||
Parses the WitnessLogic.txt logic file into useful data structures.
|
||||
This is the heart of the randomization.
|
||||
|
||||
In WitnessLogic.txt we have regions defined with their connections:
|
||||
|
||||
Region Name (Short name) - Connected Region 1 - Connection Requirement 1 - Connected Region 2...
|
||||
|
||||
And then panels in that region with the hex code used in the game
|
||||
previous panels that are required to turn them on, as well as the symbols they require:
|
||||
|
||||
0x##### (Panel Name) - Required Panels - Required Items
|
||||
|
||||
On __init__, the base logic is read and all panels are given Location IDs.
|
||||
When the world has parsed its options, a second function is called to finalize the logic.
|
||||
"""
|
||||
|
||||
import copy
|
||||
from BaseClasses import MultiWorld
|
||||
from .static_logic import StaticWitnessLogic
|
||||
from .utils import define_new_region, get_disable_unrandomized_list, parse_lambda
|
||||
from .Options import is_option_enabled
|
||||
|
||||
|
||||
class WitnessPlayerLogic:
|
||||
"""WITNESS LOGIC CLASS"""
|
||||
|
||||
def reduce_req_within_region(self, panel_hex):
|
||||
"""
|
||||
Panels in this game often only turn on when other panels are solved.
|
||||
Those other panels may have different item requirements.
|
||||
It would be slow to recursively check solvability each time.
|
||||
This is why we reduce the item dependencies within the region.
|
||||
Panels outside of the same region will still be checked manually.
|
||||
"""
|
||||
|
||||
if self.DEPENDENT_REQUIREMENTS_BY_HEX[panel_hex]["panels"] == frozenset({frozenset()}):
|
||||
return self.DEPENDENT_REQUIREMENTS_BY_HEX[panel_hex]["items"]
|
||||
|
||||
all_options = set()
|
||||
|
||||
these_items = self.DEPENDENT_REQUIREMENTS_BY_HEX[panel_hex]["items"]
|
||||
these_panels = self.DEPENDENT_REQUIREMENTS_BY_HEX[panel_hex]["panels"]
|
||||
check_obj = StaticWitnessLogic.CHECKS_BY_HEX[panel_hex]
|
||||
|
||||
for option in these_panels:
|
||||
dependent_items_for_option = frozenset({frozenset()})
|
||||
|
||||
for option_panel in option:
|
||||
new_items = set()
|
||||
dep_obj = StaticWitnessLogic.CHECKS_BY_HEX.get(option_panel)
|
||||
if option_panel in {"7 Lasers", "11 Lasers"}:
|
||||
new_items = frozenset({frozenset([option_panel])})
|
||||
# If a panel turns on when a panel in a different region turns on,
|
||||
# the latter panel will be an "event panel", unless it ends up being
|
||||
# a location itself. This prevents generation failures.
|
||||
elif dep_obj["region"]["name"] != check_obj["region"]["name"]:
|
||||
new_items = frozenset({frozenset([option_panel])})
|
||||
self.EVENT_PANELS_FROM_PANELS.add(option_panel)
|
||||
else:
|
||||
new_items = self.reduce_req_within_region(option_panel)
|
||||
|
||||
updated_items = set()
|
||||
|
||||
for items_option in dependent_items_for_option:
|
||||
for items_option2 in new_items:
|
||||
updated_items.add(items_option.union(items_option2))
|
||||
|
||||
dependent_items_for_option = updated_items
|
||||
|
||||
for items_option in these_items:
|
||||
for dependentItem in dependent_items_for_option:
|
||||
all_options.add(items_option.union(dependentItem))
|
||||
|
||||
return frozenset(all_options)
|
||||
|
||||
def make_single_adjustment(self, adj_type, line):
|
||||
"""Makes a single logic adjustment based on additional logic file"""
|
||||
|
||||
if adj_type == "Event Items":
|
||||
line_split = line.split(" - ")
|
||||
hex_set = line_split[1].split(",")
|
||||
|
||||
for hex_code in hex_set:
|
||||
self.ALWAYS_EVENT_NAMES_BY_HEX[hex_code] = line_split[0]
|
||||
|
||||
"""
|
||||
Should probably do this differently...
|
||||
Events right now depend on a panel.
|
||||
That seems bad.
|
||||
"""
|
||||
|
||||
to_remove = set()
|
||||
|
||||
for hex_code, event_name in self.ALWAYS_EVENT_NAMES_BY_HEX.items():
|
||||
if hex_code not in hex_set and event_name == line_split[0]:
|
||||
to_remove.add(hex_code)
|
||||
|
||||
for remove in to_remove:
|
||||
del self.ALWAYS_EVENT_NAMES_BY_HEX[remove]
|
||||
|
||||
return
|
||||
|
||||
if adj_type == "Requirement Changes":
|
||||
line_split = line.split(" - ")
|
||||
|
||||
required_items = parse_lambda(line_split[2])
|
||||
items_actually_in_the_game = {item[0] for item in StaticWitnessLogic.ALL_ITEMS}
|
||||
required_items = frozenset(
|
||||
subset.intersection(items_actually_in_the_game)
|
||||
for subset in required_items
|
||||
)
|
||||
|
||||
requirement = {
|
||||
"panels": parse_lambda(line_split[1]),
|
||||
"items": required_items
|
||||
}
|
||||
|
||||
self.DEPENDENT_REQUIREMENTS_BY_HEX[line_split[0]] = requirement
|
||||
|
||||
return
|
||||
|
||||
if adj_type == "Disabled Locations":
|
||||
self.COMPLETELY_DISABLED_CHECKS.add(line[:7])
|
||||
|
||||
return
|
||||
|
||||
if adj_type == "Region Changes":
|
||||
new_region_and_options = define_new_region(line + ":")
|
||||
|
||||
self.CONNECTIONS_BY_REGION_NAME[new_region_and_options[0]["name"]] = new_region_and_options[1]
|
||||
|
||||
return
|
||||
|
||||
if adj_type == "Added Locations":
|
||||
self.ADDED_CHECKS.add(line)
|
||||
|
||||
def make_options_adjustments(self, world, player):
|
||||
"""Makes logic adjustments based on options"""
|
||||
adjustment_linesets_in_order = []
|
||||
|
||||
if is_option_enabled(world, player, "challenge_victory"):
|
||||
self.VICTORY_LOCATION = "0x0356B"
|
||||
else:
|
||||
self.VICTORY_LOCATION = "0x3D9A9"
|
||||
|
||||
self.COMPLETELY_DISABLED_CHECKS.add(
|
||||
self.VICTORY_LOCATION
|
||||
)
|
||||
|
||||
if is_option_enabled(world, player, "disable_non_randomized_puzzles"):
|
||||
adjustment_linesets_in_order.append(get_disable_unrandomized_list())
|
||||
|
||||
for adjustment_lineset in adjustment_linesets_in_order:
|
||||
current_adjustment_type = None
|
||||
|
||||
for line in adjustment_lineset:
|
||||
if len(line) == 0:
|
||||
continue
|
||||
|
||||
if line[-1] == ":":
|
||||
current_adjustment_type = line[:-1]
|
||||
continue
|
||||
|
||||
self.make_single_adjustment(current_adjustment_type, line)
|
||||
|
||||
def make_dependency_reduced_checklist(self):
|
||||
"""
|
||||
Turns dependent check set into semi-independent check set
|
||||
"""
|
||||
|
||||
for check_hex in self.DEPENDENT_REQUIREMENTS_BY_HEX.keys():
|
||||
indep_requirement = self.reduce_req_within_region(check_hex)
|
||||
|
||||
self.REQUIREMENTS_BY_HEX[check_hex] = indep_requirement
|
||||
|
||||
def make_event_item_pair(self, panel):
|
||||
"""
|
||||
Makes a pair of an event panel and its event item
|
||||
"""
|
||||
name = StaticWitnessLogic.CHECKS_BY_HEX[panel]["checkName"] + " Solved"
|
||||
pair = (name, self.EVENT_ITEM_NAMES[panel])
|
||||
return pair
|
||||
|
||||
def make_event_panel_lists(self):
|
||||
"""
|
||||
Special event panel data structures
|
||||
"""
|
||||
|
||||
for region_conn in self.CONNECTIONS_BY_REGION_NAME.values():
|
||||
for region_and_option in region_conn:
|
||||
for panelset in region_and_option[1]:
|
||||
for panel in panelset:
|
||||
self.EVENT_PANELS_FROM_REGIONS.add(panel)
|
||||
|
||||
self.ALWAYS_EVENT_NAMES_BY_HEX[self.VICTORY_LOCATION] = "Victory"
|
||||
|
||||
self.ORIGINAL_EVENT_PANELS.update(self.EVENT_PANELS_FROM_PANELS)
|
||||
self.ORIGINAL_EVENT_PANELS.update(self.EVENT_PANELS_FROM_REGIONS)
|
||||
self.NECESSARY_EVENT_PANELS.update(self.EVENT_PANELS_FROM_PANELS)
|
||||
|
||||
for panel in self.EVENT_PANELS_FROM_REGIONS:
|
||||
for region_name, region in StaticWitnessLogic.ALL_REGIONS_BY_NAME.items():
|
||||
for connection in self.CONNECTIONS_BY_REGION_NAME[region_name]:
|
||||
connected_r = connection[0]
|
||||
if connected_r not in StaticWitnessLogic.ALL_REGIONS_BY_NAME:
|
||||
continue
|
||||
if region_name == "Boat" or connected_r == "Boat":
|
||||
continue
|
||||
connected_r = StaticWitnessLogic.ALL_REGIONS_BY_NAME[connected_r]
|
||||
if not any([panel in option for option in connection[1]]):
|
||||
continue
|
||||
if panel not in region["panels"] | connected_r["panels"]:
|
||||
self.NECESSARY_EVENT_PANELS.add(panel)
|
||||
|
||||
for always_hex, always_item in self.ALWAYS_EVENT_NAMES_BY_HEX.items():
|
||||
self.ALWAYS_EVENT_HEX_CODES.add(always_hex)
|
||||
self.NECESSARY_EVENT_PANELS.add(always_hex)
|
||||
self.EVENT_ITEM_NAMES[always_hex] = always_item
|
||||
|
||||
for panel in self.NECESSARY_EVENT_PANELS:
|
||||
pair = self.make_event_item_pair(panel)
|
||||
self.EVENT_ITEM_PAIRS[pair[0]] = pair[1]
|
||||
|
||||
def __init__(self, world: MultiWorld, player: int):
|
||||
self.EVENT_PANELS_FROM_PANELS = set()
|
||||
self.EVENT_PANELS_FROM_REGIONS = set()
|
||||
|
||||
self.CONNECTIONS_BY_REGION_NAME = copy.copy(StaticWitnessLogic.STATIC_CONNECTIONS_BY_REGION_NAME)
|
||||
self.DEPENDENT_REQUIREMENTS_BY_HEX = copy.copy(StaticWitnessLogic.STATIC_DEPENDENT_REQUIREMENTS_BY_HEX)
|
||||
self.REQUIREMENTS_BY_HEX = dict()
|
||||
|
||||
# Determining which panels need to be events is a difficult process.
|
||||
# At the end, we will have EVENT_ITEM_PAIRS for all the necessary ones.
|
||||
self.ORIGINAL_EVENT_PANELS = set()
|
||||
self.NECESSARY_EVENT_PANELS = set()
|
||||
self.EVENT_ITEM_PAIRS = dict()
|
||||
self.ALWAYS_EVENT_HEX_CODES = set()
|
||||
self.COMPLETELY_DISABLED_CHECKS = set()
|
||||
self.ADDED_CHECKS = set()
|
||||
self.VICTORY_LOCATION = "0x0356B"
|
||||
self.EVENT_ITEM_NAMES = {
|
||||
"0x01A0F": "Keep Laser Panel (Hedge Mazes) Activates",
|
||||
"0x09D9B": "Monastery Overhead Doors Open",
|
||||
"0x193A6": "Monastery Laser Panel Activates",
|
||||
"0x00037": "Monastery Branch Panels Activate",
|
||||
"0x0A079": "Access to Bunker Laser",
|
||||
"0x0A3B5": "Door to Tutorial Discard Opens",
|
||||
"0x01D3F": "Keep Laser Panel (Pressure Plates) Activates",
|
||||
"0x09F7F": "Mountain Access",
|
||||
"0x0367C": "Quarry Laser Mill Requirement Met",
|
||||
"0x009A1": "Swamp Rotating Bridge Near Side",
|
||||
"0x00006": "Swamp Cyan Water Drains",
|
||||
"0x00990": "Swamp Broken Shapers 1 Activates",
|
||||
"0x0A8DC": "Lower Avoid 6 Activates",
|
||||
"0x0000A": "Swamp More Rotated Shapers 1 Access",
|
||||
"0x09ED8": "Inside Mountain Second Layer Both Light Bridges Solved",
|
||||
"0x0A3D0": "Quarry Laser Boathouse Requirement Met",
|
||||
"0x00596": "Swamp Red Water Drains",
|
||||
"0x28B39": "Town Tower 4th Door Opens"
|
||||
}
|
||||
|
||||
self.ALWAYS_EVENT_NAMES_BY_HEX = {
|
||||
"0x0360D": "Symmetry Laser Activation",
|
||||
"0x03608": "Desert Laser Activation",
|
||||
"0x09F98": "Desert Laser Redirection",
|
||||
"0x03612": "Quarry Laser Activation",
|
||||
"0x19650": "Shadows Laser Activation",
|
||||
"0x0360E": "Keep Laser Hedges Activation",
|
||||
"0x03317": "Keep Laser Pressure Plates Activation",
|
||||
"0x17CA4": "Monastery Laser Activation",
|
||||
"0x032F5": "Town Laser Activation",
|
||||
"0x03616": "Jungle Laser Activation",
|
||||
"0x09DE0": "Bunker Laser Activation",
|
||||
"0x03615": "Swamp Laser Activation",
|
||||
"0x03613": "Treehouse Laser Activation",
|
||||
"0x03535": "Shipwreck Video Pattern Knowledge",
|
||||
"0x03542": "Mountain Video Pattern Knowledge",
|
||||
"0x0339E": "Desert Video Pattern Knowledge",
|
||||
"0x03481": "Tutorial Video Pattern Knowledge",
|
||||
"0x03702": "Jungle Video Pattern Knowledge",
|
||||
"0x2FAF6": "Theater Walkway Video Pattern Knowledge",
|
||||
}
|
||||
|
||||
self.make_options_adjustments(world, player)
|
||||
self.make_dependency_reduced_checklist()
|
||||
self.make_event_panel_lists()
|
|
@ -0,0 +1,89 @@
|
|||
"""
|
||||
Defines Region for The Witness, assigns locations to them,
|
||||
and connects them with the proper requirements
|
||||
"""
|
||||
|
||||
from BaseClasses import MultiWorld, Entrance
|
||||
from . import StaticWitnessLogic
|
||||
from .locations import WitnessPlayerLocations
|
||||
from .player_logic import WitnessPlayerLogic
|
||||
|
||||
|
||||
class WitnessRegions:
|
||||
"""Class that defines Witness Regions"""
|
||||
|
||||
locat = None
|
||||
logic = None
|
||||
|
||||
def make_lambda(self, panel_hex_to_solve_set, world, player, player_logic):
|
||||
"""
|
||||
Lambdas are made in a for loop, so the values have to be captured
|
||||
This function is for that purpose
|
||||
"""
|
||||
|
||||
return lambda state: state._witness_can_solve_panels(
|
||||
panel_hex_to_solve_set, world, player, player_logic, self.locat
|
||||
)
|
||||
|
||||
def connect(self, world: MultiWorld, player: int, source: str, target: str, player_logic: WitnessPlayerLogic,
|
||||
panel_hex_to_solve_set=None):
|
||||
"""
|
||||
connect two regions and set the corresponding requirement
|
||||
"""
|
||||
source_region = world.get_region(source, player)
|
||||
target_region = world.get_region(target, player)
|
||||
|
||||
connection = Entrance(
|
||||
player,
|
||||
source + " to " + target + " via " + str(panel_hex_to_solve_set),
|
||||
source_region
|
||||
)
|
||||
|
||||
connection.access_rule = self.make_lambda(panel_hex_to_solve_set, world, player, player_logic)
|
||||
|
||||
source_region.exits.append(connection)
|
||||
connection.connect(target_region)
|
||||
|
||||
def create_regions(self, world, player: int, player_logic: WitnessPlayerLogic):
|
||||
"""
|
||||
Creates all the regions for The Witness
|
||||
"""
|
||||
from . import create_region
|
||||
|
||||
world.regions += [
|
||||
create_region(world, player, 'Menu', self.locat, None, ["The Splashscreen?"]),
|
||||
]
|
||||
|
||||
all_locations = set()
|
||||
|
||||
for region_name, region in StaticWitnessLogic.ALL_REGIONS_BY_NAME.items():
|
||||
locations_for_this_region = [
|
||||
StaticWitnessLogic.CHECKS_BY_HEX[panel]["checkName"] for panel in region["panels"]
|
||||
if StaticWitnessLogic.CHECKS_BY_HEX[panel]["checkName"] in self.locat.CHECK_LOCATION_TABLE
|
||||
]
|
||||
locations_for_this_region += [
|
||||
StaticWitnessLogic.CHECKS_BY_HEX[panel]["checkName"] + " Solved" for panel in region["panels"]
|
||||
if StaticWitnessLogic.CHECKS_BY_HEX[panel]["checkName"] + " Solved" in self.locat.EVENT_LOCATION_TABLE
|
||||
]
|
||||
|
||||
all_locations = all_locations | set(locations_for_this_region)
|
||||
|
||||
world.regions += [
|
||||
create_region(world, player, region_name, self.locat,locations_for_this_region)
|
||||
]
|
||||
|
||||
for region_name, region in StaticWitnessLogic.ALL_REGIONS_BY_NAME.items():
|
||||
for connection in player_logic.CONNECTIONS_BY_REGION_NAME[region_name]:
|
||||
if connection[0] == "Entry":
|
||||
continue
|
||||
self.connect(world, player, region_name,
|
||||
connection[0], player_logic, connection[1])
|
||||
self.connect(world, player, connection[0],
|
||||
region_name, player_logic, connection[1])
|
||||
|
||||
world.get_entrance("The Splashscreen?", player).connect(
|
||||
world.get_region('First Hallway', player)
|
||||
)
|
||||
|
||||
def __init__(self, locat: WitnessPlayerLocations):
|
||||
self.locat = locat
|
|
@ -0,0 +1,171 @@
|
|||
"""
|
||||
Defines the rules by which locations can be accessed,
|
||||
depending on the items received
|
||||
"""
|
||||
|
||||
# pylint: disable=E1101
|
||||
|
||||
from BaseClasses import MultiWorld
|
||||
from .player_logic import WitnessPlayerLogic
|
||||
from .Options import is_option_enabled
|
||||
from .locations import WitnessPlayerLocations
|
||||
from . import StaticWitnessLogic
|
||||
from ..AutoWorld import LogicMixin
|
||||
from ..generic.Rules import set_rule
|
||||
|
||||
|
||||
class WitnessLogic(LogicMixin):
|
||||
"""
|
||||
Logic macros that get reused
|
||||
"""
|
||||
|
||||
def _witness_has_lasers(self, world, player: int, amount: int) -> bool:
|
||||
lasers = 0
|
||||
|
||||
lasers += int(self.has("Symmetry Laser Activation", player))
|
||||
lasers += int(self.has("Desert Laser Activation", player)
|
||||
and self.has("Desert Laser Redirection", player))
|
||||
lasers += int(self.has("Town Laser Activation", player))
|
||||
lasers += int(self.has("Monastery Laser Activation", player))
|
||||
lasers += int(self.has("Keep Laser Pressure Plates Activation", player) and (
|
||||
is_option_enabled(world, player, "disable_non_randomized_puzzles")
|
||||
or self.has("Keep Laser Hedges Activation", player)
|
||||
))
|
||||
lasers += int(self.has("Quarry Laser Activation", player))
|
||||
lasers += int(self.has("Treehouse Laser Activation", player))
|
||||
lasers += int(self.has("Jungle Laser Activation", player))
|
||||
lasers += int(self.has("Bunker Laser Activation", player))
|
||||
lasers += int(self.has("Swamp Laser Activation", player))
|
||||
lasers += int(self.has("Shadows Laser Activation", player))
|
||||
|
||||
return lasers >= amount
|
||||
|
||||
def _witness_can_solve_panel(self, panel, world, player, player_logic: WitnessPlayerLogic, locat):
|
||||
"""
|
||||
Determines whether a panel can be solved
|
||||
"""
|
||||
|
||||
panel_obj = StaticWitnessLogic.CHECKS_BY_HEX[panel]
|
||||
check_name = panel_obj["checkName"]
|
||||
|
||||
if (check_name + " Solved" in locat.EVENT_LOCATION_TABLE
|
||||
and not self.has(player_logic.EVENT_ITEM_PAIRS[check_name + " Solved"], player)):
|
||||
return False
|
||||
if panel not in player_logic.ORIGINAL_EVENT_PANELS and not self.can_reach(check_name, "Location", player):
|
||||
return False
|
||||
if (panel in player_logic.ORIGINAL_EVENT_PANELS
|
||||
and check_name + " Solved" not in locat.EVENT_LOCATION_TABLE
|
||||
and not self._witness_safe_manual_panel_check(panel, world, player, player_logic, locat)):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _witness_meets_item_requirements(self, panel, world, player, player_logic: WitnessPlayerLogic, locat):
|
||||
"""
|
||||
Checks whether item and panel requirements are met for
|
||||
a panel
|
||||
"""
|
||||
|
||||
panel_req = player_logic.REQUIREMENTS_BY_HEX[panel]
|
||||
|
||||
for option in panel_req:
|
||||
if len(option) == 0:
|
||||
return True
|
||||
|
||||
valid_option = True
|
||||
|
||||
for item in option:
|
||||
if item == "7 Lasers":
|
||||
if not self._witness_has_lasers(world, player, 7):
|
||||
valid_option = False
|
||||
break
|
||||
elif item == "11 Lasers":
|
||||
if not self._witness_has_lasers(world, player, 11):
|
||||
valid_option = False
|
||||
break
|
||||
elif item in player_logic.NECESSARY_EVENT_PANELS:
|
||||
if StaticWitnessLogic.CHECKS_BY_HEX[item]["checkName"] + " Solved" in locat.EVENT_LOCATION_TABLE:
|
||||
valid_option = self.has(player_logic.EVENT_ITEM_NAMES[item], player)
|
||||
else:
|
||||
valid_option = self.can_reach(
|
||||
StaticWitnessLogic.CHECKS_BY_HEX[item]["checkName"], "Location", player
|
||||
)
|
||||
if not valid_option:
|
||||
break
|
||||
elif not self.has(item, player):
|
||||
valid_option = False
|
||||
break
|
||||
|
||||
if valid_option:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _witness_safe_manual_panel_check(self, panel, world, player, player_logic: WitnessPlayerLogic, locat):
|
||||
"""
|
||||
nested can_reach can cause problems, but only if the region being
|
||||
checked is neither of the two original regions from the first
|
||||
can_reach.
|
||||
A nested can_reach is okay here because the only panels this
|
||||
function is called on are panels that exist on either side of all
|
||||
connections they are required for.
|
||||
The spoiler log looks so much nicer this way,
|
||||
it gets rid of a bunch of event items, only leaving a couple. :)
|
||||
"""
|
||||
region = StaticWitnessLogic.CHECKS_BY_HEX[panel]["region"]["name"]
|
||||
|
||||
return (
|
||||
self._witness_meets_item_requirements(panel, world, player, player_logic, locat)
|
||||
and self.can_reach(region, "Region", player)
|
||||
)
|
||||
|
||||
def _witness_can_solve_panels(self, panel_hex_to_solve_set, world, player, player_logic: WitnessPlayerLogic, locat):
|
||||
"""
|
||||
Checks whether a set of panels can be solved.
|
||||
"""
|
||||
|
||||
for option in panel_hex_to_solve_set:
|
||||
if len(option) == 0:
|
||||
return True
|
||||
|
||||
valid_option = True
|
||||
|
||||
for panel in option:
|
||||
if not self._witness_can_solve_panel(panel, world, player, player_logic, locat):
|
||||
valid_option = False
|
||||
break
|
||||
|
||||
if valid_option:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def make_lambda(check_hex, world, player, player_logic, locat):
|
||||
"""
|
||||
Lambdas are created in a for loop so values need to be captured
|
||||
"""
|
||||
return lambda state: state._witness_meets_item_requirements(
|
||||
check_hex, world, player, player_logic, locat
|
||||
)
|
||||
|
||||
|
||||
def set_rules(world: MultiWorld, player: int, player_logic: WitnessPlayerLogic, locat: WitnessPlayerLocations):
|
||||
"""
|
||||
Sets all rules for all locations
|
||||
"""
|
||||
|
||||
for location in locat.CHECK_LOCATION_TABLE:
|
||||
real_location = location
|
||||
|
||||
if location in locat.EVENT_LOCATION_TABLE:
|
||||
real_location = location[:-7]
|
||||
|
||||
panel = StaticWitnessLogic.CHECKS_BY_NAME[real_location]
|
||||
check_hex = panel["checkHex"]
|
||||
|
||||
rule = make_lambda(check_hex, world, player, player_logic, locat)
|
||||
|
||||
set_rule(world.get_location(location, player), rule)
|
||||
|
||||
world.completion_condition[player] = \
|
||||
lambda state: state.has('Victory', player)
|
|
@ -0,0 +1,138 @@
|
|||
import os
|
||||
|
||||
from .utils import define_new_region, parse_lambda
|
||||
|
||||
|
||||
class StaticWitnessLogic:
|
||||
ALL_ITEMS = set()
|
||||
ALL_TRAPS = set()
|
||||
ALL_BOOSTS = set()
|
||||
|
||||
EVENT_PANELS_FROM_REGIONS = set()
|
||||
|
||||
# All regions with a list of panels in them and the connections to other regions, before logic adjustments
|
||||
ALL_REGIONS_BY_NAME = dict()
|
||||
STATIC_CONNECTIONS_BY_REGION_NAME = dict()
|
||||
|
||||
CHECKS_BY_HEX = dict()
|
||||
CHECKS_BY_NAME = dict()
|
||||
STATIC_DEPENDENT_REQUIREMENTS_BY_HEX = dict()
|
||||
|
||||
def parse_items(self):
|
||||
"""
|
||||
Parses currently defined items from WitnessItems.txt
|
||||
"""
|
||||
|
||||
path = os.path.join(os.path.dirname(__file__), "WitnessItems.txt")
|
||||
with open(path, "r", encoding="utf-8") as file:
|
||||
current_set = self.ALL_ITEMS
|
||||
|
||||
for line in file.readlines():
|
||||
line = line.strip()
|
||||
|
||||
if line == "Progression:":
|
||||
current_set = self.ALL_ITEMS
|
||||
continue
|
||||
if line == "Boosts:":
|
||||
current_set = self.ALL_BOOSTS
|
||||
continue
|
||||
if line == "Traps:":
|
||||
current_set = self.ALL_TRAPS
|
||||
continue
|
||||
if line == "":
|
||||
continue
|
||||
|
||||
line_split = line.split(" - ")
|
||||
|
||||
current_set.add((line_split[1], int(line_split[0])))
|
||||
|
||||
def read_logic_file(self):
|
||||
"""
|
||||
Reads the logic file and does the initial population of data structures
|
||||
"""
|
||||
path = os.path.join(os.path.dirname(__file__), "WitnessLogic.txt")
|
||||
with open(path, "r", encoding="utf-8") as file:
|
||||
current_region = ""
|
||||
|
||||
discard_ids = 0
|
||||
normal_panel_ids = 0
|
||||
vault_ids = 0
|
||||
laser_ids = 0
|
||||
|
||||
for line in file.readlines():
|
||||
line = line.strip()
|
||||
|
||||
if line == "":
|
||||
continue
|
||||
|
||||
if line[0] != "0":
|
||||
new_region_and_connections = define_new_region(line)
|
||||
current_region = new_region_and_connections[0]
|
||||
region_name = current_region["name"]
|
||||
self.ALL_REGIONS_BY_NAME[region_name] = current_region
|
||||
self.STATIC_CONNECTIONS_BY_REGION_NAME[region_name] = new_region_and_connections[1]
|
||||
continue
|
||||
|
||||
line_split = line.split(" - ")
|
||||
|
||||
check_name_full = line_split.pop(0)
|
||||
|
||||
check_hex = check_name_full[0:7]
|
||||
check_name = check_name_full[9:-1]
|
||||
|
||||
required_panel_lambda = line_split.pop(0)
|
||||
required_item_lambda = line_split.pop(0)
|
||||
|
||||
laser_names = {
|
||||
"Laser",
|
||||
"Laser Hedges",
|
||||
"Laser Pressure Plates",
|
||||
"Desert Laser Redirect"
|
||||
}
|
||||
is_vault_or_video = "Vault" in check_name or "Video" in check_name
|
||||
|
||||
if "Discard" in check_name:
|
||||
location_type = "Discard"
|
||||
location_id = discard_ids
|
||||
discard_ids += 1
|
||||
elif is_vault_or_video or check_name == "Tutorial Gate Close":
|
||||
location_type = "Vault"
|
||||
location_id = vault_ids
|
||||
vault_ids += 1
|
||||
elif check_name in laser_names:
|
||||
location_type = "Laser"
|
||||
location_id = laser_ids
|
||||
laser_ids += 1
|
||||
else:
|
||||
location_type = "General"
|
||||
location_id = normal_panel_ids
|
||||
normal_panel_ids += 1
|
||||
|
||||
required_items = parse_lambda(required_item_lambda)
|
||||
items_actually_in_the_game = {item[0] for item in self.ALL_ITEMS}
|
||||
required_items = frozenset(
|
||||
subset.intersection(items_actually_in_the_game)
|
||||
for subset in required_items
|
||||
)
|
||||
|
||||
requirement = {
|
||||
"panels": parse_lambda(required_panel_lambda),
|
||||
"items": required_items
|
||||
}
|
||||
|
||||
self.CHECKS_BY_HEX[check_hex] = {
|
||||
"checkName": current_region["shortName"] + " " + check_name,
|
||||
"checkHex": check_hex,
|
||||
"region": current_region,
|
||||
"idOffset": location_id,
|
||||
"panelType": location_type
|
||||
}
|
||||
|
||||
self.CHECKS_BY_NAME[self.CHECKS_BY_HEX[check_hex]["checkName"]] = self.CHECKS_BY_HEX[check_hex]
|
||||
self.STATIC_DEPENDENT_REQUIREMENTS_BY_HEX[check_hex] = requirement
|
||||
|
||||
current_region["panels"].add(check_hex)
|
||||
|
||||
def __init__(self):
|
||||
self.parse_items()
|
||||
self.read_logic_file()
|
|
@ -0,0 +1,58 @@
|
|||
import os
|
||||
from Utils import cache_argsless
|
||||
|
||||
|
||||
def define_new_region(region_string):
|
||||
"""
|
||||
Returns a region object by parsing a line in the logic file
|
||||
"""
|
||||
|
||||
region_string = region_string[:-1]
|
||||
line_split = region_string.split(" - ")
|
||||
|
||||
region_name_full = line_split.pop(0)
|
||||
|
||||
region_name_split = region_name_full.split(" (")
|
||||
|
||||
region_name = region_name_split[0]
|
||||
region_name_simple = region_name_split[1][:-1]
|
||||
|
||||
options = set()
|
||||
|
||||
for _ in range(len(line_split) // 2):
|
||||
connected_region = line_split.pop(0)
|
||||
corresponding_lambda = line_split.pop(0)
|
||||
|
||||
options.add(
|
||||
(connected_region, parse_lambda(corresponding_lambda))
|
||||
)
|
||||
|
||||
region_obj = {
|
||||
"name": region_name,
|
||||
"shortName": region_name_simple,
|
||||
"panels": set()
|
||||
}
|
||||
return region_obj, options
|
||||
|
||||
|
||||
def parse_lambda(lambda_string):
|
||||
"""
|
||||
Turns a lambda String literal like this: a | b & c
|
||||
into a set of sets like this: {{a}, {b, c}}
|
||||
The lambda has to be in DNF.
|
||||
"""
|
||||
if lambda_string == "True":
|
||||
return frozenset([frozenset()])
|
||||
split_ands = set(lambda_string.split(" | "))
|
||||
lambda_set = frozenset({frozenset(a.split(" & ")) for a in split_ands})
|
||||
|
||||
return lambda_set
|
||||
|
||||
|
||||
@cache_argsless
|
||||
def get_disable_unrandomized_list():
|
||||
adjustment_file = "Disable_Unrandomized.txt"
|
||||
path = os.path.join(os.path.dirname(__file__), adjustment_file)
|
||||
|
||||
with open(path) as f:
|
||||
return [line.strip() for line in f.readlines()]
|
Loading…
Reference in New Issue