From 8e89e198830a0908ddd8f4c91cbc2bff08b0b32c Mon Sep 17 00:00:00 2001
From: Star Rauchenberger <fefferburbia@gmail.com>
Date: Sun, 17 Sep 2023 12:42:46 -0400
Subject: Use hardcoded AP ids now

---
 src/ap_state.cpp      |  87 +++++---------------------------------
 src/ap_state.h        |   6 +--
 src/area_popup.cpp    |   4 +-
 src/game_data.cpp     | 113 +++++++++++++++++++++++++++++++++++++++++++++++---
 src/game_data.h       |   7 ++++
 src/tracker_panel.cpp |  10 ++---
 src/tracker_state.cpp |  20 ++++-----
 src/tracker_state.h   |   2 +-
 8 files changed, 143 insertions(+), 106 deletions(-)

(limited to 'src')

diff --git a/src/ap_state.cpp b/src/ap_state.cpp
index ced4f83..8bc7ed0 100644
--- a/src/ap_state.cpp
+++ b/src/ap_state.cpp
@@ -52,11 +52,6 @@ struct APState {
   std::set<int64_t> checked_locations;
   std::map<std::string, bool> data_storage;
 
-  std::map<std::tuple<int, int>, int64_t> ap_id_by_location_id;
-  std::map<std::string, int64_t> ap_id_by_item_name;
-  std::map<LingoColor, int64_t> ap_id_by_color;
-  std::map<int64_t, std::string> progressive_item_by_ap_id;
-
   DoorShuffleMode door_shuffle_mode = kNO_DOORS;
   bool color_shuffle = false;
   bool painting_shuffle = false;
@@ -302,78 +297,18 @@ struct APState {
     }
 
     if (connected) {
-      for (const MapArea& map_area : GD_GetMapAreas()) {
-        for (int section_id = 0; section_id < map_area.locations.size();
-             section_id++) {
-          const Location& location = map_area.locations.at(section_id);
-
-          int64_t ap_id = apclient->get_location_id(location.ap_location_name);
-          if (ap_id == APClient::INVALID_NAME_ID) {
-            TrackerLog("Could not find AP location ID for " +
-                       location.ap_location_name);
-          } else {
-            ap_id_by_location_id[{map_area.id, section_id}] = ap_id;
-          }
-        }
-      }
-
-      for (const Door& door : GD_GetDoors()) {
-        if (!door.skip_item) {
-          ap_id_by_item_name[door.item_name] = GetItemId(door.item_name);
-
-          if (!door.group_name.empty() &&
-              !ap_id_by_item_name.count(door.group_name)) {
-            ap_id_by_item_name[door.group_name] = GetItemId(door.group_name);
-          }
-
-          for (const ProgressiveRequirement& prog_req : door.progressives) {
-            ap_id_by_item_name[prog_req.item_name] =
-                GetItemId(prog_req.item_name);
-          }
-        }
-      }
-
-      ap_id_by_color[LingoColor::kBlack] = GetItemId("Black");
-      ap_id_by_color[LingoColor::kRed] = GetItemId("Red");
-      ap_id_by_color[LingoColor::kBlue] = GetItemId("Blue");
-      ap_id_by_color[LingoColor::kYellow] = GetItemId("Yellow");
-      ap_id_by_color[LingoColor::kPurple] = GetItemId("Purple");
-      ap_id_by_color[LingoColor::kOrange] = GetItemId("Orange");
-      ap_id_by_color[LingoColor::kGreen] = GetItemId("Green");
-      ap_id_by_color[LingoColor::kBrown] = GetItemId("Brown");
-      ap_id_by_color[LingoColor::kGray] = GetItemId("Gray");
-
       RefreshTracker();
     } else {
       client_active = false;
     }
   }
 
