You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
screeps/default/spawn.js

255 lines
9.8 KiB

8 months ago
require('globals')
const EMERGENCY_MODE_TIMEOUT = 100
function getHarvestingSpots (source) {
let spots = []
let terrain = source.room.getTerrain()
8 months ago
for (let x = source.pos.x - 1; x <= source.pos.x + 1; x++) {
for (let y = source.pos.y - 1; y <= source.pos.y + 1; y++) {
8 months ago
if (terrain.get(x, y) !== TERRAIN_MASK_WALL) {
spots.push([x, y])
}
}
}
source.room.memory.harvestingSpots[source.id] = spots
return spots
}
function getBodyCost(body) {
let cost = 0
for (let part of body) {
cost = cost + BODYPART_COST[part]
}
return cost
}
module.exports = {
tickInit () {
for (let room of Object.values(Game.rooms)) {
8 months ago
let spawns = room.find(FIND_MY_SPAWNS)
room.memory.spawingRoom = spawns.length > 0
8 months ago
if (!room.memory.harvestingSpots) {
room.memory.harvestingSpots = {}
}
if (!room.memory.spawnIdle) {
room.memory.spawnIdle = 0
}
if (!room.memory.energyIncreasedAt) {
room.memory.energyIncreasedAt = Game.time
}
if (!room.memory.lastEnergy) {
room.memory.lastEnergy = 0
}
8 months ago
if (!room.memory.energyStructuresPriority || Game.time % 100 === 0) {
room.memory.energyStructuresPriority = _.sortBy(
room.find(
FIND_MY_STRUCTURES,
{filter: s => s.structureType === STRUCTURE_EXTENSION || s.structureType === STRUCTURE_SPAWN}
).map(el => {return {structure: el, range: el.pos.getRangeTo(room.storage)}}),
'range'
).map(el => el.structure.id)
}
8 months ago
if (!room.memory.sourcesData) {
room.memory.sourcesData = {}
}
for (let source of room.find(FIND_SOURCES)) {
8 months ago
if (!room.memory.harvestingSpots[source.id] || Game.time % 10 === 0) {
room.memory.harvestingSpots[source.id] = getHarvestingSpots(source)
}
if (!room.memory.sourcesData[source.id] || Game.time % 10 === 0) {
room.memory.sourcesData[source.id] = {spawnDistance: 0, energyCapacity: source.energyCapacity}
8 months ago
let spawn = source.pos.findClosestByPath(FIND_MY_SPAWNS)
if (spawn) {
room.memory.sourcesData[source.id].spawnDistance = source.pos.findPathTo(spawn.pos, {ignoreCreeps: true}).length
}
}
}
8 months ago
if (spawns.length > 0 && (Game.time + 5) % 100 === 0 && room.find(FIND_MY_CONSTRUCTION_SITES).length === 0) {
let spawn = spawns[0]
let extensions = room.find(FIND_MY_STRUCTURES, {filter: s => s.structureType === STRUCTURE_EXTENSION})
if (CONTROLLER_STRUCTURES.extension[room.controller.level] > extensions.length) {
let ring = 0
let x = spawn.pos.x
let y = spawn.pos.y
while (ring < 10 && room.createConstructionSite(x, y, STRUCTURE_EXTENSION) === ERR_INVALID_TARGET) {
x += 2
if (x > spawn.pos.x + ring) {
x = spawn.pos.x - ring
y += 2
}
if (y > spawn.pos.y + ring) {
ring++
x = spawn.pos.x - ring
y = spawn.pos.y - ring
}
}
}
}
8 months ago
}
},
tick (spawn) {
let minRoleCount
if (spawn.spawning) {
spawn.room.memory.spawnIdle = 0
let spawningCreep = Game.creeps[spawn.spawning.name];
8 months ago
let room = spawningCreep.memory.room || ''
8 months ago
spawn.room.visual.text(
8 months ago
'🛠' + spawningCreep.memory.role + ' ' + room,
8 months ago
spawn.pos.x + 1,
spawn.pos.y,
{align: 'left', opacity: 0.8});
}
else {
let newCreep, prio
for (let [roleName, role] of Object.entries(ROLES)) {
8 months ago
if (role.minRcl > spawn.room.controller.level) {
continue
}
8 months ago
let roleCreeps = _.filter(Game.creeps, {memory: {role: roleName, colony: spawn.room.name}});
8 months ago
if (minRoleCount === undefined || minRoleCount > roleCreeps.length) {
minRoleCount = roleCreeps.length
}
if (roleCreeps.length > 0 && spawn.room.memory.emergency && spawn.room.energyAvailable < spawn.room.energyCapacityAvailable) {
continue
}
let newName = roleName + Game.time;
let body = []
8 months ago
let memory = {role: roleName, colony: spawn.room.name}
if (role.nextSpawn) {
let nextSpawn = role.nextSpawn(spawn, roleCreeps)
if (nextSpawn) {
[body, memory] = nextSpawn
}
}
else if (roleName === 'harvester') {
8 months ago
for (let source of spawn.room.find(FIND_SOURCES)) {
8 months ago
let spots = spawn.room.memory.harvestingSpots[source.id]
8 months ago
let harvestingCapacity = 0
8 months ago
let sourceHarvesters = _.filter(roleCreeps, {memory: {source: source.id}})
8 months ago
if (sourceHarvesters.length >= spots.length) {
continue
}
for (let harvester of sourceHarvesters) {
8 months ago
if (!harvester.ticksToLive || harvester.ticksToLive > harvester.body.length * 3 + source.room.memory.sourcesData[source.id].spawnDistance) {
harvestingCapacity += _.filter(harvester.body, {type: WORK}).length * 2 * 300
8 months ago
}
}
8 months ago
if (harvestingCapacity < source.energyCapacity) {
for (let b of role.bodies) {
8 months ago
if (getBodyCost(b) <= (spawn.room.memory.emergency ? spawn.room.energyAvailable : spawn.room.energyCapacityAvailable)) {
body = b
memory.source = source.id
} else {
break
}
}
}
}
}
8 months ago
else if (roleName === 'remoteHarvester') {
for (let roomName of activeRemotes) {
let roomMemory = Memory.rooms[roomName]
if (roomMemory) {
for (let [sourceId, sourceData] of Object.entries(roomMemory.sourcesData)) {
let spots = roomMemory.harvestingSpots[sourceId]
let harvestingCapacity = 0
let sourceHarvesters = _.filter(Game.creeps, {memory: {role: 'remoteHarvester', source: sourceId}})
if (sourceHarvesters.length >= spots.length) {
continue
}
for (let harvester of sourceHarvesters) {
8 months ago
if (!harvester.ticksToLive || harvester.ticksToLive > harvester.body.length * 3 + sourceData.spawnDistance) {
8 months ago
harvestingCapacity += harvester.getActiveBodyparts(WORK) * 2 * 300
}
}
if (harvestingCapacity < sourceData.energyCapacity) {
for (let b of role.bodies) {
if (getBodyCost(b) <= spawn.room.energyCapacityAvailable) {
body = b
memory.source = sourceId
memory.room = roomName
if (_.filter(b, WORK).length * 2 * 300 > sourceData.energyCapacity) {
break
}
} else {
break
}
}
}
}
}
}
}
else if (roleCreeps.length < (role.getCount ? role.getCount(spawn.room) : role.count) && role.idling === 0) {
8 months ago
if (Array.isArray(role.bodies)) {
for (let b of role.bodies) {
if (getBodyCost(b) <= (spawn.room.memory.emergency ? spawn.room.energyAvailable : spawn.room.energyCapacityAvailable)) {
body = b
} else {
break
}
}
} else {
body = role.baseBody
while (getBodyCost(body) + getBodyCost(role.expandBody) <= (spawn.room.memory.emergency ? spawn.room.energyAvailable : spawn.room.energyCapacityAvailable)) {
body = body.concat(role.expandBody)
8 months ago
if (body.length >= role.baseBody.length + role.expandBody.length * role.maxExpands) {
break
}
8 months ago
}
}
}
8 months ago
memory.role = roleName
memory.colony = spawn.room.name
8 months ago
if (body.length && (!prio || role.prio * (roleCreeps.length + 1) < prio)) {
newCreep = [body, newName, {memory}]
prio = role.prio * (roleCreeps.length + 1)
}
}
8 months ago
if (spawn.room.memory.lastEnergy !== spawn.room.energyAvailable) {
spawn.room.memory.energyIncreasedAt = Game.time
spawn.room.memory.lastEnergy = spawn.room.energyAvailable
}
spawn.room.memory.emergency = false
8 months ago
if (newCreep) {
8 months ago
newCreep[2].energyStructures = spawn.room.memory.energyStructuresPriority.map(el => Game.getObjectById(el))
8 months ago
spawn.spawnCreep(...newCreep)
spawn.room.memory.spawnIdle++
spawn.room.visual.text(
`Next: ${newCreep[1]}`,
spawn.pos.x + 1,
spawn.pos.y,
{align: 'left', opacity: 0.8, size: 0.3});
8 months ago
if (minRoleCount === 0) {
let timeToEmergency = Math.max(
EMERGENCY_MODE_TIMEOUT - spawn.room.memory.spawnIdle,
EMERGENCY_MODE_TIMEOUT - (Game.time - spawn.room.memory.energyIncreasedAt)
)
if (timeToEmergency <= 0) {
spawn.room.memory.emergency = true
spawn.room.visual.text(
`Prio${prio} emergency spawn ${newCreep[1]} (${newCreep[0]})`,
spawn.pos.x + 1,
spawn.pos.y,
{align: 'left', opacity: 0.8});
} else if (timeToEmergency <= 50) {
spawn.room.visual.text(
'Emergency in ' + timeToEmergency,
spawn.pos.x + 1,
spawn.pos.y,
{align: 'left', opacity: 0.8});
}
8 months ago
}
8 months ago
}/* else {
let renewableCreeps = spawn.pos.findInRange(FIND_MY_CREEPS, 1, {filter: c => c.ticksToLive < 1200})
if (renewableCreeps.length > 0) {
spawn.renewCreep(renewableCreeps[0])
}
}*/
8 months ago
}
},
}