diff options
author | Star Rauchenberger <fefferburbia@gmail.com> | 2025-08-27 18:53:50 -0400 |
---|---|---|
committer | Star Rauchenberger <fefferburbia@gmail.com> | 2025-08-27 18:53:50 -0400 |
commit | 18e64c9102f526b04c44623aa39c9b3cb6dee1ff (patch) | |
tree | 39b856ae472a1b9033a9122e63be28bddd55bea2 /apworld/player_logic.py | |
parent | 4ae885f392261b939e6f21b47d545f609c6e1965 (diff) | |
download | lingo2-archipelago-18e64c9102f526b04c44623aa39c9b3cb6dee1ff.tar.gz lingo2-archipelago-18e64c9102f526b04c44623aa39c9b3cb6dee1ff.tar.bz2 lingo2-archipelago-18e64c9102f526b04c44623aa39c9b3cb6dee1ff.zip |
Letter requirements in apworld
Also fixed or logic so everything actually works now.
Diffstat (limited to 'apworld/player_logic.py')
-rw-r--r-- | apworld/player_logic.py | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/apworld/player_logic.py b/apworld/player_logic.py index 83c16f2..6feef99 100644 --- a/apworld/player_logic.py +++ b/apworld/player_logic.py | |||
@@ -10,7 +10,11 @@ def calculate_letter_histogram(solution: str) -> dict[str, int]: | |||
10 | for l in solution: | 10 | for l in solution: |
11 | if l.isalpha(): | 11 | if l.isalpha(): |
12 | real_l = l.upper() | 12 | real_l = l.upper() |
13 | histogram[real_l] = min(histogram.get(l, 0) + 1, 2) | 13 | histogram[real_l] = min(histogram.get(real_l, 0) + 1, 2) |
14 | |||
15 | for free_letter in "HINT": | ||
16 | if histogram.get(free_letter, 0) == 1: | ||
17 | del histogram[free_letter] | ||
14 | 18 | ||
15 | return histogram | 19 | return histogram |
16 | 20 | ||
@@ -53,6 +57,20 @@ class AccessRequirements: | |||
53 | for disjunction in other.or_logic: | 57 | for disjunction in other.or_logic: |
54 | self.or_logic.append(disjunction) | 58 | self.or_logic.append(disjunction) |
55 | 59 | ||
60 | def __repr__(self): | ||
61 | parts = [] | ||
62 | if len(self.items) > 0: | ||
63 | parts.append(f"items={self.items}") | ||
64 | if len(self.rooms) > 0: | ||
65 | parts.append(f"rooms={self.rooms}") | ||
66 | if len(self.symbols) > 0: | ||
67 | parts.append(f"symbols={self.symbols}") | ||
68 | if len(self.letters) > 0: | ||
69 | parts.append(f"letters={self.letters}") | ||
70 | if len(self.or_logic) > 0: | ||
71 | parts.append(f"or_logic={self.or_logic}") | ||
72 | return f"AccessRequirements({", ".join(parts)})" | ||
73 | |||
56 | 74 | ||
57 | class PlayerLocation(NamedTuple): | 75 | class PlayerLocation(NamedTuple): |
58 | code: int | None | 76 | code: int | None |
@@ -100,6 +118,14 @@ class Lingo2PlayerLogic: | |||
100 | self.locations_by_room.setdefault(letter.room_id, []).append(PlayerLocation(letter.ap_id, | 118 | self.locations_by_room.setdefault(letter.room_id, []).append(PlayerLocation(letter.ap_id, |
101 | AccessRequirements())) | 119 | AccessRequirements())) |
102 | 120 | ||
121 | letter_name = f"{letter.key.upper()}{'2' if letter.level2 else '1'}" | ||
122 | event_name = f"{letter_name} (Collected)" | ||
123 | self.event_loc_item_by_room.setdefault(letter.room_id, {})[event_name] = letter.key.upper() | ||
124 | |||
125 | if letter.level2: | ||
126 | event_name = f"{letter_name} (Double Collected)" | ||
127 | self.event_loc_item_by_room.setdefault(letter.room_id, {})[event_name] = letter.key.upper() | ||
128 | |||
103 | for mastery in world.static_logic.objects.masteries: | 129 | for mastery in world.static_logic.objects.masteries: |
104 | self.locations_by_room.setdefault(mastery.room_id, []).append(PlayerLocation(mastery.ap_id, | 130 | self.locations_by_room.setdefault(mastery.room_id, []).append(PlayerLocation(mastery.ap_id, |
105 | AccessRequirements())) | 131 | AccessRequirements())) |
@@ -137,17 +163,21 @@ class Lingo2PlayerLogic: | |||
137 | if answer is not None: | 163 | if answer is not None: |
138 | reqs.add_solution(answer) | 164 | reqs.add_solution(answer) |
139 | elif len(panel.proxies) > 0: | 165 | elif len(panel.proxies) > 0: |
166 | possibilities = [] | ||
167 | |||
140 | for proxy in panel.proxies: | 168 | for proxy in panel.proxies: |
141 | proxy_reqs = AccessRequirements() | 169 | proxy_reqs = AccessRequirements() |
142 | proxy_reqs.add_solution(proxy.answer) | 170 | proxy_reqs.add_solution(proxy.answer) |
143 | 171 | ||
144 | reqs.or_logic.append([proxy_reqs]) | 172 | possibilities.append(proxy_reqs) |
145 | 173 | ||
146 | if not any(proxy.answer == panel.answer for proxy in panel.proxies): | 174 | if not any(proxy.answer == panel.answer for proxy in panel.proxies): |
147 | proxy_reqs = AccessRequirements() | 175 | proxy_reqs = AccessRequirements() |
148 | proxy_reqs.add_solution(panel.answer) | 176 | proxy_reqs.add_solution(panel.answer) |
149 | 177 | ||
150 | reqs.or_logic.append([proxy_reqs]) | 178 | possibilities.append(proxy_reqs) |
179 | |||
180 | reqs.or_logic.append(possibilities) | ||
151 | else: | 181 | else: |
152 | reqs.add_solution(panel.answer) | 182 | reqs.add_solution(panel.answer) |
153 | 183 | ||
@@ -175,7 +205,7 @@ class Lingo2PlayerLogic: | |||
175 | door = self.world.static_logic.objects.doors[door_id] | 205 | door = self.world.static_logic.objects.doors[door_id] |
176 | reqs = AccessRequirements() | 206 | reqs = AccessRequirements() |
177 | 207 | ||
178 | # TODO: complete_at, control_center_color, switches, keyholders | 208 | # TODO: control_center_color, switches |
179 | if not door.HasField("complete_at") or door.complete_at == 0: | 209 | if not door.HasField("complete_at") or door.complete_at == 0: |
180 | for proxy in door.panels: | 210 | for proxy in door.panels: |
181 | panel_reqs = self.get_panel_reqs(proxy.panel, proxy.answer if proxy.HasField("answer") else None) | 211 | panel_reqs = self.get_panel_reqs(proxy.panel, proxy.answer if proxy.HasField("answer") else None) |
@@ -188,6 +218,14 @@ class Lingo2PlayerLogic: | |||
188 | # TODO: Handle complete_at > 1 | 218 | # TODO: Handle complete_at > 1 |
189 | pass | 219 | pass |
190 | 220 | ||
221 | for keyholder_uses in door.keyholders: | ||
222 | key_name = keyholder_uses.key.upper() | ||
223 | if key_name not in reqs.letters: | ||
224 | reqs.letters[key_name] = 1 | ||
225 | |||
226 | keyholder = self.world.static_logic.objects.keyholders[keyholder_uses.keyholder] | ||
227 | reqs.rooms.add(self.world.static_logic.get_room_region_name(keyholder.room_id)) | ||
228 | |||
191 | for room in door.rooms: | 229 | for room in door.rooms: |
192 | reqs.rooms.add(self.world.static_logic.get_room_region_name(room)) | 230 | reqs.rooms.add(self.world.static_logic.get_room_region_name(room)) |
193 | 231 | ||