Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 49f253a546 | |||
| e809d23f57 | |||
|
|
656cca578e | ||
| 1596283841 | |||
| 74d6e9e76d | |||
| 38082e3fc4 | |||
| e484919546 | |||
| e9134357a7 | |||
|
|
1859662e94 | ||
|
|
eea9e7d69f | ||
|
|
0c693354e6 | ||
|
|
40ab8b289a | ||
|
|
67f0afae4c | ||
|
|
cc0de10471 | ||
|
|
98b123ee0d | ||
|
|
6ee67eac47 | ||
|
|
cd1464cc94 | ||
|
|
0381ea6873 | ||
|
|
0c8da1d472 | ||
|
|
1ede4cce47 | ||
|
|
1e9e696b1e | ||
|
|
c9ce09ba1a | ||
|
|
1a74743e4f | ||
|
|
fa5d75fca3 | ||
|
|
b61743fa52 | ||
|
|
009853665d | ||
|
|
257cf85695 | ||
|
|
9a1682a857 | ||
|
|
8a39526580 | ||
|
|
5ed1329d2e | ||
|
|
7c1a84a5ca | ||
|
|
bde8a2309f | ||
|
|
8d67dcb8b8 | ||
|
|
29aa48dc3b | ||
|
|
5cfea80b19 | ||
|
|
eda20c2dce | ||
|
|
112c3c3a97 | ||
|
|
523a2e0005 | ||
|
|
cab2c3fd25 |
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# IDE
|
||||||
|
.cache/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Build files
|
||||||
|
build/*
|
||||||
|
dist/*
|
||||||
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[submodule "emsdk"]
|
||||||
|
path = emsdk
|
||||||
|
url = git@github.com:emscripten-core/emsdk.git
|
||||||
|
[submodule "screepsxx"]
|
||||||
|
path = screepsxx
|
||||||
|
url = git@github.com:DouweRavers/screepsxx.git
|
||||||
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"files.exclude": {
|
|
||||||
".*": true,
|
|
||||||
"LICENSE": true,
|
|
||||||
"*.md": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
39
CMakeLists.txt
Normal file
39
CMakeLists.txt
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(douwco_hivemind CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||||
|
|
||||||
|
# set(COMPILE_FLAGS --cache ${CMAKE_BINARY_DIR}/cache)
|
||||||
|
set(LINK_FLAGS -sASSERTIONS=0 -sMALLOC=emmalloc)
|
||||||
|
add_compile_options(${COMPILE_FLAGS})
|
||||||
|
add_link_options(${COMPILE_FLAGS} ${LINK_FLAGS})
|
||||||
|
|
||||||
|
add_subdirectory(screepsxx)
|
||||||
|
|
||||||
|
|
||||||
|
# If you change TARGET_NAME, please, make corresponding changes in main.js.
|
||||||
|
set(TARGET_NAME douwco_hivemind)
|
||||||
|
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/douwco_hivemind/include)
|
||||||
|
|
||||||
|
file(GLOB SRC_FILES ${CMAKE_SOURCE_DIR}/douwco_hivemind/src/*.cpp)
|
||||||
|
add_executable(${TARGET_NAME} ${SRC_FILES})
|
||||||
|
target_link_libraries(${TARGET_NAME} screepsxx)
|
||||||
|
target_link_options(${TARGET_NAME} PUBLIC -sMODULARIZE=1 --no-entry --bind -sEXPORT_ES6=0)
|
||||||
|
|
||||||
|
# Collect all artifacts in 'dist' directory
|
||||||
|
# WASM-module and corresponding JS-module must have different base names in order to use them in Screeps, so we add suffixes.
|
||||||
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/${TARGET_NAME}.wasm ${CMAKE_SOURCE_DIR}/dist/${TARGET_NAME}_module.wasm)
|
||||||
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/${TARGET_NAME}.js ${CMAKE_SOURCE_DIR}/dist/${TARGET_NAME}_loader.js)
|
||||||
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/js/main.js ${CMAKE_SOURCE_DIR}/dist/main.js)
|
||||||
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/js/wasm_loader.js ${CMAKE_SOURCE_DIR}/dist/wasm_loader.js)
|
||||||
|
|
||||||
|
# Following post-build step will automatically upload artifacts to
|
||||||
|
# official Screeps server. If you want to use it, please,
|
||||||
|
# set SCREEPS_TOKEN environment variable to your Screeps API token
|
||||||
|
# (https://docs.screeps.com/auth-tokens.html).
|
||||||
|
# If you don't want to use this script, please, remove following lines.
|
||||||
|
#find_package(Python COMPONENTS Interpreter REQUIRED)
|
||||||
|
#add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${Python_EXECUTABLE} ${screepsxx_SOURCE_DIR}/tools/upload.py ${CMAKE_SOURCE_DIR}/dist $ENV{SCREEPS_TOKEN})
|
||||||
61
Commands.js
61
Commands.js
@@ -1,61 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
setup(){
|
|
||||||
global.fullReset = fullReset;
|
|
||||||
global.resetRooms = resetRooms;
|
|
||||||
global.resetStructures = resetStructures;
|
|
||||||
global.resetCreeps = resetCreeps;
|
|
||||||
global.resetConstruction = resetConstruction;
|
|
||||||
|
|
||||||
global.buildRoads = buildRoads;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fullReset(){
|
|
||||||
resetRooms();
|
|
||||||
resetCreeps();
|
|
||||||
resetStructures();
|
|
||||||
resetConstruction();
|
|
||||||
global.started = false;
|
|
||||||
global.compiled = false;
|
|
||||||
return "OK";
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetRooms(){
|
|
||||||
Object.values(Game.rooms).forEach(room => room.memory = {});
|
|
||||||
return "OK";
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetStructures(){
|
|
||||||
Object.values(Game.structures).forEach(structure => structure.memory = {});
|
|
||||||
return "OK";
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetCreeps(){
|
|
||||||
Object.values(Game.creeps).forEach(creep => creep.suicide());
|
|
||||||
return "OK";
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetConstruction(){
|
|
||||||
Object.values(Game.rooms).forEach(room=>room.find(FIND_CONSTRUCTION_SITES).forEach(cs=>cs.remove()));
|
|
||||||
return "OK";
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildRoads(){
|
|
||||||
Object.values(Game.rooms).forEach(room=>
|
|
||||||
{
|
|
||||||
room.memory.layout.sources.forEach(
|
|
||||||
sId => {
|
|
||||||
const source = Game.getObjectById(sId);
|
|
||||||
var roads = [];
|
|
||||||
roads = roads.concat(source.pos.findPathTo(room.controller));
|
|
||||||
roads.pop();
|
|
||||||
roads = roads.concat(source.pos.findPathTo(room.find(FIND_MY_STRUCTURES, { filter:{ structureType:STRUCTURE_SPAWN }})[0]));
|
|
||||||
roads.pop();
|
|
||||||
roads.forEach(tile => room.createConstructionSite(tile.x, tile.y, STRUCTURE_ROAD));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return "OK";
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
const jobHarvester = require("JobHarvester");
|
|
||||||
const jobMiner = require("JobMiner");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
setup: function () {
|
|
||||||
Creep.prototype = _Creep.prototype;
|
|
||||||
global.Role = Role;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Role = {
|
|
||||||
HARVESTER: 0,
|
|
||||||
MINER: 1,
|
|
||||||
SUPPLIER: 2,
|
|
||||||
UPGRADER: 3,
|
|
||||||
BUILDER: 4
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Creep extends Creep {
|
|
||||||
begin(){
|
|
||||||
if(!this.memory.job) this.memory.job = { role: Role.HARVESTER };
|
|
||||||
switch (this.memory.job.role) {
|
|
||||||
case Role.HARVESTER: jobHarvester.begin(this); break;
|
|
||||||
case Role.MINER: jobMiner.begin(this); break;
|
|
||||||
}
|
|
||||||
this.memory.init = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
tick(){
|
|
||||||
if(!this.memory.init) this.begin();
|
|
||||||
switch (this.memory.job.role) {
|
|
||||||
case Role.HARVESTER: jobHarvester.tick(this); break;
|
|
||||||
case Role.MINER: jobMiner.tick(this); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
begin(creep){
|
|
||||||
},
|
|
||||||
|
|
||||||
tick(creep){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
begin(creep){
|
|
||||||
if(!creep.memory.harvesting) creep.memory.harvesting = false;
|
|
||||||
if(!creep.memory.counter) creep.memory.counter = 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
tick(creep){
|
|
||||||
if(creep.memory.harvesting) {
|
|
||||||
pickUpEnergy(creep);
|
|
||||||
onEnergyFullTurnToJobMode(creep);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
performJobs(creep);
|
|
||||||
onOutOfEnergyTurnHarvestingMode(creep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function pickUpEnergy(creep){
|
|
||||||
if(!creep.memory.target) {
|
|
||||||
const target = creep.pos.findClosestByRange(FIND_DROPPED_RESOURCES, {filter: {resourceType: RESOURCE_ENERGY}});
|
|
||||||
if(target) creep.memory.target = target.id;
|
|
||||||
}
|
|
||||||
const resource = Game.getObjectById(creep.memory.target);
|
|
||||||
if(!resource) creep.memory.target = undefined;
|
|
||||||
if(creep.pos.isNearTo(resource)) creep.pickup(resource);
|
|
||||||
else creep.moveTo(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
function harvestSource(creep){
|
|
||||||
if(!creep.memory.target) creep.memory.target = getSourceIdFromRoomTable(creep);
|
|
||||||
var source = Game.getObjectById(creep.memory.target);
|
|
||||||
if(creep.pos.isNearTo(source)) creep.harvest(source);
|
|
||||||
else creep.moveTo(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onEnergyFullTurnToJobMode(creep){
|
|
||||||
if(!creep.store.getFreeCapacity(RESOURCE_ENERGY)) {
|
|
||||||
creep.memory.harvesting = false;
|
|
||||||
creep.memory.target = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function performJobs(creep){
|
|
||||||
if(!creep.memory.target) creep.memory.target = getJobTarget(creep);
|
|
||||||
var target = Game.getObjectById(creep.memory.target);
|
|
||||||
if(creep.pos.isNearTo(target)) doJob(creep, target);
|
|
||||||
else creep.moveTo(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onOutOfEnergyTurnHarvestingMode(creep){
|
|
||||||
if(!creep.store.getUsedCapacity(RESOURCE_ENERGY)) {
|
|
||||||
creep.memory.harvesting = true;
|
|
||||||
creep.memory.target = undefined;
|
|
||||||
creep.memory.counter += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSourceIdFromRoomTable(creep) {
|
|
||||||
const sourceTable = creep.room.memory.layout.sources;
|
|
||||||
const sourceIterator = creep.memory.counter%creep.room.memory.layout.sources.length;
|
|
||||||
const sourceId = sourceTable[sourceIterator];
|
|
||||||
return sourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getJobTarget(creep) {
|
|
||||||
var target;
|
|
||||||
switch (creep.memory.counter%3) {
|
|
||||||
case 0: target = creep.room.controller; break;
|
|
||||||
case 1: target = creep.pos.findClosestByRange(FIND_MY_STRUCTURES, {filter:{structureType:STRUCTURE_SPAWN}}); break;
|
|
||||||
case 2: target = creep.pos.findClosestByRange(FIND_MY_CONSTRUCTION_SITES); break;
|
|
||||||
}
|
|
||||||
if(target) return target.id;
|
|
||||||
creep.memory.counter++;
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doJob(creep, target){
|
|
||||||
var response;
|
|
||||||
switch (creep.memory.counter%3) {
|
|
||||||
case 0: response = creep.upgradeController(target); break;
|
|
||||||
case 1: response = creep.transfer(target, RESOURCE_ENERGY); break;
|
|
||||||
case 2: response = creep.build(target); break;
|
|
||||||
}
|
|
||||||
if(response == ERR_FULL) {
|
|
||||||
creep.memory.counter++;
|
|
||||||
creep.memory.target = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
18
JobMiner.js
18
JobMiner.js
@@ -1,18 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
begin(creep){},
|
|
||||||
|
|
||||||
tick(creep){
|
|
||||||
const source = Game.getObjectById(creep.memory.job.source);
|
|
||||||
if(creep.memory.aboveContainer) creep.harvest(source);
|
|
||||||
if(!creep.pos.isNearTo(source)) { creep.moveTo(source); return; }
|
|
||||||
if(creep.memory.container) {
|
|
||||||
const container = Game.getObjectById(creep.memory.container);
|
|
||||||
if(container.pos.x === creep.pos.x, container.pos.y === creep.pos.y) creep.memory.aboveContainer = true;
|
|
||||||
else creep.moveTo(container);
|
|
||||||
} else{
|
|
||||||
const container = source.pos.findInRange(FIND_STRUCTURES, 1, {filter:{structureType:STRUCTURE_CONTAINER}})[0];
|
|
||||||
if(container) creep.memory.container = container.id;
|
|
||||||
else creep.harvest(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
begin(creep){
|
|
||||||
},
|
|
||||||
|
|
||||||
tick(creep){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
begin(creep){
|
|
||||||
},
|
|
||||||
|
|
||||||
tick(creep){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
7
Math.js
7
Math.js
@@ -1,7 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
clamp: function(v, min, max){
|
|
||||||
if(v<min) v = min;
|
|
||||||
else if (max < v) v = max;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
36
README.md
36
README.md
@@ -1,5 +1,33 @@
|
|||||||
# screeps
|
# Douwco Hivemind
|
||||||
My source code for the MMO-programming game: Screeps.
|
This is the sourcecode of my hivemind implementation for the MMO-programming game Screeps. This is mainly designed to learn programming with C++. This is possible throught the work done in the screepxx project, which I will and try to expand as well.
|
||||||
|
|
||||||
# Status
|
# Running the project
|
||||||
To those interested in this code. I wrote the main body of the source code when just learning programming so its kind of a mess. I'm now slowly rewriting the code base to a more SOLID version. :)
|
All commands are run starting from the root directory.
|
||||||
|
|
||||||
|
## Emsdk setup
|
||||||
|
Screeps only supports ES5 js syntax which can only be guaranteed by using emsdk 2.0.0.
|
||||||
|
|
||||||
|
```
|
||||||
|
cd emsdk && \
|
||||||
|
./emsdk install 2.0.0 && \
|
||||||
|
./emsdk activate 2.0.0 && \
|
||||||
|
source ./emsdk_env.sh && \
|
||||||
|
cd ..
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cmake setup
|
||||||
|
Create the makefiles using cmake. For more info look at the readme in screepsxx.
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake ..
|
||||||
|
```
|
||||||
|
|
||||||
|
# Build
|
||||||
|
To build the project run the following. In the dist folder the "screeps ready" project is copied.
|
||||||
|
|
||||||
|
```
|
||||||
|
cd build
|
||||||
|
cmake --build .
|
||||||
|
```
|
||||||
44
RoomClass.js
44
RoomClass.js
@@ -1,44 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
setup: function () { Room.prototype = _Room.prototype; }
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Room extends Room {
|
|
||||||
begin(){
|
|
||||||
roomScan(this);
|
|
||||||
jobScan(this);
|
|
||||||
vacancyScan(this);
|
|
||||||
this.memory.init = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
tick(){
|
|
||||||
if(!this.memory.init) this.begin();
|
|
||||||
if(Game.time%100 === 1) vacancyScan(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function roomScan(room){
|
|
||||||
room.memory.layout = {
|
|
||||||
sources: room.find(FIND_SOURCES).map(s=>s.id)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function jobScan(room){
|
|
||||||
if(!room.memory.jobs) room.memory.jobs = Array(10).fill({role: Role.HARVESTER})
|
|
||||||
.concat(room.memory.layout.sources.map(s=> {return {role: Role.MINER, source: s}}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function vacancyScan(room){
|
|
||||||
const activeJobs = room.find(FIND_MY_CREEPS).map(creep=>creep.memory.job);
|
|
||||||
console.log(activeJobs.toString());
|
|
||||||
console.log(room.memory.jobs.toString());
|
|
||||||
const jobs = room.memory.jobs.filter((j)=>{
|
|
||||||
const index = activeJobs.findIndex(aj=> _.isEqual(aj,j));
|
|
||||||
if(index < 0) return true;
|
|
||||||
activeJobs.splice(index,1);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
console.log(jobs.toString());
|
|
||||||
|
|
||||||
room.memory.vacancies = jobs;
|
|
||||||
}
|
|
||||||
|
|
||||||
21
Structure.js
21
Structure.js
@@ -1,21 +0,0 @@
|
|||||||
const spawnClass = require("StructureSpawnClass");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
setup() {
|
|
||||||
spawnClass.setup();
|
|
||||||
},
|
|
||||||
|
|
||||||
begin(structure){
|
|
||||||
switch (structure.structureType) {
|
|
||||||
case STRUCTURE_SPAWN: structure.begin(); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
tick(structure){
|
|
||||||
switch (structure.structureType) {
|
|
||||||
case STRUCTURE_SPAWN: structure.tick(); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
setup: function () { StructureSpawn.prototype = _StructureSpawn.prototype; }
|
|
||||||
}
|
|
||||||
|
|
||||||
class _StructureSpawn extends StructureSpawn {
|
|
||||||
begin(){
|
|
||||||
if (!this.memory.creepCounter) this.memory.creepCounter = 0;
|
|
||||||
this.memory.init = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
tick(){
|
|
||||||
if(!this.memory.init) this.begin();
|
|
||||||
if(this.store.getUsedCapacity(RESOURCE_ENERGY) < 300) return;
|
|
||||||
const job = this.room.memory.vacancies.pop();
|
|
||||||
if(job){
|
|
||||||
const name = getJobName(job.role);
|
|
||||||
const body = getBodyByJob(job.role);
|
|
||||||
if(this.createCreep(job, name, body) != OK) this.room.memory.vacancies.push(job);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createCreep(job, name, body) {
|
|
||||||
const response = this.spawnCreep(body, name + ": " + this.memory.creepCounter, {
|
|
||||||
memory: { job: job }
|
|
||||||
});
|
|
||||||
if (response == OK) this.memory.creepCounter++;
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getJobName(role){
|
|
||||||
switch (role) {
|
|
||||||
case Role.HARVESTER: return "Harvy";
|
|
||||||
case Role.MINER: return "minny";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBodyByJob(role){
|
|
||||||
switch (role) {
|
|
||||||
case Role.HARVESTER: return [WORK, CARRY, MOVE, MOVE];
|
|
||||||
case Role.MINER: return [WORK, WORK, MOVE];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
22
douwco_hivemind/include/Creeps/Builder.hpp
Normal file
22
douwco_hivemind/include/Creeps/Builder.hpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_BUILDER_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_BUILDER_HPP
|
||||||
|
|
||||||
|
#include "Creeps/Worker.hpp"
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
class Builder : public Worker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Builder(Screeps::Creep creep) : Worker(creep) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void depositEnergy() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Screeps::ConstructionSite> getConstructionSiteTarget();
|
||||||
|
void searchConstructionSite();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_BUILDER_HPP
|
||||||
49
douwco_hivemind/include/Creeps/CreepBase.hpp
Normal file
49
douwco_hivemind/include/Creeps/CreepBase.hpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_CREEPBASE_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_CREEPBASE_HPP
|
||||||
|
|
||||||
|
#include <Screeps/Creep.hpp>
|
||||||
|
|
||||||
|
namespace Screeps{
|
||||||
|
class RoomPosition;
|
||||||
|
class RoomObject;
|
||||||
|
class PathStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
enum CreepRole
|
||||||
|
{
|
||||||
|
UNEMPLOYED,
|
||||||
|
SUPPLIER,
|
||||||
|
UPGRADER,
|
||||||
|
BUILDER,
|
||||||
|
MAINTAINER
|
||||||
|
};
|
||||||
|
|
||||||
|
class CreepBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CreepRole role;
|
||||||
|
std::string target_id;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Screeps::Creep creep;
|
||||||
|
JSON memory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CreepBase(Screeps::Creep crp);
|
||||||
|
virtual ~CreepBase();
|
||||||
|
virtual void loop() {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool isNearTo(const Screeps::RoomPosition &pos, int dist);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void moveToTarget(int dist = 1);
|
||||||
|
std::unique_ptr<Screeps::RoomObject> getRoomObjectTarget();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_CREEPBASE_HPP
|
||||||
22
douwco_hivemind/include/Creeps/Maintainer.hpp
Normal file
22
douwco_hivemind/include/Creeps/Maintainer.hpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_MAINTAINER_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_MAINTAINER_HPP
|
||||||
|
|
||||||
|
#include "Creeps/Worker.hpp"
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
class Maintainer : public Worker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Maintainer(Screeps::Creep creep) : Worker(creep) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void depositEnergy() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Screeps::Structure> getDamagedStructureTarget();
|
||||||
|
void searchDamagedStructure();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_MAINTAINER_HPP
|
||||||
23
douwco_hivemind/include/Creeps/Miner.hpp
Normal file
23
douwco_hivemind/include/Creeps/Miner.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_MINER_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_MINER_HPP
|
||||||
|
|
||||||
|
#include <Creeps/CreepBase.hpp>
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
class Miner : public CreepBase
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool requestedContainer = false;
|
||||||
|
public:
|
||||||
|
Miner(Screeps::Creep crp);
|
||||||
|
~Miner() override;
|
||||||
|
void loop() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mineSource();
|
||||||
|
std::unique_ptr<Screeps::Source> getSourceTarget();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_MINER_HPP
|
||||||
22
douwco_hivemind/include/Creeps/Supplier.hpp
Normal file
22
douwco_hivemind/include/Creeps/Supplier.hpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_SUPPLIER_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_SUPPLIER_HPP
|
||||||
|
|
||||||
|
#include "Creeps/Worker.hpp"
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
class Supplier : public Worker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Supplier(Screeps::Creep creep) : Worker(creep) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void depositEnergy() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Screeps::Structure> getEnergyStructureTarget();
|
||||||
|
void searchEnergyStructure();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_SUPPLIER_HPP
|
||||||
18
douwco_hivemind/include/Creeps/Upgrader.hpp
Normal file
18
douwco_hivemind/include/Creeps/Upgrader.hpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_HARVESTER_UPGRADER_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_HARVESTER_UPGRADER_HPP
|
||||||
|
|
||||||
|
#include "Creeps/Worker.hpp"
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
class Upgrader : public Worker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Upgrader(Screeps::Creep creep) : Worker(creep) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void depositEnergy() override;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_HARVESTER_UPGRADER_HPP
|
||||||
29
douwco_hivemind/include/Creeps/Worker.hpp
Normal file
29
douwco_hivemind/include/Creeps/Worker.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_WORKER_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_WORKER_HPP
|
||||||
|
|
||||||
|
#include "Creeps/CreepBase.hpp"
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
class Worker : public CreepBase
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool harvesting;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Worker(Screeps::Creep crp);
|
||||||
|
~Worker() override;
|
||||||
|
|
||||||
|
void loop() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void depositEnergy(){}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void harvestSource();
|
||||||
|
std::unique_ptr<Screeps::Source> getSourceTarget();
|
||||||
|
void searchSource();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_WORKER_HPP
|
||||||
28
douwco_hivemind/include/Engine.hpp
Normal file
28
douwco_hivemind/include/Engine.hpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_ENGINE_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_ENGINE_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Creeps/CreepBase.hpp"
|
||||||
|
#include "Structures/StructureBase.hpp"
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
class Engine
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<CreepBase>> creeps;
|
||||||
|
std::vector<std::unique_ptr<StructureBase>> structures;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Engine();
|
||||||
|
void loop();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ReadOutCreeps();
|
||||||
|
void ReadOutStructures();
|
||||||
|
void clearDeadCreepMemory();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_ENGINE_HPP
|
||||||
24
douwco_hivemind/include/Structures/Spawn.hpp
Normal file
24
douwco_hivemind/include/Structures/Spawn.hpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_SPAWN_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_SPAWN_HPP
|
||||||
|
|
||||||
|
#include <Screeps/StructureSpawn.hpp>
|
||||||
|
|
||||||
|
#include "Structures/StructureBase.hpp"
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
class Spawn : public StructureBase
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Screeps::StructureSpawn spawn;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Spawn(Screeps::StructureSpawn spwn) : spawn(spwn),
|
||||||
|
StructureBase() {}
|
||||||
|
~Spawn() {}
|
||||||
|
|
||||||
|
void loop() override;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_SPAWN_HPP
|
||||||
15
douwco_hivemind/include/Structures/StructureBase.hpp
Normal file
15
douwco_hivemind/include/Structures/StructureBase.hpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_STRUCTURE_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_STRUCTURE_HPP
|
||||||
|
|
||||||
|
#include <Screeps/Structure.hpp>
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
class StructureBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void loop(){}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_STRUCTURE_HPP
|
||||||
33
douwco_hivemind/include/Tools/JsonTool.hpp
Normal file
33
douwco_hivemind/include/Tools/JsonTool.hpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_JSON_TOOLS_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_JSON_TOOLS_HPP
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::vector<T> jsonToVector(const nlohmann::json &json)
|
||||||
|
{
|
||||||
|
std::vector<T> vector;
|
||||||
|
for (const auto &item : json)
|
||||||
|
{
|
||||||
|
vector.emplace_back(item.get<T>());
|
||||||
|
}
|
||||||
|
return vector;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
nlohmann::json vectorToJson(const std::vector<T> &vector)
|
||||||
|
{
|
||||||
|
nlohmann::json json;
|
||||||
|
for (const auto &item : vector)
|
||||||
|
{
|
||||||
|
json.emplace_back(item);
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_JSON_TOOLS_HPP
|
||||||
19
douwco_hivemind/include/Tools/MeasureTool.hpp
Normal file
19
douwco_hivemind/include/Tools/MeasureTool.hpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_MEASURE_TOOL_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_MEASURE_TOOL_HPP
|
||||||
|
|
||||||
|
#include <Screeps/RoomPosition.hpp>
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
static bool isNearTo(const Screeps::RoomPosition &pos1, const Screeps::RoomPosition &pos2, int dist)
|
||||||
|
{
|
||||||
|
int dx = pos1.x() - pos2.x();
|
||||||
|
int dy = pos1.y() - pos2.y();
|
||||||
|
int dist2 = dist * dist;
|
||||||
|
return dx * dx <= dist2 &&
|
||||||
|
dy * dy <= dist2 &&
|
||||||
|
pos1.roomName() == pos2.roomName();
|
||||||
|
}
|
||||||
|
} // namespace Screeps
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_MEASURE_TOOL_HPP
|
||||||
40
douwco_hivemind/include/Tools/PathTool.hpp
Normal file
40
douwco_hivemind/include/Tools/PathTool.hpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef DOUWCO_HIVEMIND_PATH_TOOL_HPP
|
||||||
|
#define DOUWCO_HIVEMIND_PATH_TOOL_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <Screeps/Room.hpp>
|
||||||
|
|
||||||
|
namespace DouwcoHivemind
|
||||||
|
{
|
||||||
|
static std::vector<int> flattenPathSteps(const std::vector<Screeps::Room::PathStep> &pathSteps)
|
||||||
|
{
|
||||||
|
std::vector<int> flattened;
|
||||||
|
for (const auto &step : pathSteps)
|
||||||
|
{
|
||||||
|
flattened.push_back(step.x);
|
||||||
|
flattened.push_back(step.y);
|
||||||
|
flattened.push_back(step.dx);
|
||||||
|
flattened.push_back(step.dy);
|
||||||
|
flattened.push_back(step.direction);
|
||||||
|
}
|
||||||
|
return flattened;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<Screeps::Room::PathStep> unflattenPathSteps(const std::vector<int> &flattened)
|
||||||
|
{
|
||||||
|
std::vector<Screeps::Room::PathStep> pathSteps;
|
||||||
|
for (size_t i = 0; i < flattened.size(); i += 5)
|
||||||
|
{
|
||||||
|
Screeps::Room::PathStep step;
|
||||||
|
step.x = flattened[i];
|
||||||
|
step.y = flattened[i+1];
|
||||||
|
step.dx = flattened[i+2];
|
||||||
|
step.dy = flattened[i+3];
|
||||||
|
step.direction = flattened[i+4];
|
||||||
|
pathSteps.emplace_back(step);
|
||||||
|
}
|
||||||
|
return pathSteps;
|
||||||
|
}
|
||||||
|
} // namespace Screeps
|
||||||
|
|
||||||
|
#endif // DOUWCO_HIVEMIND_PATH_TOOL_HPP
|
||||||
83
douwco_hivemind/src/Builder.cpp
Normal file
83
douwco_hivemind/src/Builder.cpp
Normal 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/Builder.hpp"
|
||||||
|
|
||||||
|
void DouwcoHivemind::Builder::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::Builder::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::Builder::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();
|
||||||
|
}
|
||||||
143
douwco_hivemind/src/CreepBase.cpp
Normal file
143
douwco_hivemind/src/CreepBase.cpp
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <Screeps/Game.hpp>
|
||||||
|
#include <Screeps/Room.hpp>
|
||||||
|
#include <Screeps/RoomPosition.hpp>
|
||||||
|
|
||||||
|
#include "Creeps/CreepBase.hpp"
|
||||||
|
|
||||||
|
#include "Tools/JsonTool.hpp"
|
||||||
|
#include "Tools/PathTool.hpp"
|
||||||
|
#include "Tools/MeasureTool.hpp"
|
||||||
|
|
||||||
|
DouwcoHivemind::CreepBase::CreepBase(Screeps::Creep crp) : creep(crp),
|
||||||
|
memory(crp.memory())
|
||||||
|
{
|
||||||
|
role = memory.contains("role") ? static_cast<CreepRole>(memory["role"]) : CreepRole::UNEMPLOYED;
|
||||||
|
target_id = memory.contains("target_id") ? static_cast<std::string>(memory["target_id"]) : std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
DouwcoHivemind::CreepBase::~CreepBase()
|
||||||
|
{
|
||||||
|
memory["target_id"] = target_id;
|
||||||
|
creep.setMemory(memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouwcoHivemind::CreepBase::moveToTarget(int dist)
|
||||||
|
{
|
||||||
|
// Is move required?
|
||||||
|
auto target = getRoomObjectTarget();
|
||||||
|
if (isNearTo(target->pos(), dist))
|
||||||
|
{
|
||||||
|
memory.erase("path");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is wating?
|
||||||
|
if (memory.contains("wait") && memory["wait"] > 0)
|
||||||
|
{
|
||||||
|
memory["wait"] = memory["wait"].get<int>() - 1;
|
||||||
|
creep.say("Waiting..");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is there a path to walk?
|
||||||
|
if (!memory.contains("path") || memory["path"].empty())
|
||||||
|
{
|
||||||
|
creep.say("Searching route!");
|
||||||
|
auto target_pos = target->pos();
|
||||||
|
auto path = creep.room().findPath(creep.pos(), target_pos);
|
||||||
|
auto last = path.back();
|
||||||
|
if (last.x - target_pos.x() > dist || last.y - target_pos.y() > dist)
|
||||||
|
{
|
||||||
|
creep.say("No possible path");
|
||||||
|
memory["wait"] = rand() % 20;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memory["path"] = vectorToJson(flattenPathSteps(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
// JS::console.log(std::string("creep pos: [") +
|
||||||
|
// std::to_string(creep.pos().x()) +
|
||||||
|
// std::string(",") +
|
||||||
|
// std::to_string(creep.pos().y()) +
|
||||||
|
// std::string("]"));
|
||||||
|
|
||||||
|
// Get step from memory
|
||||||
|
int pathStepData[5] = {0};
|
||||||
|
if (memory["path"].size() > 5)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
pathStepData[i] = memory["path"][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memory.erase("path");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the move of last tick executed?
|
||||||
|
int x = creep.pos().x();
|
||||||
|
int y = creep.pos().y();
|
||||||
|
|
||||||
|
Screeps::Room::PathStep step;
|
||||||
|
step.x = pathStepData[0];
|
||||||
|
step.y = pathStepData[1];
|
||||||
|
step.dx = pathStepData[2];
|
||||||
|
step.dy = pathStepData[3];
|
||||||
|
step.direction = pathStepData[4];
|
||||||
|
|
||||||
|
if (memory.contains("last_pos"))
|
||||||
|
{
|
||||||
|
int last_x = memory["last_pos"]["x"];
|
||||||
|
int last_y = memory["last_pos"]["y"];
|
||||||
|
memory.erase("last_pos");
|
||||||
|
if (x == last_x && y == last_y)
|
||||||
|
{
|
||||||
|
creep.say("I'm stuck!");
|
||||||
|
memory["wait"] = rand() % 5;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the creep on the place intended by the path?
|
||||||
|
if (!(x == step.x - step.dx && y == step.y - step.dy))
|
||||||
|
{
|
||||||
|
creep.say("I'm lost!");
|
||||||
|
memory["wait"] = rand() % 5;
|
||||||
|
memory.erase("path");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lets move forward
|
||||||
|
int resp = creep.move(step.direction);
|
||||||
|
if (resp == Screeps::OK)
|
||||||
|
{
|
||||||
|
memory["last_pos"]["x"] = x;
|
||||||
|
memory["last_pos"]["y"] = y;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
memory["path"].erase(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Screeps::RoomObject> DouwcoHivemind::CreepBase::getRoomObjectTarget()
|
||||||
|
{
|
||||||
|
// Check if game can find target
|
||||||
|
auto roomObj = Screeps::Game.getObjectById(target_id);
|
||||||
|
if (!roomObj)
|
||||||
|
{
|
||||||
|
JS::console.log(creep.name() + ": Game can\'t find target id");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return std::move(roomObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DouwcoHivemind::CreepBase::isNearTo(const Screeps::RoomPosition &pos, int dist)
|
||||||
|
{
|
||||||
|
return DouwcoHivemind::isNearTo(creep.pos(), pos, dist);
|
||||||
|
}
|
||||||
88
douwco_hivemind/src/Engine.cpp
Normal file
88
douwco_hivemind/src/Engine.cpp
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#include <Screeps/Game.hpp>
|
||||||
|
#include <Screeps/Memory.hpp>
|
||||||
|
|
||||||
|
#include "Engine.hpp"
|
||||||
|
|
||||||
|
#include "Creeps/Supplier.hpp"
|
||||||
|
#include "Creeps/Upgrader.hpp"
|
||||||
|
#include "Creeps/Builder.hpp"
|
||||||
|
#include "Creeps/Maintainer.hpp"
|
||||||
|
|
||||||
|
#include "Structures/Spawn.hpp"
|
||||||
|
|
||||||
|
DouwcoHivemind::Engine::Engine()
|
||||||
|
{
|
||||||
|
ReadOutCreeps();
|
||||||
|
ReadOutStructures();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
if (Screeps::Game.time() % 1000 == 0)
|
||||||
|
{
|
||||||
|
clearDeadCreepMemory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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"];
|
||||||
|
if (role == CreepRole::SUPPLIER)
|
||||||
|
creeps.push_back(std::make_unique<Supplier>(creep.second));
|
||||||
|
else if (role == CreepRole::UPGRADER)
|
||||||
|
creeps.push_back(std::make_unique<Upgrader>(creep.second));
|
||||||
|
else if (role == CreepRole::BUILDER)
|
||||||
|
creeps.push_back(std::make_unique<Builder>(creep.second));
|
||||||
|
else if (role == CreepRole::MAINTAINER)
|
||||||
|
creeps.push_back(std::make_unique<Maintainer>(creep.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouwcoHivemind::Engine::ReadOutStructures()
|
||||||
|
{
|
||||||
|
JS::console.log(std::string("Reading out structures"));
|
||||||
|
auto spawns = Screeps::Game.spawns();
|
||||||
|
for (auto &spawn : spawns)
|
||||||
|
{
|
||||||
|
structures.push_back(std::make_unique<Spawn>(spawn.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouwcoHivemind::Engine::clearDeadCreepMemory()
|
||||||
|
{
|
||||||
|
auto creepMemory = Screeps::Memory["creeps"];
|
||||||
|
auto creepsMap = Screeps::Game.creeps();
|
||||||
|
int iterator = 0;
|
||||||
|
for (auto [name, creep] : creepMemory.items())
|
||||||
|
{
|
||||||
|
// avoid cpu overload
|
||||||
|
iterator++;
|
||||||
|
if (iterator == 100)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bool containsname = false;
|
||||||
|
for (auto creepObject : creepsMap)
|
||||||
|
{
|
||||||
|
if (creepObject.first == name)
|
||||||
|
{
|
||||||
|
containsname = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!containsname)
|
||||||
|
creepMemory.erase(name);
|
||||||
|
}
|
||||||
|
Screeps::Memory.set("creeps", creepMemory);
|
||||||
|
}
|
||||||
32
douwco_hivemind/src/Loop.cpp
Normal file
32
douwco_hivemind/src/Loop.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include <Screeps/Context.hpp>
|
||||||
|
#include <Screeps/Creep.hpp>
|
||||||
|
#include <Screeps/StructureSpawn.hpp>
|
||||||
|
|
||||||
|
#include <emscripten.h>
|
||||||
|
#include <emscripten/bind.h>
|
||||||
|
#include <emscripten/val.h>
|
||||||
|
|
||||||
|
#include "Engine.hpp"
|
||||||
|
#include "Structures/Spawn.hpp"
|
||||||
|
|
||||||
|
EMSCRIPTEN_KEEPALIVE
|
||||||
|
extern "C" void loop()
|
||||||
|
{
|
||||||
|
Screeps::Context::update();
|
||||||
|
|
||||||
|
JS::console.log(std::string("\n\n\n\n\n\n\n\n\n"));
|
||||||
|
JS::console.log(std::string("Processing tick:\t") + std::to_string(Screeps::Game.time()));
|
||||||
|
|
||||||
|
{
|
||||||
|
DouwcoHivemind::Engine engine;
|
||||||
|
engine.loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::console.log("Used CPU:\t" + std::to_string(Screeps::Game.cpuGetUsed()));
|
||||||
|
JS::console.log("Bucket:\t" + std::to_string(static_cast<int>(Screeps::Game.cpu()["bucket"])));
|
||||||
|
}
|
||||||
|
|
||||||
|
EMSCRIPTEN_BINDINGS(loop)
|
||||||
|
{
|
||||||
|
emscripten::function("loop", &loop);
|
||||||
|
}
|
||||||
89
douwco_hivemind/src/Maintainer.cpp
Normal file
89
douwco_hivemind/src/Maintainer.cpp
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#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/Store.hpp>
|
||||||
|
|
||||||
|
#include "Creeps/Maintainer.hpp"
|
||||||
|
|
||||||
|
void DouwcoHivemind::Maintainer::depositEnergy()
|
||||||
|
{
|
||||||
|
auto structure = getDamagedStructureTarget();
|
||||||
|
if (!structure)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isNearTo(structure->pos(), 1))
|
||||||
|
{
|
||||||
|
int resp = creep.repair(*structure);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
moveToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Screeps::Structure> DouwcoHivemind::Maintainer::getDamagedStructureTarget()
|
||||||
|
{
|
||||||
|
auto roomObj = getRoomObjectTarget();
|
||||||
|
if (!roomObj)
|
||||||
|
{
|
||||||
|
searchDamagedStructure();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto structure = std::unique_ptr<Screeps::Structure>(dynamic_cast<Screeps::Structure *>(roomObj.release()));
|
||||||
|
if (!structure)
|
||||||
|
{
|
||||||
|
searchDamagedStructure();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the structure is still broken
|
||||||
|
int damage = structure->hitsMax() - structure->hits();
|
||||||
|
if (damage == 0)
|
||||||
|
{
|
||||||
|
searchDamagedStructure();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(structure);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouwcoHivemind::Maintainer::searchDamagedStructure()
|
||||||
|
{
|
||||||
|
int lowestMaintaince = INT16_MAX;
|
||||||
|
Screeps::Structure *selectedStructure;
|
||||||
|
auto structures = creep.room().find(Screeps::FIND_STRUCTURES);
|
||||||
|
for (auto &structureObject : structures)
|
||||||
|
{
|
||||||
|
auto structure = dynamic_cast<Screeps::Structure *>(structureObject.get());
|
||||||
|
if (!structure)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int maintance = structure->hits();
|
||||||
|
auto structureType = structure->structureType();
|
||||||
|
if (structureType == Screeps::STRUCTURE_CONTROLLER)
|
||||||
|
continue;
|
||||||
|
if (maintance < lowestMaintaince)
|
||||||
|
{
|
||||||
|
lowestMaintaince = maintance;
|
||||||
|
selectedStructure = structure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedStructure)
|
||||||
|
target_id = selectedStructure->id();
|
||||||
|
else
|
||||||
|
target_id.clear();
|
||||||
|
}
|
||||||
67
douwco_hivemind/src/Miner.cpp
Normal file
67
douwco_hivemind/src/Miner.cpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include <emscripten.h>
|
||||||
|
#include <Screeps/Constants.hpp>
|
||||||
|
#include <Screeps/Source.hpp>
|
||||||
|
#include <Screeps/Room.hpp>
|
||||||
|
#include <Screeps/RoomPosition.hpp>
|
||||||
|
|
||||||
|
#include "Creeps/Miner.hpp"
|
||||||
|
|
||||||
|
DouwcoHivemind::Miner::Miner(Screeps::Creep crp) : CreepBase(crp)
|
||||||
|
{
|
||||||
|
requestedContainer = memory.contains("requestedContainer") ? static_cast<bool>(memory["requestedContainer"]) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DouwcoHivemind::Miner::~Miner()
|
||||||
|
{
|
||||||
|
memory["requestedContainer"] = requestedContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouwcoHivemind::Miner::loop()
|
||||||
|
{
|
||||||
|
if (mineSource() && !requestedContainer)
|
||||||
|
{
|
||||||
|
creep.room().createConstructionSite(creep.pos(), Screeps::STRUCTURE_CONTAINER);
|
||||||
|
requestedContainer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DouwcoHivemind::Miner::mineSource()
|
||||||
|
{
|
||||||
|
auto source = getSourceTarget();
|
||||||
|
if (!source){
|
||||||
|
EM_ASM({console.log($0 + ': Miner doesn\'t have valid source target')}, creep.name().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNearTo(source->pos(), 1))
|
||||||
|
{
|
||||||
|
int resp = creep.harvest(*source);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
moveToTarget();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Screeps::Source> DouwcoHivemind::Miner::getSourceTarget()
|
||||||
|
{
|
||||||
|
auto roomObj = getRoomObjectTarget();
|
||||||
|
if (!roomObj)
|
||||||
|
{
|
||||||
|
// todo: request source from room
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if found roomobject is an actual source
|
||||||
|
auto source = std::unique_ptr<Screeps::Source>(dynamic_cast<Screeps::Source *>(roomObj.release()));
|
||||||
|
if (!source)
|
||||||
|
{
|
||||||
|
// EM_ASM({console.log($0 + ': Can\'t cast target to Source')}, creep.name().c_str());
|
||||||
|
// todo: request source from room
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(source);
|
||||||
|
}
|
||||||
91
douwco_hivemind/src/Spawn.cpp
Normal file
91
douwco_hivemind/src/Spawn.cpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <Screeps/Game.hpp>
|
||||||
|
#include <Screeps/Room.hpp>
|
||||||
|
#include <Screeps/RoomObject.hpp>
|
||||||
|
#include <Screeps/Constants.hpp>
|
||||||
|
#include <Screeps/Structure.hpp>
|
||||||
|
|
||||||
|
#include "Creeps/CreepBase.hpp"
|
||||||
|
#include "Structures/Spawn.hpp"
|
||||||
|
|
||||||
|
void DouwcoHivemind::Spawn::loop()
|
||||||
|
{
|
||||||
|
// Only run every 50 ticks
|
||||||
|
if (Screeps::Game.time() % 50 != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto room = spawn.room();
|
||||||
|
int energyAvailable = room.energyAvailable();
|
||||||
|
int energyCapacityAvailable = room.energyCapacityAvailable();
|
||||||
|
int constructionSiteCount = room.find(Screeps::FIND_MY_CONSTRUCTION_SITES).size();
|
||||||
|
auto structures = room.find(Screeps::FIND_STRUCTURES);
|
||||||
|
int repairableStructureCount, extensionCount;
|
||||||
|
for (auto& roomObj : structures)
|
||||||
|
{
|
||||||
|
auto structure = dynamic_cast<Screeps::Structure*>(roomObj.get());
|
||||||
|
std::string type = structure->structureType();
|
||||||
|
if (type == Screeps::STRUCTURE_CONTROLLER || type == Screeps::STRUCTURE_SPAWN) continue;
|
||||||
|
repairableStructureCount++;
|
||||||
|
if (type == Screeps::STRUCTURE_EXTENSION) extensionCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int required_suppliers = std::clamp(extensionCount/5, 1, 2);
|
||||||
|
int required_maintainers = std::clamp(repairableStructureCount, 0, 1);
|
||||||
|
int required_builders = std::clamp(constructionSiteCount, 0, 5);
|
||||||
|
int required_upgraders = std::clamp(5-required_builders-required_maintainers-required_suppliers, 1, 3);
|
||||||
|
|
||||||
|
for (auto &creep : Screeps::Game.creeps())
|
||||||
|
{
|
||||||
|
CreepRole role = creep.second.memory()["role"];
|
||||||
|
|
||||||
|
if (role == CreepRole::SUPPLIER)
|
||||||
|
required_suppliers--;
|
||||||
|
else if (role == CreepRole::UPGRADER)
|
||||||
|
required_upgraders--;
|
||||||
|
else if (role == CreepRole::MAINTAINER)
|
||||||
|
required_maintainers--;
|
||||||
|
else if (role == CreepRole::BUILDER)
|
||||||
|
required_builders--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (energyAvailable < energyCapacityAvailable && required_suppliers == 0)
|
||||||
|
return;
|
||||||
|
std::string name;
|
||||||
|
JSON opts;
|
||||||
|
if (required_suppliers > 0)
|
||||||
|
{
|
||||||
|
opts["memory"]["role"] = CreepRole::SUPPLIER;
|
||||||
|
name = "Supplier: ";
|
||||||
|
}
|
||||||
|
else if (required_upgraders > 0)
|
||||||
|
{
|
||||||
|
opts["memory"]["role"] = CreepRole::UPGRADER;
|
||||||
|
name = "Upgrader: ";
|
||||||
|
}
|
||||||
|
else if (required_builders > 0)
|
||||||
|
{
|
||||||
|
opts["memory"]["role"] = CreepRole::BUILDER;
|
||||||
|
name = "Builder: ";
|
||||||
|
}
|
||||||
|
else if (required_maintainers > 0)
|
||||||
|
{
|
||||||
|
opts["memory"]["role"] = CreepRole::MAINTAINER;
|
||||||
|
name = "Maintainer: ";
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
121
douwco_hivemind/src/Supplier.cpp
Normal file
121
douwco_hivemind/src/Supplier.cpp
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
#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/Store.hpp>
|
||||||
|
|
||||||
|
#include "Creeps/Supplier.hpp"
|
||||||
|
|
||||||
|
void DouwcoHivemind::Supplier::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::Supplier::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();
|
||||||
|
}
|
||||||
|
else if (structureType == Screeps::STRUCTURE_TOWER)
|
||||||
|
{
|
||||||
|
auto extension = dynamic_cast<Screeps::StructureTower *>(structure.get());
|
||||||
|
energyCapacity = extension->store().getFreeCapacity(Screeps::RESOURCE_ENERGY).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (energyCapacity == 0)
|
||||||
|
{
|
||||||
|
searchEnergyStructure();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(structure);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouwcoHivemind::Supplier::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();
|
||||||
|
}
|
||||||
|
else if (structureType == Screeps::STRUCTURE_TOWER)
|
||||||
|
{
|
||||||
|
auto extension = dynamic_cast<Screeps::StructureTower *>(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();
|
||||||
|
}
|
||||||
33
douwco_hivemind/src/Upgrader.cpp
Normal file
33
douwco_hivemind/src/Upgrader.cpp
Normal 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/Upgrader.hpp"
|
||||||
|
|
||||||
|
void DouwcoHivemind::Upgrader::depositEnergy()
|
||||||
|
{
|
||||||
|
auto controller = creep.room().controller().value();
|
||||||
|
target_id = controller.id();
|
||||||
|
if (isNearTo(controller.pos(), 3))
|
||||||
|
{
|
||||||
|
int resp = creep.upgradeController(controller);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
moveToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
123
douwco_hivemind/src/Worker.cpp
Normal file
123
douwco_hivemind/src/Worker.cpp
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
#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/Worker.hpp"
|
||||||
|
|
||||||
|
DouwcoHivemind::Worker::Worker(Screeps::Creep crp) : CreepBase(crp)
|
||||||
|
{
|
||||||
|
harvesting = memory.contains("harvesting") ? static_cast<bool>(memory["harvesting"]) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DouwcoHivemind::Worker::~Worker()
|
||||||
|
{
|
||||||
|
memory["harvesting"] = harvesting;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouwcoHivemind::Worker::loop()
|
||||||
|
{
|
||||||
|
if (harvesting)
|
||||||
|
{
|
||||||
|
if (creep.store().getFreeCapacity(Screeps::RESOURCE_ENERGY) == 0)
|
||||||
|
{
|
||||||
|
harvesting = false;
|
||||||
|
target_id.clear();
|
||||||
|
}
|
||||||
|
harvestSource();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (creep.store().getUsedCapacity(Screeps::RESOURCE_ENERGY) == 0)
|
||||||
|
{
|
||||||
|
harvesting = true;
|
||||||
|
target_id.clear();
|
||||||
|
}
|
||||||
|
depositEnergy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouwcoHivemind::Worker::harvestSource()
|
||||||
|
{
|
||||||
|
auto source = getSourceTarget();
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isNearTo(source->pos(), 1))
|
||||||
|
{
|
||||||
|
int resp = creep.harvest(*source);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
moveToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Screeps::Source> DouwcoHivemind::Worker::getSourceTarget()
|
||||||
|
{
|
||||||
|
auto roomObj = getRoomObjectTarget();
|
||||||
|
if (!roomObj)
|
||||||
|
{
|
||||||
|
searchSource();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if found roomobject is an actual source
|
||||||
|
auto source = std::unique_ptr<Screeps::Source>(dynamic_cast<Screeps::Source *>(roomObj.release()));
|
||||||
|
if (!source)
|
||||||
|
{
|
||||||
|
// EM_ASM({console.log($0 + ': Can\'t cast target to Source')}, creep.name().c_str());
|
||||||
|
searchSource();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the source still has energy to harvest
|
||||||
|
if (source->energy() == 0)
|
||||||
|
{
|
||||||
|
searchSource();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouwcoHivemind::Worker::searchSource()
|
||||||
|
{
|
||||||
|
target_id.clear();
|
||||||
|
|
||||||
|
auto sources = creep.room().find(Screeps::FIND_SOURCES_ACTIVE);
|
||||||
|
if (sources.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int x = creep.pos().x();
|
||||||
|
int y = creep.pos().y();
|
||||||
|
|
||||||
|
int closestDistance = INT16_MAX;
|
||||||
|
Screeps::Source *selectedSource;
|
||||||
|
for(auto &sourceObject : sources){
|
||||||
|
auto source =dynamic_cast<Screeps::Source *>(sourceObject.get());
|
||||||
|
if(source->energy()==0) continue;
|
||||||
|
int dx = source->pos().x() - x;
|
||||||
|
int dy = source->pos().y() - y;
|
||||||
|
int distance = dx*dx + dy*dy;
|
||||||
|
if(distance < closestDistance){
|
||||||
|
closestDistance = distance;
|
||||||
|
selectedSource = source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!selectedSource) return;
|
||||||
|
target_id = selectedSource->id();
|
||||||
|
}
|
||||||
1
emsdk
Submodule
1
emsdk
Submodule
Submodule emsdk added at f39e849eff
14
js/main.js
Normal file
14
js/main.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const wasm_loader = require('wasm_loader')
|
||||||
|
|
||||||
|
var mod;
|
||||||
|
wasm_loader('douwco_hivemind_loader', 'douwco_hivemind_module').then((instance) => {
|
||||||
|
console.log("WASM module loaded.");
|
||||||
|
mod = instance;
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports.loop = function () {
|
||||||
|
if (mod !== undefined)
|
||||||
|
mod.loop();
|
||||||
|
}
|
||||||
24
js/wasm_loader.js
Normal file
24
js/wasm_loader.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = ((mod_js, mod_wasm, opts) => {
|
||||||
|
|
||||||
|
const mod_file = require(mod_js);
|
||||||
|
const bin_file = require(mod_wasm);
|
||||||
|
|
||||||
|
opts = opts || {};
|
||||||
|
|
||||||
|
opts.wasmBinary = bin_file;
|
||||||
|
opts.print = opts.print || ((text) => console.log(text));
|
||||||
|
opts.printErr = opts.printErr || ((text) => console.log(`error: ${text}`));
|
||||||
|
opts.onAbort = opts.onAbort || (() => console.log('WASM aborted!!!'));
|
||||||
|
|
||||||
|
// == don't call main()
|
||||||
|
if (typeof opts.noInitialRun === "undefined")
|
||||||
|
opts.noInitialRun = true;
|
||||||
|
|
||||||
|
// == don't terminate after returning from main()
|
||||||
|
if (typeof opts.noExitRuntime === "undefined")
|
||||||
|
opts.noExitRuntime = true;
|
||||||
|
|
||||||
|
return mod_file(opts);
|
||||||
|
});
|
||||||
44
main.js
44
main.js
@@ -1,44 +0,0 @@
|
|||||||
const Commands = require("Commands");
|
|
||||||
const CreepClass = require("CreepClass");
|
|
||||||
const RoomClass = require("RoomClass");
|
|
||||||
const Structure = require("Structure");
|
|
||||||
|
|
||||||
module.exports.loop = function () {
|
|
||||||
if(!global.compiled) onRecompile();
|
|
||||||
else if (!global.started) onRestart();
|
|
||||||
else onTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRecompile(){
|
|
||||||
setupClasses();
|
|
||||||
console.log("Script recompiled...");
|
|
||||||
global.compiled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRestart(){
|
|
||||||
Object.values(Game.rooms).forEach(room => room.begin());
|
|
||||||
Object.values(Game.creeps).forEach(creep => creep.begin());
|
|
||||||
Object.values(Game.structures).forEach(structure => Structure.begin(structure));
|
|
||||||
global.started = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onTick(){
|
|
||||||
Object.values(Game.rooms).forEach(room => room.tick());
|
|
||||||
Object.values(Game.creeps).forEach(creep => creep.tick());
|
|
||||||
Object.values(Game.structures).forEach(structure => Structure.tick(structure));
|
|
||||||
if(!(Game.time % 100)) cleanUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function setupClasses(){
|
|
||||||
Commands.setup();
|
|
||||||
CreepClass.setup();
|
|
||||||
RoomClass.setup();
|
|
||||||
Structure.setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
function cleanUp(){
|
|
||||||
Object.keys(Memory.rooms).forEach(roomName => { if(!Game.rooms[roomName]) Memory.rooms[roomName] = undefined; });
|
|
||||||
Object.keys(Memory.creeps).forEach(creepName => { if(!Game.creeps[creepName]) Memory.creeps[creepName] = undefined; });
|
|
||||||
}
|
|
||||||
|
|
||||||
1
screepsxx
Submodule
1
screepsxx
Submodule
Submodule screepsxx added at 3567060bf5
Reference in New Issue
Block a user