depend on factory data instead of BuildingSystem in the AI path
Ten queries that read nothing but FactoryState become free functions in FactoryQueries.h; the BuildingSystem methods stay as one-line forwards, so no existing caller moves yet. That lets the AI path drop its dependency on the system entirely. AiSystem, SalvagerSystem, DeliverScrapEvaluator and DeliverScrapExecutor took a BuildingSystem& purely to call findBuilding, findNearestBuilding and deliverScrapToSalvageBay — all three are state-pure — so they now take FactoryState& and say what they actually read. Four forward declarations of BuildingSystem go with them. No facade: the queries are plain free functions over the data. A facade was considered to spare the ~180 UI call sites, but the AI needed only the data and would have been given GameConfig it has no use for. isProductionBuildingType moves to BuildingType.h beside isAutoRecipeBuildingType and isBeltSubsystemType rather than being copied into the new file. Verified with a golden-checksum capture before and after — all four sample ticks identical. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHcUerKAZKWNvSKJxYKbnG
This commit is contained in:
122
src/lib/sim/FactoryQueries.cpp
Normal file
122
src/lib/sim/FactoryQueries.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "FactoryQueries.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "Item.h"
|
||||
#include "ItemType.h"
|
||||
|
||||
const Building* findBuilding(const FactoryState& state, BuildingId id)
|
||||
{
|
||||
for (const Building& building : state.buildings)
|
||||
{
|
||||
if (building.id == id)
|
||||
{
|
||||
return &building;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Building* findBuilding(FactoryState& state, BuildingId id)
|
||||
{
|
||||
for (Building& building : state.buildings)
|
||||
{
|
||||
if (building.id == id)
|
||||
{
|
||||
return &building;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ConstructionSite* findSite(const FactoryState& state, BuildingId id)
|
||||
{
|
||||
for (const ConstructionSite& site : state.constructionQueue)
|
||||
{
|
||||
if (site.id == id)
|
||||
{
|
||||
return &site;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<Building> getAllBuildings(const FactoryState& state)
|
||||
{
|
||||
return state.buildings;
|
||||
}
|
||||
|
||||
std::vector<ConstructionSite> getAllSites(const FactoryState& state)
|
||||
{
|
||||
return std::vector<ConstructionSite>(state.constructionQueue.begin(),
|
||||
state.constructionQueue.end());
|
||||
}
|
||||
|
||||
int getProductionBuildingCount(const FactoryState& state)
|
||||
{
|
||||
int count = 0;
|
||||
for (const Building& b : state.buildings)
|
||||
{
|
||||
if (isProductionBuildingType(b.type)) { ++count; }
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int getActiveProductionBuildingCount(const FactoryState& state)
|
||||
{
|
||||
int count = 0;
|
||||
for (const Building& b : state.buildings)
|
||||
{
|
||||
if (isProductionBuildingType(b.type) && b.production.has_value()) { ++count; }
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool isTileOccupied(const FactoryState& state, QPoint tile)
|
||||
{
|
||||
return state.grid.isOccupied(tile);
|
||||
}
|
||||
|
||||
const Building* findNearestBuilding(const FactoryState& state, QVector2D worldPos,
|
||||
BuildingType type)
|
||||
{
|
||||
const Building* best = nullptr;
|
||||
float bestDist = std::numeric_limits<float>::max();
|
||||
for (const Building& b : state.buildings)
|
||||
{
|
||||
if (b.type != type)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QVector2D center(b.anchor.x() + b.footprint.width() / 2.0f,
|
||||
b.anchor.y() + b.footprint.height() / 2.0f);
|
||||
float dist = (center - worldPos).length();
|
||||
if (dist < bestDist)
|
||||
{
|
||||
bestDist = dist;
|
||||
best = &b;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
bool deliverScrapToSalvageBay(FactoryState& state, BuildingId bayId)
|
||||
{
|
||||
Building* bay = findBuilding(state, bayId);
|
||||
if (!bay || bay->type != BuildingType::SalvageBay)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (bay->queuedForDeconstruction)
|
||||
{
|
||||
return false; // queued for deconstruction: stopped operating (REQ-BLD-DECON-QUEUE)
|
||||
}
|
||||
// Emerging scrap still counts against the bay's holding capacity
|
||||
// (REQ-MAT-OUTPUT-EMERGE).
|
||||
if (bay->getOutputItemCount() >= bay->outputBuffer.capacity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bay->outputBuffer.items.push_back(Item{ItemType{"scrap"}});
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user