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", "numbers": "cpp",
"semaphore": "cpp", "semaphore": "cpp",
"cfenv": "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. # 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) 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') const wasm_loader = require('wasm_loader')
var mod; 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."); console.log("WASM module loaded.");
mod = instance; mod = instance;
}); });

View File

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

View File

@@ -3,7 +3,7 @@
const wasm_loader = require('wasm_loader') const wasm_loader = require('wasm_loader')
var mod; 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."); console.log("WASM module loaded.");
mod = instance; mod = instance;
}); });

View File

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