about summary refs log tree commit diff stats
path: root/apworld
diff options
context:
space:
mode:
Diffstat (limited to 'apworld')
-rw-r--r--apworld/__init__.py1
-rw-r--r--apworld/options.py22
-rw-r--r--apworld/player_logic.py36
3 files changed, 49 insertions, 10 deletions
diff --git a/apworld/__init__.py b/apworld/__init__.py index d6a3acb..c45e8b3 100644 --- a/apworld/__init__.py +++ b/apworld/__init__.py
@@ -66,6 +66,7 @@ class Lingo2World(World):
66 66
67 def fill_slot_data(self): 67 def fill_slot_data(self):
68 slot_options = [ 68 slot_options = [
69 "cyan_door_behavior",
69 "daedalus_roof_access", 70 "daedalus_roof_access",
70 "keyholder_sanity", 71 "keyholder_sanity",
71 "shuffle_control_center_colors", 72 "shuffle_control_center_colors",
diff --git a/apworld/options.py b/apworld/options.py index dbf09e7..2197b0f 100644 --- a/apworld/options.py +++ b/apworld/options.py
@@ -48,6 +48,27 @@ class KeyholderSanity(Toggle):
48 display_name = "Keyholder Sanity" 48 display_name = "Keyholder Sanity"
49 49
50 50
51class CyanDoorBehavior(Choice):
52 """
53 Cyan-colored doors usually only open upon unlocking double letters. Some panels also only appear upon unlocking
54 double letters. This option determines how these unlocks should behave.
55
56 - **Collect H2**: In the base game, H2 is the first double letter you are intended to collect, so cyan doors only
57 open when you collect the H2 pickup in The Repetitive. Collecting the actual pickup is still required even with
58 remote letter shuffle enabled.
59 - **Any Double Letter**: Cyan doors will open when you have unlocked any cyan letter on your keyboard. In letter
60 shuffle, this means receiving a cyan letter, not picking up a cyan letter collectable.
61 - **Item**: Cyan doors will be grouped together in a single item.
62
63 Note that some cyan doors are impacted by door shuffle (e.g. the entrance to The Tower). When door shuffle is
64 enabled, these doors won't be affected by the value of this option.
65 """
66 display_name = "Cyan Door Behavior"
67 option_collect_h2 = 0
68 option_any_double_letter = 1
69 option_item = 2
70
71
51class DaedalusRoofAccess(Toggle): 72class DaedalusRoofAccess(Toggle):
52 """ 73 """
53 If enabled, the player will be logically expected to be able to go from the castle entrance to any part of Daedalus 74 If enabled, the player will be logically expected to be able to go from the castle entrance to any part of Daedalus
@@ -82,5 +103,6 @@ class Lingo2Options(PerGameCommonOptions):
82 shuffle_control_center_colors: ShuffleControlCenterColors 103 shuffle_control_center_colors: ShuffleControlCenterColors
83 shuffle_letters: ShuffleLetters 104 shuffle_letters: ShuffleLetters
84 keyholder_sanity: KeyholderSanity 105 keyholder_sanity: KeyholderSanity
106 cyan_door_behavior: CyanDoorBehavior
85 daedalus_roof_access: DaedalusRoofAccess 107 daedalus_roof_access: DaedalusRoofAccess
86 victory_condition: VictoryCondition 108 victory_condition: VictoryCondition
diff --git a/apworld/player_logic.py b/apworld/player_logic.py index ce9a4e5..317d13b 100644 --- a/apworld/player_logic.py +++ b/apworld/player_logic.py
@@ -3,7 +3,7 @@ from enum import IntEnum, auto
3from .generated import data_pb2 as data_pb2 3from .generated import data_pb2 as data_pb2
4from typing import TYPE_CHECKING, NamedTuple 4from typing import TYPE_CHECKING, NamedTuple
5 5
6from .options import VictoryCondition, ShuffleLetters 6from .options import VictoryCondition, ShuffleLetters, CyanDoorBehavior
7 7
8if TYPE_CHECKING: 8if TYPE_CHECKING:
9 from . import Lingo2World 9 from . import Lingo2World
@@ -124,11 +124,13 @@ class Lingo2PlayerLogic:
124 self.real_items.append(progressive.name) 124 self.real_items.append(progressive.name)
125 125
126 for door_group in world.static_logic.objects.door_groups: 126 for door_group in world.static_logic.objects.door_groups:
127 if door_group.type == data_pb2.DoorGroupType.CONNECTOR and not self.world.options.shuffle_doors: 127 if door_group.type == data_pb2.DoorGroupType.CONNECTOR:
128 continue 128 if not self.world.options.shuffle_doors:
129 129 continue
130 if (door_group.type == data_pb2.DoorGroupType.COLOR_CONNECTOR and 130 elif door_group.type == data_pb2.DoorGroupType.COLOR_CONNECTOR:
131 not self.world.options.shuffle_control_center_colors): 131 if not self.world.options.shuffle_control_center_colors:
132 continue
133 else:
132 continue 134 continue
133 135
134 for door in door_group.doors: 136 for door in door_group.doors:
@@ -157,6 +159,19 @@ class Lingo2PlayerLogic:
157 self.item_by_door[door.id] = (door_item_name, 1) 159 self.item_by_door[door.id] = (door_item_name, 1)
158 self.real_items.append(door_item_name) 160 self.real_items.append(door_item_name)
159 161
162 # We handle cyan_door_behavior = Item after door shuffle, because cyan doors that are impacted by door shuffle
163 # should be exempt from cyan_door_behavior.
164 if world.options.cyan_door_behavior == CyanDoorBehavior.option_item:
165 for door_group in world.static_logic.objects.door_groups:
166 if door_group.type != data_pb2.DoorGroupType.CYAN_DOORS:
167 continue
168
169 for door in door_group.doors:
170 if not door in self.item_by_door:
171 self.item_by_door[door] = (door_group.name, 1)
172
173 self.real_items.append(door_group.name)
174
160 for door in world.static_logic.objects.doors: 175 for door in world.static_logic.objects.doors:
161 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]: 176 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]:
162 self.locations_by_room.setdefault(door.room_id, []).append(PlayerLocation(door.ap_id, 177 self.locations_by_room.setdefault(door.room_id, []).append(PlayerLocation(door.ap_id,
@@ -295,12 +310,13 @@ class Lingo2PlayerLogic:
295 self.add_solution_reqs(reqs, door.control_center_color) 310 self.add_solution_reqs(reqs, door.control_center_color)
296 311
297 if door.double_letters: 312 if door.double_letters:
298 if self.world.options.shuffle_letters in [ShuffleLetters.option_vanilla, 313 if self.world.options.cyan_door_behavior == CyanDoorBehavior.option_collect_h2:
299 ShuffleLetters.option_vanilla_cyan]:
300 reqs.rooms.add("The Repetitive - Main Room") 314 reqs.rooms.add("The Repetitive - Main Room")
301 elif self.world.options.shuffle_letters in [ShuffleLetters.option_progressive, 315 elif self.world.options.cyan_door_behavior == CyanDoorBehavior.option_any_double_letter:
302 ShuffleLetters.option_item_cyan]:
303 reqs.cyans = True 316 reqs.cyans = True
317 elif self.world.options.cyan_door_behavior == CyanDoorBehavior.option_item:
318 # There shouldn't be any locations that are cyan doors.
319 pass
304 320
305 for keyholder_uses in door.keyholders: 321 for keyholder_uses in door.keyholders:
306 key_name = keyholder_uses.key.upper() 322 key_name = keyholder_uses.key.upper()