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:
NewSoupVi 2024-11-29 20:45:44 +01:00 committed by GitHub
parent a5231a27cc
commit b605fb1032
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 92 additions and 67 deletions

View File

@ -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

View File

@ -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")

View File

@ -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):

View File

@ -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())

View File

@ -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,

View File

@ -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))

View File

@ -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,