First working version of colony.

Harversters and spawn work.
This commit is contained in:
douwe
2025-08-13 20:43:26 +02:00
parent 8a39526580
commit 9a1682a857
28 changed files with 1328 additions and 114 deletions

215
src/harvester.cpp Normal file
View File

@@ -0,0 +1,215 @@
#include <vector>
#include <optional>
#include <emscripten.h>
#include <Screeps/Game.hpp>
#include <Screeps/Creep.hpp>
#include <Screeps/Source.hpp>
#include <Screeps/Room.hpp>
#include <Screeps/RoomPosition.hpp>
#include <Screeps/RoomObject.hpp>
#include <Screeps/Structure.hpp>
#include <Screeps/StructureController.hpp>
#include <Screeps/StructureSpawn.hpp>
#include <Screeps/StructureExtension.hpp>
#include <Screeps/StructureTower.hpp>
#include <Screeps/Constants.hpp>
#include <Screeps/Store.hpp>
#include "creeps/harvester.hpp"
bool isNearTo(const Screeps::RoomPosition &pos1, const Screeps::RoomPosition &pos2);
DouwcoHivemind::HarvesterRole::HarvesterRole(Screeps::Creep* creep_pntr)
{
creep = creep_pntr;
memory = creep->memory();
}
DouwcoHivemind::HarvesterRole::~HarvesterRole()
{
creep->setMemory(memory);
}
void DouwcoHivemind::HarvesterRole::process()
{
setupMemory();
searchTarget();
if (memory["harvesting"])
harvestSource();
else
depositEnergy();
}
void DouwcoHivemind::HarvesterRole::setupMemory()
{
if (!memory.contains("harvesting"))
{
EM_ASM({ console.log('Setup harvesting'); });
memory["harvesting"] = false;
}
if (!memory.contains("target"))
{
EM_ASM({ console.log('Setup target'); });
memory["target"] = "";
}
}
void DouwcoHivemind::HarvesterRole::searchTarget()
{
if (memory["harvesting"] && creep->store().getFreeCapacity(Screeps::RESOURCE_ENERGY) == 0)
{
EM_ASM({ console.log('Searching energy deposit'); });
memory["harvesting"] = false;
searchEnergyDeposit();
}
else if (!memory["harvesting"] && creep->store().getUsedCapacity(Screeps::RESOURCE_ENERGY) == 0)
{
EM_ASM({ console.log('Searching source'); });
memory["harvesting"] = true;
searchSource();
}
}
void DouwcoHivemind::HarvesterRole::searchEnergyDeposit()
{
auto structures = creep->room().find(Screeps::FIND_MY_STRUCTURES);
std::vector<std::unique_ptr<Screeps::RoomObject>> filtered;
for (auto &structureObject : structures)
{
auto structure = dynamic_cast<Screeps::Structure *>(structureObject.get());
if (!structure)
continue;
if (structure->structureType() == Screeps::STRUCTURE_SPAWN)
{
if (dynamic_cast<Screeps::StructureSpawn *>(structure)->store().getFreeCapacity(Screeps::RESOURCE_ENERGY) > 0)
filtered.emplace_back(std::move(structureObject));
}
else if (structure->structureType() == Screeps::STRUCTURE_EXTENSION)
{
if (dynamic_cast<Screeps::StructureExtension *>(structure)->store().getFreeCapacity(Screeps::RESOURCE_ENERGY) > 0)
filtered.emplace_back(std::move(structureObject));
}
else if (structure->structureType() == Screeps::STRUCTURE_TOWER)
{
if (dynamic_cast<Screeps::StructureTower *>(structure)->store().getFreeCapacity(Screeps::RESOURCE_ENERGY) > 0)
filtered.emplace_back(std::move(structureObject));
}
else if (structure->structureType() == Screeps::STRUCTURE_CONTROLLER)
{
filtered.emplace_back(std::move(structureObject));
}
}
auto closestObj = creep->pos().findClosestByPath(filtered);
if (closestObj)
{
auto closest = dynamic_cast<Screeps::Structure *>(closestObj.get());
memory["target"] = closest ? closest->id() : "";
}
else
memory["target"] = "";
}
void DouwcoHivemind::HarvesterRole::searchSource()
{
auto sources = creep->room().find(Screeps::FIND_SOURCES_ACTIVE);
std::vector<std::unique_ptr<Screeps::RoomObject>> sourceObjects;
for (auto &source : sources)
sourceObjects.emplace_back(std::move(source));
auto closestObj = creep->pos().findClosestByPath(sourceObjects);
if (closestObj)
{
auto closest = dynamic_cast<Screeps::Source *>(closestObj.get());
memory["target"] = closest ? closest->id() : "";
}
else
{
memory["target"] = "";
}
}
void DouwcoHivemind::HarvesterRole::harvestSource()
{
if (!memory.contains("target") || memory["target"].empty())
{
searchSource();
if (!memory.contains("target") || memory["target"].empty())
return;
}
auto sourceObj = Screeps::Game.getObjectById(memory["target"]);
if (sourceObj)
{
auto source = dynamic_cast<Screeps::Source *>(sourceObj.get());
if (!source || source->energy() == 0)
{
searchSource();
sourceObj = Screeps::Game.getObjectById(memory["target"]);
source = dynamic_cast<Screeps::Source *>(sourceObj.get());
if (!source)
return;
}
if (isNearTo(creep->pos(), source->pos()))
creep->harvest(*source);
else
creep->moveTo(*source);
}
}
void DouwcoHivemind::HarvesterRole::depositEnergy()
{
if (!memory.contains("target") || memory["target"].empty())
{
searchEnergyDeposit();
if (!memory.contains("target") || memory["target"].empty())
return;
}
auto structureObj = Screeps::Game.getObjectById(memory["target"]);
if (structureObj)
{
auto structure = dynamic_cast<Screeps::Structure *>(structureObj.get());
bool searchAgain = !structure;
if (!searchAgain)
{
if (isNearTo(creep->pos(), structure->pos()))
{
if (structure->structureType() == Screeps::STRUCTURE_CONTROLLER)
{
Screeps::StructureController *controller = dynamic_cast<Screeps::StructureController *>(structure);
if (!controller)
return;
int resp = creep->upgradeController(*controller);
if (resp != Screeps::OK)
searchAgain = true;
}
else if (structure->structureType() == Screeps::STRUCTURE_SPAWN ||
structure->structureType() == Screeps::STRUCTURE_EXTENSION ||
structure->structureType() == Screeps::STRUCTURE_TOWER)
{
int resp = creep->transfer(*structure, Screeps::RESOURCE_ENERGY);
if (resp != Screeps::OK)
searchAgain = true;
}
}
else
creep->moveTo(*structure);
}
if (searchAgain)
{
searchEnergyDeposit();
}
}
}
bool isNearTo(const Screeps::RoomPosition &pos1, const Screeps::RoomPosition &pos2)
{
int dx = pos1.x() - pos2.x();
int dy = pos1.y() - pos2.y();
return dx * dx < 2 && dy * dy < 2 && pos1.roomName() == pos2.roomName();
}

