screeps-ai/src/creep/builder.ts

118 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}