diff --git a/src/RoomPlanner/index.ts b/src/RoomPlanner/index.ts index ce440ad..8a50cc3 100644 --- a/src/RoomPlanner/index.ts +++ b/src/RoomPlanner/index.ts @@ -17,7 +17,8 @@ const structureCoding: (BuildableStructureConstant | null)[] STRUCTURE_TOWER, STRUCTURE_RAMPART]; const getCoord = (x: number, y: number): number => { - return x + y * roomSize; + return Math.max(0, Math.min(roomSize - 1, x)) + + Math.max(0, Math.min(roomSize - 1, y)) * roomSize; }; const distanceTransform = (mask: (0 | 999 | 1000)[]): number[] => { @@ -64,6 +65,7 @@ const createBuildSites = (room: Room) => { if (room.memory._planner == null) { return; } + const currentConstructionSites = room.find(FIND_MY_CONSTRUCTION_SITES); const structures = [] as (BuildableStructureConstant | null)[]; for (let i = 0; i < room.memory._planner.length; i++) { structures.push( @@ -73,6 +75,12 @@ const createBuildSites = (room: Room) => { structureCoding[(room.memory._planner.charCodeAt(i) - 32) >> 5], ); } + + let roads = currentConstructionSites.filter( + s => s.structureType === STRUCTURE_ROAD).length; + let walls = currentConstructionSites.filter( + s => s.structureType === STRUCTURE_WALL).length; + for (let x = 0; x < roomSize; x++) { for (let y = 0; y < roomSize; y++) { const struct = structures[getCoord(x, y)]; @@ -91,7 +99,8 @@ const createBuildSites = (room: Room) => { || struct == STRUCTURE_ROAD || struct == STRUCTURE_EXTENSION || struct == STRUCTURE_RAMPART - || struct == STRUCTURE_TOWER)) { + || struct == STRUCTURE_TOWER + || struct == STRUCTURE_WALL)) { continue; } if ((room.controller?.level ?? 0) < 5 @@ -100,7 +109,8 @@ const createBuildSites = (room: Room) => { || struct == STRUCTURE_EXTENSION || struct == STRUCTURE_RAMPART || struct == STRUCTURE_TOWER - || struct == STRUCTURE_WALL)) { + || struct == STRUCTURE_WALL + || struct == STRUCTURE_STORAGE)) { continue; } if ((room.controller?.level ?? 0) < 6 @@ -125,10 +135,23 @@ const createBuildSites = (room: Room) => { continue; } if (struct != null) { - if (room.createConstructionSite(x, y, struct) - === ERR_FULL) { + if ((struct === STRUCTURE_WALL && walls > 5) + || (struct === STRUCTURE_ROAD && roads > 5)) { + continue; + } + const ret = room.createConstructionSite(x, y, struct); + if (ret === ERR_FULL) { return; } + if (ret === OK && struct === STRUCTURE_WALL) { + walls++; + } + if (ret === OK && struct === STRUCTURE_ROAD) { + roads++; + } + if (struct === STRUCTURE_RAMPART) { + room.createConstructionSite(x, y, STRUCTURE_ROAD); + } } } } @@ -281,6 +304,7 @@ export default profiler.registerFN(function (room: Room) { if (mask[getCoord(x + dx, y + dy)] === 0) { structures[getCoord(x + dx, y + dy)] = STRUCTURE_ROAD; } + continue; } if (!(dx === 0 && Math.abs(dy) === 3) && !(dy === 0 && Math.abs(dx) === 3)) { @@ -383,7 +407,15 @@ export default profiler.registerFN(function (room: Room) { for (let x = 0; x < roomSize; x++) { for (let y = 0; y < roomSize; y++) { if (mask[getCoord(x, y)] === TERRAIN_MASK_WALL) { - costs.set(x, y, 1); + if (mask[getCoord(x - 1, y)] === 0 + || mask[getCoord(x + 1, y)] === 0 + || mask[getCoord(x, y + 1)] === 0 + || mask[getCoord(x, y - 1)] === 0) { + costs.set(x, y, 10); + } + else { + costs.set(x, y, 1); + } } if (structures[getCoord(x, y)] != null) { if (structures[getCoord(x, y)] == STRUCTURE_ROAD) { @@ -412,49 +444,40 @@ export default profiler.registerFN(function (room: Room) { if (centerWallPiece != null) { path.push(centerWallPiece); } + const safeBuild = (x: number, y: number) => { + if (mask[getCoord(x, y)] != TERRAIN_MASK_WALL + && structures[getCoord(x, y)] != STRUCTURE_RAMPART) { + if (structures[getCoord(x, y)] == null + || structures[getCoord(x, y)] === STRUCTURE_ROAD) { + structures[getCoord(x, y)] + = structures[getCoord(x, y)] === STRUCTURE_ROAD + ? structures[getCoord(x, y)] = STRUCTURE_RAMPART + : structures[getCoord(x, y)] = STRUCTURE_WALL; + } + } + }; for (const pos of path) { - const s = structures[getCoord(pos.x, pos.y)] === STRUCTURE_ROAD - || structures[getCoord(pos.x + 1, pos.y)] === STRUCTURE_ROAD - || structures[getCoord(pos.x - 1, pos.y)] === STRUCTURE_ROAD - || structures[getCoord(pos.x + 1, pos.y + 1)] === STRUCTURE_ROAD - || structures[getCoord(pos.x + 1, pos.y - 1)] === STRUCTURE_ROAD - || structures[getCoord(pos.x - 1, pos.y + 1)] === STRUCTURE_ROAD - || structures[getCoord(pos.x - 1, pos.y - 1)] === STRUCTURE_ROAD - || structures[getCoord(pos.x, pos.y + 1)] === STRUCTURE_ROAD - || structures[getCoord(pos.x, pos.y - 1)] === STRUCTURE_ROAD - ? STRUCTURE_RAMPART - : STRUCTURE_WALL; - if (mask[getCoord(pos.x, pos.y)] != TERRAIN_MASK_WALL) { - structures[getCoord(pos.x, pos.y)] = s; - } - else { - continue; - } - if (mask[getCoord(pos.x + 1, pos.y)] != TERRAIN_MASK_WALL - && structures[getCoord(pos.x + 1, pos.y)] != STRUCTURE_RAMPART) { - structures[getCoord(pos.x + 1, pos.y)] = s; - } - if (mask[getCoord(pos.x - 1, pos.y)] != TERRAIN_MASK_WALL - && structures[getCoord(pos.x - 1, pos.y)] != STRUCTURE_RAMPART) { - structures[getCoord(pos.x - 1, pos.y)] = s; - } - if (mask[getCoord(pos.x, pos.y + 1)] != TERRAIN_MASK_WALL - && structures[getCoord(pos.x, pos.y + 1)] != STRUCTURE_RAMPART) { - structures[getCoord(pos.x, pos.y + 1)] = s; - } - if (mask[getCoord(pos.x, pos.y - 1)] != TERRAIN_MASK_WALL - && structures[getCoord(pos.x, pos.y - 1)] != STRUCTURE_RAMPART) { - structures[getCoord(pos.x, pos.y - 1)] = s; - } + safeBuild(pos.x, pos.y); + safeBuild(pos.x + 1, pos.y); + safeBuild(pos.x - 1, pos.y); + safeBuild(pos.x, pos.y + 1); + safeBuild(pos.x, pos.y - 1); } } + structures[getCoord(room.controller.pos.x, room.controller.pos.y)] + = null; + // Render // renderHeatmap(controllerDistance, room.visual); /* for (let x = 0; x < roomSize; x++) { for (let y = 0; y < roomSize; y++) { - if (structures[getCoord(x, y)] != null) { - room.visual.structure(x, y, structures[getCoord(x, y)]); + const struct = structures[getCoord(x, y)]; + if (struct != null) { + room.visual.structure(x, y, struct); + if (struct === STRUCTURE_RAMPART) { + room.visual.structure(x, y, STRUCTURE_ROAD); + } } } } diff --git a/src/Tasks/Withdraw.ts b/src/Tasks/Withdraw.ts index 559be24..6cc6371 100644 --- a/src/Tasks/Withdraw.ts +++ b/src/Tasks/Withdraw.ts @@ -46,11 +46,11 @@ export const runWithdraw = profiler.registerFN( const capacity = creep.store.getFreeCapacity(opts.resource); const amount = Math.min(opts.amount ?? capacity, opts.limit ?? capacity - creep.store.getUsedCapacity(opts.resource)); - const amountS = target != null && "store" in target - ? target.store.getUsedCapacity(opts.resource) + const amountS = (target != null && "store" in target) + ? Math.min(amount, target.store.getUsedCapacity(opts.resource)) : amount; - if (amount <= 0) { + if (amountS <= 0) { return TaskStatus.DONE; } diff --git a/src/Workers/Clerk.ts b/src/Workers/Clerk.ts index 5dd10ca..6c30f07 100644 --- a/src/Workers/Clerk.ts +++ b/src/Workers/Clerk.ts @@ -21,8 +21,12 @@ const assignTask = (creep: Creep) => { if (tower != null) { return Tasks.Transfer(tower); } + if (creep.room.storage != null + && creep.room.storage.store.getFreeCapacity(RESOURCE_ENERGY) > 0) { + return Tasks.Transfer(creep.room.storage); + } if (creep.room.controller != null) { - if (creep.room.controller.ticksToDowngrade > 1000) { + if (creep.room.controller.ticksToDowngrade > 5000) { const urgentRepair = creep.pos.findClosestByRange(FIND_STRUCTURES, { filter: s => s.hits < s.hitsMax * 0.3 && ("my" in s ? s.my @@ -31,6 +35,11 @@ const assignTask = (creep: Creep) => { if (urgentRepair != null) { return Tasks.Repair(urgentRepair); } + const buildSite + = creep.pos.findClosestByRange(FIND_MY_CONSTRUCTION_SITES); + if (buildSite != null) { + return Tasks.Build(buildSite); + } return null; } return Tasks.Upgrade(creep.room.controller); @@ -46,7 +55,8 @@ const assignTask = (creep: Creep) => { if (container != null) { return Tasks.Withdraw(container); } - const source = creep.pos.findClosestByPath(FIND_SOURCES_ACTIVE); + const source = creep.room.sources.find(s => s.energy > 0 + && s.assignedCreeps.length == 0); if (source != null) { return Tasks.Harvest(source); } @@ -65,7 +75,7 @@ const body = (energy: number): BodyPartConstant[] => ( export const Clerk: WorkerDefinition = { assignTask, name: "clerk", - requiredCreeps: () => 3, + requiredCreeps: () => 1, bodyDefinition: body, motivationalThougts: [ "Carrying 🎒", diff --git a/src/Workers/Constructor.ts b/src/Workers/Constructor.ts index dd272ec..fece3df 100644 --- a/src/Workers/Constructor.ts +++ b/src/Workers/Constructor.ts @@ -14,7 +14,8 @@ const assignTask = (creep: Creep) => { if (container != null) { return Tasks.Withdraw(container); } - const source = creep.room.sources.find(s => s.energy > 0); + const source = creep.room.sources.find(s => s.energy > 0 + && s.assignedCreeps.length == 0); if (source != null) { return Tasks.Harvest(source); } @@ -34,9 +35,7 @@ const assignTask = (creep: Creep) => { if (constructionSite != null) { return Tasks.Build(constructionSite); } - const structure = creep.pos.findClosestByRange(FIND_MY_STRUCTURES, { - filter: s => s.hits < s.hitsMax * 0.8, - }) ?? creep.pos.findClosestByRange(FIND_STRUCTURES, { + const structure = creep.pos.findClosestByRange(FIND_STRUCTURES, { filter: s => s.hits < s.hitsMax * 0.8 && ("my" in s ? s.my : true), }); diff --git a/src/Workers/Upgrader.ts b/src/Workers/Upgrader.ts index 7a0faa4..9e5830b 100644 --- a/src/Workers/Upgrader.ts +++ b/src/Workers/Upgrader.ts @@ -15,7 +15,8 @@ const assignTask = (creep: Creep) => { if (container != null) { return Tasks.Withdraw(container); } - const source = creep.pos.findClosestByPath(FIND_SOURCES_ACTIVE); + const source = creep.room.sources.find(s => s.energy > 0 + && s.assignedCreeps.length == 0); if (source != null) { return Tasks.Harvest(source); } diff --git a/src/Workers/worker.ts b/src/Workers/worker.ts index b43c53d..eb4126a 100644 --- a/src/Workers/worker.ts +++ b/src/Workers/worker.ts @@ -11,10 +11,13 @@ export interface WorkerDefinition { export const spawnWorkers = profiler.registerFN( function (spawn: StructureSpawn, workers: WorkerDefinition[]) { + const capacity = Object.values(Game.creeps).length > 2 + ? spawn.room.energyCapacityAvailable + : spawn.store.getCapacity(RESOURCE_ENERGY); for (const worker of workers) { for (let i = 0; i < worker.requiredCreeps(spawn.room); i++) { const ret = spawn.spawnCreep( - worker.bodyDefinition(spawn.room.energyCapacityAvailable), + worker.bodyDefinition(capacity), worker.name + i.toString()); if (ret === OK || ret === ERR_NOT_ENOUGH_ENERGY) { return; diff --git a/src/index.ts b/src/index.ts index ade1745..3ce50bc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -46,7 +46,7 @@ export const loop = profiler.wrap(() => { return; } if (spawn.room.name != "sim") { - const workerTypes = [Clerk, Upgrader, Miner, Constructor]; + const workerTypes = [Clerk, Miner, Upgrader, Constructor]; spawnWorkers(spawn, workerTypes); runWorkers(workerTypes); runTowers(spawn);