Compare commits

38 Commits

Author SHA1 Message Date
douwe
6ee67eac47 Creeps extract memory completly 2025-08-22 03:11:44 +02:00
douwe
cd1464cc94 Added structure handling in engine as well. 2025-08-22 01:13:09 +02:00
douwe
0381ea6873 Fixed some bugs in harvester. 2025-08-22 00:13:32 +02:00
douwe
0c8da1d472 Finished revision harvester behaviour. Added Some metrics for every loop. 2025-08-21 23:35:00 +02:00
douwe
1ede4cce47 Improved harvester source detection. 2025-08-21 21:01:00 +02:00
douwe
1e9e696b1e Created a base engine class and let it handle all creeps. 2025-08-21 14:13:32 +02:00
douwe
c9ce09ba1a Updated screepsxx module to original url 2025-08-20 17:42:37 +02:00
Douwe Ravers
1a74743e4f Merge pull request #9 from DouweRavers/develop
Develop
2025-08-13 21:14:16 +02:00
douwe
fa5d75fca3 Update with gitignore 2025-08-13 21:12:38 +02:00
Douwe Ravers
b61743fa52 Create .gitignore 2025-08-13 21:11:09 +02:00
Douwe Ravers
009853665d Merge pull request #8 from DouweRavers/develop
Develop
2025-08-13 21:09:51 +02:00
douwe
257cf85695 Minor bug fixes 2025-08-13 21:08:26 +02:00
douwe
9a1682a857 First working version of colony.
Harversters and spawn work.
2025-08-13 20:43:26 +02:00
Douwe Ravers
8a39526580 Update README.md 2025-08-13 00:01:45 +02:00
douwe
5ed1329d2e Basic setup for Cpp based screeping. 2025-08-12 23:56:10 +02:00
unknown
7c1a84a5ca Changed miner search functions 2023-08-31 19:19:41 +02:00
unknown
bde8a2309f Changed miner movement; 2023-08-31 19:13:22 +02:00
unknown
8d67dcb8b8 Minor changes 2023-08-31 19:04:10 +02:00
unknown
29aa48dc3b Changed spawn checktime to 100 2023-08-30 23:57:38 +02:00
unknown
5cfea80b19 Changed update function of spawn to only check every 300 ticks. 2023-08-30 23:53:35 +02:00
unknown
eda20c2dce Removed the harvester. Introduced the cleaner (not active yet) spawners use full room capacity now. 2023-08-30 23:37:04 +02:00
unknown
112c3c3a97 Created supplier and builder functions 2023-08-29 20:43:10 +02:00
Douwe Ravers
523a2e0005 Merge pull request #2 from DouweRavers/develop
fixed wrong vacancy generation bug.
2023-08-26 21:32:06 +02:00
Douwe Ravers
91448edc0a fixed wrong vacancy generation bug. 2023-08-26 21:31:29 +02:00
Douwe Ravers
cab2c3fd25 Merge pull request #1 from DouweRavers/develop
Develop
2023-08-26 20:49:17 +02:00
Douwe Ravers
e294ad29fe Created miner, made harvester pick resources and added reset commands. 2023-08-26 16:57:38 +02:00
Douwe Ravers
76650e22ac Improved harvester behaviour, reworked the job register system and added auto roadbuilding. 2023-08-25 17:30:27 +02:00
Douwe Ravers
8c3528419a Implemented upgrader, source refill and builder functions to harvester. 2023-08-25 08:48:57 +02:00
Douwe Ravers
ccd0557339 Basic setup new system. 2023-08-24 01:48:31 +02:00
unknown
ae3812aa83 Simplyfied the code. Ready to rebuild on top of. 2023-08-20 16:31:21 +02:00
Gebruiker
15c86d3c14 reverse previous commit 2022-10-23 01:26:06 +02:00
Gebruiker
90448c79e4 changed git root 2022-10-23 01:23:27 +02:00
Gebruiker
ef9159260b Chanded some filenames
Removed automatic path placement.
Started command section.
2022-10-23 01:19:58 +02:00
DouweRavers
1806935c50 Slight improvements to movement. Started using regions. 2022-05-03 20:28:24 +02:00
DouweRavers
4e3ad07fff Improved performance of walking.
Switches to manual walking when close to target.
2022-05-01 00:52:48 +02:00
DouweRavers
744b4a2478 First working version of new system. 2022-04-30 14:23:44 +02:00
DouweRavers
3e962ed04a Rewriting from scratch. Fixing old code is just less fun. 2022-04-29 01:45:27 +02:00
DouweRavers
5494f6fb17 Reimplemented 5/7 roles. 2022-04-15 23:05:03 +02:00
33 changed files with 792 additions and 875 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
build

6
.gitmodules vendored Normal file
View 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:UltraCoderRU/screepsxx.git

2
.sync
View File

@@ -1,2 +0,0 @@
1650024834746
5ce5d401e947ee7ab16cc8db

114
.vscode/settings.json vendored
View File

@@ -1,7 +1,113 @@
{
"files.exclude": {
".*": true,
"LICENSE": true,
"*.md": true
"files.associations": {
"__hash_table": "cpp",
"__string": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"locale": "cpp",
"utility": "cpp",
"mutex": "cpp",
"shared_mutex": "cpp",
"stop_token": "cpp",
"cassert": "cpp",
"vector": "cpp",
"optional": "cpp",
"*.inc": "cpp",
"thread": "cpp",
"atomic": "cpp",
"__config": "cpp",
"__debug": "cpp",
"__errc": "cpp",
"__functional_03": "cpp",
"__mutex_base": "cpp",
"__nullptr": "cpp",
"__split_buffer": "cpp",
"__tree": "cpp",
"any": "cpp",
"array": "cpp",
"bit": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"complex": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"exception": "cpp",
"filesystem": "cpp",
"forward_list": "cpp",
"iterator": "cpp",
"list": "cpp",
"map": "cpp",
"memory_resource": "cpp",
"regex": "cpp",
"set": "cpp",
"string": "cpp",
"type_traits": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"fstream": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"memory": "cpp",
"new": "cpp",
"numeric": "cpp",
"ostream": "cpp",
"queue": "cpp",
"random": "cpp",
"ratio": "cpp",
"span": "cpp",
"sstream": "cpp",
"stack": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string_view": "cpp",
"strstream": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"cerrno": "cpp",
"cfloat": "cpp",
"climits": "cpp",
"concepts": "cpp",
"format": "cpp",
"numbers": "cpp",
"semaphore": "cpp",
"cfenv": "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",
"csignal": "cpp",
"coroutine": "cpp",
"source_location": "cpp",
"stdfloat": "cpp",
"typeindex": "cpp"
}
}

39
CMakeLists.txt Normal file
View File

@@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.16)
project(example 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}/include)
file(GLOB SRC_FILES ${CMAKE_SOURCE_DIR}/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})

