diff options
Diffstat (limited to 'src/tracker_state.cpp')
| -rw-r--r-- | src/tracker_state.cpp | 95 |
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 | ||
| 13 | namespace { | 17 | namespace { |
| 14 | 18 | ||
| 15 | struct Requirements { | 19 | struct 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 |
