266 lines
12 KiB
JavaScript
266 lines
12 KiB
JavaScript
var _ = require('lodash');
|
|
|
|
var roleBase = require('role.base');
|
|
var roleIdle = require('role.idle');
|
|
var roleHarvester = require('role.harvester');
|
|
var roleHarvesterV2 = require('role.harvester.v2');
|
|
var roleRefiller = require('role.refiller');
|
|
var roleUpgrader = require('role.upgrader');
|
|
var roleBuilder = require('role.builder');
|
|
var roleRepairer = require('role.repairer');
|
|
var roleWallRepairer = require('role.wallrepairer');
|
|
var rolePickup = require('role.pickup');
|
|
|
|
/* About behaviour levels:
|
|
Level -1
|
|
Special level to make all creeps move to an idle location.
|
|
|
|
Level 1
|
|
The starting level, this can be run from the start of the map.
|
|
All bots will mine the resources they need, then do their task.
|
|
|
|
Level 2
|
|
This introduces refillers, overhauls harvesters and changes the behaviour of the rest.
|
|
Harvesters will deposit mined energy into a container or storage unit placed nearby.
|
|
Refillers will take energy to structures that need them.
|
|
Other creeps will take energy from the container/storage instead of mining them themselves.
|
|
|
|
Requirements: Containers placed next to all free spots of the sources in the room.
|
|
Harvesters will then place themselves between the container and the source.
|
|
For example: (S = source, H = harvester, C = container, X = wall, _ = empty)
|
|
__C__
|
|
_HHH_
|
|
CHSXX
|
|
_HXXX
|
|
__XXX
|
|
*/
|
|
var behaviourLevel = 2;
|
|
|
|
require('creep.custom')();
|
|
|
|
// Profiler - https://github.com/screepers/screeps-profiler
|
|
const profiler = require('screeps-profiler');
|
|
// Monkey-patch in the profiler
|
|
profiler.enable();
|
|
|
|
module.exports.loop = function () {
|
|
// Wrap my code in the profiler
|
|
profiler.wrap(function() {
|
|
|
|
// Setup variables with in-game objects for use in the script
|
|
var towers = _.filter(Game.structures, {structureType: STRUCTURE_TOWER});
|
|
var harvesters = _.filter(Game.creeps, (creep) => creep.memory.role == 'harvester');
|
|
var refillers = _.filter(Game.creeps, (creep) => creep.memory.role == 'refiller');
|
|
var builders = _.filter(Game.creeps, (creep) => creep.memory.role == 'builder');
|
|
var upgraders = _.filter(Game.creeps, (creep) => creep.memory.role == 'upgrader');
|
|
var repairers = _.filter(Game.creeps, (creep) => creep.memory.role == 'repairer');
|
|
var wallRepairers = _.filter(Game.creeps, (creep) => creep.memory.role == 'wallRepairer');
|
|
var pickups = _.filter(Game.creeps, (creep) => creep.memory.role == 'pickup');
|
|
|
|
// Cleanup memory
|
|
for(var name in Memory.creeps) {
|
|
if(!Game.creeps[name]) {
|
|
roleBase.clearMemory(name);
|
|
delete Memory.creeps[name];
|
|
console.log('Clearing non-existing creep memory:', name);
|
|
}
|
|
}
|
|
|
|
if(Memory.rooms == undefined) {Memory.rooms = {};}
|
|
for (var name in Game.rooms) {
|
|
if(Memory.rooms[name] == undefined) {
|
|
Memory.rooms[name] = {};
|
|
}
|
|
if(Memory.rooms[name].repairs == undefined) {
|
|
Memory.rooms[name].repairs = []
|
|
}
|
|
if(Memory.rooms[name].sources == undefined) {
|
|
Memory.rooms[name].sources = {};
|
|
for(let source of Game.rooms[name].find(FIND_SOURCES)) {
|
|
Memory.rooms[name].sources[source.id] = 0;
|
|
}
|
|
}
|
|
if(Memory.rooms[name].sources_spots == undefined) {
|
|
Memory.rooms[name].sources_spots = {};
|
|
for(let source of Game.rooms[name].find(FIND_SOURCES)) {
|
|
var num_spots = 0;
|
|
for (let x of [-1, 0, 1]) {
|
|
for (let y of [-1, 0, 1]) {
|
|
if(!(x == 0 && y == 0)){
|
|
var pos = new RoomPosition(source.pos.x + x, source.pos.y + y, source.pos.roomName);
|
|
if(pos.lookFor(LOOK_TERRAIN) == "plain"){
|
|
num_spots += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Memory.rooms[name].sources_spots[source.id] = num_spots;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Tower auto-repair structures nearby
|
|
for(var tower_id in towers) {
|
|
var tower = towers[tower_id];
|
|
// var closestDamagedStructure = tower.pos.findClosestByRange(FIND_STRUCTURES, {
|
|
// filter: (structure) => structure.hits < structure.hitsMax
|
|
// });
|
|
// if(closestDamagedStructure) {
|
|
// tower.repair(closestDamagedStructure);
|
|
// }
|
|
|
|
var closestHostile = tower.pos.findClosestByRange(FIND_HOSTILE_CREEPS);
|
|
if(closestHostile) {
|
|
tower.attack(closestHostile);
|
|
}
|
|
}
|
|
|
|
// Auto-spawn new creeps
|
|
var to_spawn = [];
|
|
|
|
var gameTime = Game.time.toString();
|
|
var name_index = gameTime.substring(gameTime.length-4, gameTime.length);
|
|
|
|
if(harvesters.length < 2) {
|
|
to_spawn.push(['harvester', 'Harvey' + name_index, [WORK, CARRY, MOVE]]);
|
|
}
|
|
// Refillers only necessary from behaviour level 2
|
|
if(behaviourLevel >= 2) {
|
|
if(refillers.length < 2) {
|
|
to_spawn.push(['refiller', 'Reffy' + name_index, [WORK, CARRY, MOVE]]);
|
|
}
|
|
}
|
|
if(builders.length < 1) {
|
|
to_spawn.push(['builder', 'Bob' + name_index, [WORK, CARRY, MOVE]]);
|
|
}
|
|
if(repairers.length < 2) {
|
|
to_spawn.push(['repairer', 'Reppy' + name_index, [WORK, CARRY, MOVE]]);
|
|
}
|
|
if(upgraders.length < 1) {
|
|
to_spawn.push(['upgrader', 'Uppy' + name_index, [WORK, CARRY, MOVE]]);
|
|
}
|
|
if(wallRepairers.length < 1) {
|
|
to_spawn.push(['wallRepairer', 'Wally' + name_index, [WORK, CARRY, MOVE]]);
|
|
}
|
|
if(pickups.length < 1) {
|
|
to_spawn.push(['pickup', 'Picky' + name_index, [WORK, CARRY, MOVE]]);
|
|
}
|
|
|
|
if(to_spawn.length > 0) {
|
|
for(var spawner_id in Game.spawns) {
|
|
var spawner = Game.spawns[spawner_id];
|
|
if(!spawner.spawning){
|
|
var entry = to_spawn.shift();
|
|
console.log("Spawning " + entry[0]);
|
|
var spawned = false;
|
|
var max_available_energy = spawner.store.getCapacity(RESOURCE_ENERGY);
|
|
for(let extension of _.filter(Game.structures, {structureType: STRUCTURE_EXTENSION, room: spawner.room})) {
|
|
max_available_energy += extension.store.getCapacity(RESOURCE_ENERGY);
|
|
}
|
|
//max_available_energy = 300;
|
|
|
|
var result = spawner.spawnCustomCreep(entry[0], entry[1], max_available_energy, behaviourLevel);
|
|
|
|
if (result == OK) {
|
|
spawner.room.visual.text('Spawning ' + entry[1] + ' /w ' + max_available_energy + " energy.", spawner.pos.x + 1, spawner.pos.y, {align: 'left', opacity: 0.8});
|
|
}
|
|
|
|
// If there are no harvesters any more, and there is not enough energy, spawn a basic harvester.
|
|
if(harvesters.length == 0 && result == ERR_NOT_ENOUGH_ENERGY) {
|
|
result = spawner.spawnCreep([WORK, CARRY, MOVE], "BasicHarvester", {memory: {role: 'harvester'}});
|
|
if (result == OK) {
|
|
spawner.room.visual.text('Spawning BasicHarvester.');
|
|
}
|
|
}
|
|
// If there are no refillers any more, and there is not enough energy, spawn a basic refiller.
|
|
if(refillers.length == 0 && result == ERR_NOT_ENOUGH_ENERGY) {
|
|
result = spawner.spawnCreep([WORK, CARRY, MOVE], "BasicRefiller", {memory: {role: 'refiller'}});
|
|
if (result == OK) {
|
|
spawner.room.visual.text('Spawning BasicRefiller.');
|
|
}
|
|
}
|
|
|
|
if (result != OK) {
|
|
switch (result) {
|
|
case ERR_BUSY:
|
|
console.log("Could not spawn " + entry[1] + ", spawner is busy.");
|
|
break;
|
|
case ERR_NOT_ENOUGH_ENERGY:
|
|
console.log("Could not spawn " + entry[1] + ", not enough energy.");
|
|
break;
|
|
case ERR_RCL_NOT_ENOUGH:
|
|
console.log("Could not spawn " + entry[1] + ", RCL not high enough.");
|
|
break;
|
|
default:
|
|
console.log("Could not spawn " + entry[1] + ", error code " + result);
|
|
break;
|
|
}
|
|
} else {
|
|
spawned = true;
|
|
}
|
|
}
|
|
}
|
|
if(!spawned){
|
|
console.log("Could not spawn, all spawners are busy or errored.");
|
|
}
|
|
}
|
|
|
|
// Execute creep ticks
|
|
for(var name in Game.creeps) {
|
|
var creep = Game.creeps[name];
|
|
|
|
var continue_with_role = roleBase.run(creep, behaviourLevel);
|
|
|
|
// If we are at behaviour level -1, move all bots to an idle position
|
|
if (behaviourLevel == -1) {
|
|
roleIdle.run(creep, behaviourLevel);
|
|
} else {
|
|
// Else, continue with the normal roles
|
|
if(continue_with_role) {
|
|
switch(creep.memory.role) {
|
|
case "harvester":
|
|
if (behaviourLevel >= 2) {
|
|
roleHarvesterV2.run(creep, behaviourLevel);
|
|
} else {
|
|
roleHarvester.run(creep, behaviourLevel);
|
|
}
|
|
break;
|
|
case "refiller":
|
|
if (behaviourLevel >= 2) {
|
|
roleRefiller.run(creep, behaviourLevel);
|
|
} else {
|
|
// No defined behaviour for refillers on level 1, just act as a Harvester.
|
|
roleHarvester.run(creep, behaviourLevel);
|
|
}
|
|
break;
|
|
case "upgrader":
|
|
roleUpgrader.run(creep, behaviourLevel);
|
|
break;
|
|
case "builder":
|
|
roleBuilder.run(creep, behaviourLevel);
|
|
break;
|
|
case "repairer":
|
|
roleRepairer.run(creep, behaviourLevel);
|
|
break;
|
|
case "wallRepairer":
|
|
roleWallRepairer.run(creep, behaviourLevel);
|
|
break;
|
|
case "pickup":
|
|
rolePickup.run(creep, behaviourLevel);
|
|
break;
|
|
default:
|
|
console.log("Creep with role " + creep.memory.role + " has no defined behaviour.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Print used CPU ticks every 10 game ticks
|
|
if(Game.time % 100 == 0) {
|
|
if(Game.cpu.limit){
|
|
console.log("Used " + Game.cpu.getUsed() + " / " + Game.cpu.limit + "(L) / " + Game.cpu.tickLimit + " (B) CPU this tick. Bucket level: " + Game.cpu.bucket);
|
|
}
|
|
}
|
|
|
|
});
|
|
} |