View File

@@ -6,6 +6,8 @@
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include "Constants.hpp"
#include "creeps/harvester.hpp"
#include "structures/spawn.hpp"
EMSCRIPTEN_KEEPALIVE
@@ -13,14 +15,22 @@ extern "C" void loop()
{
Screeps::Context::update();
EM_ASM({ console.log('Starting loop...'); });
auto spawnManager = SpawnManager();
spawnManager.process();
// Structures
for (auto& spawn_entry : Screeps::Game.spawns())
{
auto spawn = DouwcoHivemind::Spawn(&spawn_entry.second);
spawn.process();
}
// Creeps
auto creeps = Screeps::Game.creeps();
for (auto& creep : creeps)
creep.second.say("screepsxx");
for (auto& creep : creeps){
if (creep.second.memory()["role"] == DouwcoHivemind::ROLE_HARVESTER)
{
auto harvester = DouwcoHivemind::HarvesterRole(&creep.second);
harvester.process();
}
}
}
EMSCRIPTEN_BINDINGS(loop)

View File

@@ -1,18 +1,25 @@
#include <nlohmann/json.hpp>
#include <Screeps/JS.hpp>
#include <Screeps/Game.hpp>
#include <Screeps/Room.hpp>
#include <Screeps/StructureSpawn.hpp>
#include <emscripten.h>
#include "Constants.hpp"
#include "structures/spawn.hpp"
void SpawnManager::process()
void DouwcoHivemind::Spawn::process()
{
for (auto& spawn : Screeps::Game.spawns())
{
int creepcount = spawn.second.room().find(Screeps::FIND_MY_CREEPS, nullptr).size();
// EM_ASM({ console.log('creepcount: ' + $0); }, creepcount);
if (creepcount >= 3) continue;
int resp = spawn.second.spawnCreep({"work", "carry", "move"}, "harvester" + std::to_string(creepcount + 1));
}
int creepcount = structure->room().find(Screeps::FIND_MY_CREEPS, nullptr).size();
EM_ASM({ console.log('creepcount: ' + $0); }, creepcount);
if (creepcount >= 10) return;
JSON opts;
opts["memory"]["role"] = DouwcoHivemind::ROLE_HARVESTER;
int resp = structure->spawnCreep(
{"work", "carry", "move"},
"harvester" + std::to_string(creepcount + 1),
opts
);
}