import { Apollo } from './apollo'
import { errorMapper } from './modules/errorMapper'
import { OK_STOP_CURRENT, OK_STOP_CUSTOM, OK_STOP_NEXT } from './modules/proc/proc'
import { assertWithMsg } from './utils'
// Upgrader 信号量
const upgraderOccupiedSignal = {}
const upgraderSlotSignal = {}
// Harvester 信号量
const harvesterOccupiedSignal = {}
const harvesterSlotSignal = {}
// Spawn 容量信号量
const capacitySignal = {}
// Spawn 能量信号量
const energySignal = {};
(function() {
// 创建信号量
for (const name in Game.spawns) {
// Upgrader
upgraderOccupiedSignal[name] = Apollo.proc.signal.createSignal((`${name}_upgrader` in Game.creeps)? 1: 0)
upgraderSlotSignal[name] = Apollo.proc.signal.createSignal((`${name}_upgrader` in Game.creeps)? 0: 1)
// Harvester
harvesterOccupiedSignal[name] = Apollo.proc.signal.createSignal((`${name}_harvester` in Game.creeps)? 1: 0)
harvesterSlotSignal[name] = Apollo.proc.signal.createSignal((`${name}_harvester` in Game.creeps)? 0: 1)
capacitySignal[name] = Apollo.proc.signal.createSignal(Game.spawns[name].store.getFreeCapacity())
energySignal[name] = Apollo.proc.signal.createSignal(Game.spawns[name].store[RESOURCE_ENERGY])
}
// 创建生 Creep 进程
for (const name in Game.spawns) {
// 生 Harvester
Apollo.proc.createProc([
["_START", () => Apollo.proc.signal.Swait(
{signalId: energySignal[name], lowerbound: 150, request: 150},
{signalId: harvesterSlotSignal[name], lowerbound: 1, request: 1}
)],
() => {
const spawn = Game.spawns[name]
if (spawn.spawning || (spawn as any).isSpawning) return OK_STOP_CURRENT
else {
assertWithMsg(spawn.spawnCreep([WORK, CARRY, MOVE], `${name}_harvester`) === OK);
(spawn as any).isSpawning = true // Hack ;D
return OK_STOP_NEXT
}
},
() => Apollo.proc.signal.Ssignal(
{signalId: capacitySignal[name], request: 150},
{signalId: harvesterOccupiedSignal[name], request: 1}
),
() => [OK_STOP_CUSTOM, "_START"]
], `${name} => Harvester`)
// 生 Upgrader
Apollo.proc.createProc([
["_START", () => Apollo.proc.signal.Swait(
{signalId: energySignal[name], lowerbound: 150, request: 150},
{signalId: upgraderSlotSignal[name], lowerbound: 1, request: 1}
)],
() => {
const spawn = Game.spawns[name]
if (spawn.spawning || (spawn as any).isSpawning) return OK_STOP_CURRENT
else {
assertWithMsg(spawn.spawnCreep([WORK, CARRY, MOVE], `${name}_upgrader`) === OK);
(spawn as any).isSpawning = true // Hack ;D
return OK_STOP_NEXT
}
},
() => Apollo.proc.signal.Ssignal(
{signalId: capacitySignal[name], request: 150},
{signalId: upgraderOccupiedSignal[name], request: 1}
),
() => [OK_STOP_CUSTOM, "_START"]
], `${name} => Upgrader`)
}
for (const name in Game.spawns) {
// Upgrader 进程流程
Apollo.proc.createProc([
["_START", () => Apollo.proc.signal.Swait(
{signalId: upgraderOccupiedSignal[name], lowerbound: 1, request: 0}
)],
() => {
const creep = Game.creeps[`${name}_upgrader`]
if (!creep) return [OK_STOP_CUSTOM, "_START"]
if (creep.store.getFreeCapacity(RESOURCE_ENERGY) === 0) return OK
const source = creep.pos.findClosestByRange(FIND_SOURCES)
if (creep.harvest(source) === ERR_NOT_IN_RANGE) creep.moveTo(source)
return OK_STOP_CURRENT
},
() => {
const creep = Game.creeps[`${name}_upgrader`]
if (!creep) return [OK_STOP_CUSTOM, "_START"]
if (creep.store.getUsedCapacity(RESOURCE_ENERGY) === 0) return [OK_STOP_CUSTOM, "_START"]
const controller = creep.room.controller
if (creep.upgradeController(controller) === ERR_NOT_IN_RANGE) creep.moveTo(controller)
return OK_STOP_CURRENT
}
], `${name}'s Upgrader Work`)
// Harvester 进程流程
Apollo.proc.createProc([
["_START", () => Apollo.proc.signal.Swait(
{signalId: harvesterOccupiedSignal[name], lowerbound: 1, request: 0}
)],
() => {
const creep = Game.creeps[`${name}_harvester`]
if (!creep) return [OK_STOP_CUSTOM, "_START"]
if (creep.store.getFreeCapacity(RESOURCE_ENERGY) === 0) return OK
const source = creep.pos.findClosestByRange(FIND_SOURCES)
if (creep.harvest(source) === ERR_NOT_IN_RANGE) creep.moveTo(source)
return OK_STOP_CURRENT
},
() => {
const creep = Game.creeps[`${name}_harvester`]
if (!creep) return [OK_STOP_CUSTOM, "_START"]
if (creep.store.getUsedCapacity(RESOURCE_ENERGY) === 0) return [OK_STOP_CUSTOM, "_START"]
const spawn = Game.spawns[name]
const amount = Math.min(creep.store.getUsedCapacity(RESOURCE_ENERGY), spawn.store.getFreeCapacity(RESOURCE_ENERGY))
if (creep.transfer(spawn, RESOURCE_ENERGY, amount) === ERR_NOT_IN_RANGE) creep.moveTo(spawn)
else {
// 放到下一 tick 更新会更好
Apollo.proc.signal.Ssignal(
{signalId: capacitySignal[name], request: -amount},
{signalId: energySignal[name], request: amount}
)
}
return OK_STOP_CURRENT
}
], `${name}'s Harvester Work`)
}
// 监视死亡的 Creep 进程
Apollo.proc.createProc([
() => {
// 清除死亡的 Creep Memory
for (const name in Memory.creeps) {
if (!(name in Game.creeps)) {
const desc = name.split('_')
const spawnName = desc[0], role = desc[1]
if (role === "harvester") {
Apollo.proc.signal.Ssignal(
{signalId: harvesterOccupiedSignal[spawnName], request: -1},
{signalId: harvesterSlotSignal[spawnName], request: 1}
)
} else if (role === "upgrader") {
Apollo.proc.signal.Ssignal(
{signalId: upgraderOccupiedSignal[spawnName], request: -1},
{signalId: upgraderSlotSignal[spawnName], request: 1}
)
}
delete Memory.creeps[name]
}
}
return OK_STOP_CURRENT
}
], "监视死亡 Creep")
for (const name in Game.spawns)
// 监视自增长的 Spawn Energy
Apollo.proc.createProc([
() => {
const spawn = Game.spawns[name]
if (spawn.store.getFreeCapacity(RESOURCE_ENERGY) > 0)
Apollo.proc.signal.Ssignal(
{signalId: capacitySignal[name], request: -1},
{signalId: energySignal[name], request: 1}
)
return OK_STOP_CURRENT
}
], `监视${name}自增 Energy`)
})()
export const loop = errorMapper(() => {
Apollo.proc.tick()
})