Changed behaviour of maintainer and fixed screep cleanup.

This commit is contained in:
2026-07-12 02:53:46 +02:00
parent 88deef5109
commit 591fd97be0
6 changed files with 127 additions and 120 deletions

View File

@@ -14,7 +14,7 @@ public:
std::vector<std::string> sourceIds = {}; std::vector<std::string> sourceIds = {};
std::vector<std::string> sourceContainerIds = {}; std::vector<std::string> sourceContainerIds = {};
std::vector<std::string> SpawnIds = {}; std::vector<std::string> SpawnIds = {};
std::vector<std::string> screepNames = {}; std::vector<std::string> creepNames = {};
private: private:
int minerIterator; int minerIterator;
@@ -33,6 +33,8 @@ protected:
void updateSpawnIds(); void updateSpawnIds();
void updateContainerIds(); void updateContainerIds();
void cleanupManagedCreeps();
std::map<CreepRole, int> calculateRequiredJobs(); std::map<CreepRole, int> calculateRequiredJobs();
std::map<CreepRole, int> countCurrentJobs(); std::map<CreepRole, int> countCurrentJobs();
std::string getNewCreepName(CreepRole role); std::string getNewCreepName(CreepRole role);

View File

@@ -25,6 +25,8 @@ DouwcoHivemind::CreepBase::~CreepBase() {
memory["role"] = role; memory["role"] = role;
memory["targetId"] = targetId; memory["targetId"] = targetId;
creep.setMemory(memory); creep.setMemory(memory);
if (!creep.spawning() && creep.ticksToLive() == 1)
JS::getGlobal("eval")("delete Memory.creeps['" + creep.name() + "']");
} }
void DouwcoHivemind::CreepBase::moveToTarget(int dist) { void DouwcoHivemind::CreepBase::moveToTarget(int dist) {
@@ -65,12 +67,6 @@ void DouwcoHivemind::CreepBase::moveToTarget(int dist) {
memory["path"] = vectorToJson(flattenPathSteps(path)); memory["path"] = vectorToJson(flattenPathSteps(path));
} }
// JS::console.log(std::string("creep pos: [") +
// std::to_string(creep.pos().x()) +
// std::string(",") +
// std::to_string(creep.pos().y()) +
// std::string("]"));
// Get step from memory // Get step from memory
int pathStepData[5] = {0}; int pathStepData[5] = {0};
if (memory["path"].size() > 5) { if (memory["path"].size() > 5) {

View File

@@ -1,58 +1,53 @@
#include <vector>
#include <optional>
#include <emscripten.h> #include <emscripten.h>
#include <optional>
#include <vector>
#include <Screeps/Game.hpp>
#include <Screeps/Creep.hpp> #include <Screeps/Creep.hpp>
#include <Screeps/Source.hpp> #include <Screeps/Game.hpp>
#include <Screeps/Room.hpp> #include <Screeps/Room.hpp>
#include <Screeps/RoomPosition.hpp>
#include <Screeps/RoomObject.hpp> #include <Screeps/RoomObject.hpp>
#include <Screeps/RoomPosition.hpp>
#include <Screeps/Source.hpp>
#include <Screeps/Store.hpp>
#include <Screeps/Structure.hpp> #include <Screeps/Structure.hpp>
#include <Screeps/StructureController.hpp> #include <Screeps/StructureController.hpp>
#include <Screeps/StructureSpawn.hpp>
#include <Screeps/StructureExtension.hpp> #include <Screeps/StructureExtension.hpp>
#include <Screeps/StructureSpawn.hpp>
#include <Screeps/StructureTower.hpp> #include <Screeps/StructureTower.hpp>
#include <Screeps/Store.hpp>
#include "Creeps/Maintainer.hpp"
#include "Creeps/CreepBase.hpp" #include "Creeps/CreepBase.hpp"
#include "Creeps/Maintainer.hpp"
#include "Screeps/Constants.hpp" #include "Screeps/Constants.hpp"
void DouwcoHivemind::Maintainer::depositEnergy() void DouwcoHivemind::Maintainer::depositEnergy() {
{
auto structure = getDamagedStructureTarget(); auto structure = getDamagedStructureTarget();
if (!structure) return; if (!structure)
if (isNearTo(structure->pos(), 1)) return;
{ if (isNearTo(structure->pos(), 1)) {
int resp = creep.repair(*structure); int resp = creep.repair(*structure);
} } else {
else
{
moveToTarget(); moveToTarget();
} }
} }
std::unique_ptr<Screeps::Structure> DouwcoHivemind::Maintainer::getDamagedStructureTarget() std::unique_ptr<Screeps::Structure>
{ DouwcoHivemind::Maintainer::getDamagedStructureTarget() {
auto roomObj = getRoomObjectTarget(); auto roomObj = getRoomObjectTarget();
if (!roomObj) if (!roomObj) {
{
searchDamagedStructure(); searchDamagedStructure();
return nullptr; return nullptr;
} }
auto structure = std::unique_ptr<Screeps::Structure>(dynamic_cast<Screeps::Structure *>(roomObj.release())); auto structure = std::unique_ptr<Screeps::Structure>(
if (!structure) dynamic_cast<Screeps::Structure *>(roomObj.release()));
{ if (!structure) {
searchDamagedStructure(); searchDamagedStructure();
return nullptr; return nullptr;
} }
// Check if the structure is still broken // Check if the structure is still broken
int damage = structure->hitsMax() - structure->hits(); int damage = structure->hitsMax() - structure->hits();
if (damage == 0) if (damage == 0) {
{
searchDamagedStructure(); searchDamagedStructure();
return nullptr; return nullptr;
} }
@@ -60,31 +55,30 @@ std::unique_ptr<Screeps::Structure> DouwcoHivemind::Maintainer::getDamagedStruct
return std::move(structure); return std::move(structure);
} }
void DouwcoHivemind::Maintainer::searchDamagedStructure() void DouwcoHivemind::Maintainer::searchDamagedStructure() {
{
int highestDamage = 0; int highestDamage = 0;
Screeps::Structure *selectedStructure; Screeps::Structure *selectedStructure;
auto structures = creep.room().find(Screeps::FIND_STRUCTURES); auto structures = creep.room().find(Screeps::FIND_STRUCTURES);
for (auto &structureObject : structures) for (auto &structureObject : structures) {
{ auto structure =
auto structure = dynamic_cast<Screeps::Structure *>(structureObject.release()); dynamic_cast<Screeps::Structure *>(structureObject.release());
if (!structure) if (!structure)
continue; continue;
int damage = structure->hitsMax() - structure->hits();
auto structureType = structure->structureType(); auto structureType = structure->structureType();
if (structureType == Screeps::STRUCTURE_CONTROLLER) if (structureType == Screeps::STRUCTURE_CONTROLLER)
continue; continue;
if(structureType == Screeps::STRUCTURE_WALL || structureType == Screeps::STRUCTURE_RAMPART) int damage =
continue; // todo cover this situation as well. 100 * (structure->hitsMax() - structure->hits()) / structure->hitsMax();
if (highestDamage < damage) if (structureType == Screeps::STRUCTURE_WALL) continue;
{ if (highestDamage < damage) {
highestDamage = damage; highestDamage = damage;
selectedStructure = structure; selectedStructure = structure;
} }
} }
if (selectedStructure && selectedStructure->hits() != selectedStructure->hitsMax()) if (selectedStructure &&
selectedStructure->hits() != selectedStructure->hitsMax())
targetId = selectedStructure->id(); targetId = selectedStructure->id();
else else
targetId.clear(); targetId.clear();

View File

@@ -3,6 +3,7 @@
#include <Screeps/StructureController.hpp> #include <Screeps/StructureController.hpp>
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <string>
#include "Engine.hpp" #include "Engine.hpp"
@@ -13,37 +14,44 @@
#include "Creeps/Upgrader.hpp" #include "Creeps/Upgrader.hpp"
#include "Screeps/Constants.hpp" #include "Screeps/Constants.hpp"
#include "Screeps/JS.hpp"
#include "Screeps/StructureSpawn.hpp" #include "Screeps/StructureSpawn.hpp"
#include "Structures/Spawn.hpp" #include "Structures/Spawn.hpp"
#include "Structures/Tower.hpp" #include "Structures/Tower.hpp"
DouwcoHivemind::Engine::Engine() { DouwcoHivemind::Engine::Engine() {
instance = this; instance = this;
JS::console.log(std::string("Reading out owned rooms")); // JS::console.log(std::string("Reading out owned rooms"));
ReadOutRooms(); ReadOutRooms();
JS::console.log(std::string("Reading out creeps")); // JS::console.log(std::string("Reading out creeps"));
ReadOutCreeps(); ReadOutCreeps();
JS::console.log(std::string("Reading out structures")); // JS::console.log(std::string("Reading out structures"));
ReadOutStructures(); ReadOutStructures();
} }
void DouwcoHivemind::Engine::loop() { void DouwcoHivemind::Engine::loop() {
JS::console.log(std::string("Iterating over rooms")); int totalCost = Screeps::Game.cpuGetUsed();
for (auto &room : Rooms) for (auto &room : Rooms)
room.second->loop(); room.second->loop();
JS::console.log("Used CPU by rooms:\t" +
std::to_string(Screeps::Game.cpuGetUsed() - totalCost));
totalCost = Screeps::Game.cpuGetUsed();
JS::console.log(std::string("Iterating over creeps"));
for (auto &creep : Creeps) for (auto &creep : Creeps)
creep.second->loop(); creep.second->loop();
JS::console.log("Used CPU by creeps:\t" +
std::to_string(Screeps::Game.cpuGetUsed() - totalCost));
totalCost = Screeps::Game.cpuGetUsed();
JS::console.log(std::string("Iterating over structures"));
for (auto &structure : Structures) for (auto &structure : Structures)
structure.second->loop(); structure.second->loop();
JS::console.log("Used CPU by structures:\t" +
std::to_string(Screeps::Game.cpuGetUsed() - totalCost));
totalCost = Screeps::Game.cpuGetUsed();
if (Screeps::Game.time() % 100 == 0) { if (Screeps::Game.time() % 1000 == 0)
clearDeadCreepMemory(); clearDeadCreepMemory();
} }
}
void DouwcoHivemind::Engine::ReadOutRooms() { void DouwcoHivemind::Engine::ReadOutRooms() {
auto src_rooms = Screeps::Game.rooms(); auto src_rooms = Screeps::Game.rooms();
@@ -90,24 +98,16 @@ void DouwcoHivemind::Engine::ReadOutStructures() {
} }
void DouwcoHivemind::Engine::clearDeadCreepMemory() { void DouwcoHivemind::Engine::clearDeadCreepMemory() {
auto creepMemory = Screeps::Memory["creeps"];
auto creepsMap = Screeps::Game.creeps();
int iterator = 0;
for (auto [name, creep] : creepMemory.items()) {
// avoid cpu overload
iterator++;
if (iterator == 100)
break;
bool containsname = false; auto creepMemory = JS::getGlobal("Memory")["creeps"];
for (auto creepObject : creepsMap) { auto creepNames = JS::gObject.call<JS::Value>("keys", creepMemory);
if (creepObject.first == name) { int size = creepNames["length"].as<int>();
containsname = true;
break; for (int i = 0; i < size; i++) {
auto name = creepNames[i].as<std::string>();
if (Engine::getInstance()->Creeps.find(name) ==
Engine::getInstance()->Creeps.end()) {
JS::getGlobal("eval")("delete Memory.creeps['" + name + "']");
} }
} }
if (!containsname)
creepMemory.erase(name);
}
Screeps::Memory.set("creeps", creepMemory);
} }

View File

@@ -16,21 +16,29 @@
#include "Screeps/StructureSpawn.hpp" #include "Screeps/StructureSpawn.hpp"
#include "Structures/Spawn.hpp" #include "Structures/Spawn.hpp"
#include <cstdint> #include <cstdint>
#include <string>
#include <vector>
DouwcoHivemind::Room::Room(Screeps::Room rm) : roomJs(rm), memory(rm.memory()) { DouwcoHivemind::Room::Room(Screeps::Room rm) : roomJs(rm), memory(rm.memory()) {
if (memory.contains("sources")) if (memory.contains("sourceIds"))
sourceIds = static_cast<std::vector<std::string>>(memory["sources"]); sourceIds = static_cast<std::vector<std::string>>(memory["sourceIds"]);
if (memory.contains("sourceContainers")) if (memory.contains("sourceContainerIds"))
sourceContainerIds = sourceContainerIds =
static_cast<std::vector<std::string>>(memory["sourceContainers"]); static_cast<std::vector<std::string>>(memory["sourceContainerIds"]);
if (memory.contains("SpawnIds"))
SpawnIds = static_cast<std::vector<std::string>>(memory["SpawnIds"]);
if (memory.contains("creepNames"))
creepNames = static_cast<std::vector<std::string>>(memory["creepNames"]);
minerIterator = memory.contains("minerIterator") minerIterator = memory.contains("minerIterator")
? static_cast<int>(memory["minerIterator"]) ? static_cast<int>(memory["minerIterator"])
: 0; : 0;
} }
DouwcoHivemind::Room::~Room() { DouwcoHivemind::Room::~Room() {
memory["sources"] = sourceIds; memory["sourceIds"] = sourceIds;
memory["sourceContainers"] = sourceContainerIds; memory["sourceContainerIds"] = sourceContainerIds;
memory["SpawnIds"] = SpawnIds;
memory["creepNames"] = creepNames;
memory["minerIterator"] = minerIterator; memory["minerIterator"] = minerIterator;
roomJs.setMemory(memory); roomJs.setMemory(memory);
} }
@@ -47,15 +55,16 @@ void DouwcoHivemind::Room::manageStructures() {
} }
void DouwcoHivemind::Room::manageScreeps() { void DouwcoHivemind::Room::manageScreeps() {
// Get energy data // Clean dead creeps from managed creepNames list.
int energyAvailable = roomJs.energyAvailable(); cleanupManagedCreeps();
int energyCapacityAvailable = roomJs.energyCapacityAvailable();
// Get job status // Get job status
auto requiredJobs = calculateRequiredJobs(); auto requiredJobs = calculateRequiredJobs();
auto currentJobs = countCurrentJobs(); auto currentJobs = countCurrentJobs();
// Check if max energy used // Check if max energy used
int energyAvailable = roomJs.energyAvailable();
int energyCapacityAvailable = roomJs.energyCapacityAvailable();
if (energyAvailable < energyCapacityAvailable && 0 < currentJobs[SUPPLIER]) if (energyAvailable < energyCapacityAvailable && 0 < currentJobs[SUPPLIER])
return; return;
@@ -71,6 +80,8 @@ void DouwcoHivemind::Room::manageScreeps() {
break; break;
} }
} }
if (role == UNEMPLOYED)
return;
// Set creep properties // Set creep properties
std::string name = getNewCreepName(role); std::string name = getNewCreepName(role);
@@ -80,10 +91,18 @@ void DouwcoHivemind::Room::manageScreeps() {
// Create creep // Create creep
auto spawn = static_cast<Spawn *>( auto spawn = static_cast<Spawn *>(
Engine::getInstance()->Structures[SpawnIds[0]].get()); Engine::getInstance()->Structures[SpawnIds[0]].get());
std::string unique_name = name + std::to_string(Screeps::Game.time()); spawn->spawnJs.spawnCreep(body, name, opts);
spawn->spawnJs.spawnCreep(body, unique_name, opts);
// Store creepname in managed list. // Store creepname in managed list.
screepNames.push_back(unique_name); creepNames.push_back(name);
}
void DouwcoHivemind::Room::cleanupManagedCreeps() {
std::vector<std::string> cleanedCreepNames;
for (std::string creepName : creepNames) {
if (Engine::getInstance()->Creeps.contains(creepName))
cleanedCreepNames.push_back(creepName);
}
creepNames = cleanedCreepNames;
} }
void DouwcoHivemind::Room::updateSourceIds() { void DouwcoHivemind::Room::updateSourceIds() {
@@ -188,12 +207,10 @@ DouwcoHivemind::Room::countCurrentJobs() {
currentJobs.emplace(BUILDER, 0); currentJobs.emplace(BUILDER, 0);
currentJobs.emplace(MINER, 0); currentJobs.emplace(MINER, 0);
for (std::string creepName : screepNames) { for (std::string creepName : creepNames) {
if (Engine::getInstance()->Creeps.contains(creepName)) { if (Engine::getInstance()->Creeps.contains(creepName)) {
CreepRole role = Engine::getInstance()->Creeps[creepName]->role; CreepRole role = Engine::getInstance()->Creeps[creepName]->role;
currentJobs[role] += 1; currentJobs[role] += 1;
} else {
Engine::getInstance()->Creeps.erase(creepName);
} }
} }
return currentJobs; return currentJobs;
@@ -261,6 +278,7 @@ JSON DouwcoHivemind::Room::getNewCreepOptions(CreepRole role) {
switch (role) { switch (role) {
case MINER: case MINER:
opts["memory"]["sourceId"] = sourceIds[minerIterator]; opts["memory"]["sourceId"] = sourceIds[minerIterator];
minerIterator = (minerIterator + 1) % sourceIds.size();
break; break;
default: default:
break; break;

View File

@@ -20,9 +20,6 @@ extern "C" void loop() {
{ {
DouwcoHivemind::Engine engine; DouwcoHivemind::Engine engine;
engine.loop(); engine.loop();
auto test = &(DouwcoHivemind::Engine::getInstance()->Structures);
JS::console.log(std::string("test: ") + std::to_string(test->size()));
} }
JS::console.log("Used CPU:\t" + std::to_string(Screeps::Game.cpuGetUsed())); JS::console.log("Used CPU:\t" + std::to_string(Screeps::Game.cpuGetUsed()));