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

167 lines
5.8 KiB

require('globals')
const EMERGENCY_MODE_TIMEOUT = 100
function getHarvestingSpots (source) {
if (source.room.memory.harvestingSpots[source.id]) {
return source.room.memory.harvestingSpots[source.id]
}
let spots = []
let terrain = source.room.getTerrain()
for (let x = source.pos.x; x <= source.pos.x + 1; x++) {
for (let y = source.pos.y; y <= source.pos.y + 1; y++) {
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)) {
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
}
if (!room.memory.sourcesData) {
room.memory.sourcesData = {}
}
for (let source of room.find(FIND_SOURCES)) {
if (!room.memory.sourcesData[source.id]) {
room.memory.sourcesData[source.id] = {spawnDistance: 0}
let spawn = source.pos.findClosestByPath(FIND_MY_SPAWNS)
if (spawn) {
room.memory.sourcesData[source.id].spawnDistance = source.pos.findPathTo(spawn.pos, {ignoreCreeps: true}).length
}
}
}
}
},
tick (spawn) {
let minRoleCount
if (spawn.spawning) {
spawn.room.memory.spawnIdle = 0
let spawningCreep = Game.creeps[spawn.spawning.name];
spawn.room.visual.text(
'🛠' + spawningCreep.memory.role,
spawn.pos.x + 1,
spawn.pos.y,
{align: 'left', opacity: 0.8});
}
else {
let newCreep, prio
for (let [roleName, role] of Object.entries(ROLES)) {
let roleCreeps = _.filter(Game.creeps, (creep) => creep.memory.role === roleName);
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 = []
let memory = {role: roleName}
if (roleName === 'harvester') {
for (let source of spawn.room.find(FIND_SOURCES)) {
let spots = getHarvestingSpots(source)
let harvestingCapacity = 0
let sourceHarvesters = _.filter(Game.creeps, {memory: {role: 'harvester', source: source.id}})
if (sourceHarvesters.length >= spots.length) {
continue
}
for (let harvester of sourceHarvesters) {
if (harvester.ticksToLive > harvester.body.length * 3 + source.room.memory.sourcesData[source.id].spawnDistance) {
harvestingCapacity += harvester.getActiveBodyparts(WORK) * 2 * 300
}
}
if (harvestingCapacity <= source.energyCapacity) {
for (let b of ROLES.harvester.bodies) {
if (getBodyCost(b) <= (spawn.room.memory.emergency ? spawn.room.energyAvailable : spawn.room.energyCapacityAvailable)) {
body = b
memory.source = source.id
} else {
break
}
}
}
}
}
else if (roleCreeps.length < role.count && role.idling === 0) {
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)
}
}
}
if (body.length && (!prio || role.prio * (roleCreeps.length + 1) < prio)) {
newCreep = [body, newName, {memory}]
prio = role.prio * (roleCreeps.length + 1)
}
}
if (newCreep) {
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});
}
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
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 ' + (EMERGENCY_MODE_TIMEOUT - spawn.room.memory.spawnIdle),
spawn.pos.x + 1,
spawn.pos.y,
{align: 'left', opacity: 0.8});
}
}
}
},
}