Divided harveste into 3 jobs

This commit is contained in:
douwe
2025-08-25 02:20:58 +02:00
parent 67f0afae4c
commit 40ab8b289a
14 changed files with 370 additions and 161 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -14,7 +14,9 @@ namespace DouwcoHivemind
enum CreepRole
{
UNEMPLOYED,
HARVESTER
HARVESTER_SUPPLIER,
HARVESTER_UPGRADER,
HARVESTER_BUILDER
};
class Creep

View File

@@ -1,35 +1,28 @@
#ifndef DOUWCO_HIVEMIND_HARVESTER_HPP
#define DOUWCO_HIVEMIND_HARVESTER_HPP
#include "Creeps/Creep.hpp"
namespace {
class Creep;
}
namespace DouwcoHivemind
{
class HarvesterRole : public Creep
class Harvester : public Creep
{
private:
bool harvesting;
int taskCounter;
public:
HarvesterRole(Screeps::Creep crp);
~HarvesterRole() override;
Harvester(Screeps::Creep crp);
~Harvester() override;
void loop() override;
protected:
virtual void depositEnergy(){}
private:
void harvestSource();
std::unique_ptr<Screeps::Source> getSourceTarget();
void searchSource();
void depositEnergy();
std::unique_ptr<Screeps::Structure> getDepositTarget();
void searchDeposit();
};
}

View File

@@ -0,0 +1,22 @@
#ifndef DOUWCO_HIVEMIND_HARVESTER_BUILDER_HPP
#define DOUWCO_HIVEMIND_HARVESTER_BUILDER_HPP
#include "Creeps/Harvester.hpp"
namespace DouwcoHivemind
{
class HarvesterBuilder : public Harvester
{
public:
HarvesterBuilder(Screeps::Creep creep) : Harvester(creep) {}
protected:
void depositEnergy() override;
private:
std::unique_ptr<Screeps::ConstructionSite> getConstructionSiteTarget();
void searchConstructionSite();
};
}
#endif // DOUWCO_HIVEMIND_HARVESTER_BUILDER_HPP

View File

@@ -0,0 +1,22 @@
#ifndef DOUWCO_HIVEMIND_HARVESTER_SUPPLIER_HPP
#define DOUWCO_HIVEMIND_HARVESTER_SUPPLIER_HPP
#include "Creeps/Harvester.hpp"
namespace DouwcoHivemind
{
class HarvesterSupplier : public Harvester
{
public:
HarvesterSupplier(Screeps::Creep creep) : Harvester(creep) {}
protected:
void depositEnergy() override;
private:
std::unique_ptr<Screeps::Structure> getEnergyStructureTarget();
void searchEnergyStructure();
};
}
#endif // DOUWCO_HIVEMIND_HARVESTER_SUPPLIER_HPP

View File

@@ -0,0 +1,18 @@
#ifndef DOUWCO_HIVEMIND_HARVESTER_UPGRADER_HPP
#define DOUWCO_HIVEMIND_HARVESTER_UPGRADER_HPP
#include "Creeps/Harvester.hpp"
namespace DouwcoHivemind
{
class HarvesterUpgrader : public Harvester
{
public:
HarvesterUpgrader(Screeps::Creep creep) : Harvester(creep) {}
protected:
void depositEnergy() override;
};
}
#endif // DOUWCO_HIVEMIND_HARVESTER_UPGRADER_HPP

View File

