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