From 149e7c0836927e14a926a952bd1a7f0d1b49e779 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Fri, 5 May 2023 15:46:58 -0400 Subject: Organised repo --- src/tracker_state.cpp | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 src/tracker_state.cpp (limited to 'src/tracker_state.cpp') diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp new file mode 100644 index 0000000..858ec3e --- /dev/null +++ b/src/tracker_state.cpp @@ -0,0 +1,181 @@ +#include "tracker_state.h" + +#include +#include + +#include "ap_state.h" +#include "game_data.h" + +bool IsDoorReachable_Helper(int door_id, const std::set& reachable_rooms); + +bool IsPanelReachable_Helper(int panel_id, + const std::set& reachable_rooms) { + const Panel& panel_obj = GetGameData().GetPanel(panel_id); + + if (!reachable_rooms.count(panel_obj.room)) { + return false; + } + + if (panel_obj.name == "THE MASTER") { + int achievements_accessible = 0; + + for (int achieve_id : GetGameData().GetAchievementPanels()) { + if (IsPanelReachable_Helper(achieve_id, reachable_rooms)) { + achievements_accessible++; + + if (achievements_accessible >= AP_GetMasteryRequirement()) { + break; + } + } + } + + return (achievements_accessible >= AP_GetMasteryRequirement()); + } + + for (int room_id : panel_obj.required_rooms) { + if (!reachable_rooms.count(room_id)) { + return false; + } + } + + for (int door_id : panel_obj.required_doors) { + if (!IsDoorReachable_Helper(door_id, reachable_rooms)) { + return false; + } + } + + if (AP_IsColorShuffle()) { + for (LingoColor color : panel_obj.colors) { + if (!AP_HasColorItem(color)) { + return false; + } + } + } + + return true; +} + +bool IsDoorReachable_Helper(int door_id, const std::set& reachable_rooms) { + const Door& door_obj = GetGameData().GetDoor(door_id); + + if (AP_GetDoorShuffleMode() == kNO_DOORS || door_obj.skip_item) { + if (!reachable_rooms.count(door_obj.room)) { + return false; + } + + for (int panel_id : door_obj.panels) { + if (!IsPanelReachable_Helper(panel_id, reachable_rooms)) { + return false; + } + } + + return true; + } else if (AP_GetDoorShuffleMode() == kSIMPLE_DOORS && + !door_obj.group_name.empty()) { + return AP_HasItem(door_obj.group_name); + } else { + bool has_item = AP_HasItem(door_obj.item_name); + + if (!has_item) { + for (const ProgressiveRequirement& prog_req : door_obj.progressives) { + if (AP_HasItem(prog_req.item_name, prog_req.quantity)) { + has_item = true; + break; + } + } + } + + return has_item; + } +} + +void TrackerState::CalculateState() { + reachability_.clear(); + + std::set reachable_rooms; + + std::list flood_boundary; + flood_boundary.push_back( + {.destination_room = GetGameData().GetRoomByName("Menu")}); + + bool reachable_changed = true; + while (reachable_changed) { + reachable_changed = false; + + std::list new_boundary; + for (const Exit& room_exit : flood_boundary) { + if (reachable_rooms.count(room_exit.destination_room)) { + continue; + } + + bool valid_transition = false; + if (room_exit.door.has_value()) { + if (IsDoorReachable_Helper(*room_exit.door, reachable_rooms)) { + valid_transition = true; + } else if (AP_GetDoorShuffleMode() == kNO_DOORS) { + new_boundary.push_back(room_exit); + } + } else { + valid_transition = true; + } + + if (valid_transition) { + reachable_rooms.insert(room_exit.destination_room); + reachable_changed = true; + + const Room& room_obj = + GetGameData().GetRoom(room_exit.destination_room); + for (const Exit& out_edge : room_obj.exits) { + if (!out_edge.painting || !AP_IsPaintingShuffle()) { + new_boundary.push_back(out_edge); + } + } + + if (AP_IsPaintingShuffle()) { + for (const PaintingExit& out_edge : room_obj.paintings) { + if (AP_GetPaintingMapping().count(out_edge.id)) { + Exit painting_exit; + painting_exit.destination_room = GetGameData().GetRoomForPainting( + AP_GetPaintingMapping().at(out_edge.id)); + painting_exit.door = out_edge.door; + + new_boundary.push_back(painting_exit); + } + } + } + } + } + + flood_boundary = new_boundary; + } + + for (const MapArea& map_area : GetGameData().GetMapAreas()) { + for (int section_id = 0; section_id < map_area.locations.size(); + section_id++) { + const Location& location_section = map_area.locations.at(section_id); + bool reachable = reachable_rooms.count(location_section.room); + if (reachable) { + for (int panel_id : location_section.panels) { + reachable &= IsPanelReachable_Helper(panel_id, reachable_rooms); + } + } + + reachability_[{map_area.id, section_id}] = reachable; + } + } +} + +bool TrackerState::IsLocationReachable(int area_id, int section_id) { + std::tuple key = {area_id, section_id}; + + if (reachability_.count(key)) { + return reachability_.at(key); + } else { + return false; + } +} + +TrackerState& GetTrackerState() { + static TrackerState* instance = new TrackerState(); + return *instance; +} -- cgit 1.4.1