improved the code of Room

This commit is contained in:
2026-07-10 19:50:24 +02:00
parent fb07ab70fc
commit 88deef5109
3 changed files with 159 additions and 99 deletions

View File

@@ -26,9 +26,19 @@ public:
void loop(); void loop();
protected: protected:
void manageScreeps();
void manageStructures(); void manageStructures();
void placeContainers(); void manageScreeps();
void updateSourceIds();
void updateSpawnIds();
void updateContainerIds();
std::map<CreepRole, int> calculateRequiredJobs();
std::map<CreepRole, int> countCurrentJobs();
std::string getNewCreepName(CreepRole role);
std::vector<std::string> getNewCreepBody(CreepRole role);
JSON getNewCreepOptions(CreepRole role);
}; };
} // namespace DouwcoHivemind } // namespace DouwcoHivemind

View File

@@ -79,5 +79,5 @@ void DouwcoHivemind::Builder::searchConstructionSite()
if (selectedConstructionSite) if (selectedConstructionSite)
targetId = selectedConstructionSite->id(); targetId = selectedConstructionSite->id();
else else
targetId.clear(); creep.suicide();
} }

View File

@@ -40,125 +40,73 @@ void DouwcoHivemind::Room::loop() {
manageScreeps(); manageScreeps();
} }
void DouwcoHivemind::Room::manageStructures() { placeContainers(); } void DouwcoHivemind::Room::manageStructures() {
updateSourceIds();
updateSpawnIds();
updateContainerIds();
}
void DouwcoHivemind::Room::manageScreeps() { void DouwcoHivemind::Room::manageScreeps() {
// Get energy data // Get energy data
int energyAvailable = roomJs.energyAvailable(); int energyAvailable = roomJs.energyAvailable();
int energyCapacityAvailable = roomJs.energyCapacityAvailable(); int energyCapacityAvailable = roomJs.energyCapacityAvailable();
// Calculate needed creep roles // Get job status
int required_upgraders = 1; auto requiredJobs = calculateRequiredJobs();
int required_suppliers = 2; auto currentJobs = countCurrentJobs();
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++;
}
// Check if max energy used // Check if max energy used
if (energyAvailable < energyCapacityAvailable && 0 < existing_suppliers) if (energyAvailable < energyCapacityAvailable && 0 < currentJobs[SUPPLIER])
return; return;
// Select based on priority which role needs to be made first
const std::vector<CreepRole> 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 // Set creep properties
std::string name; std::string name = getNewCreepName(role);
JSON opts; auto body = getNewCreepBody(role);
CreepRole role = CreepRole::UNEMPLOYED; JSON opts = getNewCreepOptions(role);
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<std::string> 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<Screeps::StructureSpawn *>(spawnStructure.get())->id());
}
}
// 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()); std::string unique_name = name + std::to_string(Screeps::Game.time());
spawn->spawnJs.spawnCreep(body, unique_name, opts); spawn->spawnJs.spawnCreep(body, unique_name, opts);
// Store creepname in managed list.
screepNames.push_back(unique_name); screepNames.push_back(unique_name);
} }
void DouwcoHivemind::Room::placeContainers() { void DouwcoHivemind::Room::updateSourceIds() {
// If no sources stored yet
if (sourceIds.size() == 0) { if (sourceIds.size() == 0) {
auto sources_ = roomJs.find(Screeps::FIND_SOURCES); auto sources = roomJs.find(Screeps::FIND_SOURCES);
for (auto &source : sources_) { for (auto &source : sources) {
sourceIds.push_back(static_cast<Screeps::Source *>(source.get())->id()); sourceIds.push_back(static_cast<Screeps::Source *>(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<Screeps::StructureSpawn *>(spawnStructure.get())->id());
}
}
}
void DouwcoHivemind::Room::updateContainerIds() {
// No containers planned or build, planning now // No containers planned or build, planning now
if (sourceContainerIds.size() < sourceIds.size()) { if (sourceContainerIds.size() < sourceIds.size()) {
int controller_x = roomJs.controller().value().pos().x(); int controller_x = roomJs.controller().value().pos().x();
@@ -217,3 +165,105 @@ void DouwcoHivemind::Room::placeContainers() {
sourceContainerIds.erase(sourceContainerIds.begin() + i); sourceContainerIds.erase(sourceContainerIds.begin() + i);
} }
} }
std::map<DouwcoHivemind::CreepRole, int>
DouwcoHivemind::Room::calculateRequiredJobs() {
std::map<DouwcoHivemind::CreepRole, int> 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::CreepRole, int>
DouwcoHivemind::Room::countCurrentJobs() {
std::map<DouwcoHivemind::CreepRole, int> 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<std::string> DouwcoHivemind::Room::getNewCreepBody(CreepRole role) {
int energyAvailable = roomJs.energyAvailable();
std::vector<std::string> 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;
}