From 2115232d2fec48fceef052b476af4afb02746ad1 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Fri, 19 Sep 2025 11:04:48 -0400 Subject: Added strict purple/cyan ending options --- apworld/__init__.py | 2 ++ apworld/options.py | 18 ++++++++++++++++++ apworld/regions.py | 6 ++++++ data/maps/the_parthenon/connections.txtpb | 1 + data/maps/the_sun_temple/connections.txtpb | 1 + proto/data.proto | 2 ++ proto/human.proto | 8 ++++++++ tools/datapacker/main.cpp | 10 ++++++++++ 8 files changed, 48 insertions(+) diff --git a/apworld/__init__.py b/apworld/__init__.py index 8b2e42e..f1de503 100644 --- a/apworld/__init__.py +++ b/apworld/__init__.py @@ -100,6 +100,8 @@ class Lingo2World(World): "shuffle_gallery_paintings", "shuffle_letters", "shuffle_symbols", + "strict_cyan_ending", + "strict_purple_ending", "victory_condition", ] diff --git a/apworld/options.py b/apworld/options.py index 52d2034..3646eea 100644 --- a/apworld/options.py +++ b/apworld/options.py @@ -92,6 +92,22 @@ class DaedalusRoofAccess(Toggle): display_name = "Allow Daedalus Roof Access" +class StrictPurpleEnding(DefaultOnToggle): + """ + If enabled, the player will be required to have all purple (level 1) letters in order to get Purple Ending. + Otherwise, some of the letters may be skippable depending on the other options. + """ + display_name = "Strict Purple Ending" + + +class StrictCyanEnding(DefaultOnToggle): + """ + If enabled, the player will be required to have all cyan (level 2) letters in order to get Cyan Ending. Otherwise, + at least J2, Q2, and V2 are skippable. Others may also be skippable depending on the options chosen. + """ + display_name = "Strict Cyan Ending" + + class VictoryCondition(Choice): """ This option determines what your goal is. @@ -144,5 +160,7 @@ class Lingo2Options(PerGameCommonOptions): keyholder_sanity: KeyholderSanity cyan_door_behavior: CyanDoorBehavior daedalus_roof_access: DaedalusRoofAccess + strict_purple_ending: StrictPurpleEnding + strict_cyan_ending: StrictCyanEnding victory_condition: VictoryCondition trap_percentage: TrapPercentage diff --git a/apworld/regions.py b/apworld/regions.py index fad9bc7..993eec8 100644 --- a/apworld/regions.py +++ b/apworld/regions.py @@ -97,6 +97,12 @@ def create_regions(world: "Lingo2World"): else: connection_name = f"{connection_name} (via panel {panel.name})" + if connection.HasField("purple_ending") and connection.purple_ending and world.options.strict_purple_ending: + world.player_logic.add_solution_reqs(reqs, "abcdefghijklmnopqrstuvwxyz") + + if connection.HasField("cyan_ending") and connection.cyan_ending and world.options.strict_cyan_ending: + world.player_logic.add_solution_reqs(reqs, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz") + reqs.simplify() reqs.remove_room(from_region) diff --git a/data/maps/the_parthenon/connections.txtpb b/data/maps/the_parthenon/connections.txtpb index a07d858..331ac66 100644 --- a/data/maps/the_parthenon/connections.txtpb +++ b/data/maps/the_parthenon/connections.txtpb @@ -7,6 +7,7 @@ connections { from_room: "Main Area" to_room: "Ending" door { name: "Ending Door" } + cyan_ending: true } connections { from_room: "Main Area" diff --git a/data/maps/the_sun_temple/connections.txtpb b/data/maps/the_sun_temple/connections.txtpb index b0b3a0a..ffe4d5d 100644 --- a/data/maps/the_sun_temple/connections.txtpb +++ b/data/maps/the_sun_temple/connections.txtpb @@ -7,6 +7,7 @@ connections { from_room: "Temple" to_room: "Ending" door { name: "Ending" } + purple_ending: true } connections { from_room: "Temple" diff --git a/proto/data.proto b/proto/data.proto index 7a1918a..64e3ddc 100644 --- a/proto/data.proto +++ b/proto/data.proto @@ -109,6 +109,8 @@ message Connection { } optional bool roof_access = 7; + optional bool purple_ending = 8; + optional bool cyan_ending = 9; } message Door { diff --git a/proto/human.proto b/proto/human.proto index f9517bd..c247edf 100644 --- a/proto/human.proto +++ b/proto/human.proto @@ -70,6 +70,14 @@ message HumanConnection { // This means that the connection intentionally skips the target object's // required door. optional bool bypass_target_door = 8; + + // This means that the connection should additionally require all purple + // letters when the Strict Purple Ending option is on. + optional bool purple_ending = 9; + + // This means that the connection should additionally require all cyan letters + // when the Strict Cyan Ending option is on. + optional bool cyan_ending = 10; } message HumanConnections { diff --git a/tools/datapacker/main.cpp b/tools/datapacker/main.cpp index c13a4df..596259b 100644 --- a/tools/datapacker/main.cpp +++ b/tools/datapacker/main.cpp @@ -473,6 +473,16 @@ class DataPacker { r_connection.set_roof_access(human_connection.roof_access()); } + if (human_connection.has_purple_ending()) { + f_connection.set_purple_ending(human_connection.purple_ending()); + r_connection.set_purple_ending(human_connection.purple_ending()); + } + + if (human_connection.has_cyan_ending()) { + f_connection.set_cyan_ending(human_connection.cyan_ending()); + r_connection.set_cyan_ending(human_connection.cyan_ending()); + } + container_.AddConnection(f_connection); if (!human_connection.oneway()) { container_.AddConnection(r_connection); -- cgit 1.4.1