View File

@@ -2,4 +2,4 @@
My source code for the MMO-programming game: Screeps.
# Status
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. :)
As a way to learn c++ programming I used the screepsxx repo for controlling the screeps with c++.

View File

@@ -1,59 +0,0 @@
/* ###########################
# Cross room managment AI #
########################### */
var roles = require("roles");
module.exports = {
run: function () {
if (Memory.AImain == null) Memory.AImain = {};
if (Memory.AImain.MainHub == null) Memory.AImain.MainHub = "insert name"
for (var n_flag in Game.flags) {
var flag = Game.flags[n_flag];
if (flag.color == COLOR_YELLOW) {
if (flag.room != undefined && flag.room.find(FIND_MY_CREEPS).length != flag.room.find(FIND_CREEPS).length) {
Game.spawns[Memory.AImain.MainHub].spawnCreep([TOUGH, TOUGH, TOUGH, TOUGH, TOUGH, TOUGH, TOUGH, ATTACK, ATTACK, ATTACK, MOVE],
"Defender", { memory: { role: roles.ROLE_DEFENDER, flag: flag.name } });
break;
}
if (flag.room == undefined || (flag.room != undefined && (flag.room.controller.reservation == undefined || flag.room.controller.reservation.ticksToEnd < 4500))) {
if (Memory.AImain.MainHub != "insert name") Game.spawns[Memory.AImain.MainHub].spawnCreep([MOVE, CLAIM, CLAIM], "columbus: "+flag.name, { memory: { role: roles.ROLE_RESERVER, target: flag.name, home: Memory.AImain.MainHub } });
}
if (flag.room != undefined && flag.room.controller.reservation != undefined) {
var containers = flag.room.find(FIND_STRUCTURES, { filter: (s) => (s.structureType == STRUCTURE_CONTAINER) });
if (containers.length > 0) {
var has_miner = false;
var creeps = flag.room.find(FIND_CREEPS);
for (var cp in creeps) {
console.log(creeps[cp]);
var creep = creeps[cp];
if (creep.memory.role == roles.ROLE_MINER) {
has_miner = true;
}
}
if (!has_miner) {
Game.spawns[Memory.AImain.MainHub].spawnCreep([WORK, WORK, WORK, WORK, WORK, MOVE], "ForeignMiner", { memory: { role: roles.ROLE_MINER, container_id: containers[0].id } });
}
}
var harvs = flag.room.find(FIND_MY_CREEPS).length;
var source_id = flag.room.find(FIND_SOURCES)[0].id;
if (harvs < 4) {
var spawn = Game.spawns[Memory.AImain.MainHub];
var body = [];
for (let i = 0; i < Math.floor(spawn.room.energyAvailable / 200); i++) {
body.push(WORK);
body.push(CARRY);
body.push(MOVE);
}
var name = "ForeignHarvy" + spawn.memory.creep_iterate;
spawn.spawnCreep(body, name, {
memory:
{ role: roles.ROLE_RESERVED_HARVESTER, source_id: source_id }
});
}
}
}
}
}
};

View File

@@ -1,33 +0,0 @@
module.exports = {
configure: function () {
// Room management
global.RoomInfo = function () { RoomInfo(); };
global.RoomAdd = function (name, colonize) { RoomAdd(name, colonize) };
global.RoomRemove = function (name) { RoomRemove(name) };
}
}
//#region Room management
function RoomInfo() {
var message = "";
Memory.system.rooms.forEach(room => {
message += room.name + ": ";
message += room.colonize ? "colonize: " : "control: ";
var roomObject = Game.rooms[room.name];
if (roomObject.controller != undefined) {
message += roomObject.controller.my ? "done" : "in progress";
}
message += "\n";
});
console.log(message);
}
function RoomAdd(name, colonize) {
Memory.system.rooms.push({ name: name, colonize: colonize });
}
function RoomRemove(name) {
Memory.system.rooms = Memory.system.rooms.filter((x) => { return x.name != name; })
}
//#endregion

View File

@@ -1,92 +0,0 @@
/* ###################################################################
# An inherited creep class and a module to expose it to the loop. #
###################################################################*/
const roles = require("roles");
module.exports = {
configure: function () {
// Replaces the creep class by the MyCreep class which changes the type of all Creep objects as well.
Creep.prototype = MyCreep.prototype;
setConstants();
// configure all creeps (in case new memory requirements).
for (const name in Game.creeps) {
Game.creeps[name].configure();
}
},
// All creeps execute their roles every tick.
execute: function () {
for (const name in Game.creeps) {
Game.creeps[name].execute();
}
}
};
class MyCreep extends Creep {
configure() {
}
execute() {
switch (this.memory.role) {
case roles.ROLE_HARVESTER: roles.harvest(this);
break;
case roles.ROLE_MINER:
if (this.goTo(this.memory.container_id)) {
this.harvestSource();
}
break;
case roles.ROLE_SUPPLIER: roles.supply(this);
break;
case roles.ROLE_BUILDER: roles.build(this);
break;
case roles.ROLE_UPGRADER: roles.upgrade(this);
break;
case roles.ROLE_DEFENDER: roles.defend(this);
break;
case roles.ROLE_RESERVER: roles.reserve(this);
break;
case roles.ROLE_RESERVED_HARVESTER: roles.harvest_reserved(this);
break;
}
}
// Moves to the object with given id. Returns true if arrived.
goTo(id) {
const target = Game.getObjectById(id)
if (target != null) {
if (this.pos.isEqualTo(target.pos)) return true;
this.moveTo(target);
} else {
console.log(this.name + " can't find object with id: " + id);
}
return false;
}
// harvests set or closest source, moves to it if to far and return true if fully loaded.
harvestSource() {
if (this.memory.source_id == undefined) {
this.memory.source_id = this.pos.findClosestByPath(FIND_SOURCES).id;
}
const result = this.harvest(Game.getObjectById(this.memory.source_id));
if (result == ERR_NOT_IN_RANGE) this.goTo(this.memory.source_id);
return this.store.getFreeCapacity(RESOURCE_ENERGY) == 0;
}
}
function setConstants() {
global.HARVESTER = 0;
global.MINER = 1;
global.SUPPLIER = 2;
global.BUILDER = 3;
global.UPGRADER = 4;
global.DEFENDER = 5;
global.RESERVER = 6;
global.RESERVED_HARVESTER = 7;
}

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.

