Improved harvester source detection.

This commit is contained in:
douwe
2025-08-21 21:01:00 +02:00
parent 1e9e696b1e
commit 1ede4cce47
10 changed files with 157 additions and 119 deletions

10
.vscode/settings.json vendored
View File

@@ -95,6 +95,14 @@
"numbers": "cpp",
"semaphore": "cpp",
"cfenv": "cpp",
"cinttypes": "cpp"
"cinttypes": "cpp",
"__bit_reference": "cpp",
"__functional_base": "cpp",
"__locale": "cpp",
"__node_handle": "cpp",
"__sso_allocator": "cpp",
"__std_stream": "cpp",
"__threading_support": "cpp",
"__tuple": "cpp"
}
}

View File

@@ -14,7 +14,7 @@ add_subdirectory(screepsxx)
# If you change TARGET_NAME, please, make corresponding changes in main.js.
set(TARGET_NAME app)
set(TARGET_NAME douwco_hivemind)
include_directories(${CMAKE_SOURCE_DIR}/include)

22
dist/app_loader.js vendored

File diff suppressed because one or more lines are too long

BIN
dist/app_module.wasm vendored

Binary file not shown.

22
dist/douwco_hivemind_loader.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/douwco_hivemind_module.wasm vendored Normal file

Binary file not shown.

2
dist/main.js vendored
View File

@@ -3,7 +3,7 @@
const wasm_loader = require('wasm_loader')
var mod;
wasm_loader('app_loader', 'app_module').then((instance) => {
wasm_loader('douwco_hivemind_loader', 'douwco_hivemind_module').then((instance) => {
console.log("WASM module loaded.");
mod = instance;
});

View File

@@ -16,11 +16,11 @@ namespace DouwcoHivemind
void loop() override;
private:
void setupMemory();
void harvestSource();
std::unique_ptr<Screeps::Source> getSourceTarget();
void searchTarget();
void searchEnergyDeposit();
void searchSource();
void harvestSource();
void depositEnergy();
};
}

View File