@@ -7,7 +7,7 @@
#include "Structures/Structure.hpp"
namespace DouwcoHivemind
{
{
class Engine
{
private:

View File

@@ -2,7 +2,10 @@
#include "Engine.hpp"
#include "Creeps/Harvester.hpp"
#include "Creeps/HarvesterSupplier.hpp"
#include "Creeps/HarvesterUpgrader.hpp"
#include "Creeps/HarvesterBuilder.hpp"
#include "Structures/Spawn.hpp"
DouwcoHivemind::Engine::Engine()
@@ -13,33 +16,34 @@ DouwcoHivemind::Engine::Engine()
void DouwcoHivemind::Engine::loop()
{
JS::console.log(std::string("Iterating over creeps"));
for (auto &creep : creeps)
creep->loop();
JS::console.log(std::string("Iterating over structures"));
for (auto &structure : structures)
structure->loop();
}
void DouwcoHivemind::Engine::ReadOutCreeps()
{
JS::console.log(std::string("Reading out creeps"));
auto src_creeps = Screeps::Game.creeps();
for (auto &creep : src_creeps)
{
CreepRole role = creep.second.memory()["role"];
switch (role)
{
case CreepRole::HARVESTER:
creeps.push_back(std::make_unique<HarvesterRole>(creep.second));
break;
case CreepRole::UNEMPLOYED:
default:
break;
}
if (role == CreepRole::HARVESTER_SUPPLIER)
creeps.push_back(std::make_unique<HarvesterSupplier>(creep.second));
else if (role == CreepRole::HARVESTER_UPGRADER)
creeps.push_back(std::make_unique<HarvesterUpgrader>(creep.second));
else if (role == CreepRole::HARVESTER_BUILDER)
creeps.push_back(std::make_unique<HarvesterBuilder>(creep.second));
}
}
void DouwcoHivemind::Engine::ReadOutStructures()
{
JS::console.log(std::string("Reading out structures"));
auto spawns = Screeps::Game.spawns();
for (auto &spawn : spawns)
{

View File

@@ -18,19 +18,17 @@
#include "Creeps/Harvester.hpp"
DouwcoHivemind::HarvesterRole::HarvesterRole(Screeps::Creep crp) : Creep(crp)
DouwcoHivemind::Harvester::Harvester(Screeps::Creep crp) : Creep(crp)
{
harvesting = memory.contains("harvesting") ? static_cast<bool>(memory["harvesting"]) : false;
taskCounter = memory.contains("taskCounter") ? static_cast<int>(memory["taskCounter"]) : 0;
}
DouwcoHivemind::HarvesterRole::~HarvesterRole()
DouwcoHivemind::Harvester::~Harvester()
{
memory["harvesting"] = harvesting;
memory["taskCounter"] = taskCounter;
}
void DouwcoHivemind::HarvesterRole::loop()
void DouwcoHivemind::Harvester::loop()
{
if (harvesting)
{
@@ -52,7 +50,7 @@ void DouwcoHivemind::HarvesterRole::loop()
}
}
void DouwcoHivemind::HarvesterRole::harvestSource()
void DouwcoHivemind::Harvester::harvestSource()
{
auto source = getSourceTarget();
if (!source)
@@ -68,7 +66,7 @@ void DouwcoHivemind::HarvesterRole::harvestSource()
}
}
std::unique_ptr<Screeps::Source> DouwcoHivemind::HarvesterRole::getSourceTarget()
std::unique_ptr<Screeps::Source> DouwcoHivemind::Harvester::getSourceTarget()
{
auto roomObj = getRoomObjectTarget();
if (!roomObj)
@@ -96,7 +94,7 @@ std::unique_ptr<Screeps::Source> DouwcoHivemind::HarvesterRole::getSourceTarget(
return std::move(source);
}
void DouwcoHivemind::HarvesterRole::searchSource()
void DouwcoHivemind::Harvester::searchSource()
{
target_id.clear();
@@ -127,122 +125,3 @@ void DouwcoHivemind::HarvesterRole::searchSource()
}
target_id = selectedSource->id();
}
void DouwcoHivemind::HarvesterRole::depositEnergy()
{
auto structure = getDepositTarget();
if (!structure)
return;
if (structure->structureType() == Screeps::STRUCTURE_CONTROLLER)
{
if (isNearTo(structure->pos(), 3))
{
auto controller = dynamic_cast<Screeps::StructureController *>(structure.get());
if (!controller)
return;
int resp = creep.upgradeController(*controller);
}
else
{
moveToTarget();
}
}
else
{
if (isNearTo(structure->pos(), 1))
{
int resp = creep.transfer(*structure, Screeps::RESOURCE_ENERGY);
}
else
{
moveToTarget();
}
}
}
std::unique_ptr<Screeps::Structure> DouwcoHivemind::HarvesterRole::getDepositTarget()
{
auto roomObj = getRoomObjectTarget();
if (!roomObj)
{
searchDeposit();
return nullptr;
}
// Check if found roomobject is an actual structure
auto structure = std::unique_ptr<Screeps::Structure>(dynamic_cast<Screeps::Structure *>(roomObj.release()));
if (!structure)
{
// EM_ASM({console.log($0 + ': Can\'t cast target to Source')}, creep.name().c_str());
searchDeposit();
return nullptr;
}
// Check if the structure can receive energy to harvest
int energyCapacity;
auto structureType = structure->structureType();
if (structureType == Screeps::STRUCTURE_CONTROLLER)
{
energyCapacity = 1;
}
else if (structureType == Screeps::STRUCTURE_SPAWN)
{
auto spawn = dynamic_cast<Screeps::StructureSpawn *>(structure.get());
energyCapacity = spawn->store().getFreeCapacity(Screeps::RESOURCE_ENERGY).value();
}
else if (structureType == Screeps::STRUCTURE_EXTENSION)
{
auto extension = dynamic_cast<Screeps::StructureExtension *>(structure.get());
energyCapacity = extension->store().getFreeCapacity(Screeps::RESOURCE_ENERGY).value();
}
if (energyCapacity == 0)
{
searchDeposit();
return nullptr;
}
return std::move(structure);
}
void DouwcoHivemind::HarvesterRole::searchDeposit()
{
int highestEnergyNeed = 0;
Screeps::Structure *selectedStructure;
auto structures = creep.room().find(Screeps::FIND_MY_STRUCTURES);
for (auto &structureObject : structures)
{
auto structure = dynamic_cast<Screeps::Structure *>(structureObject.get());
if (!structure)
continue;
int energyNeed;
auto structureType = structure->structureType();
if (structureType == Screeps::STRUCTURE_SPAWN)
{
auto spawn = dynamic_cast<Screeps::StructureSpawn *>(structure);
energyNeed = spawn->store().getFreeCapacity(Screeps::RESOURCE_ENERGY).value();
}
else if (structureType == Screeps::STRUCTURE_EXTENSION)
{
auto extension = dynamic_cast<Screeps::StructureExtension *>(structure);
energyNeed = extension->store().getFreeCapacity(Screeps::RESOURCE_ENERGY).value();
}
else if (structureType == Screeps::STRUCTURE_CONTROLLER)
{
energyNeed = 1;
}
if (energyNeed > highestEnergyNeed)
{
highestEnergyNeed = energyNeed;
selectedStructure = structure;
}
}
if (selectedStructure)
target_id = selectedStructure->id();
else
target_id.clear();
}

View File

@@ -0,0 +1,83 @@
#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 <Screeps/ConstructionSite.hpp>
#include "Creeps/HarvesterBuilder.hpp"
void DouwcoHivemind::HarvesterBuilder::depositEnergy()
{
auto constructionSite = getConstructionSiteTarget();
if (!constructionSite)
return;
if (isNearTo(constructionSite->pos(), 1))
{
int resp = creep.build(*constructionSite);
}
else
{
moveToTarget();
}
}
std::unique_ptr<Screeps::ConstructionSite> DouwcoHivemind::HarvesterBuilder::getConstructionSiteTarget()
{
auto roomObj = getRoomObjectTarget();
if (!roomObj)
{
searchConstructionSite();
return nullptr;
}
auto constructionSite = std::unique_ptr<Screeps::ConstructionSite>(dynamic_cast<Screeps::ConstructionSite *>(roomObj.release()));
if (!constructionSite)
{
searchConstructionSite();
return nullptr;
}
return std::move(constructionSite);
}
void DouwcoHivemind::HarvesterBuilder::searchConstructionSite()
{
int leastProgressLeft = INT16_MAX;
Screeps::ConstructionSite *selectedConstructionSite;
auto constructionSites = creep.room().find(Screeps::FIND_MY_CONSTRUCTION_SITES);
for (auto &constructionSiteObject : constructionSites)
{
auto constructionSite = dynamic_cast<Screeps::ConstructionSite *>(constructionSiteObject.get());
if (!constructionSite)
continue;
int progressLeft = constructionSite->progressTotal() - constructionSite->progress();
if(constructionSite->structureType() == Screeps::STRUCTURE_ROAD) progressLeft *= 100;
if (progressLeft < leastProgressLeft)
{
leastProgressLeft = progressLeft;
selectedConstructionSite = constructionSite;
}
}
if (selectedConstructionSite)
target_id = selectedConstructionSite->id();
else
target_id.clear();
}

View File

@@ -0,0 +1,112 @@
#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/HarvesterSupplier.hpp"
void DouwcoHivemind::HarvesterSupplier::depositEnergy()
{
auto structure = getEnergyStructureTarget();
if (!structure)
return;
if (isNearTo(structure->pos(), 1))
{
int resp = creep.transfer(*structure, Screeps::RESOURCE_ENERGY);
}
else
{
moveToTarget();
}
}
std::unique_ptr<Screeps::Structure> DouwcoHivemind::HarvesterSupplier::getEnergyStructureTarget()
{
auto roomObj = getRoomObjectTarget();
if (!roomObj)
{
searchEnergyStructure();
return nullptr;
}
auto structure = std::unique_ptr<Screeps::Structure>(dynamic_cast<Screeps::Structure *>(roomObj.release()));
if (!structure)
{
searchEnergyStructure();
return nullptr;
}
// Check if the structure can receive energy to harvest
int energyCapacity;
auto structureType = structure->structureType();
if (structureType == Screeps::STRUCTURE_SPAWN)
{
auto spawn = dynamic_cast<Screeps::StructureSpawn *>(structure.get());
energyCapacity = spawn->store().getFreeCapacity(Screeps::RESOURCE_ENERGY).value();
}
else if (structureType == Screeps::STRUCTURE_EXTENSION)
{
auto extension = dynamic_cast<Screeps::StructureExtension *>(structure.get());
energyCapacity = extension->store().getFreeCapacity(Screeps::RESOURCE_ENERGY).value();
}
if (energyCapacity == 0)
{
searchEnergyStructure();
return nullptr;
}
return std::move(structure);
}
void DouwcoHivemind::HarvesterSupplier::searchEnergyStructure()
{
int mostEnergyNeeded = 0;
Screeps::Structure *selectedStructure;
auto structures = creep.room().find(Screeps::FIND_MY_STRUCTURES);
for (auto &structureObject : structures)
{
auto structure = dynamic_cast<Screeps::Structure *>(structureObject.get());
if (!structure)
continue;
int energyRequired;
auto structureType = structure->structureType();
if (structureType == Screeps::STRUCTURE_SPAWN)
{
auto spawn = dynamic_cast<Screeps::StructureSpawn *>(structure);
energyRequired = spawn->store().getFreeCapacity(Screeps::RESOURCE_ENERGY).value();
}
else if (structureType == Screeps::STRUCTURE_EXTENSION)
{
auto extension = dynamic_cast<Screeps::StructureExtension *>(structure);
energyRequired = extension->store().getFreeCapacity(Screeps::RESOURCE_ENERGY).value();
}
if (energyRequired > mostEnergyNeeded)
{
mostEnergyNeeded = energyRequired;
selectedStructure = structure;
}
}
if (selectedStructure)
target_id = selectedStructure->id();
else
target_id.clear();
}

View File

@@ -0,0 +1,33 @@
#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/HarvesterUpgrader.hpp"
void DouwcoHivemind::HarvesterUpgrader::depositEnergy()
{
auto controller = creep.room().controller().value();
target_id = controller.id();
if (isNearTo(controller.pos(), 3))
{
int resp = creep.upgradeController(controller);
}
else
{
moveToTarget();
}
}

View File

@@ -6,17 +6,58 @@
void DouwcoHivemind::Spawn::loop()
{
int creepcount = spawn.room().find(Screeps::FIND_MY_CREEPS).size();
if (creepcount > 10)
{
// Only run every 50 ticks
if (Screeps::Game.time() % 50 != 0)
return;
int energyAvailable = spawn.room().energyAvailable();
int energyCapacityAvailable = spawn.room().energyCapacityAvailable();
int required_upgraders = 4;
int required_suppliers = energyCapacityAvailable/200;
int required_builders = 4;
for (auto &creep : Screeps::Game.creeps())
{
CreepRole role = creep.second.memory()["role"];
if (role == CreepRole::HARVESTER_SUPPLIER)
required_suppliers--;
else if (role == CreepRole::HARVESTER_UPGRADER)
required_upgraders--;
else if (role == CreepRole::HARVESTER_BUILDER)
required_builders--;
}
if(energyAvailable < energyCapacityAvailable && required_suppliers == 0) return;
std::string name;
JSON opts;
opts["memory"]["role"] = CreepRole::HARVESTER;
if (required_suppliers > 0){
opts["memory"]["role"] = CreepRole::HARVESTER_SUPPLIER;
name = "Susi Harviston\n";
}
else if (required_upgraders > 0){
opts["memory"]["role"] = CreepRole::HARVESTER_UPGRADER;
name = "Upperheim Harviston\n";
int resp = spawn.spawnCreep(
{"work", "work", "carry", "move"},
"harvester" + std::to_string(Screeps::Game.time()),
}
else if (required_builders > 0){
opts["memory"]["role"] = CreepRole::HARVESTER_BUILDER;
name = "Bob Harviston\n";
}
else
return;
std::vector<std::string> body;
for (int i = 0; i < energyAvailable / 200; i++)
{
body.push_back("work");
body.push_back("carry");
body.push_back("move");
}
spawn.spawnCreep(
body,
name + std::to_string(Screeps::Game.time()),
opts);
}