The Witness: Fix Tunnels Theater Flower EP Access Logic + Add Unit Test for it (and Expert PP2) (#3807)
* Tunnels Theater Flowers fix + Flowers&PP2 Unit Tests * copypaste * Can just do it like this * This is even better probably * Also do some cleanup :3 * God damnit
This commit is contained in:
parent
9277cb39ef
commit
182f7e24e5
|
@ -74,10 +74,10 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
player = world.player
|
player = world.player
|
||||||
player_regions = world.player_regions
|
two_way_entrance_register = world.player_regions.two_way_entrance_register
|
||||||
|
|
||||||
front_access = (
|
front_access = (
|
||||||
any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 2nd Pressure Plate", "Keep"])
|
any(e.can_reach(state) for e in two_way_entrance_register["Keep 2nd Pressure Plate", "Keep"])
|
||||||
and state.can_reach_region("Keep", player)
|
and state.can_reach_region("Keep", player)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool:
|
||||||
# Front access works. Now, we need to check for the many ways to access PP2 from the back.
|
# Front access works. Now, we need to check for the many ways to access PP2 from the back.
|
||||||
# All of those ways lead through the PP3 exit door from PP4. So we check this first.
|
# All of those ways lead through the PP3 exit door from PP4. So we check this first.
|
||||||
|
|
||||||
fourth_to_third = any(e.can_reach(state) for e in player_regions.two_way_entrance_register[
|
fourth_to_third = any(e.can_reach(state) for e in two_way_entrance_register[
|
||||||
"Keep 3rd Pressure Plate", "Keep 4th Pressure Plate"
|
"Keep 3rd Pressure Plate", "Keep 4th Pressure Plate"
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool:
|
||||||
# The shadows shortcut is the simplest way.
|
# The shadows shortcut is the simplest way.
|
||||||
|
|
||||||
shadows_shortcut = (
|
shadows_shortcut = (
|
||||||
any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 4th Pressure Plate", "Shadows"])
|
any(e.can_reach(state) for e in two_way_entrance_register["Keep 4th Pressure Plate", "Shadows"])
|
||||||
)
|
)
|
||||||
|
|
||||||
if shadows_shortcut:
|
if shadows_shortcut:
|
||||||
|
@ -108,9 +108,7 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool:
|
||||||
|
|
||||||
# We don't have the Shadows shortcut. This means we need to come in through the PP4 exit door instead.
|
# We don't have the Shadows shortcut. This means we need to come in through the PP4 exit door instead.
|
||||||
|
|
||||||
tower_to_pp4 = any(
|
tower_to_pp4 = any(e.can_reach(state) for e in two_way_entrance_register["Keep 4th Pressure Plate", "Keep Tower"])
|
||||||
e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 4th Pressure Plate", "Keep Tower"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# If we don't have the PP4 exit door, we've run out of options.
|
# If we don't have the PP4 exit door, we've run out of options.
|
||||||
if not tower_to_pp4:
|
if not tower_to_pp4:
|
||||||
|
@ -119,7 +117,7 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool:
|
||||||
# We have the PP4 exit door. If we can get to Keep Tower from behind, we can do PP2.
|
# We have the PP4 exit door. If we can get to Keep Tower from behind, we can do PP2.
|
||||||
# The simplest way would be the Tower Shortcut.
|
# The simplest way would be the Tower Shortcut.
|
||||||
|
|
||||||
tower_shortcut = any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep", "Keep Tower"])
|
tower_shortcut = any(e.can_reach(state) for e in two_way_entrance_register["Keep", "Keep Tower"])
|
||||||
|
|
||||||
if tower_shortcut:
|
if tower_shortcut:
|
||||||
return True
|
return True
|
||||||
|
@ -128,18 +126,14 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool:
|
||||||
# Getting to Keep Tower through the hedge mazes. This can be done in a multitude of ways.
|
# Getting to Keep Tower through the hedge mazes. This can be done in a multitude of ways.
|
||||||
# No matter what, though, we would need Hedge Maze 4 Exit to Keep Tower.
|
# No matter what, though, we would need Hedge Maze 4 Exit to Keep Tower.
|
||||||
|
|
||||||
tower_access_from_hedges = any(
|
tower_access_from_hedges = any(e.can_reach(state) for e in two_way_entrance_register["Keep 4th Maze", "Keep Tower"])
|
||||||
e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 4th Maze", "Keep Tower"]
|
|
||||||
)
|
|
||||||
|
|
||||||
if not tower_access_from_hedges:
|
if not tower_access_from_hedges:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# We can reach Keep Tower from Hedge Maze 4. If we now have the Hedge 4 Shortcut, we are immediately good.
|
# We can reach Keep Tower from Hedge Maze 4. If we now have the Hedge 4 Shortcut, we are immediately good.
|
||||||
|
|
||||||
hedge_4_shortcut = any(
|
hedge_4_shortcut = any(e.can_reach(state) for e in two_way_entrance_register["Keep 4th Maze", "Keep"])
|
||||||
e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 4th Maze", "Keep"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# If we have the hedge 4 shortcut, that works.
|
# If we have the hedge 4 shortcut, that works.
|
||||||
if hedge_4_shortcut:
|
if hedge_4_shortcut:
|
||||||
|
@ -147,27 +141,21 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool:
|
||||||
|
|
||||||
# We don't have the hedge 4 shortcut. This means we would now need to come through Hedge Maze 3.
|
# We don't have the hedge 4 shortcut. This means we would now need to come through Hedge Maze 3.
|
||||||
|
|
||||||
hedge_3_to_4 = any(
|
hedge_3_to_4 = any(e.can_reach(state) for e in two_way_entrance_register["Keep 4th Maze", "Keep 3rd Maze"])
|
||||||
e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 4th Maze", "Keep 3rd Maze"]
|
|
||||||
)
|
|
||||||
|
|
||||||
if not hedge_3_to_4:
|
if not hedge_3_to_4:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# We can get to Hedge 4 from Hedge 3. If we have the Hedge 3 Shortcut, we're good.
|
# We can get to Hedge 4 from Hedge 3. If we have the Hedge 3 Shortcut, we're good.
|
||||||
|
|
||||||
hedge_3_shortcut = any(
|
hedge_3_shortcut = any(e.can_reach(state) for e in two_way_entrance_register["Keep 3rd Maze", "Keep"])
|
||||||
e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 3rd Maze", "Keep"]
|
|
||||||
)
|
|
||||||
|
|
||||||
if hedge_3_shortcut:
|
if hedge_3_shortcut:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# We don't have Hedge 3 Shortcut. This means we would now need to come through Hedge Maze 2.
|
# We don't have Hedge 3 Shortcut. This means we would now need to come through Hedge Maze 2.
|
||||||
|
|
||||||
hedge_2_to_3 = any(
|
hedge_2_to_3 = any(e.can_reach(state) for e in two_way_entrance_register["Keep 3rd Maze", "Keep 2nd Maze"])
|
||||||
e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 3rd Maze", "Keep 2nd Maze"]
|
|
||||||
)
|
|
||||||
|
|
||||||
if not hedge_2_to_3:
|
if not hedge_2_to_3:
|
||||||
return False
|
return False
|
||||||
|
@ -175,9 +163,7 @@ def _can_do_expert_pp2(state: CollectionState, world: "WitnessWorld") -> bool:
|
||||||
# We can get to Hedge 3 from Hedge 2. If we can get from Keep to Hedge 2, we're good.
|
# We can get to Hedge 3 from Hedge 2. If we can get from Keep to Hedge 2, we're good.
|
||||||
# This covers both Hedge 1 Exit and Hedge 2 Shortcut, because Hedge 1 is just part of the Keep region.
|
# This covers both Hedge 1 Exit and Hedge 2 Shortcut, because Hedge 1 is just part of the Keep region.
|
||||||
|
|
||||||
return any(
|
return any(e.can_reach(state) for e in two_way_entrance_register["Keep 2nd Maze", "Keep"])
|
||||||
e.can_reach(state) for e in player_regions.two_way_entrance_register["Keep 2nd Maze", "Keep"]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _can_do_theater_to_tunnels(state: CollectionState, world: "WitnessWorld") -> bool:
|
def _can_do_theater_to_tunnels(state: CollectionState, world: "WitnessWorld") -> bool:
|
||||||
|
@ -189,11 +175,11 @@ def _can_do_theater_to_tunnels(state: CollectionState, world: "WitnessWorld") ->
|
||||||
# Checking for access to Theater is not necessary, as solvability of Tutorial Video is checked in the other half
|
# Checking for access to Theater is not necessary, as solvability of Tutorial Video is checked in the other half
|
||||||
# of the Theater Flowers EP condition.
|
# of the Theater Flowers EP condition.
|
||||||
|
|
||||||
player_regions = world.player_regions
|
two_way_entrance_register = world.player_regions.two_way_entrance_register
|
||||||
|
|
||||||
direct_access = (
|
direct_access = (
|
||||||
any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Tunnels", "Windmill Interior"])
|
any(e.can_reach(state) for e in two_way_entrance_register["Tunnels", "Windmill Interior"])
|
||||||
and any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Theater", "Windmill Interior"])
|
and any(e.can_reach(state) for e in two_way_entrance_register["Theater", "Windmill Interior"])
|
||||||
)
|
)
|
||||||
|
|
||||||
if direct_access:
|
if direct_access:
|
||||||
|
@ -210,9 +196,9 @@ def _can_do_theater_to_tunnels(state: CollectionState, world: "WitnessWorld") ->
|
||||||
# We also need a way from Town to Tunnels.
|
# We also need a way from Town to Tunnels.
|
||||||
|
|
||||||
return (
|
return (
|
||||||
any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Tunnels", "Windmill Interior"])
|
any(e.can_reach(state) for e in two_way_entrance_register["Tunnels", "Windmill Interior"])
|
||||||
and any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Town", "Windmill Interior"])
|
and any(e.can_reach(state) for e in two_way_entrance_register["Outside Windmill", "Windmill Interior"])
|
||||||
or any(e.can_reach(state) for e in player_regions.two_way_entrance_register["Tunnels", "Town"])
|
or any(e.can_reach(state) for e in two_way_entrance_register["Tunnels", "Town"])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
from ..test import WitnessTestBase
|
||||||
|
|
||||||
|
|
||||||
|
class TestWeirdTraversalRequirements(WitnessTestBase):
|
||||||
|
options = {
|
||||||
|
"shuffle_vault_boxes": True,
|
||||||
|
"shuffle_symbols": False,
|
||||||
|
"shuffle_EPs": "individual",
|
||||||
|
"EP_difficulty": "tedious",
|
||||||
|
"shuffle_doors": "doors",
|
||||||
|
"door_groupings": "off",
|
||||||
|
"puzzle_randomization": "sigma_expert",
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_weird_traversal_requirements(self) -> None:
|
||||||
|
"""
|
||||||
|
Test that Tunnels Theater Flowers EP and Expert PP2 consider all valid paths logically.
|
||||||
|
"""
|
||||||
|
|
||||||
|
with self.subTest("Tunnels Theater Flowers EP"):
|
||||||
|
self.assertAccessDependency(
|
||||||
|
["Tunnels Theater Flowers EP"],
|
||||||
|
[
|
||||||
|
["Theater Exit Left (Door)", "Windmill Entry (Door)", "Tunnels Theater Shortcut (Door)"],
|
||||||
|
["Theater Exit Right (Door)", "Windmill Entry (Door)", "Tunnels Theater Shortcut (Door)"],
|
||||||
|
["Theater Exit Left (Door)", "Tunnels Town Shortcut (Door)"],
|
||||||
|
["Theater Exit Right (Door)", "Tunnels Town Shortcut (Door)"],
|
||||||
|
["Theater Entry (Door)", "Tunnels Theater Shortcut (Door)"],
|
||||||
|
["Theater Entry (Door)", "Windmill Entry (Door)", "Tunnels Town Shortcut (Door)"],
|
||||||
|
],
|
||||||
|
only_check_listed=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.subTest("Expert Keep Pressure Plates 2"):
|
||||||
|
# Always necessary
|
||||||
|
self.assertAccessDependency(
|
||||||
|
["Keep Pressure Plates 2"],
|
||||||
|
[["Keep Pressure Plates 1 Exit (Door)"]],
|
||||||
|
only_check_listed=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Always necessary
|
||||||
|
self.assertAccessDependency(
|
||||||
|
["Keep Pressure Plates 2"],
|
||||||
|
[["Keep Pressure Plates 3 Exit (Door)"]],
|
||||||
|
only_check_listed=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# All the possible "Exit methods" from PP3
|
||||||
|
self.assertAccessDependency(
|
||||||
|
["Keep Pressure Plates 2"],
|
||||||
|
[
|
||||||
|
["Keep Shadows Shortcut (Door)"],
|
||||||
|
["Keep Pressure Plates 4 Exit (Door)", "Keep Tower Shortcut (Door)"],
|
||||||
|
["Keep Pressure Plates 4 Exit (Door)", "Keep Hedge Maze 4 Exit (Door)",
|
||||||
|
"Keep Hedge Maze 4 Shortcut (Door)"],
|
||||||
|
["Keep Pressure Plates 4 Exit (Door)", "Keep Hedge Maze 4 Exit (Door)",
|
||||||
|
"Keep Hedge Maze 3 Exit (Door)", "Keep Hedge Maze 3 Shortcut (Door)"],
|
||||||
|
["Keep Pressure Plates 4 Exit (Door)", "Keep Hedge Maze 4 Exit (Door)",
|
||||||
|
"Keep Hedge Maze 3 Exit (Door)", "Keep Hedge Maze 2 Exit (Door)",
|
||||||
|
"Keep Hedge Maze 2 Shortcut (Door)"],
|
||||||
|
["Keep Pressure Plates 4 Exit (Door)", "Keep Hedge Maze 4 Exit (Door)",
|
||||||
|
"Keep Hedge Maze 3 Exit (Door)", "Keep Hedge Maze 2 Exit (Door)", "Keep Hedge Maze 1 Exit (Door)"],
|
||||||
|
],
|
||||||
|
only_check_listed=True,
|
||||||
|
)
|
Loading…
Reference in New Issue