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.cpp83
1 files changed, 69 insertions, 14 deletions
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
27class StateCalculator;
28
27struct StateCalculatorOptions { 29struct 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
32class StateCalculator { 35class 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