diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ap_state.cpp | 18 | ||||
-rw-r--r-- | src/ap_state.h | 29 | ||||
-rw-r--r-- | src/game_data.cpp | 19 | ||||
-rw-r--r-- | src/game_data.h | 9 | ||||
-rw-r--r-- | src/tracker_state.cpp | 83 |
5 files changed, 139 insertions, 19 deletions
diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 1937597..bdd9cb2 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp | |||
@@ -64,6 +64,8 @@ struct APState { | |||
64 | VictoryCondition victory_condition = kTHE_END; | 64 | VictoryCondition victory_condition = kTHE_END; |
65 | bool early_color_hallways = false; | 65 | bool early_color_hallways = false; |
66 | bool pilgrimage_enabled = false; | 66 | bool pilgrimage_enabled = false; |
67 | bool pilgrimage_allows_roof_access = false; | ||
68 | bool pilgrimage_allows_paintings = false; | ||
67 | SunwarpAccess sunwarp_access = kSUNWARP_ACCESS_NORMAL; | 69 | SunwarpAccess sunwarp_access = kSUNWARP_ACCESS_NORMAL; |
68 | 70 | ||
69 | std::map<std::string, std::string> painting_mapping; | 71 | std::map<std::string, std::string> painting_mapping; |
@@ -135,6 +137,8 @@ struct APState { | |||
135 | victory_condition = kTHE_END; | 137 | victory_condition = kTHE_END; |
136 | early_color_hallways = false; | 138 | early_color_hallways = false; |
137 | pilgrimage_enabled = false; | 139 | pilgrimage_enabled = false; |
140 | pilgrimage_allows_roof_access = false; | ||
141 | pilgrimage_allows_paintings = false; | ||
138 | sunwarp_access = kSUNWARP_ACCESS_NORMAL; | 142 | sunwarp_access = kSUNWARP_ACCESS_NORMAL; |
139 | 143 | ||
140 | connected = false; | 144 | connected = false; |
@@ -240,6 +244,12 @@ struct APState { | |||
240 | slot_data["early_color_hallways"].get<int>() == 1; | 244 | slot_data["early_color_hallways"].get<int>() == 1; |
241 | pilgrimage_enabled = slot_data.contains("enable_pilgrimage") && | 245 | pilgrimage_enabled = slot_data.contains("enable_pilgrimage") && |
242 | slot_data["enable_pilgrimage"].get<int>() == 1; | 246 | slot_data["enable_pilgrimage"].get<int>() == 1; |
247 | pilgrimage_allows_roof_access = | ||
248 | slot_data.contains("pilgrimage_allows_roof_access") && | ||
249 | slot_data["pilgrimage_allows_roof_access"].get<int>() == 1; | ||
250 | pilgrimage_allows_paintings = | ||
251 | slot_data.contains("pilgrimage_allows_paintings") && | ||
252 | slot_data["pilgrimage_allows_paintings"].get<int>() == 1; | ||
243 | sunwarp_access = slot_data["sunwarp_access"].get<SunwarpAccess>(); | 253 | sunwarp_access = slot_data["sunwarp_access"].get<SunwarpAccess>(); |
244 | 254 | ||
245 | if (painting_shuffle && slot_data.contains("painting_entrance_to_exit")) { | 255 | if (painting_shuffle && slot_data.contains("painting_entrance_to_exit")) { |
@@ -454,6 +464,14 @@ bool AP_HasEarlyColorHallways() { return GetState().early_color_hallways; } | |||
454 | 464 | ||
455 | bool AP_IsPilgrimageEnabled() { return GetState().pilgrimage_enabled; } | 465 | bool AP_IsPilgrimageEnabled() { return GetState().pilgrimage_enabled; } |
456 | 466 | ||
467 | bool AP_DoesPilgrimageAllowRoofAccess() { | ||
468 | return GetState().pilgrimage_allows_roof_access; | ||
469 | } | ||
470 | |||
471 | bool AP_DoesPilgrimageAllowPaintings() { | ||
472 | return GetState().pilgrimage_allows_paintings; | ||
473 | } | ||
474 | |||
457 | SunwarpAccess AP_GetSunwarpAccess() { return GetState().sunwarp_access; } | 475 | SunwarpAccess AP_GetSunwarpAccess() { return GetState().sunwarp_access; } |
458 | 476 | ||
459 | bool AP_HasReachedGoal() { return GetState().HasReachedGoal(); } | 477 | bool AP_HasReachedGoal() { return GetState().HasReachedGoal(); } |
diff --git a/src/ap_state.h b/src/ap_state.h index e3c2d7f..e1f34c7 100644 --- a/src/ap_state.h +++ b/src/ap_state.h | |||
@@ -10,11 +10,26 @@ class TrackerFrame; | |||
10 | 10 | ||
11 | enum DoorShuffleMode { kNO_DOORS = 0, kSIMPLE_DOORS = 1, kCOMPLEX_DOORS = 2 }; | 11 | enum DoorShuffleMode { kNO_DOORS = 0, kSIMPLE_DOORS = 1, kCOMPLEX_DOORS = 2 }; |
12 | 12 | ||
13 | enum VictoryCondition { kTHE_END = 0, kTHE_MASTER = 1, kLEVEL_2 = 2, kPILGRIMAGE = 3 }; | 13 | enum VictoryCondition { |
14 | 14 | kTHE_END = 0, | |
15 | enum LocationChecks { kNORMAL_LOCATIONS = 0, kREDUCED_LOCATIONS = 1, kPANELSANITY = 2 }; | 15 | kTHE_MASTER = 1, |
16 | 16 | kLEVEL_2 = 2, | |
17 | enum SunwarpAccess { kSUNWARP_ACCESS_NORMAL = 0, kSUNWARP_ACCESS_DISABLED = 1, kSUNWARP_ACCESS_UNLOCK = 2, kSUNWARP_ACCESS_PROGRESSIVE = 3 }; | 17 | kPILGRIMAGE = 3 |
18 | }; | ||
19 | |||
20 | enum LocationChecks { | ||
21 | kNORMAL_LOCATIONS = 0, | ||
22 | kREDUCED_LOCATIONS = 1, | ||
23 | kPANELSANITY = 2 | ||
24 | }; | ||
25 | |||
26 | enum SunwarpAccess { | ||
27 | kSUNWARP_ACCESS_NORMAL = 0, | ||
28 | kSUNWARP_ACCESS_DISABLED = 1, | ||
29 | kSUNWARP_ACCESS_UNLOCK = 2, | ||
30 | kSUNWARP_ACCESS_INDIVIDUAL = 3, | ||
31 | kSUNWARP_ACCESS_PROGRESSIVE = 4 | ||
32 | }; | ||
18 | 33 | ||
19 | void AP_SetTrackerFrame(TrackerFrame* tracker_frame); | 34 | void AP_SetTrackerFrame(TrackerFrame* tracker_frame); |
20 | 35 | ||
@@ -48,6 +63,10 @@ bool AP_HasEarlyColorHallways(); | |||
48 | 63 | ||
49 | bool AP_IsPilgrimageEnabled(); | 64 | bool AP_IsPilgrimageEnabled(); |
50 | 65 | ||
66 | bool AP_DoesPilgrimageAllowRoofAccess(); | ||
67 | |||
68 | bool AP_DoesPilgrimageAllowPaintings(); | ||
69 | |||
51 | SunwarpAccess AP_GetSunwarpAccess(); | 70 | SunwarpAccess AP_GetSunwarpAccess(); |
52 | 71 | ||
53 | bool AP_HasReachedGoal(); | 72 | bool AP_HasReachedGoal(); |
diff --git a/src/game_data.cpp b/src/game_data.cpp index 28ca598..75c5b7e 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp | |||
@@ -58,6 +58,8 @@ struct GameData { | |||
58 | 58 | ||
59 | std::map<LingoColor, int> ap_id_by_color_; | 59 | std::map<LingoColor, int> ap_id_by_color_; |
60 | 60 | ||
61 | std::vector<int> sunwarp_doors_; | ||
62 | |||
61 | bool loaded_area_data_ = false; | 63 | bool loaded_area_data_ = false; |
62 | std::set<std::string> malconfigured_areas_; | 64 | std::set<std::string> malconfigured_areas_; |
63 | 65 | ||
@@ -125,6 +127,11 @@ struct GameData { | |||
125 | exit_obj.type = EntranceType::kWarp; | 127 | exit_obj.type = EntranceType::kWarp; |
126 | } | 128 | } |
127 | 129 | ||
130 | if (rooms_[from_room_id].name == "Crossroads" && | ||
131 | rooms_[room_id].name == "Roof") { | ||
132 | exit_obj.type == EntranceType::kCrossroadsRoofAccess; | ||
133 | } | ||
134 | |||
128 | rooms_[from_room_id].exits.push_back(exit_obj); | 135 | rooms_[from_room_id].exits.push_back(exit_obj); |
129 | }; | 136 | }; |
130 | 137 | ||
@@ -401,6 +408,14 @@ struct GameData { | |||
401 | doors_[door_id].exclude_reduce = | 408 | doors_[door_id].exclude_reduce = |
402 | !door_it.second["include_reduce"].as<bool>(); | 409 | !door_it.second["include_reduce"].as<bool>(); |
403 | } | 410 | } |
411 | |||
412 | if (doors_[door_id].name.ends_with(" Sunwarp")) { | ||
413 | sunwarp_doors_.push_back(door_id); | ||
414 | doors_[door_id].type = DoorType::kSunwarp; | ||
415 | } else if (doors_[door_id].item_name == | ||
416 | "Pilgrim Room - Sun Painting") { | ||
417 | doors_[door_id].type = DoorType::kSunPainting; | ||
418 | } | ||
404 | } | 419 | } |
405 | } | 420 | } |
406 | 421 | ||
@@ -667,3 +682,7 @@ const std::vector<int> &GD_GetAchievementPanels() { | |||
667 | int GD_GetItemIdForColor(LingoColor color) { | 682 | int GD_GetItemIdForColor(LingoColor color) { |
668 | return GetState().ap_id_by_color_.at(color); | 683 | return GetState().ap_id_by_color_.at(color); |
669 | } | 684 | } |
685 | |||
686 | const std::vector<int> &GD_GetSunwarpDoors() { | ||
687 | return GetState().sunwarp_doors_; | ||
688 | } | ||
diff --git a/src/game_data.h b/src/game_data.h index 2c18588..16d006c 100644 --- a/src/game_data.h +++ b/src/game_data.h | |||
@@ -29,6 +29,13 @@ enum class EntranceType { | |||
29 | kSunwarp, | 29 | kSunwarp, |
30 | kWarp, | 30 | kWarp, |
31 | kPilgrimage, | 31 | kPilgrimage, |
32 | kCrossroadsRoofAccess, | ||
33 | }; | ||
34 | |||
35 | enum class DoorType { | ||
36 | kNormal, | ||
37 | kSunwarp, | ||
38 | kSunPainting, | ||
32 | }; | 39 | }; |
33 | 40 | ||
34 | struct Panel { | 41 | struct Panel { |
@@ -69,6 +76,7 @@ struct Door { | |||
69 | int ap_item_id = -1; | 76 | int ap_item_id = -1; |
70 | int group_ap_item_id = -1; | 77 | int group_ap_item_id = -1; |
71 | int ap_location_id = -1; | 78 | int ap_location_id = -1; |
79 | DoorType type = DoorType::kNormal; | ||
72 | }; | 80 | }; |
73 | 81 | ||
74 | struct Exit { | 82 | struct Exit { |
@@ -120,5 +128,6 @@ const Panel& GD_GetPanel(int panel_id); | |||
120 | int GD_GetRoomForPainting(const std::string& painting_id); | 128 | int GD_GetRoomForPainting(const std::string& painting_id); |
121 | const std::vector<int>& GD_GetAchievementPanels(); | 129 | const std::vector<int>& GD_GetAchievementPanels(); |
122 | int GD_GetItemIdForColor(LingoColor color); | 130 | int GD_GetItemIdForColor(LingoColor color); |
131 | const std::vector<int>& GD_GetSunwarpDoors(); | ||
123 | 132 | ||
124 | #endif /* end of include guard: GAME_DATA_H_9C42AC51 */ | 133 | #endif /* end of include guard: GAME_DATA_H_9C42AC51 */ |
diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index cc941ef..5a99254 100644 --- a/src/tracker_state.cpp +++ b/src/tracker_state.cpp | |||
@@ -24,9 +24,12 @@ TrackerState& GetState() { | |||
24 | return *instance; | 24 | return *instance; |
25 | } | 25 | } |
26 | 26 | ||
27 | class StateCalculator; | ||
28 | |||
27 | struct StateCalculatorOptions { | 29 | struct StateCalculatorOptions { |
28 | std::string start = "Menu"; | 30 | std::string start = "Menu"; |
29 | bool pilgrimage = false; | 31 | bool pilgrimage = false; |
32 | StateCalculator* parent = nullptr; | ||
30 | }; | 33 | }; |
31 | 34 | ||
32 | class StateCalculator { | 35 | class StateCalculator { |
@@ -136,15 +139,43 @@ class StateCalculator { | |||
136 | 139 | ||
137 | const std::set<int>& GetReachableRooms() const { return reachable_rooms_; } | 140 | const std::set<int>& GetReachableRooms() const { return reachable_rooms_; } |
138 | 141 | ||
142 | const std::map<int, Decision>& GetDoorDecisions() const { return door_decisions_; } | ||
143 | |||
139 | const std::set<int>& GetSolveablePanels() const { return solveable_panels_; } | 144 | const std::set<int>& GetSolveablePanels() const { return solveable_panels_; } |
140 | 145 | ||
141 | private: | 146 | private: |
142 | Decision IsDoorReachable(int door_id) { | 147 | Decision IsNonGroupedDoorReachable(const Door& door_obj) { |
148 | bool has_item = AP_HasItem(door_obj.ap_item_id); | ||
149 | |||
150 | if (!has_item) { | ||
151 | for (const ProgressiveRequirement& prog_req : door_obj.progressives) { | ||
152 | if (AP_HasItem(prog_req.ap_item_id, prog_req.quantity)) { | ||
153 | has_item = true; | ||
154 | break; | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | |||
159 | return has_item ? kYes : kNo; | ||
160 | } | ||
161 | |||
162 | Decision IsDoorReachable_Helper(int door_id) { | ||
143 | const Door& door_obj = GD_GetDoor(door_id); | 163 | const Door& door_obj = GD_GetDoor(door_id); |
144 | 164 | ||
145 | if (!AP_IsPilgrimageEnabled() && | 165 | if (!AP_IsPilgrimageEnabled() && door_obj.type == DoorType::kSunPainting) { |
146 | door_obj.item_name == "Pilgrim Room - Sun Painting") { | ||
147 | return AP_HasItem(door_obj.ap_item_id) ? kYes : kNo; | 166 | return AP_HasItem(door_obj.ap_item_id) ? kYes : kNo; |
167 | } else if (door_obj.type == DoorType::kSunwarp) { | ||
168 | switch (AP_GetSunwarpAccess()) { | ||
169 | case kSUNWARP_ACCESS_NORMAL: | ||
170 | return kYes; | ||
171 | case kSUNWARP_ACCESS_DISABLED: | ||
172 | return kNo; | ||
173 | case kSUNWARP_ACCESS_UNLOCK: | ||
174 | return AP_HasItem(door_obj.group_ap_item_id) ? kYes : kNo; | ||
175 | case kSUNWARP_ACCESS_INDIVIDUAL: | ||
176 | case kSUNWARP_ACCESS_PROGRESSIVE: | ||
177 | return IsNonGroupedDoorReachable(door_obj); | ||
178 | } | ||
148 | } else if (AP_GetDoorShuffleMode() == kNO_DOORS || door_obj.skip_item) { | 179 | } else if (AP_GetDoorShuffleMode() == kNO_DOORS || door_obj.skip_item) { |
149 | if (!reachable_rooms_.count(door_obj.room)) { | 180 | if (!reachable_rooms_.count(door_obj.room)) { |
150 | return kMaybe; | 181 | return kMaybe; |
@@ -161,19 +192,25 @@ class StateCalculator { | |||
161 | !door_obj.group_name.empty()) { | 192 | !door_obj.group_name.empty()) { |
162 | return AP_HasItem(door_obj.group_ap_item_id) ? kYes : kNo; | 193 | return AP_HasItem(door_obj.group_ap_item_id) ? kYes : kNo; |
163 | } else { | 194 | } else { |
164 | bool has_item = AP_HasItem(door_obj.ap_item_id); | 195 | return IsNonGroupedDoorReachable(door_obj); |
196 | } | ||
197 | } | ||
165 | 198 | ||
166 | if (!has_item) { | 199 | Decision IsDoorReachable(int door_id) { |
167 | for (const ProgressiveRequirement& prog_req : door_obj.progressives) { | 200 | if (options_.parent) { |
168 | if (AP_HasItem(prog_req.ap_item_id, prog_req.quantity)) { | 201 | return options_.parent->IsDoorReachable(door_id); |
169 | has_item = true; | 202 | } |
170 | break; | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | 203 | ||
175 | return has_item ? kYes : kNo; | 204 | if (door_decisions_.count(door_id)) { |
205 | return door_decisions_.at(door_id); | ||
176 | } | 206 | } |
207 | |||
208 | Decision result = IsDoorReachable_Helper(door_id); | ||
209 | if (result != kMaybe) { | ||
210 | door_decisions_[door_id] = result; | ||
211 | } | ||
212 | |||
213 | return result; | ||
177 | } | 214 | } |
178 | 215 | ||
179 | Decision IsPanelReachable(int panel_id) { | 216 | Decision IsPanelReachable(int panel_id) { |
@@ -258,6 +295,15 @@ class StateCalculator { | |||
258 | return kNo; | 295 | return kNo; |
259 | } | 296 | } |
260 | 297 | ||
298 | if (AP_GetSunwarpAccess() != kSUNWARP_ACCESS_NORMAL) { | ||
299 | for (int door_id : GD_GetSunwarpDoors()) { | ||
300 | Decision sub_decision = IsDoorReachable(door_id); | ||
301 | if (sub_decision != kYes) { | ||
302 | return sub_decision; | ||
303 | } | ||
304 | } | ||
305 | } | ||
306 | |||
261 | static const std::vector<std::tuple<std::string, std::string>> | 307 | static const std::vector<std::tuple<std::string, std::string>> |
262 | pilgrimage_pairs = { | 308 | pilgrimage_pairs = { |
263 | {"Crossroads", "Hot Crusts Area"}, | 309 | {"Crossroads", "Hot Crusts Area"}, |
@@ -268,7 +314,7 @@ class StateCalculator { | |||
268 | 314 | ||
269 | for (const auto& [from_room, to_room] : pilgrimage_pairs) { | 315 | for (const auto& [from_room, to_room] : pilgrimage_pairs) { |
270 | StateCalculator pilgrimage_calculator( | 316 | StateCalculator pilgrimage_calculator( |
271 | {.start = from_room, .pilgrimage = true}); | 317 | {.start = from_room, .pilgrimage = true, .parent = this}); |
272 | pilgrimage_calculator.Calculate(); | 318 | pilgrimage_calculator.Calculate(); |
273 | 319 | ||
274 | if (!pilgrimage_calculator.GetReachableRooms().count( | 320 | if (!pilgrimage_calculator.GetReachableRooms().count( |
@@ -285,6 +331,14 @@ class StateCalculator { | |||
285 | room_exit.type == EntranceType::kSunwarp) { | 331 | room_exit.type == EntranceType::kSunwarp) { |
286 | return kNo; | 332 | return kNo; |
287 | } | 333 | } |
334 | if (room_exit.type == EntranceType::kCrossroadsRoofAccess && | ||
335 | !AP_DoesPilgrimageAllowRoofAccess()) { | ||
336 | return kNo; | ||
337 | } | ||
338 | if (room_exit.type == EntranceType::kPainting && | ||
339 | !AP_DoesPilgrimageAllowPaintings()) { | ||
340 | return kNo; | ||
341 | } | ||
288 | } | 342 | } |
289 | 343 | ||
290 | if (room_exit.type == EntranceType::kSunwarp) { | 344 | if (room_exit.type == EntranceType::kSunwarp) { |
@@ -305,6 +359,7 @@ class StateCalculator { | |||
305 | StateCalculatorOptions options_; | 359 | StateCalculatorOptions options_; |
306 | 360 | ||
307 | std::set<int> reachable_rooms_; | 361 | std::set<int> reachable_rooms_; |
362 | std::map<int, Decision> door_decisions_; | ||
308 | std::set<int> solveable_panels_; | 363 | std::set<int> solveable_panels_; |
309 | }; | 364 | }; |
310 | 365 | ||