14
dist/main.js vendored Normal file
View 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
dist/wasm_loader.js vendored Normal file
View 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);
});

1
emsdk Submodule

Submodule emsdk added at f39e849eff

10
include/Constants.hpp Normal file
View File

@@ -0,0 +1,10 @@
#ifndef DOUWCO_HIVEMIND_CONSTANTS_HPP
#define DOUWCO_HIVEMIND_CONSTANTS_HPP
namespace DouwcoHivemind{
enum CreepRole{ UNEMPLOYED, HARVESTER };
}
#endif // DOUWCO_HIVEMIND_CONSTANTS_HPP

33
include/Creeps/Creep.hpp Normal file
View File

@@ -0,0 +1,33 @@
#ifndef DOUWCO_HIVEMIND_CREEP_HPP
#define DOUWCO_HIVEMIND_CREEP_HPP
#include <Screeps/Creep.hpp>
#include "Constants.hpp"
namespace DouwcoHivemind
{
class Creep
{
public:
CreepRole role;
protected:
Screeps::Creep creep;
JSON memory;
public:
Creep(Screeps::Creep crp) : creep(crp),
memory(crp.memory())
{
role = memory.contains("role") ? static_cast<CreepRole>(memory["role"]) : CreepRole::UNEMPLOYED;
}
virtual ~Creep() {
creep.setMemory(memory);
}
virtual void loop() {}
};
}
#endif // DOUWCO_HIVEMIND_CREEP_HPP

View File

@@ -0,0 +1,47 @@
#ifndef DOUWCO_HIVEMIND_HARVESTER_HPP
#define DOUWCO_HIVEMIND_HARVESTER_HPP
#include <Screeps/Creep.hpp>
#include "Creeps/Creep.hpp"
namespace DouwcoHivemind
{
class HarvesterRole : public Creep
{
private:
bool harvesting;
std::string target_id;
int taskCounter;
public:
HarvesterRole(Screeps::Creep crp) : Creep(crp)
{
harvesting = memory.contains("harvesting") ? static_cast<bool>(memory["harvesting"]) : false;
target_id = memory.contains("target_id") ? static_cast<std::string>(memory["target_id"]) : std::string();
taskCounter = memory.contains("taskCounter") ? static_cast<int>(memory["taskCounter"]) : 0;
}
~HarvesterRole() override
{
memory["harvesting"] = harvesting;
memory["target_id"] = target_id;
memory["taskCounter"] = taskCounter;
}
void loop() override;
private:
void harvestSource();
std::unique_ptr<Screeps::Source> getSourceTarget();
void searchSource();
void depositEnergy();
std::unique_ptr<Screeps::Structure> getDepositTarget();
void searchDeposit();
std::unique_ptr<Screeps::RoomObject> getRoomObjectTarget();
};
}
#endif // DOUWCO_HIVEMIND_HARVESTER_HPP

74
include/Engine.hpp Normal file
View File

@@ -0,0 +1,74 @@
#ifndef DOUWCO_HIVEMIND_ENGINE_HPP
#define DOUWCO_HIVEMIND_ENGINE_HPP
#include <vector>
#include <Screeps/JS.hpp>
#include <Screeps/Game.hpp>
#include <Screeps/Creep.hpp>
#include "Constants.hpp"
#include "Creeps/Creep.hpp"
#include "Creeps/Harvester.hpp"
#include "Structures/Structure.hpp"
#include "Structures/Spawn.hpp"
namespace DouwcoHivemind
{
class Creep;
class Structure;
class Engine
{
private:
std::vector<std::unique_ptr<Creep>> creeps;
std::vector<std::unique_ptr<Structure>> structures;
public:
Engine()
{
ReadOutCreeps();
ReadOutStructures();
}
~Engine() {}
void loop()
{
for (auto &creep : creeps)
creep->loop();
for (auto &structure : structures)
structure->loop();
}
private:
void ReadOutCreeps()
{
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:
EM_ASM({console.log('Undefined role for creep' + $0)}, creep.first.c_str());
break;
}
}
}
void ReadOutStructures()
{
auto spawns = Screeps::Game.spawns();
for (auto &spawn : spawns)
{
structures.push_back(std::make_unique<Spawn>(spawn.second));
}
}
};
}
#endif // DOUWCO_HIVEMIND_ENGINE_HPP

View File

@@ -0,0 +1,24 @@
#ifndef DOUWCO_HIVEMIND_SPAWN_HPP
#define DOUWCO_HIVEMIND_SPAWN_HPP
#include <Screeps/StructureSpawn.hpp>
#include "Structures/Structure.hpp"
namespace DouwcoHivemind
{
class Spawn : public Structure
{
private:
Screeps::StructureSpawn spawn;
public:
Spawn(Screeps::StructureSpawn spwn) : spawn(spwn),
Structure() {}
~Spawn() {}
void loop() override;
};
}
#endif // DOUWCO_HIVEMIND_SPAWN_HPP

View File

