#include "terrainyieldmanager.h" #include "yamlparser.h" #include "pathfinder.h" #include #include TerrainYieldManager& TerrainYieldManager::instance() { static TerrainYieldManager s_instance; return s_instance; } TerrainYieldManager::TerrainYieldManager() : m_loaded(false) { } bool TerrainYieldManager::loadConfigs(const QString &baseDir) { // 1. Load city.yaml QString cityFile = baseDir + "/config/city.yaml"; YamlNode cityRoot = YamlParser::parseFile(cityFile); if (!cityRoot.children.isEmpty()) { m_cityConfig.initialInhabitants = cityRoot["initial_inhabitants"].asInt(1000); m_cityConfig.inhabitantsPerPop = cityRoot["inhabitants_per_pop"].asInt(100000); m_cityConfig.initialBorderRadius = cityRoot["initial_border_radius"].asInt(1); m_cityConfig.maxWorkableRadius = cityRoot["max_workable_radius"].asInt(3); m_cityConfig.defaultTileSlots = cityRoot["default_tile_slots"].asInt(1); } // 2. Load terrain_yields.yaml QString yieldsFile = baseDir + "/config/terrain_yields.yaml"; YamlNode yieldsRoot = YamlParser::parseFile(yieldsFile); for (auto it = yieldsRoot.children.begin(); it != yieldsRoot.children.end(); ++it) { QString typeKey = it.key(); const YamlNode &node = it.value(); TerrainYieldConfig cfg; cfg.id = typeKey; cfg.name = node["name"].asString(typeKey); cfg.workable = node["workable"].asBool(true); cfg.defaultSlots = node["default_slots"].asInt(cfg.workable ? 1 : 0); cfg.primaryResource = node["primary_resource"].asString("voedsel"); if (node.hasChild("yields")) { const YamlNode &yNode = node["yields"]; for (auto yIt = yNode.children.begin(); yIt != yNode.children.end(); ++yIt) { cfg.yields[yIt.key()] = yIt.value().asInt(0); } } m_yieldConfigs[typeKey] = cfg; } m_loaded = true; qDebug() << "TerrainYieldManager loaded" << m_yieldConfigs.size() << "terrain types and city config."; return true; } QString TerrainYieldManager::getTerrainType(int tx, int ty, Matrix2D *mapPoints, int numPoints05) const { if (!mapPoints || numPoints05 <= 0) return "grasland"; QVector2D w = Pathfinder::hexToWorld(tx, ty); float scaleX = numPoints05 * 2.0f; float scaleY = numPoints05 / LOD_0_SIZE_Y; int mapX = (int) std::round(w.x() * scaleX); int mapY = (int) std::round(w.y() * scaleY); if (mapX < 0) mapX = 0; if (mapX >= (int)mapPoints->getWidth()) mapX = (int)mapPoints->getWidth() - 1; if (mapY < 0) mapY = 0; if (mapY >= (int)mapPoints->getHeight()) mapY = (int)mapPoints->getHeight() - 1; TerrainPoint tp = mapPoints->operator()(mapX, mapY); // Sea level water if (tp.height < 6) return "water"; float heightKm = (tp.height / 255.0f) * 3.5f + 1.0f; // High peaks have snow if (heightKm >= 3.1f) return "sneeuw"; // Mountain rock if (heightKm >= 2.3f) return "steen"; switch (tp.type) { case 0: return "grasland"; case 1: return "sahara"; case 2: return "tundra"; case 3: return "red_canyon"; case 4: return "bos"; default: return "grasland"; } } const TerrainYieldConfig* TerrainYieldManager::getYieldConfig(const QString &terrainType) const { auto it = m_yieldConfigs.find(terrainType); if (it != m_yieldConfigs.end()) { return &it.value(); } return nullptr; }