-  bool HasCheckedGameLocation(int area_id, int section_id) {
-    std::tuple<int, int> location_key = {area_id, section_id};
-
-    if (ap_id_by_location_id.count(location_key)) {
-      return checked_locations.count(ap_id_by_location_id.at(location_key));
-    } else {
-      return false;
-    }
-  }
-
-  bool HasColorItem(LingoColor color) {
-    if (ap_id_by_color.count(color)) {
-      return inventory.count(ap_id_by_color.at(color));
-    } else {
-      return false;
-    }
+  bool HasCheckedGameLocation(int location_id) {
+    return checked_locations.count(location_id);
   }
 
-  bool HasItem(const std::string& item, int quantity) {
-    if (ap_id_by_item_name.count(item)) {
-      int64_t ap_id = ap_id_by_item_name.at(item);
-      return inventory.count(ap_id) && inventory.at(ap_id) >= quantity;
-    } else {
-      return false;
-    }
+  bool HasItem(int item_id, int quantity) {
+    return inventory.count(item_id) && inventory.at(item_id) >= quantity;
   }
 
   bool HasAchievement(const std::string& name) {
@@ -417,16 +352,12 @@ void AP_Connect(std::string server, std::string player, std::string password) {
   GetState().Connect(server, player, password);
 }
 
-bool AP_HasCheckedGameLocation(int area_id, int section_id) {
-  return GetState().HasCheckedGameLocation(area_id, section_id);
+bool AP_HasCheckedGameLocation(int location_id) {
+  return GetState().HasCheckedGameLocation(location_id);
 }
 
-bool AP_HasColorItem(LingoColor color) {
-  return GetState().HasColorItem(color);
-}
-
-bool AP_HasItem(const std::string& item, int quantity) {
-  return GetState().HasItem(item, quantity);
+bool AP_HasItem(int item_id, int quantity) {
+  return GetState().HasItem(item_id, quantity);
 }
 
 DoorShuffleMode AP_GetDoorShuffleMode() { return GetState().door_shuffle_mode; }
@@ -451,6 +382,8 @@ bool AP_IsLocationVisible(int classification) {
       return classification & kLOCATION_REDUCED;
     case kPANELSANITY:
       return classification & kLOCATION_INSANITY;
+    default:
+      return false;
   }
 }
 
diff --git a/src/ap_state.h b/src/ap_state.h
index e9b9f92..64caeea 100644
--- a/src/ap_state.h
+++ b/src/ap_state.h
@@ -18,11 +18,9 @@ void AP_SetTrackerFrame(TrackerFrame* tracker_frame);
 
 void AP_Connect(std::string server, std::string player, std::string password);
 
-bool AP_HasCheckedGameLocation(int area_id, int section_id);
+bool AP_HasCheckedGameLocation(int location_id);
 
-bool AP_HasColorItem(LingoColor color);
-
-bool AP_HasItem(const std::string& item, int quantity = 1);
+bool AP_HasItem(int item_id, int quantity = 1);
 
 DoorShuffleMode AP_GetDoorShuffleMode();
 
diff --git a/src/area_popup.cpp b/src/area_popup.cpp
index 28554d0..0657ea3 100644
--- a/src/area_popup.cpp
+++ b/src/area_popup.cpp
@@ -57,8 +57,8 @@ void AreaPopup::UpdateIndicators() {
       container_sizer->Show(eye_indicators_[section_id]);
     }
 
-    bool checked = AP_HasCheckedGameLocation(area_id_, section_id);
-    bool reachable = IsLocationReachable(area_id_, section_id);
+    bool checked = AP_HasCheckedGameLocation(location.ap_location_id);
+    bool reachable = IsLocationReachable(location.ap_location_id);
     const wxColour* text_color = reachable ? wxWHITE : wxRED;
 
     section_labels_[section_id]->SetForegroundColour(*text_color);
diff --git a/src/game_data.cpp b/src/game_data.cpp
index 06eb80a..f51d7ac 100644
--- a/src/game_data.cpp
+++ b/src/game_data.cpp
@@ -30,7 +30,10 @@ LingoColor GetColorForString(const std::string &str) {
   } else if (str == "purple") {
     return LingoColor::kPurple;
   } else {
-    std::cout << "Invalid color: " << str << std::endl;
+    std::ostringstream errmsg;
+    errmsg << "Invalid color: " << str;
+    TrackerLog(errmsg.str());
+
     return LingoColor::kNone;
   }
 }
@@ -52,6 +55,8 @@ struct GameData {
 
   std::vector<int> achievement_panels_;
 
+  std::map<LingoColor, int> ap_id_by_color_;
+
   bool loaded_area_data_ = false;
   std::set<std::string> malconfigured_areas_;
 
@@ -59,6 +64,31 @@ struct GameData {
     YAML::Node lingo_config = YAML::LoadFile("assets/LL1.yaml");
     YAML::Node areas_config = YAML::LoadFile("assets/areas.yaml");
     YAML::Node pilgrimage_config = YAML::LoadFile("assets/pilgrimage.yaml");
+    YAML::Node ids_config = YAML::LoadFile("assets/ids.yaml");
+
+    auto init_color_id = [this, &ids_config](const std::string &color_name) {
+      if (ids_config["special_items"] &&
+          ids_config["special_items"][color_name]) {
+        std::string input_name = color_name;
+        input_name[0] = std::tolower(input_name[0]);
+        ap_id_by_color_[GetColorForString(input_name)] =
+            ids_config["special_items"][color_name].as<int>();
+      } else {
+        std::ostringstream errmsg;
+        errmsg << "Missing AP item ID for color " << color_name;
+        TrackerLog(errmsg.str());
+      }
+    };
+
+    init_color_id("Black");
+    init_color_id("Red");
+    init_color_id("Blue");
+    init_color_id("Yellow");
+    init_color_id("Green");
+    init_color_id("Orange");
+    init_color_id("Purple");
+    init_color_id("Brown");
+    init_color_id("Gray");
 
     rooms_.reserve(lingo_config.size() * 2);
 
@@ -225,6 +255,17 @@ struct GameData {
           if (panel_it.second["non_counting"]) {
             panel_obj.non_counting = panel_it.second["non_counting"].as<bool>();
           }
+
+          if (ids_config["panels"] && ids_config["panels"][room_obj.name] &&
+              ids_config["panels"][room_obj.name][panel_obj.name]) {
+            panel_obj.ap_location_id =
+                ids_config["panels"][room_obj.name][panel_obj.name].as<int>();
+          } else {
+            std::ostringstream errmsg;
+            errmsg << "Missing AP location ID for panel " << room_obj.name
+                   << " - " << panel_obj.name;
+            TrackerLog(errmsg.str());
+          }
         }
       }
 
@@ -272,8 +313,34 @@ struct GameData {
             door_obj.item_name = room_obj.name + " - " + door_obj.name;
           }
 
+          if (!door_it.second["skip_item"] && !door_it.second["event"]) {
+            if (ids_config["doors"] && ids_config["doors"][room_obj.name] &&
+                ids_config["doors"][room_obj.name][door_obj.name] &&
+                ids_config["doors"][room_obj.name][door_obj.name]["item"]) {
+              door_obj.ap_item_id =
+                  ids_config["doors"][room_obj.name][door_obj.name]["item"]
+                      .as<int>();
+            } else {
+              std::ostringstream errmsg;
+              errmsg << "Missing AP item ID for door " << room_obj.name << " - "
+                     << door_obj.name;
+              TrackerLog(errmsg.str());
+            }
+          }
+
           if (door_it.second["group"]) {
             door_obj.group_name = door_it.second["group"].as<std::string>();
+
+            if (ids_config["door_groups"] &&
+                ids_config["door_groups"][door_obj.group_name]) {
+              door_obj.group_ap_item_id =
+                  ids_config["door_groups"][door_obj.group_name].as<int>();
+            } else {
+              std::ostringstream errmsg;
+              errmsg << "Missing AP item ID for door group "
+                     << door_obj.group_name;
+              TrackerLog(errmsg.str());
+            }
           }
 
           if (door_it.second["location_name"]) {
@@ -282,18 +349,34 @@ struct GameData {
           } else if (!door_it.second["skip_location"] &&
                      !door_it.second["event"]) {
             if (has_external_panels) {
-              std::cout
+              std::ostringstream errmsg;
+              errmsg
                   << room_obj.name << " - " << door_obj.name
                   << " has panels from other rooms but does not have an "
                      "explicit "
-                     "location name and is not marked skip_location or event"
-                  << std::endl;
+                     "location name and is not marked skip_location or event";
+              TrackerLog(errmsg.str());
             }
 
             door_obj.location_name =
                 room_obj.name + " - " + hatkirby::implode(panel_names, ", ");
           }
 
+          if (!door_it.second["skip_location"] && !door_it.second["event"]) {
+            if (ids_config["doors"] && ids_config["doors"][room_obj.name] &&
+                ids_config["doors"][room_obj.name][door_obj.name] &&
+                ids_config["doors"][room_obj.name][door_obj.name]["location"]) {
+              door_obj.ap_location_id =
+                  ids_config["doors"][room_obj.name][door_obj.name]["location"]
+                      .as<int>();
+            } else {
+              std::ostringstream errmsg;
+              errmsg << "Missing AP location ID for door " << room_obj.name
+                     << " - " << door_obj.name;
+              TrackerLog(errmsg.str());
+            }
+          }
+
           if (door_it.second["include_reduce"]) {
             door_obj.exclude_reduce =
                 !door_it.second["include_reduce"].as<bool>();
@@ -330,6 +413,18 @@ struct GameData {
           std::string progressive_item_name =
               progression_it.first.as<std::string>();
 
+          int progressive_item_id = -1;
+          if (ids_config["progression"] &&
+              ids_config["progression"][progressive_item_name]) {
+            progressive_item_id =
+                ids_config["progression"][progressive_item_name].as<int>();
+          } else {
+            std::ostringstream errmsg;
+            errmsg << "Missing AP item ID for progressive item "
+                   << progressive_item_name;
+            TrackerLog(errmsg.str());
+          }
+
           int index = 1;
           for (const auto &stage : progression_it.second) {
             int door_id = -1;
@@ -342,7 +437,9 @@ struct GameData {
             }
 
             doors_[door_id].progressives.push_back(
-                {.item_name = progressive_item_name, .quantity = index});
+                {.item_name = progressive_item_name,
+                 .ap_item_id = progressive_item_id,
+                 .quantity = index});
             index++;
           }
         }
@@ -393,6 +490,7 @@ struct GameData {
       map_area.locations.push_back(
           {.name = panel.name,
            .ap_location_name = room_name + " - " + panel.name,
+           .ap_location_id = panel.ap_location_id,
            .room = panel.room,
            .panels = {panel.id},
            .classification = classification});
@@ -436,6 +534,7 @@ struct GameData {
           // room field should be the original room ID
           map_area.locations.push_back({.name = section_name,
                                         .ap_location_name = door.location_name,
+                                        .ap_location_id = door.ap_location_id,
                                         .room = door.room,
                                         .panels = door.panels,
                                         .classification = classification});
@@ -564,3 +663,7 @@ int GD_GetRoomForPainting(const std::string &painting_id) {
 const std::vector<int> &GD_GetAchievementPanels() {
   return GetState().achievement_panels_;
 }
+
+int GD_GetItemIdForColor(LingoColor color) {
+  return GetState().ap_id_by_color_.at(color);
+}
diff --git a/src/game_data.h b/src/game_data.h
index d9c909b..b3e2466 100644
--- a/src/game_data.h
+++ b/src/game_data.h
@@ -36,10 +36,12 @@ struct Panel {
   bool achievement = false;
   std::string achievement_name;
   bool non_counting = false;
+  int ap_location_id = -1;
 };
 
 struct ProgressiveRequirement {
   std::string item_name;
+  int ap_item_id = -1;
   int quantity = 0;
 };
 
@@ -55,6 +57,9 @@ struct Door {
   std::vector<int> panels;
   bool exclude_reduce = true;
   std::vector<ProgressiveRequirement> progressives;
+  int ap_item_id = -1;
+  int group_ap_item_id = -1;
+  int ap_location_id = -1;
 };
 
 struct Exit {
@@ -78,6 +83,7 @@ struct Room {
 struct Location {
   std::string name;
   std::string ap_location_name;
+  int ap_location_id = -1;
   int room;
   std::vector<int> panels;
   int classification = 0;
@@ -101,5 +107,6 @@ const Door& GD_GetDoor(int door_id);
 const Panel& GD_GetPanel(int panel_id);
 int GD_GetRoomForPainting(const std::string& painting_id);
 const std::vector<int>& GD_GetAchievementPanels();
+int GD_GetItemIdForColor(LingoColor color);
 
 #endif /* end of include guard: GAME_DATA_H_9C42AC51 */
diff --git a/src/tracker_panel.cpp b/src/tracker_panel.cpp
index 40d3ced..5580068 100644
--- a/src/tracker_panel.cpp
+++ b/src/tracker_panel.cpp
@@ -104,12 +104,10 @@ void TrackerPanel::Redraw() {
 
     bool has_reachable_unchecked = false;
     bool has_unreachable_unchecked = false;
-    for (int section_id = 0; section_id < map_area.locations.size();
-         section_id++) {
-      if (AP_IsLocationVisible(
-              map_area.locations.at(section_id).classification) &&
-          !AP_HasCheckedGameLocation(area.area_id, section_id)) {
-        if (IsLocationReachable(area.area_id, section_id)) {
+    for (const Location &section : map_area.locations) {
+      if (AP_IsLocationVisible(section.classification) &&
+          !AP_HasCheckedGameLocation(section.ap_location_id)) {
+        if (IsLocationReachable(section.ap_location_id)) {
           has_reachable_unchecked = true;
         } else {
           has_unreachable_unchecked = true;
diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp
index e462b29..cc19b19 100644
--- a/src/tracker_state.cpp
+++ b/src/tracker_state.cpp
@@ -12,7 +12,7 @@
 namespace {
 
 struct TrackerState {
-  std::map<std::tuple<int, int>, bool> reachability;
+  std::map<int, bool> reachability;
 };
 
 enum Decision { kYes, kNo, kMaybe };
@@ -41,13 +41,13 @@ Decision IsDoorReachable_Helper(int door_id,
     return kYes;
   } else if (AP_GetDoorShuffleMode() == kSIMPLE_DOORS &&
              !door_obj.group_name.empty()) {
-    return AP_HasItem(door_obj.group_name) ? kYes : kNo;
+    return AP_HasItem(door_obj.group_ap_item_id) ? kYes : kNo;
   } else {
-    bool has_item = AP_HasItem(door_obj.item_name);
+    bool has_item = AP_HasItem(door_obj.ap_item_id);
 
     if (!has_item) {
       for (const ProgressiveRequirement& prog_req : door_obj.progressives) {
-        if (AP_HasItem(prog_req.item_name, prog_req.quantity)) {
+        if (AP_HasItem(prog_req.ap_item_id, prog_req.quantity)) {
           has_item = true;
           break;
         }
@@ -127,7 +127,7 @@ Decision IsPanelReachable_Helper(int panel_id,
 
   if (AP_IsColorShuffle()) {
     for (LingoColor color : panel_obj.colors) {
-      if (!AP_HasColorItem(color)) {
+      if (!AP_HasItem(GD_GetItemIdForColor(color))) {
         return kNo;
       }
     }
@@ -232,16 +232,14 @@ void RecalculateReachability() {
         }
       }
 
-      GetState().reachability[{map_area.id, section_id}] = reachable;
+      GetState().reachability[location_section.ap_location_id] = reachable;
     }
   }
 }
 
-bool IsLocationReachable(int area_id, int section_id) {
-  std::tuple<int, int> key = {area_id, section_id};
-
-  if (GetState().reachability.count(key)) {
-    return GetState().reachability.at(key);
+bool IsLocationReachable(int location_id) {
+  if (GetState().reachability.count(location_id)) {
+    return GetState().reachability.at(location_id);
   } else {
     return false;
   }
diff --git a/src/tracker_state.h b/src/tracker_state.h
index d8256e2..e73607f 100644
--- a/src/tracker_state.h
+++ b/src/tracker_state.h
@@ -3,6 +3,6 @@
 
 void RecalculateReachability();
 
-bool IsLocationReachable(int area_id, int section_id);
+bool IsLocationReachable(int location_id);
 
 #endif /* end of include guard: TRACKER_STATE_H_8639BC90 */
-- 
cgit 1.4.1