@@ -0,0 +1,15 @@
#ifndef DOUWCO_HIVEMIND_STRUCTURE_HPP
#define DOUWCO_HIVEMIND_STRUCTURE_HPP
#include <Screeps/Structure.hpp>
namespace DouwcoHivemind
{
class Structure
{
public:
virtual void loop(){}
};
}
#endif // DOUWCO_HIVEMIND_STRUCTURE_HPP

14
js/main.js Normal file
View 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
View 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);
});

40
main.js
View File

@@ -1,40 +0,0 @@
/* ######################
# Screeps 2022 #
######################*/
const spawns = require("spawns");
const creeps = require("creeps");
const towers = require("towers");
const ai_main = require("ai_main");
const system = require("system");
module.exports.loop = function () {
// New system
if (global.started == undefined) {
console.log("Recompiled...");
global.started = true;
system.start();
}
system.update();
// Old system
ai_main.run();
towers.run();
spawns.run();
if (Game.time % 60 == 0) {
clear_dead_creeps_from_memory();
}
}
function clear_dead_creeps_from_memory() {
for (var cr in Memory.creeps) {
if (Game.creeps[cr] == null) {
delete (Memory.creeps[cr]);
}
}
}

398
roles.js
View File

@@ -1,398 +0,0 @@
/* ##############################
# Roles: Creep functionality #
############################## */
module.exports = {
ROLE_HARVESTER: 0,
ROLE_MINER: 1,
ROLE_SUPPLIER: 2,
ROLE_BUILDER: 3,
ROLE_UPGRADER: 4,
ROLE_DEFENDER: 5,
ROLE_RESERVER: 6,
ROLE_RESERVED_HARVESTER: 7,
harvest: function (creep) {
setupMemory();
if (creep.memory.harvesting) {
extractEnergySource();
}
else {
searchTarget();
var response = performJob();
handleResponse(response);
}
function setupMemory() {
if (creep.memory.harvesting == undefined) creep.memory.harvesting = true;
if (creep.memory.counter == undefined) creep.memory.counter = 0;
if (creep.memory.target == undefined) creep.memory.target = null;
}
function extractEnergySource() {
var result = OK;
var target = creep.pos.findClosestByPath(FIND_STRUCTURES, { filter: (s) => (s.structureType == STRUCTURE_CONTAINER && s.store.getUsedCapacity(RESOURCE_ENERGY) > creep.store.getFreeCapacity(RESOURCE_ENERGY)) });
if (target == null) {
target = Game.getObjectById(creep.memory.source_id);
result = creep.harvest(target);
} else {
result = creep.withdraw(target, RESOURCE_ENERGY);
}
if (result == ERR_NOT_IN_RANGE) {
creep.moveTo(target);
}
if (result == ERR_NOT_ENOUGH_RESOURCES || creep.store.getFreeCapacity(RESOURCE_ENERGY) == 0) {
creep.memory.harvesting = false;
creep.memory.target = null;
}
}
function searchTarget() {
if (creep.memory.target == null) {
var role_type = creep.memory.counter % 10;
if (role_type == 0) {
creep.memory.target = creep.room.controller.id;
}
else if (role_type < 5) {
var target = creep.pos.findClosestByRange(FIND_MY_STRUCTURES, {
filter: (s) => (s.structureType == STRUCTURE_SPAWN || s.structureType == STRUCTURE_EXTENSION) && s.store.getFreeCapacity(RESOURCE_ENERGY) > 0
});
if (target != null) creep.memory.target = target.id;
else creep.memory.counter += 1;
}
else if (role_type < 9) {
var target = creep.pos.findClosestByRange(FIND_CONSTRUCTION_SITES);
if (target != null) creep.memory.target = target.id;
else creep.memory.counter += 1;
} else {
var target = creep.pos.findClosestByRange(FIND_STRUCTURES, {
filter: (s) => (s.structureType != STRUCTURE_WALL && s.structureType != STRUCTURE_RAMPART) && s.hits < s.hitsMax
});
if (target != null) creep.memory.target = target.id;
else creep.memory.counter += 1;
}
}
}
function performJob() {
var target = Game.getObjectById(creep.memory.target);
var response = OK;
var role_type = creep.memory.counter % 10;
if (role_type == 0) {
response = creep.transfer(target, RESOURCE_ENERGY);
}
else if (role_type < 5) {
response = creep.transfer(target, RESOURCE_ENERGY);
if (target != null && target.store.getFreeCapacity(RESOURCE_ENERGY) == 0) creep.memory.target = null;
}
else if (role_type < 9) {
response = creep.build(target);
if (target != null && target.progress == target.progressTotal) creep.memory.target = null;
} else {
response = creep.repair(target);
if (target != null && target.hits == target.hitsMax) creep.memory.target = null;
}
return response;
}
function handleResponse(response) {
if (response == ERR_NOT_IN_RANGE) {
var target = Game.getObjectById(creep.memory.target);
creep.moveTo(target);
} else if (response == ERR_FULL || response == ERR_INVALID_TARGET) {
creep.memory.target = null;
}
if (creep.store.getUsedCapacity(RESOURCE_ENERGY) == 0) {
creep.memory.harvesting = true;
creep.memory.target = null;
creep.memory.counter += 1;
}
}
},
mine: function (creep) {
var container = Game.getObjectById(creep.memory.container_id);
if (container != null && creep.pos.isEqualTo(container.pos)) {
if (creep.memory.source_id == undefined) creep.memory.source_id = creep.pos.findClosestByPath(FIND_SOURCES).id;
creep.harvest(Game.getObjectById(creep.memory.source_id));
} else {
creep.moveTo(Game.getObjectById(creep.memory.container_id));
}
},
supply: function (creep) {
// Memory creation
if (creep.memory.restock == undefined) creep.memory.restock = true;
if (creep.memory.target == undefined) creep.memory.target = null;
// Job implementation
if (creep.memory.restock) {
if (creep.memory.target == null) { // aquire target
var target = creep.pos.findClosestByPath(FIND_DROPPED_RESOURCES);
if (target == null) target = creep.pos.findClosestByPath(FIND_TOMBSTONES);
if (target == null) target = creep.pos.findClosestByPath(FIND_STRUCTURES,
{
filter: (s) => (s.structureType == STRUCTURE_CONTAINER
&& 0 < s.store.getUsedCapacity(RESOURCE_ENERGY))
});
if (target == null) target = creep.room.storage;
if (target != null) creep.memory.target = target.id;
}
var target = Game.getObjectById(creep.memory.target);
if (creep.withdraw(target, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE || creep.pickup(target) == ERR_NOT_IN_RANGE) creep.moveTo(target);
if (target != null && target.store != null && target.store.getUsedCapacity(RESOURCE_ENERGY) == 0) creep.memory.target = null;
if (creep.store.getFreeCapacity(RESOURCE_ENERGY) == 0) {
creep.memory.restock = false;
creep.memory.target = null;
}
} else {
if (creep.memory.target == null) { // aquire target
var structure = creep.pos.findClosestByPath(FIND_MY_STRUCTURES,
{ filter: (s) => (s.structureType == STRUCTURE_TOWER && s.store.getUsedCapacity(RESOURCE_ENERGY) < 900) });
if (structure == null) structure = creep.pos.findClosestByPath(FIND_MY_STRUCTURES,
{
filter: (s) => ((s.structureType == STRUCTURE_SPAWN || s.structureType == STRUCTURE_EXTENSION)
&& s.store.getFreeCapacity(RESOURCE_ENERGY) > s.store.getCapacity(RESOURCE_ENERGY) * 0.1)
});
if (structure == null) structure = creep.pos.findClosestByPath(FIND_MY_STRUCTURES,
{ filter: (s) => ((s.id == "5f3e44e1014017c66fc5df10") && s.store.getFreeCapacity() > 100) });
if (structure == null) structure = creep.room.storage;
if (structure == null) return;
creep.memory.target = structure.id;
}
var target = Game.getObjectById(creep.memory.target);
if (creep.transfer(target, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) creep.moveTo(target);
if (target != null && target.store.getFreeCapacity(RESOURCE_ENERGY) == 0) creep.memory.target = null;
if (creep.store.getUsedCapacity(RESOURCE_ENERGY) == 0) {
creep.memory.restock = true;
creep.memory.target = null;
}
}
},
build: function (creep) {
//creep.memory.target = null;
// Memory creation
if (creep.memory.restock == undefined) creep.memory.restock = true;
if (creep.memory.target == undefined) creep.memory.target = null;
// Job implementation
if (creep.memory.restock) {
if (creep.memory.target == null) {
if (creep.room.storage != null && 1000 < creep.room.storage.store.getUsedCapacity(RESOURCE_ENERGY)) creep.memory.target = creep.room.storage.id;
else {
var container = creep.pos.findClosestByPath(FIND_STRUCTURES,
{
filter: (s) => (s.structureType == STRUCTURE_CONTAINER
&& 0 < s.store.getUsedCapacity(RESOURCE_ENERGY))
});
if (container != null) creep.memory.target = container.id;
}
}
var target = Game.getObjectById(creep.memory.target);
if (creep.withdraw(target, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) creep.moveTo(target);
if (target != null && target.store.getUsedCapacity(RESOURCE_ENERGY) < creep.store.getFreeCapacity(RESOURCE_ENERGY) * 0.4) creep.memory.target = null;
if (creep.store.getFreeCapacity(RESOURCE_ENERGY) == 0) {
creep.memory.restock = false;
creep.memory.target = null;
}
} else {
if (creep.memory.target == null) { // aquire target
// constuction
var structure = creep.pos.findClosestByRange(FIND_MY_CONSTRUCTION_SITES);
// buildings
if (structure == null) {
var buildings = creep.room.find(FIND_STRUCTURES,
{ filter: (s) => ((s.structureType != STRUCTURE_RAMPART || s.structureType != STRUCTURE_WALL) && s.hits < s.hitsMax) });
for (var building in buildings) {
building = buildings[building];
if (structure == null || structure.hits > building.hits) structure = building;
}
}
// ramparts and walls
if (structure == null) {
var ramparts = creep.room.find(FIND_STRUCTURES,
{ filter: (s) => ((s.structureType == STRUCTURE_RAMPART || s.structureType == STRUCTURE_WALL) && s.hits < s.hitsMax) });
for (var ramp in ramparts) {
ramp = ramparts[ramp];
if (structure == null || structure.hits > ramp.hits) structure = ramp;
}
}
creep.memory.target = structure.id;
}
var target = Game.getObjectById(creep.memory.target);
if (target == null || target.hits == target.hitsMax) creep.memory.target = null;
if (creep.build(target) == ERR_NOT_IN_RANGE || creep.repair(target) == ERR_NOT_IN_RANGE) creep.moveTo(target);
if (creep.store.getUsedCapacity(RESOURCE_ENERGY) == 0) {
creep.memory.restock = true;
creep.memory.target = null;
}
}
},
upgrade: function (creep) {
// Memory creation
if (creep.memory.restock == undefined) creep.memory.restock = true;
if (creep.memory.target == undefined) creep.memory.target = null;
// Job implementation
if (creep.memory.restock) {
if (creep.memory.target == null) {
if (creep.room.storage != null && 1000 < creep.room.storage.store.getUsedCapacity(RESOURCE_ENERGY)) creep.memory.target = creep.room.storage.id;
else {
var container = creep.pos.findClosestByPath(FIND_STRUCTURES,
{
filter: (s) => (s.structureType == STRUCTURE_CONTAINER
&& 0 < s.store.getUsedCapacity(RESOURCE_ENERGY))
});
if (container != null) creep.memory.target = container.id;
}
}
var target = Game.getObjectById(creep.memory.target);
if (creep.withdraw(target, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) creep.moveTo(target);
if (target != null && target.store.getUsedCapacity(RESOURCE_ENERGY) < creep.store.getFreeCapacity(RESOURCE_ENERGY) * 0.4) creep.memory.target = null;
if (creep.store.getFreeCapacity(RESOURCE_ENERGY) == 0) {
creep.memory.restock = false;
creep.memory.target = null;
}
} else {
if (creep.memory.target == null) { // aquire target
var structure = structure = creep.room.controller;
creep.memory.target = structure.id;
}
var target = Game.getObjectById(creep.memory.target);
if (creep.transfer(target, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) creep.moveTo(target);
if (creep.store.getUsedCapacity(RESOURCE_ENERGY) == 0) {
creep.memory.restock = true;
creep.memory.target = null;
}
}
},
defend: function (creep) {
if (creep.memory.flag != undefined && Game.flags[creep.memory.flag].room.name != creep.room.name) creep.moveTo(Game.flags[creep.memory.flag]);
if (creep.memory.target == undefined) creep.memory.target = null;
if (creep.memory.target == null) {
var enemy = creep.pos.findClosestByPath(FIND_HOSTILE_CREEPS);
if (enemy != null) creep.memory.target = enemy.id;
}
var enemy = Game.getObjectById(creep.memory.target);
if (enemy != null) {
creep.say("ATTACK");
if (creep.attack(enemy) == ERR_NOT_IN_RANGE) creep.moveTo(enemy);
} else {
creep.memory.target = null;
}
},
reserve: function (creep) {
if (Game.flags[creep.memory.target].room != undefined && Game.flags[creep.memory.target].room == creep.room) {
if (creep.memory.target == "xxx") {
if (creep.claimController(creep.room.controller) == ERR_NOT_IN_RANGE) {
creep.moveTo(creep.room.controller);
}
} else {
if (creep.reserveController(creep.room.controller) == ERR_NOT_IN_RANGE) {
creep.moveTo(creep.room.controller);
}
}
} else {
creep.moveTo(Game.flags[creep.memory.target]);
}
},
harvest_reserved: function (creep) {
creep.memory.home = "SpawnAlpha"
//memory setup
if (creep.memory.harvesting == undefined) creep.memory.harvesting = true;
if (creep.memory.counter == undefined) creep.memory.counter = 0;
if (creep.memory.target == undefined) creep.memory.target = null;
if (creep.memory.harvesting) {
var source = Game.getObjectById(creep.memory.source_id);
if (source != undefined && creep.room.name == source.room.name) {
var container = creep.pos.findClosestByPath(FIND_STRUCTURES, { filter: (s) => (s.structureType == STRUCTURE_CONTAINER && s.store.getUsedCapacity(RESOURCE_ENERGY) > creep.store.getFreeCapacity(RESOURCE_ENERGY)) });
if (container == null) {
result = creep.harvest(source);
if (result == ERR_NOT_IN_RANGE) {
creep.moveTo(source);
}
} else {
var result = creep.withdraw(container, RESOURCE_ENERGY);
if (result == ERR_NOT_IN_RANGE) {
creep.moveTo(container);
}
}
if (creep.store.getFreeCapacity(RESOURCE_ENERGY) == 0) {
creep.memory.harvesting = false;
creep.memory.target = null;
}
} else {
creep.moveTo(source);
}
} else {
if (creep.memory.target == null) {
switch (creep.memory.counter % 3) {
case 0: // building
creep.memory.target = creep.pos.findClosestByRange(FIND_CONSTRUCTION_SITES);
if (creep.memory.target != null) creep.memory.target = creep.memory.target.id;
else creep.memory.counter += 1;
break;
case 1: // repairing (no walls or ramparts)
creep.memory.target = creep.pos.findClosestByRange(FIND_STRUCTURES, {
filter: (s) => (s.structureType != STRUCTURE_WALL && s.structureType != STRUCTURE_RAMPART) && s.hits < s.hitsMax - creep.store.getUsedCapacity(RESOURCE_ENERGY) * 3 / 4
});
if (creep.memory.target != null) creep.memory.target = creep.memory.target.id;
else creep.memory.counter += 1;
break;
case 2: // suppling
var home = Game.spawns[creep.memory.home];
if (creep.room.name == home.room.name) {
creep.memory.target = creep.pos.findClosestByRange(FIND_MY_STRUCTURES, {
filter: (s) => (s.structureType == STRUCTURE_SPAWN || s.structureType == STRUCTURE_EXTENSION || s.structureType == STRUCTURE_STORAGE) && s.store.getFreeCapacity(RESOURCE_ENERGY) > 0
});
if (creep.memory.target != null) creep.memory.target = creep.memory.target.id;
else creep.memory.counter += 1;
} else {
creep.moveTo(home);
}
break;
}
}
var target = Game.getObjectById(creep.memory.target);
var response = OK;
switch (creep.memory.counter % 3) {
case 0: // building
response = creep.build(target);
if (target != null && target.progress == target.progressTotal) creep.memory.target = null;
break;
case 1: // repairing
response = creep.repair(target);
if (target != null && target.hits == target.hitsMax) creep.memory.target = null;
break;
case 2: // suppling
response = creep.transfer(target, RESOURCE_ENERGY);
if (target != null && target.store.getFreeCapacity(RESOURCE_ENERGY) == 0) creep.memory.target = null;
break;
}
if (response == ERR_NOT_IN_RANGE) {
creep.moveTo(target);
} else if (response == ERR_FULL || response == ERR_INVALID_TARGET) {
creep.memory.target = null;
}
if (creep.store.getUsedCapacity(RESOURCE_ENERGY) == 0) {
creep.memory.harvesting = true;
creep.memory.target = null;
creep.memory.counter += 1;
}
}
}
};

View File

@@ -1,7 +0,0 @@
/**
* Managing the behavior of buildings and creeps is on a per room level.
*/
module.exports = {
}

15
running notes.txt Normal file
View File

@@ -0,0 +1,15 @@
# Emsdk
Use emsdk 2.0.0 to only use ES5 syntax for js.
cd emsdk && \
./emsdk install 2.0.0 && \
./emsdk activate 2.0.0 && \
source ./emsdk_env.sh && \
cd ..
# Cmake
In screeps project run dit om cmake setup in te stellen:
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake ..
Run dit om de code te compilen:
cmake --build .

1
screepsxx Submodule

Submodule screepsxx added at 8500506e1c

183
spawns.js
View File

@@ -1,183 +0,0 @@
/* #####################################
# Controls the way creeps are spawn #
#####################################*/
var roles = require("roles");
module.exports = {
run: function () {
for (var sp in Game.spawns) {
sp = Game.spawns[sp]
// values
var creep_count = 0
for (var cr in Game.creeps) {
if (Game.creeps[cr].room.name == sp.room.name) creep_count += 1;
}
var source_count = 0;
if (sp.memory.sources_ids != undefined) source_count = sp.memory.sources_ids.length;
// Memory setup
if (sp.memory.creep_iterate == undefined) sp.memory.creep_iterate = 0;
if (sp.memory.sources_ids == undefined) {
sp.memory.sources_ids = [];
var sources = sp.room.find(FIND_SOURCES);
for (var source in sources) {
source = sources[source];
sp.memory.sources_ids.push(source.id);
}
source_count = sp.memory.sources_ids.length;
}
if (sp.memory.containers_ids == undefined || sp.memory.containers_ids.length != source_count) {
sp.memory.containers_ids = [];
var containers = sp.room.find(FIND_STRUCTURES, { filter: { structureType: STRUCTURE_CONTAINER } });
if (containers.length > 0) {
for (let i = 0; i < containers.length; i += 1) {
sp.memory.containers_ids.push(containers[i].id);
}
}
}
// Different spawning configurations
// Add improved versions at top of if-else statement
if (sp.memory.containers_ids.length >= source_count && sp.room.energyCapacityAvailable >= 550 && creep_count > source_count) { // Miner method: Miners fille containers rest picks up from them
// Check current creep_jobs
var jobs = { miner: 0, supplier: 0, builder: 0, upgrader: 0, defender: 0 };
var container_id = sp.memory.containers_ids[0];
for (var creep in Game.creeps) {
var creep = Game.creeps[creep];
if (creep.room.name != sp.room.name) continue;
switch (creep.memory.role) {
case roles.ROLE_MINER:
jobs.miner += 1;
for (let i = 0; i < sp.memory.containers_ids.length; i++) {
if (creep.memory.container_id != sp.memory.containers_ids[i]) container_id = sp.memory.containers_ids[i];
}
break;
case roles.ROLE_SUPPLIER:
jobs.supplier += creep.body.length;
break;
case roles.ROLE_BUILDER:
jobs.builder += creep.body.length;
break;
case roles.ROLE_UPGRADER:
jobs.upgrader += creep.body.length;
break;
case roles.ROLE_DEFENDER:
jobs.defender += 1;
break;
default:
break;
}
}
if (jobs.miner < source_count) {
if (sp.room.energyAvailable >= 550) create_miner(sp, container_id);
}
else if (jobs.supplier < source_count * 15 && sp.room.energyAvailable >= 300 && jobs.miner > 0) create_supplier(sp);
else if (jobs.builder < source_count * 5 && sp.room.energyAvailable >= 300 && jobs.miner > 0) create_builder(sp);
else if (jobs.upgrader < source_count * 5 && sp.room.energyAvailable >= 300 && jobs.miner > 0) create_upgrader(sp);
else if (jobs.defender < 0 && sp.room.energyAvailable >= sp.room.energyCapacityAvailable * 0.8 && jobs.miner > 0) create_defender(sp);
} else { // Harvesting method: everybody mines own sources
if (sp.room.find(FIND_MY_CREEPS).length < source_count * 5 && sp.room.energyAvailable >= 300) {
var source_id = sp.memory.sources_ids[sp.memory.creep_iterate % source_count];
create_harvester(sp, source_id);
}
}
}
}
};
function create_harvester(sp, source_id) {
var body = [];
for (let i = 0; i < Math.floor(sp.room.energyAvailable / 200); i++) {
body.push(WORK);
body.push(CARRY);
body.push(MOVE);
}
var name = "Harvy" + sp.memory.creep_iterate;
sp.spawnCreep(body, name, {
memory:
{ role: roles.ROLE_HARVESTER, source_id: source_id }
});
sp.memory.creep_iterate += 1;
}
function create_miner(sp, container_id) {
var body = [WORK, WORK, WORK, WORK, WORK, MOVE]; // (creep)5*work(2energy/tick)=10energy/tick -> (source)3000energy/300tick=10energy/tick
var name = "Mindy" + sp.memory.creep_iterate;
sp.spawnCreep(body, name, {
memory:
{ role: roles.ROLE_MINER, container_id: container_id }
});
sp.memory.creep_iterate += 1;
}
function create_supplier(sp) {
var body = [WORK];
for (let i = 0; i < Math.floor(sp.room.energyAvailable / 100) - 1 && i < 8; i++) { // as big as possible
body.push(CARRY);
body.push(MOVE);
}
var name = "Suppry" + sp.memory.creep_iterate;
sp.spawnCreep(body, name, {
memory:
{ role: roles.ROLE_SUPPLIER }
});
sp.memory.creep_iterate += 1;
}
function create_builder(sp) {
var body = [];
for (let i = 0; i < Math.floor(sp.room.energyAvailable / 200); i++) { // as big as possible
body.push(CARRY);
body.push(MOVE);
body.push(WORK);
}
var name = "Bobby" + sp.memory.creep_iterate;
sp.spawnCreep(body, name, {
memory:
{ role: roles.ROLE_BUILDER }
});
sp.memory.creep_iterate += 1;
}
function create_upgrader(sp) {
var body = [];
for (let i = 0; i < Math.floor(sp.room.energyAvailable / 300); i++) { // as big as possible
body.push(CARRY);
body.push(MOVE);
body.push(WORK);
body.push(WORK);
}
var name = "Undy" + sp.memory.creep_iterate;
sp.spawnCreep(body, name, {
memory:
{ role: roles.ROLE_UPGRADER }
});
sp.memory.creep_iterate += 1;
}
function create_defender(sp) {
var body = [];
for (let i = 0; i < Math.floor(sp.room.energyAvailable / 150); i++) { // as big as possible
body.push(TOUGH);
body.push(TOUGH);
body.push(ATTACK);
body.push(MOVE);
}
var name = "Destroyer CODE" + sp.memory.creep_iterate;
sp.spawnCreep(body, name, {
memory:
{ role: roles.ROLE_DEFENDER }
});
sp.memory.creep_iterate += 1;
}

255
src/harvester.cpp Normal file
View File

@@ -0,0 +1,255 @@
#include <vector>
#include <optional>
#include <emscripten.h>
#include <Screeps/Game.hpp>
#include <Screeps/Creep.hpp>
#include <Screeps/Source.hpp>
#include <Screeps/Room.hpp>
#include <Screeps/RoomPosition.hpp>
#include <Screeps/RoomObject.hpp>
#include <Screeps/Structure.hpp>
#include <Screeps/StructureController.hpp>
#include <Screeps/StructureSpawn.hpp>
#include <Screeps/StructureExtension.hpp>
#include <Screeps/StructureTower.hpp>
#include <Screeps/Constants.hpp>
#include <Screeps/Store.hpp>
#include "Creeps/Harvester.hpp"
bool isNearTo(const Screeps::RoomPosition &pos1, const Screeps::RoomPosition &pos2, int dist);
void DouwcoHivemind::HarvesterRole::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::HarvesterRole::harvestSource()
{
auto source = getSourceTarget();
if (!source)
return;
if (isNearTo(creep.pos(), source->pos(), 1))
{
int resp = creep.harvest(*source);
}
else
creep.moveTo(*source);
}
std::unique_ptr<Screeps::Source> DouwcoHivemind::HarvesterRole::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::HarvesterRole::searchSource()
{
target_id.clear();
auto sources = creep.room().find(Screeps::FIND_SOURCES_ACTIVE);
if (sources.size() == 0)
return;
Screeps::Source *selectedSource;
int maxEnergy = 0;
for (auto &sourceObj : sources)
{
auto source = dynamic_cast<Screeps::Source *>(sourceObj.get());
if (!source)
continue;
auto sourceEnergy = source->energy();
if (sourceEnergy > maxEnergy)
{
maxEnergy = sourceEnergy;
selectedSource = source;
}
}
if (!selectedSource)
{
// EM_ASM({console.log($0 + ': No sources with energy found!')}, creep.name().c_str());
return;
}
target_id = selectedSource->id();
}
void DouwcoHivemind::HarvesterRole::depositEnergy()
{
auto structure = getDepositTarget();
if (!structure)
return;
if (structure->structureType() == Screeps::STRUCTURE_CONTROLLER)
{
if (isNearTo(creep.pos(), structure->pos(), 3))
{
auto controller = dynamic_cast<Screeps::StructureController *>(structure.get());
if (!controller)
return;
int resp = creep.upgradeController(*controller);
}
else
creep.moveTo(*structure);
}
else
{
if (isNearTo(creep.pos(), structure->pos(), 1))
{
int resp = creep.transfer(*structure, Screeps::RESOURCE_ENERGY);
}
else
creep.moveTo(*structure);
}
}
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();
}
std::unique_ptr<Screeps::RoomObject> DouwcoHivemind::HarvesterRole::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 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();
}

33
src/loop.cpp Normal file
View File

@@ -0,0 +1,33 @@
#include <Screeps/Context.hpp>
#include <Screeps/Creep.hpp>
#include <Screeps/StructureSpawn.hpp>
#include <emscripten.h>
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include "Constants.hpp"
#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);
}

28
src/spawn.cpp Normal file
View File

@@ -0,0 +1,28 @@
#include <nlohmann/json.hpp>
#include <Screeps/JS.hpp>
#include <Screeps/Game.hpp>
#include <Screeps/Room.hpp>
#include <Screeps/StructureSpawn.hpp>
#include <emscripten.h>
#include "Constants.hpp"
#include "Structures/Spawn.hpp"
void DouwcoHivemind::Spawn::loop()
{
int creepcount = spawn.room().find(Screeps::FIND_MY_CREEPS).size();
if (creepcount > 10)
{
EM_ASM({ console.log('To much creeps in this room'); });
return;
}
EM_ASM({ console.log('Creating a harvester'); });
JSON opts;
opts["memory"]["role"] = CreepRole::HARVESTER;
int resp = spawn.spawnCreep(
{"work", "carry", "move"},
"harvester" + std::to_string(Screeps::Game.time()),
opts);
}

View File

@@ -1,19 +0,0 @@
/**
* Basis of the entire system. Everything will be managed from here on out.
*/
const commands = require("commands");
const creeps = require("creeps")
module.exports = {
// Gets called when recompiling and when Restart command is called.
start: function () {
commands.configure();
creeps.configure();
},
// Gets called every tick.
update: function () {
creeps.execute();
}
}

View File

@@ -1,36 +0,0 @@
module.exports = {
run: function(){
for(var spawn in Game.spawns){
var room = Game.spawns[spawn].room;
var towers = room.find(FIND_MY_STRUCTURES,
{filter: {structureType: STRUCTURE_TOWER}});
for(var tower in towers){
tower = towers[tower];
var enemy = tower.pos.findClosestByRange(FIND_HOSTILE_CREEPS);
if(enemy != null) tower.attack(enemy);
else {
var healt_creep = false;
for(var creep in Game.creeps){
creep = Game.creeps[creep];
if(creep.hits < creep.hitsMax) {
tower.heal(creep);
healt_creep = true;
}
}
if(!healt_creep && 500 < tower.energy){
var structure = tower.pos.findClosestByPath(FIND_STRUCTURES,
{filter: (s)=>(s.structureType != STRUCTURE_RAMPART && s.structureType != STRUCTURE_WALL && s.hits < s.hitsMax)});
if(750 < tower.energy && structure == null) {
var structures = tower.room.find(FIND_STRUCTURES, {filter: { structureType: STRUCTURE_RAMPART, structureType: STRUCTURE_WALL }});
structures.sort(function(a,b){return a.hits - b.hits});
structure = structures[0];
}
tower.repair(structure);
}
}
}
}
}
};