Files
screeps-ai/src/creep/builder.ts
T
2021-08-14 11:46:07 +03:00

118 lines
3.4 KiB
TypeScript

import * as _ from 'lodash';
import { harvestEnergyFromTombstone, selectSource } from './common';
interface BuilderMemory extends CreepMemory {
building: boolean | undefined;
}
export function runAsBuilder(creep: Creep) {
const memory = creep.memory as BuilderMemory;
if (memory.building && creep.store[RESOURCE_ENERGY] === 0) {
memory.building = false;
memory.repairTargetId = '';
}
if (!memory.building && creep.store.getFreeCapacity() === 0) {
memory.building = true;
}
if (!memory.sourceId) {
memory.sourceId = selectSource(creep.room);
}
harvestEnergyFromTombstone(creep);
if (memory.building) {
if (build(creep)) {
return;
}
if (repair(creep)) {
return;
}
const spawns = creep.room.find(FIND_MY_SPAWNS);
if (spawns.length > 0) {
creep.say('To spawn');
creep.moveTo(spawns[0]);
}
} else {
const source = Game.getObjectById(memory.sourceId);
if (source && creep.harvest(source) == ERR_NOT_IN_RANGE) {
creep.say('🔄 harvest');
creep.moveTo(source, { visualizePathStyle: { stroke: '#ffaa00' } });
}
}
}
function build(creep: Creep): boolean {
const targets = creep.room.find(FIND_MY_CONSTRUCTION_SITES);
if (targets.length === 0) {
return false;
}
if (creep.build(targets[0]) == ERR_NOT_IN_RANGE) {
creep.say('🚧 build');
creep.moveTo(targets[0], { visualizePathStyle: { stroke: '#ffffff' } });
}
return true;
}
/**
* Починить.
*
* Если цель нужно чинить, то дойти до цели и произвести починку.
* Если цель починена, найти ближайшую цель в радиусе починки и чинить ее.
*
* @param creep
*/
function repair(creep: Creep) {
const memory = creep.memory as BuilderMemory;
let repairTarget;
// Если уже установлена цель, то получаем объект,
// иначе ищем подходящую цель для ремонта.
if (memory.repairTargetId) {
repairTarget = Game.getObjectById(memory.repairTargetId);
} else {
repairTarget = findBestRepairTarget(creep);
memory.repairTargetId = repairTarget ? repairTarget.id : '';
}
// Если цель ремонта не найдена, то ничего не делаем.
if (!repairTarget) {
memory.repairTargetId = '';
return false;
}
if (repairTarget.hits < repairTarget.hitsMax) {
if (creep.repair(repairTarget) == ERR_NOT_IN_RANGE) {
creep.say('🚧 repair');
creep.moveTo(repairTarget, { visualizePathStyle: { stroke: '#ffffff' } });
}
} else {
const closestRepairTarget = findClosestRepairTarget(creep);
if (closestRepairTarget) {
if (creep.repair(closestRepairTarget) !== OK) {
memory.repairTargetId = '';
}
} else {
memory.repairTargetId = '';
}
}
return true;
}
function findBestRepairTarget(creep: Creep): Structure | undefined {
const targets = creep.room.find(FIND_STRUCTURES, {
filter: (t) => t.hits < t.hitsMax && t.structureType !== STRUCTURE_ROAD
});
if (targets.length > 0) {
targets.sort((t1, t2) => t1.hits - t2.hits);
return targets[0];
}
return undefined;
}
function findClosestRepairTarget(creep: Creep): Structure | undefined {
const targets = creep.pos.findInRange(FIND_STRUCTURES, 3, {
filter: (t) => t.hits < t.hitsMax && t.structureType !== STRUCTURE_ROAD
});
return _.first(targets);
}