diff options
author | Star Rauchenberger <fefferburbia@gmail.com> | 2025-08-14 12:30:12 -0400 |
---|---|---|
committer | Star Rauchenberger <fefferburbia@gmail.com> | 2025-08-14 12:32:43 -0400 |
commit | a17b7e1cbfb43141af21263f838f9593836a9c52 (patch) | |
tree | 453b8a6193e9c9c22863d6de5ecf6bffe3f6dfc6 /apworld/player_logic.py | |
parent | 0fbaff9e15d1214192bd2b70bf4bc90d873727b6 (diff) | |
download | lingo2-archipelago-a17b7e1cbfb43141af21263f838f9593836a9c52.tar.gz lingo2-archipelago-a17b7e1cbfb43141af21263f838f9593836a9c52.tar.bz2 lingo2-archipelago-a17b7e1cbfb43141af21263f838f9593836a9c52.zip |
Fixed some issues with door logic
If a door is shuffled, the door's item should be used in connections and in requirements specified by panels, ports, paintings, and other doors. However, the original requirements still need to be used for locations.
Diffstat (limited to 'apworld/player_logic.py')
-rw-r--r-- | apworld/player_logic.py | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/apworld/player_logic.py b/apworld/player_logic.py index 7209ee5..c2850d5 100644 --- a/apworld/player_logic.py +++ b/apworld/player_logic.py | |||
@@ -63,6 +63,7 @@ class Lingo2PlayerLogic: | |||
63 | world: "Lingo2World" | 63 | world: "Lingo2World" |
64 | 64 | ||
65 | locations_by_room: dict[int, list[PlayerLocation]] | 65 | locations_by_room: dict[int, list[PlayerLocation]] |
66 | item_by_door: dict[int, str] | ||
66 | 67 | ||
67 | panel_reqs: dict[int, AccessRequirements] | 68 | panel_reqs: dict[int, AccessRequirements] |
68 | proxy_reqs: dict[int, dict[str, AccessRequirements]] | 69 | proxy_reqs: dict[int, dict[str, AccessRequirements]] |
@@ -73,19 +74,25 @@ class Lingo2PlayerLogic: | |||
73 | def __init__(self, world: "Lingo2World"): | 74 | def __init__(self, world: "Lingo2World"): |
74 | self.world = world | 75 | self.world = world |
75 | self.locations_by_room = {} | 76 | self.locations_by_room = {} |
77 | self.item_by_door = {} | ||
76 | self.panel_reqs = dict() | 78 | self.panel_reqs = dict() |
77 | self.proxy_reqs = dict() | 79 | self.proxy_reqs = dict() |
78 | self.door_reqs = dict() | 80 | self.door_reqs = dict() |
79 | self.real_items = list() | 81 | self.real_items = list() |
80 | 82 | ||
83 | # We iterate through the doors in two parts because it is essential that we determine which doors are shuffled | ||
84 | # before we calculate any access requirements. | ||
85 | for door in world.static_logic.objects.doors: | ||
86 | if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.ITEM_ONLY] and self.world.options.shuffle_doors: | ||
87 | door_item_name = self.world.static_logic.get_door_item_name(door.id) | ||
88 | self.item_by_door[door.id] = door_item_name | ||
89 | self.real_items.append(door_item_name) | ||
90 | |||
81 | for door in world.static_logic.objects.doors: | 91 | for door in world.static_logic.objects.doors: |
82 | if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY]: | 92 | if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY]: |
83 | self.locations_by_room.setdefault(door.room_id, []).append(PlayerLocation(door.ap_id, | 93 | self.locations_by_room.setdefault(door.room_id, []).append(PlayerLocation(door.ap_id, |
84 | self.get_door_reqs(door.id))) | 94 | self.get_door_reqs(door.id))) |
85 | 95 | ||
86 | if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.ITEM_ONLY] and self.world.options.shuffle_doors: | ||
87 | self.real_items.append(self.world.static_logic.get_door_item_name(door.id)) | ||
88 | |||
89 | for letter in world.static_logic.objects.letters: | 96 | for letter in world.static_logic.objects.letters: |
90 | self.locations_by_room.setdefault(letter.room_id, []).append(PlayerLocation(letter.ap_id, | 97 | self.locations_by_room.setdefault(letter.room_id, []).append(PlayerLocation(letter.ap_id, |
91 | AccessRequirements())) | 98 | AccessRequirements())) |
@@ -127,7 +134,7 @@ class Lingo2PlayerLogic: | |||
127 | reqs.symbols.add(symbol) | 134 | reqs.symbols.add(symbol) |
128 | 135 | ||
129 | if panel.HasField("required_door"): | 136 | if panel.HasField("required_door"): |
130 | door_reqs = self.get_door_reqs(panel.required_door) | 137 | door_reqs = self.get_door_open_reqs(panel.required_door) |
131 | reqs.merge(door_reqs) | 138 | reqs.merge(door_reqs) |
132 | 139 | ||
133 | if panel.HasField("required_room"): | 140 | if panel.HasField("required_room"): |
@@ -135,6 +142,8 @@ class Lingo2PlayerLogic: | |||
135 | 142 | ||
136 | return reqs | 143 | return reqs |
137 | 144 | ||
145 | # This gets/calculates the requirements described by the door object. This is most notably used as the requirements | ||
146 | # for clearing a location, or opening a door when the door is not shuffled. | ||
138 | def get_door_reqs(self, door_id: int) -> AccessRequirements: | 147 | def get_door_reqs(self, door_id: int) -> AccessRequirements: |
139 | if door_id not in self.door_reqs: | 148 | if door_id not in self.door_reqs: |
140 | self.door_reqs[door_id] = self.calculate_door_reqs(door_id) | 149 | self.door_reqs[door_id] = self.calculate_door_reqs(door_id) |
@@ -161,7 +170,18 @@ class Lingo2PlayerLogic: | |||
161 | reqs.rooms.add(self.world.static_logic.get_room_region_name(room)) | 170 | reqs.rooms.add(self.world.static_logic.get_room_region_name(room)) |
162 | 171 | ||
163 | for sub_door_id in door.doors: | 172 | for sub_door_id in door.doors: |
164 | sub_reqs = self.get_door_reqs(sub_door_id) | 173 | sub_reqs = self.get_door_open_reqs(sub_door_id) |
165 | reqs.merge(sub_reqs) | 174 | reqs.merge(sub_reqs) |
166 | 175 | ||
167 | return reqs | 176 | return reqs |
177 | |||
178 | # This gets the requirements to open a door within the world. When a door is shuffled, this means having the item | ||
179 | # that acts as the door's key. | ||
180 | def get_door_open_reqs(self, door_id: int) -> AccessRequirements: | ||
181 | if door_id in self.item_by_door: | ||
182 | reqs = AccessRequirements() | ||
183 | reqs.items.add(self.item_by_door.get(door_id)) | ||
184 | |||
185 | return reqs | ||
186 | else: | ||
187 | return self.get_door_reqs(door_id) | ||