From 2944687cbbaa53d0815fea9f5f2506500e2e1db3 Mon Sep 17 00:00:00 2001
From: Star Rauchenberger <fefferburbia@gmail.com>
Date: Sun, 9 Jun 2024 23:52:14 -0400
Subject: Fix panel door reachability calculation

---
 src/tracker_state.cpp | 69 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 38 insertions(+), 31 deletions(-)

(limited to 'src')

diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp
index fb143f8..eaf3e6b 100644
--- a/src/tracker_state.cpp
+++ b/src/tracker_state.cpp
@@ -15,11 +15,12 @@ namespace {
 struct Requirements {
   bool disabled = false;
 
-  std::set<int> doors;      // non-grouped, handles progressive
-  std::set<int> items;      // all other items
-  std::set<int> rooms;      // maybe
-  bool mastery = false;     // maybe
-  bool panel_hunt = false;  // maybe
+  std::set<int> doors;       // non-grouped, handles progressive
+  std::set<int> panel_doors; // non-grouped, handles progressive
+  std::set<int> items;       // all other items
+  std::set<int> rooms;       // maybe
+  bool mastery = false;      // maybe
+  bool panel_hunt = false;   // maybe
 
   void Merge(const Requirements& rhs) {
     if (rhs.disabled) {
@@ -29,6 +30,9 @@ struct Requirements {
     for (int id : rhs.doors) {
       doors.insert(id);
     }
+    for (int id : rhs.panel_doors) {
+      panel_doors.insert(id);
+    }
     for (int id : rhs.items) {
       items.insert(id);
     }
@@ -74,15 +78,14 @@ class RequirementCalculator {
             requirements.doors.insert(door_obj.id);
             break;
         }
-      } else if (AP_GetDoorShuffleMode() == kNO_DOORS || door_obj.skip_item) {
+      } else if (AP_GetDoorShuffleMode() != kDOORS_MODE || door_obj.skip_item) {
         requirements.rooms.insert(door_obj.room);
 
         for (int panel_id : door_obj.panels) {
           const Requirements& panel_reqs = GetPanel(panel_id);
           requirements.Merge(panel_reqs);
         }
-      } else if (AP_GetDoorShuffleMode() == kSIMPLE_DOORS &&
-                 !door_obj.group_name.empty()) {
+      } else if (AP_AreDoorsGrouped() && !door_obj.group_name.empty()) {
         requirements.items.insert(door_obj.group_ap_item_id);
       } else {
         requirements.doors.insert(door_obj.id);
@@ -129,6 +132,17 @@ class RequirementCalculator {
           requirements.items.insert(GD_GetItemIdForColor(color));
         }
       }
+      
+      if (panel_obj.panel_door != -1 &&
+          AP_GetDoorShuffleMode() == kPANELS_MODE) {
+        const PanelDoor& panel_door_obj = GD_GetPanelDoor(panel_obj.panel_door);
+
+        if (panel_door_obj.group_ap_item_id != -1 && AP_AreDoorsGrouped()) {
+          requirements.items.insert(panel_door_obj.group_ap_item_id);
+        } else {
+          requirements.panel_doors.insert(panel_obj.panel_door);
+        }
+      }
 
       panels_[panel_id] = requirements;
     }
@@ -337,7 +351,8 @@ class StateCalculator {
   }
 
  private:
-  Decision IsNonGroupedDoorReachable(const Door& door_obj) {
+  template <typename T>
+  Decision IsNonGroupedDoorReachable(const T& door_obj) {
     bool has_item = AP_HasItem(door_obj.ap_item_id);
 
     if (!has_item) {
@@ -373,6 +388,20 @@ class StateCalculator {
       }
     }
 
+    for (int panel_door_id : reqs.panel_doors) {
+      const PanelDoor& panel_door_obj = GD_GetPanelDoor(panel_door_id);
+      Decision decision = IsNonGroupedDoorReachable(panel_door_obj);
+
+      if (report) {
+        (*report)[AP_GetItemName(panel_door_obj.ap_item_id)] =
+            (decision == kYes);
+      }
+
+      if (decision != kYes) {
+        final_decision = decision;
+      }
+    }
+
     for (int item_id : reqs.items) {
       bool has_item = AP_HasItem(item_id);
       if (report) {
@@ -486,28 +515,6 @@ class StateCalculator {
       return IsDoorReachable(*painting.door);
     }
 
-    if (panel_obj.panel_door != -1 && AP_GetDoorShuffleMode() == kPANELS_MODE) {
-      const PanelDoor& panel_door_obj = GD_GetPanelDoor(panel_obj.panel_door);
-
-      if (AP_AreDoorsGrouped() && panel_door_obj.group_ap_item_id != -1) {
-        return AP_HasItem(panel_door_obj.group_ap_item_id) ? kYes : kNo;
-      } else {
-        bool has_item = AP_HasItem(panel_door_obj.ap_item_id);
-
-        if (!has_item) {
-          for (const ProgressiveRequirement& prog_req :
-               panel_door_obj.progressives) {
-            if (AP_HasItem(prog_req.ap_item_id, prog_req.quantity)) {
-              has_item = true;
-              break;
-            }
-          }
-        }
-
-        return has_item ? kYes : kNo;
-      }
-    }
-
     return kYes;
   }
 
-- 
cgit 1.4.1