The Witness: Make Elevators Come To You an OptionSet (#4000)
* Split elevators come to you * . * unit test * mypy stuff * Fine. I'll fix the fcking commented out code. Happy? * ruff * """""Backwards compatibility""""" * ruff * make it look better * # * fix presets * fix a unit test * Make that explicit in the code * Improve description
This commit is contained in:
parent
a5231a27cc
commit
b605fb1032
|
@ -1,11 +0,0 @@
|
|||
New Connections:
|
||||
Quarry - Quarry Elevator - TrueOneWay
|
||||
Outside Quarry - Quarry Elevator - TrueOneWay
|
||||
Outside Bunker - Bunker Elevator - TrueOneWay
|
||||
Outside Swamp - Swamp Long Bridge - TrueOneWay
|
||||
Swamp Near Boat - Swamp Long Bridge - TrueOneWay
|
||||
Town Red Rooftop - Town Maze Rooftop - TrueOneWay
|
||||
|
||||
|
||||
Requirement Changes:
|
||||
0x035DE - 0x17E2B - True
|
|
@ -204,10 +204,6 @@ def get_caves_except_path_to_challenge_exclusion_list() -> List[str]:
|
|||
return get_adjustment_file("settings/Exclusions/Caves_Except_Path_To_Challenge.txt")
|
||||
|
||||
|
||||
def get_elevators_come_to_you() -> List[str]:
|
||||
return get_adjustment_file("settings/Door_Shuffle/Elevators_Come_To_You.txt")
|
||||
|
||||
|
||||
def get_entity_hunt() -> List[str]:
|
||||
return get_adjustment_file("settings/Entity_Hunt.txt")
|
||||
|
||||
|
|
|
@ -2,7 +2,18 @@ from dataclasses import dataclass
|
|||
|
||||
from schema import And, Schema
|
||||
|
||||
from Options import Choice, DefaultOnToggle, OptionDict, OptionGroup, PerGameCommonOptions, Range, Toggle, Visibility
|
||||
from Options import (
|
||||
Choice,
|
||||
DefaultOnToggle,
|
||||
OptionDict,
|
||||
OptionError,
|
||||
OptionGroup,
|
||||
OptionSet,
|
||||
PerGameCommonOptions,
|
||||
Range,
|
||||
Toggle,
|
||||
Visibility,
|
||||
)
|
||||
|
||||
from .data import static_logic as static_witness_logic
|
||||
from .data.item_definition_classes import ItemCategory, WeightedItemDefinition
|
||||
|
@ -294,12 +305,33 @@ class ChallengeLasers(Range):
|
|||
default = 11
|
||||
|
||||
|
||||
class ElevatorsComeToYou(Toggle):
|
||||
class ElevatorsComeToYou(OptionSet):
|
||||
"""
|
||||
If on, the Quarry Elevator, Bunker Elevator and Swamp Long Bridge will "come to you" if you approach them.
|
||||
This does actually affect logic as it allows unintended backwards / early access into these areas.
|
||||
In vanilla, some bridges/elevators come to you if you walk up to them when they are not currently there.
|
||||
However, there are some that don't. Notably, this prevents Quarry Elevator from being a logical access method into Quarry, because you can send it away without riding ot and then permanently be locked out of using it.
|
||||
|
||||
This option allows you to change specific elevators/bridges to "come to you" as well.
|
||||
|
||||
- Quarry Elevator: Makes the Quarry Elevator come down when you approach it from lower Quarry and back up when you approach it from above
|
||||
- Swamp Long Bridge: Rotates the side you approach it from towards you, but also rotates the other side away
|
||||
- Bunker Elevator: Makes the Bunker Elevator come to any floor that you approach it from, meaning it can be accessed from the roof immediately
|
||||
"""
|
||||
display_name = "All Bridges & Elevators come to you"
|
||||
|
||||
# Used to be a toggle
|
||||
@classmethod
|
||||
def from_text(cls, text: str):
|
||||
if text.lower() in {"off", "0", "false", "none", "null", "no"}:
|
||||
raise OptionError('elevators_come_to_you is an OptionSet now. The equivalent of "false" is {}')
|
||||
if text.lower() in {"on", "1", "true", "yes"}:
|
||||
raise OptionError(
|
||||
f'elevators_come_to_you is an OptionSet now. The equivalent of "true" is {set(cls.valid_keys)}'
|
||||
)
|
||||
return super().from_text(text)
|
||||
|
||||
display_name = "Elevators come to you"
|
||||
|
||||
valid_keys = frozenset({"Quarry Elevator", "Swamp Long Bridge", "Bunker Elevator"})
|
||||
default = frozenset({"Quarry Elevator"})
|
||||
|
||||
|
||||
class TrapPercentage(Range):
|
||||
|
|
|
@ -34,7 +34,6 @@ from .data.utils import (
|
|||
get_discard_exclusion_list,
|
||||
get_early_caves_list,
|
||||
get_early_caves_start_list,
|
||||
get_elevators_come_to_you,
|
||||
get_entity_hunt,
|
||||
get_ep_all_individual,
|
||||
get_ep_easy,
|
||||
|
@ -626,8 +625,29 @@ class WitnessPlayerLogic:
|
|||
if world.options.early_caves == "add_to_pool" and not remote_doors:
|
||||
adjustment_linesets_in_order.append(get_early_caves_list())
|
||||
|
||||
if world.options.elevators_come_to_you:
|
||||
adjustment_linesets_in_order.append(get_elevators_come_to_you())
|
||||
if "Quarry Elevator" in world.options.elevators_come_to_you:
|
||||
adjustment_linesets_in_order.append([
|
||||
"New Connections:",
|
||||
"Quarry - Quarry Elevator - TrueOneWay",
|
||||
"Outside Quarry - Quarry Elevator - TrueOneWay",
|
||||
])
|
||||
if "Bunker Elevator" in world.options.elevators_come_to_you:
|
||||
adjustment_linesets_in_order.append([
|
||||
"New Connections:",
|
||||
"Outside Bunker - Bunker Elevator - TrueOneWay",
|
||||
])
|
||||
if "Swamp Long Bridge" in world.options.elevators_come_to_you:
|
||||
adjustment_linesets_in_order.append([
|
||||
"New Connections:",
|
||||
"Outside Swamp - Swamp Long Bridge - TrueOneWay",
|
||||
"Swamp Near Boat - Swamp Long Bridge - TrueOneWay",
|
||||
"Requirement Changes:",
|
||||
"0x035DE - 0x17E2B - True", # Swamp Purple Sand Bottom EP
|
||||
])
|
||||
# if "Town Maze Rooftop Bridge" in world.options.elevators_come_to_you:
|
||||
# adjustment_linesets_in_order.append([
|
||||
# "New Connections:"
|
||||
# "Town Red Rooftop - Town Maze Rooftop - TrueOneWay"
|
||||
|
||||
if world.options.victory_condition == "panel_hunt":
|
||||
adjustment_linesets_in_order.append(get_entity_hunt())
|
||||
|
|
|
@ -35,7 +35,8 @@ witness_option_presets: Dict[str, Dict[str, Any]] = {
|
|||
"challenge_lasers": 11,
|
||||
|
||||
"early_caves": EarlyCaves.option_off,
|
||||
"elevators_come_to_you": False,
|
||||
|
||||
"elevators_come_to_you": ElevatorsComeToYou.default,
|
||||
|
||||
"trap_percentage": TrapPercentage.default,
|
||||
"puzzle_skip_amount": PuzzleSkipAmount.default,
|
||||
|
@ -73,7 +74,8 @@ witness_option_presets: Dict[str, Dict[str, Any]] = {
|
|||
"challenge_lasers": 9,
|
||||
|
||||
"early_caves": EarlyCaves.option_off,
|
||||
"elevators_come_to_you": False,
|
||||
|
||||
"elevators_come_to_you": ElevatorsComeToYou.default,
|
||||
|
||||
"trap_percentage": TrapPercentage.default,
|
||||
"puzzle_skip_amount": 15,
|
||||
|
@ -111,7 +113,8 @@ witness_option_presets: Dict[str, Dict[str, Any]] = {
|
|||
"challenge_lasers": 9,
|
||||
|
||||
"early_caves": EarlyCaves.option_off,
|
||||
"elevators_come_to_you": True,
|
||||
|
||||
"elevators_come_to_you": ElevatorsComeToYou.valid_keys,
|
||||
|
||||
"trap_percentage": TrapPercentage.default,
|
||||
"puzzle_skip_amount": 15,
|
||||
|
|
|
@ -1,49 +1,25 @@
|
|||
from ..test import WitnessMultiworldTestBase, WitnessTestBase
|
||||
|
||||
|
||||
class TestElevatorsComeToYou(WitnessTestBase):
|
||||
options = {
|
||||
"elevators_come_to_you": True,
|
||||
"shuffle_doors": "mixed",
|
||||
"shuffle_symbols": False,
|
||||
}
|
||||
|
||||
def test_bunker_laser(self) -> None:
|
||||
"""
|
||||
In elevators_come_to_you, Bunker can be entered from the back.
|
||||
This means that you can access the laser with just Bunker Elevator Control (Panel).
|
||||
It also means that you can, for example, access UV Room with the Control and the Elevator Room Entry Door.
|
||||
"""
|
||||
|
||||
self.assertFalse(self.multiworld.state.can_reach("Bunker Laser Panel", "Location", self.player))
|
||||
|
||||
self.collect_by_name("Bunker Elevator Control (Panel)")
|
||||
|
||||
self.assertTrue(self.multiworld.state.can_reach("Bunker Laser Panel", "Location", self.player))
|
||||
self.assertFalse(self.multiworld.state.can_reach("Bunker UV Room 2", "Location", self.player))
|
||||
|
||||
self.collect_by_name("Bunker Elevator Room Entry (Door)")
|
||||
self.collect_by_name("Bunker Drop-Down Door Controls (Panel)")
|
||||
|
||||
self.assertTrue(self.multiworld.state.can_reach("Bunker UV Room 2", "Location", self.player))
|
||||
from ..test import WitnessMultiworldTestBase
|
||||
|
||||
|
||||
class TestElevatorsComeToYouBleed(WitnessMultiworldTestBase):
|
||||
options_per_world = [
|
||||
{
|
||||
"elevators_come_to_you": False,
|
||||
"elevators_come_to_you": {},
|
||||
},
|
||||
{
|
||||
"elevators_come_to_you": True,
|
||||
"elevators_come_to_you": {"Quarry Elevator", "Swamp Long Bridge", "Bunker Elevator"},
|
||||
},
|
||||
{
|
||||
"elevators_come_to_you": False,
|
||||
"elevators_come_to_you": {}
|
||||
},
|
||||
]
|
||||
|
||||
common_options = {
|
||||
"shuffle_symbols": False,
|
||||
"shuffle_doors": "panels",
|
||||
"shuffle_boat": True,
|
||||
"shuffle_EPs": "individual",
|
||||
"obelisk_keys": False,
|
||||
}
|
||||
|
||||
def test_correct_access_per_player(self) -> None:
|
||||
|
@ -53,14 +29,22 @@ class TestElevatorsComeToYouBleed(WitnessMultiworldTestBase):
|
|||
(This is essentially a "does connection info bleed over" test).
|
||||
"""
|
||||
|
||||
self.assertFalse(self.multiworld.state.can_reach("Bunker Laser Panel", "Location", 1))
|
||||
self.assertFalse(self.multiworld.state.can_reach("Bunker Laser Panel", "Location", 2))
|
||||
self.assertFalse(self.multiworld.state.can_reach("Bunker Laser Panel", "Location", 3))
|
||||
combinations = [
|
||||
("Quarry Elevator Control (Panel)", "Quarry Boathouse Intro Left"),
|
||||
("Swamp Long Bridge (Panel)", "Swamp Long Bridge Side EP"),
|
||||
("Bunker Elevator Control (Panel)", "Bunker Laser Panel"),
|
||||
]
|
||||
|
||||
self.collect_by_name(["Bunker Elevator Control (Panel)"], 1)
|
||||
self.collect_by_name(["Bunker Elevator Control (Panel)"], 2)
|
||||
self.collect_by_name(["Bunker Elevator Control (Panel)"], 3)
|
||||
for item, location in combinations:
|
||||
with self.subTest(f"Test that {item} only locks {location} for player 2"):
|
||||
self.assertFalse(self.multiworld.state.can_reach_location(location, 1))
|
||||
self.assertFalse(self.multiworld.state.can_reach_location(location, 2))
|
||||
self.assertFalse(self.multiworld.state.can_reach_location(location, 3))
|
||||
|
||||
self.assertFalse(self.multiworld.state.can_reach("Bunker Laser Panel", "Location", 1))
|
||||
self.assertTrue(self.multiworld.state.can_reach("Bunker Laser Panel", "Location", 2))
|
||||
self.assertFalse(self.multiworld.state.can_reach("Bunker Laser Panel", "Location", 3))
|
||||
self.collect_by_name(item, 1)
|
||||
self.collect_by_name(item, 2)
|
||||
self.collect_by_name(item, 3)
|
||||
|
||||
self.assertFalse(self.multiworld.state.can_reach_location(location, 1))
|
||||
self.assertTrue(self.multiworld.state.can_reach_location(location, 2))
|
||||
self.assertFalse(self.multiworld.state.can_reach_location(location, 3))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from ..options import ElevatorsComeToYou
|
||||
from ..test import WitnessTestBase
|
||||
|
||||
# These are just some random options combinations, just to catch whether I broke anything obvious
|
||||
|
@ -19,7 +20,7 @@ class TestExpertNonRandomizedEPs(WitnessTestBase):
|
|||
class TestVanillaAutoElevatorsPanels(WitnessTestBase):
|
||||
options = {
|
||||
"puzzle_randomization": "none",
|
||||
"elevators_come_to_you": True,
|
||||
"elevators_come_to_you": ElevatorsComeToYou.valid_keys - ElevatorsComeToYou.default, # Opposite of default
|
||||
"shuffle_doors": "panels",
|
||||
"victory_condition": "mountain_box_short",
|
||||
"early_caves": True,
|
||||
|
|
Loading…
Reference in New Issue