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