@@ -3,7 +3,7 @@
const wasm_loader = require('wasm_loader')
var mod;
wasm_loader('app_loader', 'app_module').then((instance) => {
wasm_loader('douwco_hivemind_loader', 'douwco_hivemind_module').then((instance) => {
console.log("WASM module loaded.");
mod = instance;
});

View File

@@ -22,126 +22,106 @@ bool isNearTo(const Screeps::RoomPosition &pos1, const Screeps::RoomPosition &po
void DouwcoHivemind::HarvesterRole::loop()
{
setupMemory();
searchTarget();
if (!memory.contains("harvesting"))
memory["harvesting"] = false;
if (memory["harvesting"])
harvestSource();
else
depositEnergy();
}
void DouwcoHivemind::HarvesterRole::setupMemory()
void DouwcoHivemind::HarvesterRole::harvestSource()
{
if (!memory.contains("harvesting"))
auto source = getSourceTarget();
if (!source)
return;
if (isNearTo(creep.pos(), source->pos()))
{
EM_ASM({ console.log('Setup harvesting'); });
memory["harvesting"] = false;
int resp = creep.harvest(*source);
// switch (resp)
// {
// case Screeps::ERR_NOT_IN_RANGE:
// /* code */
// break;
// default:
// break;
// }
}
else
creep.moveTo(*source);
}
std::unique_ptr<Screeps::Source> DouwcoHivemind::HarvesterRole::getSourceTarget()
{
// Check if target is still valid
if (!memory.contains("target") || memory["target"].empty())
{
EM_ASM({ console.log('Setup target'); });
if (memory["harvesting"])
searchSource();
else
searchEnergyDeposit();
return nullptr;
}
}
void DouwcoHivemind::HarvesterRole::searchTarget()
{
if (memory["harvesting"] && creep.store().getFreeCapacity(Screeps::RESOURCE_ENERGY) == 0)
// Check if game can find target
auto sourceObj = Screeps::Game.getObjectById(memory["target"]);
if (!sourceObj)
{
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;
JS::console.log(creep.name() + ": Game can\'t find target id");
// EM_ASM({console.log($0 + ': Game can\'t find target id')}, creep.name().c_str());
searchSource();
return nullptr;
}
}
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)
// Check if found roomobject is an actual source
auto source = std::unique_ptr<Screeps::Source>(dynamic_cast<Screeps::Source *>(sourceObj.release()));
if (!source)
{
auto structure = dynamic_cast<Screeps::Structure *>(structureObject.get());
if (!structure)
continue;
if (structure->structureType() == Screeps::STRUCTURE_SPAWN &&
dynamic_cast<Screeps::StructureSpawn *>(structure)->store().getFreeCapacity(Screeps::RESOURCE_ENERGY) > 0)
filtered.emplace_back(std::move(structureObject));
else if (structure->structureType() == Screeps::STRUCTURE_EXTENSION &&
dynamic_cast<Screeps::StructureSpawn *>(structure)->store().getFreeCapacity(Screeps::RESOURCE_ENERGY) > 0)
filtered.emplace_back(std::move(structureObject));
else if (structure->structureType() == Screeps::STRUCTURE_TOWER &&
dynamic_cast<Screeps::StructureSpawn *>(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));
// EM_ASM({console.log($0 + ': Can\'t cast target to Source')}, creep.name().c_str());
searchSource();
return nullptr;
}
auto closestObj = creep.pos().findClosestByPath(filtered);
if (closestObj)
// Check if the source still has energy to harvest
if (source->energy() == 0)
{
auto closest = dynamic_cast<Screeps::Structure *>(closestObj.get());
memory["target"] = closest ? closest->id() : "";
searchSource();
return nullptr;
}
else
memory["target"].clear();
return std::move(source);
}
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"].clear();
}
}
void DouwcoHivemind::HarvesterRole::harvestSource()
{
if (!memory.contains("target") || memory["target"].empty())
{
searchSource();
if (!memory.contains("target") || memory["target"].empty())
auto sources = creep.room().find(Screeps::FIND_SOURCES_ACTIVE);
if (sources.size() == 0)
return;
}
auto sourceObj = Screeps::Game.getObjectById(memory["target"]);
if (sourceObj)
Screeps::Source *selectedSource;
int maxEnergy = 0;
for (auto &sourceObj : sources)
{
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;
continue;
auto sourceEnergy = source->energy();
if (sourceEnergy > maxEnergy)
{
maxEnergy = sourceEnergy;
selectedSource = source;
}
}
if (isNearTo(creep.pos(), source->pos()))
creep.harvest(*source);
else
creep.moveTo(*source);
if (!selectedSource)
{
// EM_ASM({console.log($0 + ': No sources with energy found!')}, creep.name().c_str());
return;
}
memory["target"] = selectedSource->id();
}
void DouwcoHivemind::HarvesterRole::depositEnergy()
@@ -190,6 +170,56 @@ void DouwcoHivemind::HarvesterRole::depositEnergy()
}
}
void DouwcoHivemind::HarvesterRole::searchTarget()
{
if (memory["harvesting"] && creep.store().getFreeCapacity(Screeps::RESOURCE_ENERGY) == 0)
{
memory["harvesting"] = false;
searchEnergyDeposit();
}
else if (!memory["harvesting"] && creep.store().getUsedCapacity(Screeps::RESOURCE_ENERGY) == 0)
{
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 &&
dynamic_cast<Screeps::StructureSpawn *>(structure)->store().getFreeCapacity(Screeps::RESOURCE_ENERGY) > 0)
filtered.emplace_back(std::move(structureObject));
else if (structure->structureType() == Screeps::STRUCTURE_EXTENSION &&
dynamic_cast<Screeps::StructureSpawn *>(structure)->store().getFreeCapacity(Screeps::RESOURCE_ENERGY) > 0)
filtered.emplace_back(std::move(structureObject));
else if (structure->structureType() == Screeps::STRUCTURE_TOWER &&
dynamic_cast<Screeps::StructureSpawn *>(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());
if (closest)
{
memory["target"] = closest->id();
return;
}
}
memory["target"].clear();
}
bool isNearTo(const Screeps::RoomPosition &pos1, const Screeps::RoomPosition &pos2)
{
int dx = pos1.x() - pos2.x();