From 88deef51093dbc7ce543d5eeb1d6b8c838c36aef Mon Sep 17 00:00:00 2001 From: Douwe Ravers Date: Fri, 10 Jul 2026 19:50:24 +0200 Subject: [PATCH] improved the code of Room --- douwco_hivemind/include/Entity/Room.hpp | 16 +- douwco_hivemind/src/Creeps/Builder.cpp | 2 +- douwco_hivemind/src/Entity/Room.cpp | 240 ++++++++++++++---------- 3 files changed, 159 insertions(+), 99 deletions(-) diff --git a/douwco_hivemind/include/Entity/Room.hpp b/douwco_hivemind/include/Entity/Room.hpp index 95fc3a9..fd800d5 100644 --- a/douwco_hivemind/include/Entity/Room.hpp +++ b/douwco_hivemind/include/Entity/Room.hpp @@ -15,7 +15,7 @@ public: std::vector sourceContainerIds = {}; std::vector SpawnIds = {}; std::vector screepNames = {}; - + private: int minerIterator; @@ -26,9 +26,19 @@ public: void loop(); protected: - void manageScreeps(); void manageStructures(); - void placeContainers(); + void manageScreeps(); + + void updateSourceIds(); + void updateSpawnIds(); + void updateContainerIds(); + + std::map calculateRequiredJobs(); + std::map countCurrentJobs(); + std::string getNewCreepName(CreepRole role); + std::vector getNewCreepBody(CreepRole role); + JSON getNewCreepOptions(CreepRole role); + }; } // namespace DouwcoHivemind diff --git a/douwco_hivemind/src/Creeps/Builder.cpp b/douwco_hivemind/src/Creeps/Builder.cpp index ad8d7b2..1d7ffe6 100644 --- a/douwco_hivemind/src/Creeps/Builder.cpp +++ b/douwco_hivemind/src/Creeps/Builder.cpp @@ -79,5 +79,5 @@ void DouwcoHivemind::Builder::searchConstructionSite() if (selectedConstructionSite) targetId = selectedConstructionSite->id(); else - targetId.clear(); + creep.suicide(); } diff --git a/douwco_hivemind/src/Entity/Room.cpp b/douwco_hivemind/src/Entity/Room.cpp index d0b68c0..223b59e 100644 --- a/douwco_hivemind/src/Entity/Room.cpp +++ b/douwco_hivemind/src/Entity/Room.cpp @@ -40,125 +40,73 @@ void DouwcoHivemind::Room::loop() { manageScreeps(); } -void DouwcoHivemind::Room::manageStructures() { placeContainers(); } +void DouwcoHivemind::Room::manageStructures() { + updateSourceIds(); + updateSpawnIds(); + updateContainerIds(); +} void DouwcoHivemind::Room::manageScreeps() { // Get energy data int energyAvailable = roomJs.energyAvailable(); int energyCapacityAvailable = roomJs.energyCapacityAvailable(); - // Calculate needed creep roles - int required_upgraders = 1; - int required_suppliers = 2; - int required_maintainers = 1; - int required_builders = - roomJs.find(Screeps::FIND_MY_CONSTRUCTION_SITES).size() > 0 ? 1 : 0; - int required_miners = sourceIds.size(); - - // Count existing roles - int existing_upgraders = 0; - int existing_suppliers = 0; - int existing_maintainers = 0; - int existing_builders = 0; - int existing_miners = 0; - - for (auto &creep : Engine::getInstance()->Creeps) { - CreepRole role = creep.second->role; - - if (role == CreepRole::SUPPLIER) - existing_suppliers++; - else if (role == CreepRole::UPGRADER) - existing_upgraders++; - else if (role == CreepRole::MAINTAINER) - existing_maintainers++; - else if (role == CreepRole::BUILDER) - existing_builders++; - else if (role == CreepRole::MINER) - existing_miners++; - } + // Get job status + auto requiredJobs = calculateRequiredJobs(); + auto currentJobs = countCurrentJobs(); // Check if max energy used - if (energyAvailable < energyCapacityAvailable && 0 < existing_suppliers) + if (energyAvailable < energyCapacityAvailable && 0 < currentJobs[SUPPLIER]) return; + // Select based on priority which role needs to be made first + const std::vector rolePriority = { + CreepRole::MINER, CreepRole::SUPPLIER, CreepRole::UPGRADER, + CreepRole::BUILDER, CreepRole::MAINTAINER}; + + CreepRole role = CreepRole::UNEMPLOYED; + for (CreepRole roleType : rolePriority) { + if (requiredJobs[roleType] > currentJobs[roleType]) { + role = roleType; + break; + } + } + // Set creep properties - std::string name; - JSON opts; - CreepRole role = CreepRole::UNEMPLOYED; - if (required_miners > existing_miners) { - role = CreepRole::MINER; - opts["memory"]["sourceId"] = sourceIds[minerIterator]; - minerIterator = (minerIterator + 1) % sourceIds.size(); - name = "Miner: "; - } else if (required_suppliers > existing_suppliers) { - role = CreepRole::SUPPLIER; - name = "Supplier: "; - } else if (required_upgraders > existing_upgraders) { - role = CreepRole::UPGRADER; - name = "Upgrader: "; - } else if (required_builders > existing_builders) { - role = CreepRole::BUILDER; - name = "Builder: "; - } else if (required_maintainers > existing_maintainers) { - role = CreepRole::MAINTAINER; - name = "Maintainer: "; - } else - return; - - opts["memory"]["role"] = role; - - // Build creep body - std::vector body; - // Miner body with up to 5 work (10 en/s) bits for 3000 source mining in 300 - // tick regen. - if (role == CreepRole::MINER) { - body.push_back("move"); - body.push_back("work"); - for (int i = 0; i < (energyAvailable - 150) / 100 && i < 5; i++) { - body.push_back("work"); - } - } - // Supplier body with only move and carry to move energy around - else if (role == SUPPLIER) { - for (int i = 0; i < energyAvailable / 100; i++) { - body.push_back("move"); - body.push_back("carry"); - } - } - // Worker body with balanced parts. - else { - for (int i = 0; i < energyAvailable / 200; i++) { - body.push_back("work"); - body.push_back("carry"); - body.push_back("move"); - } - } - - // If no spawns stored yet - if (SpawnIds.size() == 0) { - auto spawnStructures = roomJs.find(Screeps::FIND_MY_SPAWNS); - for (auto &spawnStructure : spawnStructures) { - SpawnIds.push_back( - static_cast(spawnStructure.get())->id()); - } - } + std::string name = getNewCreepName(role); + auto body = getNewCreepBody(role); + JSON opts = getNewCreepOptions(role); // Create creep auto spawn = static_cast( Engine::getInstance()->Structures[SpawnIds[0]].get()); std::string unique_name = name + std::to_string(Screeps::Game.time()); spawn->spawnJs.spawnCreep(body, unique_name, opts); + // Store creepname in managed list. screepNames.push_back(unique_name); } -void DouwcoHivemind::Room::placeContainers() { - // If no sources stored yet +void DouwcoHivemind::Room::updateSourceIds() { if (sourceIds.size() == 0) { - auto sources_ = roomJs.find(Screeps::FIND_SOURCES); - for (auto &source : sources_) { + auto sources = roomJs.find(Screeps::FIND_SOURCES); + for (auto &source : sources) { sourceIds.push_back(static_cast(source.get())->id()); } } +} + +void DouwcoHivemind::Room::updateSpawnIds() { + if (SpawnIds.size() == 0 || Screeps::Game.time() % 1000 == 0) { + SpawnIds.clear(); + auto spawnStructures = roomJs.find(Screeps::FIND_MY_SPAWNS); + for (auto &spawnStructure : spawnStructures) { + SpawnIds.push_back( + static_cast(spawnStructure.get())->id()); + } + } +} + +void DouwcoHivemind::Room::updateContainerIds() { // No containers planned or build, planning now if (sourceContainerIds.size() < sourceIds.size()) { int controller_x = roomJs.controller().value().pos().x(); @@ -217,3 +165,105 @@ void DouwcoHivemind::Room::placeContainers() { sourceContainerIds.erase(sourceContainerIds.begin() + i); } } + +std::map +DouwcoHivemind::Room::calculateRequiredJobs() { + std::map requiredJobs; + requiredJobs.emplace(UPGRADER, 1); + requiredJobs.emplace(SUPPLIER, 2); + requiredJobs.emplace(MAINTAINER, 1); + requiredJobs.emplace( + BUILDER, + roomJs.find(Screeps::FIND_MY_CONSTRUCTION_SITES).size() > 0 ? 1 : 0); + requiredJobs.emplace(MINER, sourceIds.size()); + return requiredJobs; +} + +std::map +DouwcoHivemind::Room::countCurrentJobs() { + std::map currentJobs; + currentJobs.emplace(UPGRADER, 0); + currentJobs.emplace(SUPPLIER, 0); + currentJobs.emplace(MAINTAINER, 0); + currentJobs.emplace(BUILDER, 0); + currentJobs.emplace(MINER, 0); + + for (std::string creepName : screepNames) { + if (Engine::getInstance()->Creeps.contains(creepName)) { + CreepRole role = Engine::getInstance()->Creeps[creepName]->role; + currentJobs[role] += 1; + } else { + Engine::getInstance()->Creeps.erase(creepName); + } + } + return currentJobs; +} + +std::string DouwcoHivemind::Room::getNewCreepName(CreepRole role) { + std::string name; + switch (role) { + case UPGRADER: + name = "Upgrader"; + break; + case SUPPLIER: + name = "Supplier"; + break; + case MAINTAINER: + name = "Maintainer"; + break; + case BUILDER: + name = "Builder"; + break; + case MINER: + name = "Miner"; + break; + default: + name = "creep"; + break; + } + return name + " - " + std::to_string(Screeps::Game.time()); +} + +std::vector DouwcoHivemind::Room::getNewCreepBody(CreepRole role) { + int energyAvailable = roomJs.energyAvailable(); + + std::vector body; + switch (role) { + case MINER: + body.push_back("move"); + body.push_back("work"); + for (int i = 0; i < (energyAvailable - 150) / 100 && i < 5; i++) { + body.push_back("work"); + } + break; + case SUPPLIER: + for (int i = 0; i < energyAvailable / 100; i++) { + body.push_back("move"); + body.push_back("carry"); + } + break; + default: + for (int i = 0; i < energyAvailable / 200; i++) { + body.push_back("work"); + body.push_back("carry"); + body.push_back("move"); + } + break; + } + + return body; +} + +JSON DouwcoHivemind::Room::getNewCreepOptions(CreepRole role) { + JSON opts; + opts["memory"]["role"] = role; + + switch (role) { + case MINER: + opts["memory"]["sourceId"] = sourceIds[minerIterator]; + break; + default: + break; + } + return opts; +} \ No newline at end of file