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.cpp75
1 files changed, 64 insertions, 11 deletions
diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index 1a2d116..8d5d904 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,6 +12,7 @@
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
@@ -148,6 +152,7 @@ struct TrackerState {
148 std::mutex reachability_mutex; 152 std::mutex reachability_mutex;
149 RequirementCalculator requirements; 153 RequirementCalculator requirements;
150 std::map<int, std::map<std::string, bool>> door_reports; 154 std::map<int, std::map<std::string, bool>> door_reports;
155 bool pilgrimage_doable = false;
151}; 156};
152 157
153enum Decision { kYes, kNo, kMaybe }; 158enum Decision { kYes, kNo, kMaybe };
@@ -176,7 +181,8 @@ class StateCalculator {
176 std::list<int> panel_boundary; 181 std::list<int> panel_boundary;
177 std::list<int> painting_boundary; 182 std::list<int> painting_boundary;
178 std::list<Exit> flood_boundary; 183 std::list<Exit> flood_boundary;
179 flood_boundary.push_back({.destination_room = options_.start}); 184 flood_boundary.push_back(
185 {.source_room = -1, .destination_room = options_.start});
180 186
181 bool reachable_changed = true; 187 bool reachable_changed = true;
182 while (reachable_changed) { 188 while (reachable_changed) {
@@ -217,7 +223,9 @@ class StateCalculator {
217 PaintingExit target_painting = 223 PaintingExit target_painting =
218 GD_GetPaintingExit(GD_GetPaintingByName( 224 GD_GetPaintingExit(GD_GetPaintingByName(
219 AP_GetPaintingMapping().at(cur_painting.internal_id))); 225 AP_GetPaintingMapping().at(cur_painting.internal_id)));
226 painting_exit.source_room = cur_painting.room;
220 painting_exit.destination_room = target_painting.room; 227 painting_exit.destination_room = target_painting.room;
228 painting_exit.type = EntranceType::kPainting;
221 229
222 new_boundary.push_back(painting_exit); 230 new_boundary.push_back(painting_exit);
223 } 231 }
@@ -244,6 +252,12 @@ class StateCalculator {
244 reachable_rooms_.insert(room_exit.destination_room); 252 reachable_rooms_.insert(room_exit.destination_room);
245 reachable_changed = true; 253 reachable_changed = true;
246 254
255#ifndef NDEBUG
256 std::list<int> room_path = paths_[room_exit.source_room];
257 room_path.push_back(room_exit.destination_room);
258 paths_[room_exit.destination_room] = room_path;
259#endif
260
247 const Room& room_obj = GD_GetRoom(room_exit.destination_room); 261 const Room& room_obj = GD_GetRoom(room_exit.destination_room);
248 for (const Exit& out_edge : room_obj.exits) { 262 for (const Exit& out_edge : room_obj.exits) {
249 if (out_edge.type == EntranceType::kPainting && 263 if (out_edge.type == EntranceType::kPainting &&
@@ -270,32 +284,44 @@ class StateCalculator {
270 if (AP_GetSunwarpMapping().count(index)) { 284 if (AP_GetSunwarpMapping().count(index)) {
271 const SunwarpMapping& sm = AP_GetSunwarpMapping().at(index); 285 const SunwarpMapping& sm = AP_GetSunwarpMapping().at(index);
272 286
273 Exit sunwarp_exit; 287 new_boundary.push_back(
274 sunwarp_exit.destination_room = 288 {.source_room = room_exit.destination_room,
275 GD_GetRoomForSunwarp(sm.exit_index); 289 .destination_room = GD_GetRoomForSunwarp(sm.exit_index),
276 sunwarp_exit.door = GD_GetSunwarpDoors().at(sm.dots - 1); 290 .door = GD_GetSunwarpDoors().at(sm.dots - 1),
277 291 .type = EntranceType::kSunwarp});
278 new_boundary.push_back(sunwarp_exit);
279 } 292 }
280 } 293 }
281 } 294 }
282 295
283 if (AP_HasEarlyColorHallways() && room_obj.name == "Starting Room") { 296 if (AP_HasEarlyColorHallways() && room_obj.name == "Starting Room") {
284 new_boundary.push_back( 297 new_boundary.push_back(
285 {.destination_room = GD_GetRoomByName("Color Hallways"), 298 {.source_room = room_exit.destination_room,
299 .destination_room = GD_GetRoomByName("Color Hallways"),
286 .type = EntranceType::kPainting}); 300 .type = EntranceType::kPainting});
287 } 301 }
288 302
289 if (AP_IsPilgrimageEnabled()) { 303 if (AP_IsPilgrimageEnabled()) {
290 if (room_obj.name == "Hub Room") { 304 int pilgrimage_start_id = GD_GetRoomByName("Hub Room");
305 if (AP_IsSunwarpShuffle()) {
306 for (const auto& [start_index, mapping] :
307 AP_GetSunwarpMapping()) {
308 if (mapping.dots == 1) {
309 pilgrimage_start_id = GD_GetRoomForSunwarp(start_index);
310 }
311 }
312 }
313
314 if (room_exit.destination_room == pilgrimage_start_id) {
291 new_boundary.push_back( 315 new_boundary.push_back(
292 {.destination_room = GD_GetRoomByName("Pilgrim Antechamber"), 316 {.source_room = room_exit.destination_room,
317 .destination_room = GD_GetRoomByName("Pilgrim Antechamber"),
293 .type = EntranceType::kPilgrimage}); 318 .type = EntranceType::kPilgrimage});
294 } 319 }
295 } else { 320 } else {
296 if (room_obj.name == "Starting Room") { 321 if (room_obj.name == "Starting Room") {
297 new_boundary.push_back( 322 new_boundary.push_back(
298 {.destination_room = GD_GetRoomByName("Pilgrim Antechamber"), 323 {.source_room = room_exit.destination_room,
324 .destination_room = GD_GetRoomByName("Pilgrim Antechamber"),
299 .door = 325 .door =
300 GD_GetDoorByName("Pilgrim Antechamber - Sun Painting"), 326 GD_GetDoorByName("Pilgrim Antechamber - Sun Painting"),
301 .type = EntranceType::kPainting}); 327 .type = EntranceType::kPainting});
@@ -336,6 +362,21 @@ class StateCalculator {
336 return door_report_; 362 return door_report_;
337 } 363 }
338 364
365 bool IsPilgrimageDoable() const { return pilgrimage_doable_; }
366
367 std::string GetPathToRoom(int room_id) const {
368 if (!paths_.count(room_id)) {
369 return "";
370 }
371
372 const std::list<int>& path = paths_.at(room_id);
373 std::vector<std::string> room_names;
374 for (int room_id : path) {
375 room_names.push_back(GD_GetRoom(room_id).name);
376 }
377 return hatkirby::implode(room_names, " -> ");
378 }
379
339 private: 380 private:
340 Decision IsNonGroupedDoorReachable(const Door& door_obj) { 381 Decision IsNonGroupedDoorReachable(const Door& door_obj) {
341 bool has_item = AP_HasItem(door_obj.ap_item_id); 382 bool has_item = AP_HasItem(door_obj.ap_item_id);
@@ -534,6 +575,8 @@ class StateCalculator {
534 } 575 }
535 } 576 }
536 577
578 pilgrimage_doable_ = true;
579
537 return kYes; 580 return kYes;
538 } 581 }
539 582
@@ -574,6 +617,9 @@ class StateCalculator {
574 std::set<int> solveable_panels_; 617 std::set<int> solveable_panels_;
575 std::set<int> reachable_paintings_; 618 std::set<int> reachable_paintings_;
576 std::map<int, std::map<std::string, bool>> door_report_; 619 std::map<int, std::map<std::string, bool>> door_report_;
620 bool pilgrimage_doable_ = false;
621
622 std::map<int, std::list<int>> paths_;
577}; 623};
578 624
579} // namespace 625} // namespace
@@ -623,6 +669,7 @@ void RecalculateReachability() {
623 std::swap(GetState().reachable_doors, new_reachable_doors); 669 std::swap(GetState().reachable_doors, new_reachable_doors);
624 std::swap(GetState().reachable_paintings, reachable_paintings); 670 std::swap(GetState().reachable_paintings, reachable_paintings);
625 std::swap(GetState().door_reports, door_reports); 671 std::swap(GetState().door_reports, door_reports);
672 GetState().pilgrimage_doable = state_calculator.IsPilgrimageDoable();
626} 673}
627 674
628bool IsLocationReachable(int location_id) { 675bool IsLocationReachable(int location_id) {
@@ -652,3 +699,9 @@ const std::map<std::string, bool>& GetDoorRequirements(int door_id) {
652 699
653 return GetState().door_reports[door_id]; 700 return GetState().door_reports[door_id];
654} 701}
702
703bool IsPilgrimageDoable() {
704 std::lock_guard reachability_guard(GetState().reachability_mutex);
705
706 return GetState().pilgrimage_doable;
707}