about summary refs log tree commit diff stats
path: root/src/tracker_state.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tracker_state.cpp')
-rw-r--r--src/tracker_state.cpp95
1 files changed, 82 insertions, 13 deletions
diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index 1a2d116..66a9f94 100644 --- a/src/tracker_state.cpp +++ b/src/tracker_state.cpp
@@ -1,5 +1,8 @@
1#include "tracker_state.h" 1#include "tracker_state.h"
2 2
3#include <fmt/core.h>
4#include <hkutil/string.h>
5
3#include <list> 6#include <list>
4#include <map> 7#include <map>
5#include <mutex> 8#include <mutex>
@@ -9,17 +12,19 @@
9 12
10#include "ap_state.h" 13#include "ap_state.h"
11#include "game_data.h" 14#include "game_data.h"
15#include "logger.h"
12 16
13namespace { 17namespace {
14 18
15struct Requirements { 19struct Requirements {
16 bool disabled = false; 20 bool disabled = false;
17 21
18 std::set<int> doors; // non-grouped, handles progressive 22 std::set<int> doors; // non-grouped, handles progressive
19 std::set<int> items; // all other items 23 std::set<int> panel_doors; // non-grouped, handles progressive
20 std::set<int> rooms; // maybe 24 std::set<int> items; // all other items
21 bool mastery = false; // maybe 25 std::set<int> rooms; // maybe
22 bool panel_hunt = false; // maybe 26 bool mastery = false; // maybe
27 bool panel_hunt = false; // maybe
23 28
24 void Merge(const Requirements& rhs) { 29 void Merge(const Requirements& rhs) {
25 if (rhs.disabled) { 30 if (rhs.disabled) {
@@ -29,6 +34,9 @@ struct Requirements {
29 for (int id : rhs.doors) { 34 for (int id : rhs.doors) {
30 doors.insert(id); 35 doors.insert(id);
31 } 36 }
37 for (int id : rhs.panel_doors) {
38 panel_doors.insert(id);
39 }
32 for (int id : rhs.items) { 40 for (int id : rhs.items) {
33 items.insert(id); 41 items.insert(id);
34 } 42 }
@@ -74,15 +82,14 @@ class RequirementCalculator {
74 requirements.doors.insert(door_obj.id); 82 requirements.doors.insert(door_obj.id);
75 break; 83 break;
76 } 84 }
77 } else if (AP_GetDoorShuffleMode() == kNO_DOORS || door_obj.skip_item) { 85 } else if (AP_GetDoorShuffleMode() != kDOORS_MODE || door_obj.skip_item) {
78 requirements.rooms.insert(door_obj.room); 86 requirements.rooms.insert(door_obj.room);
79 87
80 for (int panel_id : door_obj.panels) { 88 for (int panel_id : door_obj.panels) {
81 const Requirements& panel_reqs = GetPanel(panel_id); 89 const Requirements& panel_reqs = GetPanel(panel_id);
82 requirements.Merge(panel_reqs); 90 requirements.Merge(panel_reqs);
83 } 91 }
84 } else if (AP_GetDoorShuffleMode() == kSIMPLE_DOORS && 92 } else if (AP_AreDoorsGrouped() && !door_obj.group_name.empty()) {
85 !door_obj.group_name.empty()) {
86 requirements.items.insert(door_obj.group_ap_item_id); 93 requirements.items.insert(door_obj.group_ap_item_id);
87 } else { 94 } else {
88 requirements.doors.insert(door_obj.id); 95 requirements.doors.insert(door_obj.id);
@@ -129,6 +136,17 @@ class RequirementCalculator {
129 requirements.items.insert(GD_GetItemIdForColor(color)); 136 requirements.items.insert(GD_GetItemIdForColor(color));
130 } 137 }
131 } 138 }
139
140 if (panel_obj.panel_door != -1 &&
141 AP_GetDoorShuffleMode() == kPANELS_MODE) {
142 const PanelDoor& panel_door_obj = GD_GetPanelDoor(panel_obj.panel_door);
143
144 if (panel_door_obj.group_ap_item_id != -1 && AP_AreDoorsGrouped()) {
145 requirements.items.insert(panel_door_obj.group_ap_item_id);
146 } else {
147 requirements.panel_doors.insert(panel_obj.panel_door);
148 }
149 }
132 150
133 panels_[panel_id] = requirements; 151 panels_[panel_id] = requirements;
134 } 152 }
@@ -217,7 +235,9 @@ class StateCalculator {
217 PaintingExit target_painting = 235 PaintingExit target_painting =
218 GD_GetPaintingExit(GD_GetPaintingByName( 236 GD_GetPaintingExit(GD_GetPaintingByName(
219 AP_GetPaintingMapping().at(cur_painting.internal_id))); 237 AP_GetPaintingMapping().at(cur_painting.internal_id)));
238 painting_exit.source_room = cur_painting.room;
220 painting_exit.destination_room = target_painting.room; 239 painting_exit.destination_room = target_painting.room;
240 painting_exit.type = EntranceType::kPainting;
221 241
222 new_boundary.push_back(painting_exit); 242 new_boundary.push_back(painting_exit);
223 } 243 }
@@ -244,6 +264,12 @@ class StateCalculator {
244 reachable_rooms_.insert(room_exit.destination_room); 264 reachable_rooms_.insert(room_exit.destination_room);
245 reachable_changed = true; 265 reachable_changed = true;
246 266
267#ifndef NDEBUG
268 std::list<int> room_path = paths_[room_exit.source_room];
269 room_path.push_back(room_exit.destination_room);
270 paths_[room_exit.destination_room] = room_path;
271#endif
272
247 const Room& room_obj = GD_GetRoom(room_exit.destination_room); 273 const Room& room_obj = GD_GetRoom(room_exit.destination_room);
248 for (const Exit& out_edge : room_obj.exits) { 274 for (const Exit& out_edge : room_obj.exits) {
249 if (out_edge.type == EntranceType::kPainting && 275 if (out_edge.type == EntranceType::kPainting &&
@@ -282,20 +308,33 @@ class StateCalculator {
282 308
283 if (AP_HasEarlyColorHallways() && room_obj.name == "Starting Room") { 309 if (AP_HasEarlyColorHallways() && room_obj.name == "Starting Room") {
284 new_boundary.push_back( 310 new_boundary.push_back(
285 {.destination_room = GD_GetRoomByName("Color Hallways"), 311 {.source_room = room_exit.destination_room,
312 .destination_room = GD_GetRoomByName("Color Hallways"),
286 .type = EntranceType::kPainting}); 313 .type = EntranceType::kPainting});
287 } 314 }
288 315
289 if (AP_IsPilgrimageEnabled()) { 316 if (AP_IsPilgrimageEnabled()) {
290 if (room_obj.name == "Hub Room") { 317 int pilgrimage_start_id = GD_GetRoomByName("Hub Room");
318 if (AP_IsSunwarpShuffle()) {
319 for (const auto& [start_index, mapping] :
320 AP_GetSunwarpMapping()) {
321 if (mapping.dots == 1) {
322 pilgrimage_start_id = GD_GetRoomForSunwarp(start_index);
323 }
324 }
325 }
326
327 if (room_exit.destination_room == pilgrimage_start_id) {
291 new_boundary.push_back( 328 new_boundary.push_back(
292 {.destination_room = GD_GetRoomByName("Pilgrim Antechamber"), 329 {.source_room = room_exit.destination_room,
330 .destination_room = GD_GetRoomByName("Pilgrim Antechamber"),
293 .type = EntranceType::kPilgrimage}); 331 .type = EntranceType::kPilgrimage});
294 } 332 }
295 } else { 333 } else {
296 if (room_obj.name == "Starting Room") { 334 if (room_obj.name == "Starting Room") {
297 new_boundary.push_back( 335 new_boundary.push_back(
298 {.destination_room = GD_GetRoomByName("Pilgrim Antechamber"), 336 {.source_room = room_exit.destination_room,
337 .destination_room = GD_GetRoomByName("Pilgrim Antechamber"),
299 .door = 338 .door =
300 GD_GetDoorByName("Pilgrim Antechamber - Sun Painting"), 339 GD_GetDoorByName("Pilgrim Antechamber - Sun Painting"),
301 .type = EntranceType::kPainting}); 340 .type = EntranceType::kPainting});
@@ -336,8 +375,22 @@ class StateCalculator {
336 return door_report_; 375 return door_report_;
337 } 376 }
338 377
378 std::string GetPathToRoom(int room_id) const {
379 if (!paths_.count(room_id)) {
380 return "";
381 }
382
383 const std::list<int>& path = paths_.at(room_id);
384 std::vector<std::string> room_names;
385 for (int room_id : path) {
386 room_names.push_back(GD_GetRoom(room_id).name);
387 }
388 return hatkirby::implode(room_names, " -> ");
389 }
390
339 private: 391 private:
340 Decision IsNonGroupedDoorReachable(const Door& door_obj) { 392 template <typename T>
393 Decision IsNonGroupedDoorReachable(const T& door_obj) {
341 bool has_item = AP_HasItem(door_obj.ap_item_id); 394 bool has_item = AP_HasItem(door_obj.ap_item_id);
342 395
343 if (!has_item) { 396 if (!has_item) {
@@ -373,6 +426,20 @@ class StateCalculator {
373 } 426 }
374 } 427 }
375 428
429 for (int panel_door_id : reqs.panel_doors) {
430 const PanelDoor& panel_door_obj = GD_GetPanelDoor(panel_door_id);
431 Decision decision = IsNonGroupedDoorReachable(panel_door_obj);
432
433 if (report) {
434 (*report)[AP_GetItemName(panel_door_obj.ap_item_id)] =
435 (decision == kYes);
436 }
437
438 if (decision != kYes) {
439 final_decision = decision;
440 }
441 }
442
376 for (int item_id : reqs.items) { 443 for (int item_id : reqs.items) {
377 bool has_item = AP_HasItem(item_id); 444 bool has_item = AP_HasItem(item_id);
378 if (report) { 445 if (report) {
@@ -574,6 +641,8 @@ class StateCalculator {
574 std::set<int> solveable_panels_; 641 std::set<int> solveable_panels_;
575 std::set<int> reachable_paintings_; 642 std::set<int> reachable_paintings_;
576 std::map<int, std::map<std::string, bool>> door_report_; 643 std::map<int, std::map<std::string, bool>> door_report_;
644
645 std::map<int, std::list<int>> paths_;
577}; 646};
578 647
579} // namespace 648} // namespace