From c048630291ba9d825cced306c18ee6de550d6820 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 3 Aug 2023 20:31:15 +0200 Subject: [PATCH] Provide an interface over store contents --- src/Colony.ts | 14 +- src/Overseer.ts | 4 +- src/declarations/index.d.ts | 6 +- src/declarations/prototypes.d.ts | 47 ++--- src/deprecated/TerminalNetwork.ts | 18 +- src/directives/colony/poisonRoom.ts | 2 +- src/directives/logistics/drop.ts | 22 +-- src/directives/resource/haul.ts | 24 +-- src/directives/situational/stronghold.ts | 4 +- src/hiveClusters/commandCenter.ts | 4 +- src/hiveClusters/evolutionChamber.ts | 2 +- src/hiveClusters/sporeCrawler.ts | 4 +- src/logistics/Energetics.ts | 4 +- src/logistics/LogisticsNetwork.ts | 46 +++-- src/logistics/RoadLogistics.ts | 4 +- src/logistics/TerminalNetwork_v2.ts | 14 +- src/overlords/colonization/pioneer.ts | 2 +- src/overlords/colonization/roomPoisoner.ts | 2 +- src/overlords/core/manager.ts | 10 +- src/overlords/core/queen.ts | 8 +- src/overlords/core/queen_bunker.ts | 15 +- src/overlords/core/transporter.ts | 4 +- src/overlords/core/upgrader.ts | 2 +- src/overlords/core/worker.ts | 2 +- src/overlords/mining/miner.ts | 40 ++--- src/overlords/powerMining/PowerHauler.ts | 16 +- src/overlords/situational/bootstrap.ts | 2 +- src/overlords/situational/hauler.ts | 24 +-- src/overlords/situational/remoteUpgrader.ts | 20 +-- src/overlords/~template/templateOverlord.ts | 4 +- src/prototypes/Structures.ts | 185 +++++--------------- src/resources/Abathur.ts | 10 +- src/resources/map_resources.ts | 2 +- src/roomPlanner/RoomPlanner.ts | 2 +- src/tasks/instances/build.ts | 2 +- src/tasks/instances/drop.ts | 2 +- src/tasks/instances/fortify.ts | 2 +- src/tasks/instances/generateSafeMode.ts | 2 +- src/tasks/instances/harvest.ts | 2 +- src/tasks/instances/pickup.ts | 2 +- src/tasks/instances/recharge.ts | 2 +- src/tasks/instances/repair.ts | 2 +- src/tasks/instances/transfer.ts | 4 +- src/tasks/instances/transferAll.ts | 6 +- src/tasks/instances/upgrade.ts | 2 +- src/tasks/instances/withdraw.ts | 4 +- src/tasks/instances/withdrawAll.ts | 4 +- src/utilities/utils.ts | 15 +- src/zerg/AnyZerg.ts | 14 +- src/zerg/PowerZerg.ts | 2 - src/zerg/Zerg.ts | 4 +- 51 files changed, 249 insertions(+), 391 deletions(-) diff --git a/src/Colony.ts b/src/Colony.ts index 86dece17c..475d73955 100644 --- a/src/Colony.ts +++ b/src/Colony.ts @@ -100,14 +100,6 @@ const getDefaultColonyMemory: () => ColonyMemory = () => ({ outposts : {}, }); -export interface Assets { - energy: number; - power: number; - ops: number; - - [resourceType: string]: number; -} - /** * Colonies are the highest-level object other than the global Overmind. A colony groups together all rooms, structures, * creeps, utilities, etc. which are run from a single owned room. @@ -127,7 +119,7 @@ export class Colony { // abandonedOutposts: AbandonedOutpost[]; // Outposts that are not currently maintained, not used for now rooms: Room[]; // All rooms including the primary room pos: RoomPosition; - assets: Assets; + assets: StoreContents; // Physical colony structures and roomObjects controller: StructureController; // These are all duplicated from room properties spawns: StructureSpawn[]; // | @@ -654,13 +646,13 @@ export class Colony { * Summarizes the total of all resources in colony store structures, labs, and some creeps. Will always return * 0 for an asset that it has none of (not undefined) */ - private computeAssets(verbose = false): Assets { + private computeAssets(verbose = false): StoreContents { // Include storage structures, lab contents, and manager carry const assetStructures = _.compact([this.storage, this.terminal, this.factory, ...this.labs]); const assetCreeps = [...this.getCreepsByRole(Roles.queen), ...this.getCreepsByRole(Roles.manager)]; const assetStores = _.map([...assetStructures, ...assetCreeps], thing => thing!.store); - const allAssets = mergeSum([...assetStores, ALL_ZERO_ASSETS]) as Assets; + const allAssets = mergeSum(...assetStores, ALL_ZERO_ASSETS); if (verbose) log.debug(`${this.room.print} assets: ` + JSON.stringify(allAssets)); return allAssets; diff --git a/src/Overseer.ts b/src/Overseer.ts index c1db8c5d8..0bc0cc9df 100644 --- a/src/Overseer.ts +++ b/src/Overseer.ts @@ -184,8 +184,8 @@ export class Overseer implements IOverseer { } // Place a logistics request directive for every tombstone with non-empty store that isn't on a container for (const tombstone of colony.tombstones) { - if (_.sum(tombstone.store) > LogisticsNetwork.settings.droppedEnergyThreshold - || _.sum(tombstone.store) > tombstone.store.energy) { + if (tombstone.store.getUsedCapacity() > LogisticsNetwork.settings.droppedEnergyThreshold + || tombstone.store.getUsedCapacity() > tombstone.store.energy) { if (colony.bunker && tombstone.pos.isEqualTo(colony.bunker.anchor)) continue; colony.logisticsNetwork.requestOutput(tombstone, {resourceType: 'all'}); } diff --git a/src/declarations/index.d.ts b/src/declarations/index.d.ts index 51b024a8a..cfa491cc0 100644 --- a/src/declarations/index.d.ts +++ b/src/declarations/index.d.ts @@ -331,7 +331,7 @@ type TransferrableStoreStructure = | StructureTerminal | StructureTower; -// interface StoreLike { -// [resourceType: string]: number -// } +type StoreContentsArray = [resourceType: ResourceConstant, amount: number][]; +type StoreContents = { [resourceType in ResourceConstant]: number }; +type DropContents = { [resourceType in ResourceConstant]: Resource[] }; diff --git a/src/declarations/prototypes.d.ts b/src/declarations/prototypes.d.ts index 67515e0bd..aef08a3cf 100644 --- a/src/declarations/prototypes.d.ts +++ b/src/declarations/prototypes.d.ts @@ -220,12 +220,21 @@ interface Structure { isWalkable: boolean; } -interface StructureContainer { +interface StoreBase { + contents: StoreContentsArray; +} + +interface _StoreLike { energy: number; isFull: boolean; isEmpty: boolean; } +interface StructureContainer extends _StoreLike {} +interface StructureExtension extends _StoreLike {} +interface StructureLink extends _StoreLike {} +interface StructureStorage extends _StoreLike {} + interface StructureController { reservedByMe: boolean; signedByMe: boolean; @@ -234,46 +243,16 @@ interface StructureController { needsReserving(reserveBuffer: number): boolean; } -interface StructureExtension { - isFull: boolean; - isEmpty: boolean; -} - -interface StructureLink { - isFull: boolean; - isEmpty: boolean; - storeCapacity: number; -} - -interface StructureStorage { - energy: number; - isFull: boolean; - isEmpty: boolean; -} - -interface Store { - contents: [ResourceConstant, number][]; -} - -interface StructureSpawn { - isFull: boolean; - isEmpty: boolean; - +interface StructureSpawn extends _StoreLike { cost(bodyArray: string[]): number; } -interface StructureTerminal { - energy: any; - isFull: boolean; - isEmpty: boolean; +interface StructureTerminal extends _StoreLike { isReady: boolean; hasReceived: boolean; } -interface StructureTower { - isFull: boolean; - isEmpty: boolean; - +interface StructureTower extends _StoreLike { // run(): void; // // attackNearestEnemy(): number; diff --git a/src/deprecated/TerminalNetwork.ts b/src/deprecated/TerminalNetwork.ts index a60f360b1..54142a8c8 100644 --- a/src/deprecated/TerminalNetwork.ts +++ b/src/deprecated/TerminalNetwork.ts @@ -117,7 +117,7 @@ export class TerminalNetwork /*implements ITerminalNetwork*/ { this.exceptionTerminals = {}; // populated in init() this.assets = {}; // populated in init() this.notifications = []; - this.averageFullness = _.sum(this.terminals, t => _.sum(t.store) / t.storeCapacity) / this.terminals.length; + this.averageFullness = _.sum(this.terminals, t => t.store.getUsedCapacity() / t.store.getCapacity()) / this.terminals.length; } refresh(): void { @@ -131,13 +131,13 @@ export class TerminalNetwork /*implements ITerminalNetwork*/ { this.exceptionTerminals = {}; // populated in init() this.assets = {}; // populated in init() this.notifications = []; - this.averageFullness = _.sum(this.terminals, t => _.sum(t.store) / t.storeCapacity) / this.terminals.length; + this.averageFullness = _.sum(this.terminals, t => t.store.getUsedCapacity() / t.store.getCapacity()) / this.terminals.length; } /* Summarizes the total of all resources currently in a colony store structure */ private getAllAssets(): { [resourceType: string]: number } { - return mergeSum(_.map(this.terminals, terminal => - (colonyOf(terminal) != undefined ? colonyOf(terminal).assets : {}))); + const p = _.map(this.terminals, terminal => (!!colonyOf(terminal) ? colonyOf(terminal).assets : {})); + return mergeSum(...p); } private logTransfer(resourceType: ResourceConstant, amount: number, origin: string, destination: string) { @@ -174,10 +174,10 @@ export class TerminalNetwork /*implements ITerminalNetwork*/ { private remainingRoomCapacity(room: Room): number { let remainingCapacity = 0; if (room.storage) { - remainingCapacity += room.storage.storeCapacity - _.sum(room.storage.store); + remainingCapacity += room.storage.store.getFreeCapacity(); } if (room.terminal) { - remainingCapacity += room.terminal.storeCapacity - _.sum(room.terminal.store); + remainingCapacity += room.terminal.store.getFreeCapacity(); } return remainingCapacity; } @@ -362,7 +362,7 @@ export class TerminalNetwork /*implements ITerminalNetwork*/ { sendAmount = Math.floor(Math.max(sendAmount, 0)); const sendCost = Game.market.calcTransactionCost(sendAmount, sender.room.name, receiver.room.name); sendAmount = Math.min(sendAmount, (sender.store[resourceType] || 0) - sendCost - 10, - (receiver.storeCapacity - _.sum(receiver.store))); + (receiver.store.getFreeCapacity())); if (sendAmount < TERMINAL_MIN_SEND) { if (verbose) log.debug(` Size too small`); @@ -437,7 +437,7 @@ export class TerminalNetwork /*implements ITerminalNetwork*/ { // Terminal output state - push resources away from this colony if (state.type == 'out' || state.type == 'in/out') { if (terminal.cooldown == 0 && amount > targetAmount + tolerance) { - const receiver = minBy(this.terminals, t => _.sum(t.store)); + const receiver = minBy(this.terminals, t => t.store.getUsedCapacity()); if (receiver) { let sendAmount: number; if (resource == RESOURCE_ENERGY) { @@ -446,7 +446,7 @@ export class TerminalNetwork /*implements ITerminalNetwork*/ { } else { sendAmount = minMax(amount - targetAmount, TERMINAL_MIN_SEND, maxSendSize); } - if (receiver.storeCapacity - _.sum(receiver.store) > sendAmount) { + if (receiver.store.getFreeCapacity() >= sendAmount) { this.transfer(terminal, receiver, resource, sendAmount, 'exception state out'); return; } diff --git a/src/directives/colony/poisonRoom.ts b/src/directives/colony/poisonRoom.ts index 316cbe4da..c7a2323d2 100644 --- a/src/directives/colony/poisonRoom.ts +++ b/src/directives/colony/poisonRoom.ts @@ -138,7 +138,7 @@ export class DirectivePoisonRoom extends Directive { } // Don't lock off the last position unless there's a creep with energy to build the site const enoughEnergyToBuildFinalWall = _.any(this.overlords.roomPoisoner.roomPoisoners, - creep => creep.carry.energy >= BUILD_POWER); + creep => creep.store.energy >= BUILD_POWER); if (this.blockPositions.length == 1 && !enoughEnergyToBuildFinalWall) { return; } diff --git a/src/directives/logistics/drop.ts b/src/directives/logistics/drop.ts index fc424510a..501bc8016 100644 --- a/src/directives/logistics/drop.ts +++ b/src/directives/logistics/drop.ts @@ -19,8 +19,8 @@ export class DirectiveDrop extends Directive { static color = COLOR_GREEN; static secondaryColor = COLOR_GREEN; - private _store: StoreDefinition; - private _drops: { [resourceType: string]: Resource[] }; + private _store: StoreDefinition | undefined; + private _drops: DropContents; memory: DirectiveDropMemory; @@ -37,24 +37,24 @@ export class DirectiveDrop extends Directive { return Overmind.cache.targets[this.ref]; } - private get drops(): { [resourceType: string]: Resource[] } { + private get drops(): DropContents { if (!this.pos.isVisible) { - return {}; + return {} as DropContents; } if (!this._drops) { - const drops = (this.pos.lookFor(LOOK_RESOURCES) || []) as Resource[]; - this._drops = _.groupBy(drops, drop => drop.resourceType); + const drops = this.pos.lookFor(LOOK_RESOURCES); + this._drops = _.groupBy(drops, drop => drop.resourceType) as DropContents; } return this._drops; } - get store(): { [resource: string]: number } { + get store() { if (!this._store) { // Merge the "storage" of drops with the store of structure - const store: { [resourceType: string]: number } = {energy: 0}; + const store: StoreDefinition = { energy: 0 } as StoreDefinition; // Merge with drops - for (const resourceType of _.keys(this.drops)) { - const totalResourceAmount = _.sum(this.drops[resourceType], drop => drop.amount); + for (const resourceType of _.keys(this.drops) as ResourceConstant[]) { + const totalResourceAmount = _.sum(this.drops[resourceType]!, drop => drop.amount); if (store[resourceType]) { store[resourceType] += totalResourceAmount; } else { @@ -80,7 +80,7 @@ export class DirectiveDrop extends Directive { init(): void { this.registerEnergyRequests(); - this.alert(`Drop directive active - ${_.sum(this.store)}`); + this.alert(`Drop directive active - ${_.sum(this.store as StoreContents)}`); } run(): void { diff --git a/src/directives/resource/haul.ts b/src/directives/resource/haul.ts index df36e3038..e1441e18d 100644 --- a/src/directives/resource/haul.ts +++ b/src/directives/resource/haul.ts @@ -26,8 +26,8 @@ export class DirectiveHaul extends Directive { static color = COLOR_YELLOW; static secondaryColor = COLOR_BLUE; - private _store: StoreDefinition; - private _drops: { [resourceType: string]: Resource[] }; + private _store: StoreContents | undefined; + private _drops: DropContents; private _finishAtTime: number; memory: DirectiveHaulMemory; @@ -44,13 +44,13 @@ export class DirectiveHaul extends Directive { return Overmind.cache.targets[this.ref]; } - get drops(): { [resourceType: string]: Resource[] } { + get drops(): DropContents { if (!this.pos.isVisible) { - return {}; + return {}; } if (!this._drops) { const drops = (this.pos.lookFor(LOOK_RESOURCES) || []) as Resource[]; - this._drops = _.groupBy(drops, drop => drop.resourceType); + this._drops = _.groupBy(drops, drop => drop.resourceType); } return this._drops; } @@ -67,30 +67,30 @@ export class DirectiveHaul extends Directive { this.pos.lookForStructure(STRUCTURE_TERMINAL) || this.pos.lookForStructure(STRUCTURE_NUKER) || this.pos.lookForStructure(STRUCTURE_CONTAINER) || - this.pos.lookFor(LOOK_RUINS).filter(ruin => _.sum(ruin.store) > 0)[0]; + this.pos.lookFor(LOOK_RUINS).filter(ruin => ruin.store.getUsedCapacity() > 0)[0]; } return undefined; } - get store(): { [resource: string]: number } { + get store(): StoreContents { if (!this._store) { // Merge the "storage" of drops with the store of structure - let store: { [resourceType: string]: number } = {}; + let store = {}; if (this.storeStructure) { store = this.storeStructure.store; } else { - store = {energy: 0}; + store = {energy: 0}; } // Merge with drops - for (const resourceType of _.keys(this.drops)) { - const totalResourceAmount = _.sum(this.drops[resourceType], drop => drop.amount); + for (const resourceType of (_.keys(this.drops) as ResourceConstant[])) { + const totalResourceAmount = _.sum(this.drops[resourceType] as Resource[], drop => drop.amount); if (store[resourceType]) { store[resourceType] += totalResourceAmount; } else { store[resourceType] = totalResourceAmount; } } - this._store = store as StoreDefinition; + this._store = store; } // log.alert(`Haul directive ${this.print} has store of ${JSON.stringify(this._store)}`); return this._store; diff --git a/src/directives/situational/stronghold.ts b/src/directives/situational/stronghold.ts index 050cdfd50..8da402cf1 100644 --- a/src/directives/situational/stronghold.ts +++ b/src/directives/situational/stronghold.ts @@ -88,10 +88,10 @@ export class DirectiveStronghold extends Directive { const ruins = this.room.ruins; if (containers) { returns = returns.concat(containers.filter(container => - container.pos.getRangeTo(this.pos) < 5 && _.sum(container.store) > 0)); + container.pos.getRangeTo(this.pos) < 5 && container.store.getUsedCapacity() > 0)); } if (ruins) { - returns = returns.concat(ruins.filter(ruin => ruin.pos.getRangeTo(this.pos) <= 3 && _.sum(ruin.store) > 0)); + returns = returns.concat(ruins.filter(ruin => ruin.pos.getRangeTo(this.pos) <= 3 && ruin.store.getUsedCapacity() > 0)); } return returns; } diff --git a/src/hiveClusters/commandCenter.ts b/src/hiveClusters/commandCenter.ts index 950345f78..2e5eb0c5b 100644 --- a/src/hiveClusters/commandCenter.ts +++ b/src/hiveClusters/commandCenter.ts @@ -238,13 +238,13 @@ export class CommandCenter extends HiveCluster { y = titleCoords.y + 0.25; if (this.storage) { Visualizer.text('Storage', {x: boxX, y: y, roomName: this.room.name}); - Visualizer.barGraph(_.sum(this.storage.store) / this.storage.storeCapacity, + Visualizer.barGraph(this.storage.store.getUsedCapacity() / this.storage.store.getCapacity(), {x: boxX + 4, y: y, roomName: this.room.name}, 5); y += 1; } if (this.terminal) { Visualizer.text('Terminal', {x: boxX, y: y, roomName: this.room.name}); - Visualizer.barGraph(_.sum(this.terminal.store) / this.terminal.storeCapacity, + Visualizer.barGraph(this.terminal.store.getUsedCapacity() / this.terminal.store.getCapacity(), {x: boxX + 4, y: y, roomName: this.room.name}, 5); y += 1; } diff --git a/src/hiveClusters/evolutionChamber.ts b/src/hiveClusters/evolutionChamber.ts index 92294430b..df8816eb7 100644 --- a/src/hiveClusters/evolutionChamber.ts +++ b/src/hiveClusters/evolutionChamber.ts @@ -485,7 +485,7 @@ export class EvolutionChamber extends HiveCluster { } const amountNeeded = this.neededBoosts[boost] + amountUnavailable; - if (amountNeeded > this.colony.assets[boost]) { + if (amountNeeded > this.colony.assets[boost]) { this.debug(`Requesting boost from terminal network: ${this.neededBoosts[boost]} ${boost}`); this.terminalNetwork.requestResource(this.colony, boost, amountNeeded); } else { diff --git a/src/hiveClusters/sporeCrawler.ts b/src/hiveClusters/sporeCrawler.ts index 20c629f8e..f6fba05d0 100644 --- a/src/hiveClusters/sporeCrawler.ts +++ b/src/hiveClusters/sporeCrawler.ts @@ -40,8 +40,8 @@ export class SporeCrawler extends HiveCluster { private registerEnergyRequests() { // Request energy from transporters if below request threshold for (const tower of this.towers) { - if (tower.energy < SporeCrawler.settings.requestThreshold) { - const multiplier = tower.energy < SporeCrawler.settings.criticalEnergyThreshold ? 2 : 1; + if (tower.store[RESOURCE_ENERGY] < SporeCrawler.settings.requestThreshold) { + const multiplier = tower.store[RESOURCE_ENERGY] < SporeCrawler.settings.criticalEnergyThreshold ? 2 : 1; const dAmountdt = this.room.hostiles.length > 0 ? 10 : 0; this.colony.logisticsNetwork.requestInput(tower, {multiplier: multiplier, dAmountdt: dAmountdt}); } diff --git a/src/logistics/Energetics.ts b/src/logistics/Energetics.ts index fb1b46cae..1fe192f24 100644 --- a/src/logistics/Energetics.ts +++ b/src/logistics/Energetics.ts @@ -32,8 +32,8 @@ export class Energetics { static lowPowerMode(colony: Colony): boolean { if (colony.stage == ColonyStage.Adult) { - if (_.sum(colony.storage!.store) > this.settings.storage.total.cap && - colony.terminal && _.sum(colony.terminal.store) > this.settings.terminal.total.cap) { + if (colony.storage!.store.getUsedCapacity() > this.settings.storage.total.cap && + colony.terminal && colony.terminal.store.getUsedCapacity() > this.settings.terminal.total.cap) { return true; } } diff --git a/src/logistics/LogisticsNetwork.ts b/src/logistics/LogisticsNetwork.ts index 51a8df45e..a7abbeb8d 100644 --- a/src/logistics/LogisticsNetwork.ts +++ b/src/logistics/LogisticsNetwork.ts @@ -84,7 +84,7 @@ export class LogisticsNetwork { // private logisticPositions: { [roomName: string]: RoomPosition[] }; private cache: { nextAvailability: { [transporterName: string]: [number, RoomPosition] }, - predictedTransporterCarry: { [transporterName: string]: { [resourceType: string]: number } }, + predictedTransporterCarry: { [transporterName: string]: StoreContents }, resourceChangeRate: { [requestID: string]: { [transporterName: string]: number } }, }; static settings = { @@ -172,7 +172,7 @@ export class LogisticsNetwork { dAmountdt : 0, }); if (opts.resourceType == 'all' && !isResource(target)) { - if (_.sum(target.store) == target.store.energy) { + if (target.store.getUsedCapacity() == target.store[RESOURCE_ENERGY]) { opts.resourceType = RESOURCE_ENERGY; // convert "all" requests to energy if that's all they have } } @@ -366,27 +366,25 @@ export class LogisticsNetwork { * Returns the predicted state of the transporter's carry after completing its current task */ private computePredictedTransporterCarry(transporter: Zerg, - nextAvailability?: [number, RoomPosition]): { - [resourceType: string]: number - } { + nextAvailability?: [number, RoomPosition]): StoreContents { if (transporter.task && transporter.task.target) { const requestID = this.targetToRequest[transporter.task.target.ref]; if (requestID) { const request = this.requests[requestID]; if (request) { - const carry = transporter.carry as { [resourceType: string]: number }; - const remainingCapacity = transporter.carryCapacity - _.sum(carry); + const carry = transporter.store; + const remainingCapacity = carry.getFreeCapacity() const resourceAmount = -1 * this.predictedRequestAmount(transporter, request, nextAvailability); // ^ need to multiply amount by -1 since transporter is doing complement of what request needs if (request.resourceType == 'all') { if (isResource(request.target)) { log.error(ALL_RESOURCE_TYPE_ERROR); - return {energy: 0} as StoreDefinition; + return {energy: 0}; } for (const [resourceType, storeAmt] of request.target.store.contents) { - const resourceFraction = storeAmt / _.sum(request.target.store); + const resourceFraction = storeAmt / (request.target.store.getUsedCapacity(resourceType) || storeAmt); if (carry[resourceType]) { - carry[resourceType]! += resourceAmount * resourceFraction; + carry[resourceType] += resourceAmount * resourceFraction; carry[resourceType] = minMax(carry[resourceType]!, 0, remainingCapacity); } else { carry[resourceType] = minMax(resourceAmount, 0, remainingCapacity); @@ -400,17 +398,17 @@ export class LogisticsNetwork { carry[request.resourceType] = minMax(resourceAmount, 0, remainingCapacity); } } - return carry as StoreDefinition; + return carry; } } } - return transporter.carry; + return transporter.store; } /** * Returns the predicted state of the transporter's carry after completing its task */ - private predictedTransporterCarry(transporter: Zerg): { [resourceType: string]: number } { + private predictedTransporterCarry(transporter: Zerg): StoreContents { if (!this.cache.predictedTransporterCarry[transporter.name]) { this.cache.predictedTransporterCarry[transporter.name] = this.computePredictedTransporterCarry(transporter); } @@ -452,7 +450,7 @@ export class LogisticsNetwork { } // TODO: this is incorrect; should incorporate request amount const resourceInflux = _.sum(_.map(otherTargetingTransporters, - other => (other.carry[request.resourceType] || 0))); + other => (other.store[request.resourceType] || 0))); predictedAmount = Math.max(predictedAmount - resourceInflux, 0); return predictedAmount; } else { // output state, resources withdrawn from target @@ -467,7 +465,7 @@ export class LogisticsNetwork { predictedAmount = minMax(predictedAmount, -1 * request.target.store.getCapacity(request.resourceType), 0); } const resourceOutflux = _.sum(_.map(otherTargetingTransporters, - other => other.carryCapacity - _.sum(other.carry))); + other => other.store.getCapacity() - other.store.getUsedCapacity())); predictedAmount = Math.min(predictedAmount + resourceOutflux, 0); return predictedAmount; } @@ -486,13 +484,13 @@ export class LogisticsNetwork { const [ticksUntilFree, newPos] = this.nextAvailability(transporter); const choices: { dQ: number, dt: number, targetRef: string }[] = []; const amount = this.predictedRequestAmount(transporter, request, [ticksUntilFree, newPos]); - let carry: { [resourceType: string]: number }; + let carry: StoreContents; if (!transporter.task || transporter.task.target != request.target) { // If you are not targeting the requestor, use predicted carry after completing current task carry = this.predictedTransporterCarry(transporter); } else { // If you are targeting the requestor, use current carry for computations - carry = transporter.carry; + carry = transporter.store; } // requestInput instance, needs refilling @@ -511,12 +509,12 @@ export class LogisticsNetwork { dt : dt_direct, targetRef: request.target.ref }); - if ((carry[request.resourceType] || 0) > amount || _.sum(carry) == transporter.carryCapacity) { + if ((carry[request.resourceType] || 0) > amount || _.sum(carry) == transporter.store.getCapacity()) { return choices; // Return early if you already have enough resources to go direct or are already full } // Change in resources if transporter picks up resources from a buffer first for (const buffer of this.buffers) { - const dQ_buffer = Math.min(amount, transporter.carryCapacity, buffer.store[request.resourceType] || 0); + const dQ_buffer = Math.min(amount, transporter.store.getCapacity(), buffer.store[request.resourceType] || 0); const dt_buffer = newPos.getMultiRoomRangeTo(buffer.pos) * LogisticsNetwork.settings.rangeToPathHeuristic + (Pathing.distance(buffer.pos, request.target.pos) || Infinity) + ticksUntilFree; choices.push({ @@ -530,7 +528,7 @@ export class LogisticsNetwork { // requestOutput instance, needs pickup else if (amount < 0) { // Change in resources if transporter goes straight to the output - const remainingCarryCapacity = transporter.carryCapacity - _.sum(carry); + const remainingCarryCapacity = transporter.store.getCapacity() - _.sum(carry); const dQ_direct = Math.min(Math.abs(amount), remainingCarryCapacity); const dt_direct = newPos.getMultiRoomRangeTo(request.target.pos) * LogisticsNetwork.settings.rangeToPathHeuristic + ticksUntilFree; @@ -539,13 +537,13 @@ export class LogisticsNetwork { dt : dt_direct, targetRef: request.target.ref }); - if (remainingCarryCapacity >= Math.abs(amount) || remainingCarryCapacity == transporter.carryCapacity) { + if (remainingCarryCapacity >= Math.abs(amount) || remainingCarryCapacity == transporter.store.getCapacity()) { return choices; // Return early you have sufficient free space or are empty } // Change in resources if transporter drops off resources at a buffer first for (const buffer of this.buffers) { - const dQ_buffer = Math.min(Math.abs(amount), transporter.carryCapacity, - buffer.storeCapacity - _.sum(buffer.store)); + const dQ_buffer = Math.min(Math.abs(amount), transporter.store.getCapacity(), + buffer.store.getFreeCapacity()); const dt_buffer = newPos.getMultiRoomRangeTo(buffer.pos) * LogisticsNetwork.settings.rangeToPathHeuristic + (Pathing.distance(buffer.pos, request.target.pos) || Infinity) + ticksUntilFree; choices.push({ @@ -668,7 +666,7 @@ export class LogisticsNetwork { } else { if (request.resourceType == 'all') { if (!isResource(request.target)) { - amount = _.sum(request.target.store); + amount = request.target.store.getUsedCapacity() || 0; } else { amount = -0.001; } diff --git a/src/logistics/RoadLogistics.ts b/src/logistics/RoadLogistics.ts index b08f41252..af9980f03 100644 --- a/src/logistics/RoadLogistics.ts +++ b/src/logistics/RoadLogistics.ts @@ -47,7 +47,7 @@ export class RoadLogistics { return this.repairableRoads(room).length > 0; } else { // If worker is not already assigned, repair if critical roads or repaving energy >= carry capacity - return this.criticalRoads(room).length > 0 || this.energyToRepave(room.name) >= worker.carryCapacity; + return this.criticalRoads(room).length > 0 || this.energyToRepave(room.name) >= worker.store.getCapacity(); } } else { return false; @@ -164,7 +164,7 @@ export class RoadLogistics { } buildPavingManifest(worker: Zerg, room: Room): Task | null { - let energy = worker.carry.energy; + let energy = worker.store.energy; const targetRefs: { [ref: string]: boolean } = {}; const tasks: Task[] = []; let target: StructureRoad | undefined; diff --git a/src/logistics/TerminalNetwork_v2.ts b/src/logistics/TerminalNetwork_v2.ts index f04e92eed..fe6fff76f 100644 --- a/src/logistics/TerminalNetwork_v2.ts +++ b/src/logistics/TerminalNetwork_v2.ts @@ -302,7 +302,7 @@ export class TerminalNetworkV2 implements ITerminalNetwork { private passiveRequestors: { [resourceType: string]: Colony[] }; private activeRequestors: { [resourceType: string]: Colony[] }; - private assets: { [resourceType: string]: number }; + private assets: StoreContents; private notifications: string[]; private memory: TerminalNetworkMemory; @@ -342,7 +342,7 @@ export class TerminalNetworkV2 implements ITerminalNetwork { this.passiveRequestors = {}; // _.clone(EMPTY_COLONY_TIER); this.activeRequestors = {}; // _.clone(EMPTY_COLONY_TIER); - this.assets = {}; // populated when getAssets() is called in init() + this.assets = {}; // populated when getAssets() is called in init() this.terminalOverload = {}; this.notifications = []; @@ -367,9 +367,9 @@ export class TerminalNetworkV2 implements ITerminalNetwork { } } - getAssets(): { [resourceType: string]: number } { + getAssets(): StoreContents { if (_.isEmpty(this.assets)) { - this.assets = mergeSum(_.map(this.colonies, colony => colony.assets)); + this.assets = mergeSum(..._.map(this.colonies, colony => colony.assets)); } return this.assets; } @@ -422,8 +422,8 @@ export class TerminalNetworkV2 implements ITerminalNetwork { private getRemainingSpace(colony: Colony, includeFactoryCapacity = false): number { let totalAssets = _.sum(colony.assets); // Overfilled storage gets counted as just 100% full - if (colony.storage && _.sum(colony.storage.store) > STORAGE_CAPACITY) { - totalAssets -= (_.sum(colony.storage.store) - STORAGE_CAPACITY); + if (colony.storage && colony.storage.store.getUsedCapacity() > STORAGE_CAPACITY) { + totalAssets -= (colony.storage.store.getUsedCapacity() - STORAGE_CAPACITY); } const roomCapacity = (colony.terminal ? TERMINAL_CAPACITY : 0) + @@ -1205,7 +1205,7 @@ export class TerminalNetworkV2 implements ITerminalNetwork { `${colony.print} actively requesting ----------------------------------------------------\n` + `${bullet}${activeRequestors[colony.name] || '(None)'}\n`; } else { - const resource = resourceOrColony || undefined; + const resource = resourceOrColony || undefined; if (resource) { info += `Active providers for ${resource} -----------------------------------------------------\n` + `${bullet}${_.map(this.activeProviders[resource], col => diff --git a/src/overlords/colonization/pioneer.ts b/src/overlords/colonization/pioneer.ts index d08bd3641..3b77378c5 100644 --- a/src/overlords/colonization/pioneer.ts +++ b/src/overlords/colonization/pioneer.ts @@ -57,7 +57,7 @@ export class PioneerOverlord extends Overlord { } } // Build and recharge - if (pioneer.carry.energy == 0) { + if (pioneer.store.energy == 0) { pioneer.task = Tasks.recharge(); } else if (this.room && this.room.controller && (this.room.controller.ticksToDowngrade < (0.1 * CONTROLLER_DOWNGRADE[this.room.controller.level]) diff --git a/src/overlords/colonization/roomPoisoner.ts b/src/overlords/colonization/roomPoisoner.ts index ddee7c6a0..69fb24e22 100644 --- a/src/overlords/colonization/roomPoisoner.ts +++ b/src/overlords/colonization/roomPoisoner.ts @@ -45,7 +45,7 @@ export class RoomPoisonerOverlord extends Overlord { private handleRoomPoisoner(posioner: Zerg): void { // Recharge if needed - if (posioner.carry.energy < BUILD_POWER) { + if (posioner.store.energy < BUILD_POWER) { posioner.task = Tasks.recharge(); return; } diff --git a/src/overlords/core/manager.ts b/src/overlords/core/manager.ts index d38345a96..69e7804ea 100644 --- a/src/overlords/core/manager.ts +++ b/src/overlords/core/manager.ts @@ -136,7 +136,7 @@ export class CommandCenterOverlord extends Overlord { if (manager.store.getUsedCapacity() == 0) { return false; } else { - manager.debug(`Unloading carry: ${JSON.stringify(manager.carry)}`); + manager.debug(`Unloading carry: ${JSON.stringify(manager.store)}`); manager.task = Tasks.transferAll(this.commandCenter.storage); // placeholder solution return true; } @@ -150,7 +150,7 @@ export class CommandCenterOverlord extends Overlord { manager.debug('supplyActions'); const request = this.commandCenter.transportRequests.getPrioritizedClosestRequest(manager.pos, 'supply'); if (request) { - const amount = Math.min(request.amount, manager.carryCapacity); + const amount = Math.min(request.amount, manager.store.getCapacity()); const resource = request.resourceType; // If we have enough to fulfill the request, we're done if (manager.store[request.resourceType] >= amount) { @@ -254,7 +254,7 @@ export class CommandCenterOverlord extends Overlord { } const transferAmount = Math.min(terminal.store[resource] - target, storage.store.getFreeCapacity(resource), - manager.carryCapacity); + manager.store.getCapacity()); manager.task = Tasks.chain([Tasks.withdraw(terminal, resource, transferAmount), Tasks.transfer(storage, resource, transferAmount)]); // manager.debug(`Assigned task ${print(manager.task)}`) @@ -269,7 +269,7 @@ export class CommandCenterOverlord extends Overlord { } const transferAmount = Math.min(target - terminal.store[resource], storage.store[resource], - manager.carryCapacity); + manager.store.getCapacity()); manager.task = Tasks.chain([Tasks.withdraw(storage, resource, transferAmount), Tasks.transfer(terminal, resource, transferAmount)]); // manager.debug(`Assigned task ${print(manager.task)}`) @@ -543,7 +543,7 @@ export class CommandCenterOverlord extends Overlord { manager.debug('idleActions'); if (this.mode == 'bunker' && this.managerRepairTarget && manager.getActiveBodyparts(WORK) > 0) { // Repair ramparts when idle - if (manager.carry.energy > 0) { + if (manager.store.energy > 0) { manager.repair(this.managerRepairTarget); } else { const storage = this.commandCenter.storage; diff --git a/src/overlords/core/queen.ts b/src/overlords/core/queen.ts index 70bab04e2..d44f1a1f7 100644 --- a/src/overlords/core/queen.ts +++ b/src/overlords/core/queen.ts @@ -74,13 +74,13 @@ export class QueenOverlord extends Overlord { // Can energy be moved from the link to the battery? if (battery && !battery.isFull && !this.hatchery.link.isEmpty) { // Move energy to battery as needed - if (queen.carry.energy < queen.carryCapacity) { + if (queen.store.energy < queen.store.getCapacity()) { queen.task = Tasks.withdraw(this.hatchery.link); } else { queen.task = Tasks.transfer(battery); } } else { - if (queen.carry.energy < queen.carryCapacity) { // make sure you're recharged + if (queen.store.energy < queen.store.getCapacity()) { // make sure you're recharged if (!this.hatchery.link.isEmpty) { queen.task = Tasks.withdraw(this.hatchery.link); } else if (battery && !battery.isEmpty) { @@ -89,14 +89,14 @@ export class QueenOverlord extends Overlord { } } } else { - if (battery && queen.carry.energy < queen.carryCapacity) { + if (battery && queen.store.energy < queen.store.getCapacity()) { queen.task = Tasks.withdraw(battery); } } } private handleQueen(queen: Zerg): void { - if (queen.carry.energy > 0) { + if (queen.store.energy > 0) { this.supplyActions(queen); } else { this.rechargeActions(queen); diff --git a/src/overlords/core/queen_bunker.ts b/src/overlords/core/queen_bunker.ts index b3de194fc..7d3fda824 100644 --- a/src/overlords/core/queen_bunker.ts +++ b/src/overlords/core/queen_bunker.ts @@ -122,7 +122,7 @@ export class BunkerQueenOverlord extends Overlord { // Step 1: empty all contents (this shouldn't be necessary since queen is normally empty at this point) let queenPos = queen.pos; - if (_.sum(queen.carry) > 0) { + if (queen.store.getUsedCapacity() > 0) { const transferTarget = this.colony.terminal || this.colony.storage || this.batteries[0]; if (transferTarget) { tasks.push(Tasks.transferAll(transferTarget)); @@ -134,8 +134,9 @@ export class BunkerQueenOverlord extends Overlord { } // Step 2: figure out what you need to supply for and calculate the needed resources - const queenCarry = {} as { [resourceType: string]: number }; - const allStore = mergeSum(_.map(this.storeStructures, s => s.store)); + const queenCarry = {}; + const allStore = mergeSum(..._.map(this.storeStructures, s => s.store)); + const supplyRequests: TransportRequest[] = []; for (const priority in this.colony.transportRequests.supply) { for (const request of this.colony.transportRequests.supply[priority]) { @@ -147,7 +148,7 @@ export class BunkerQueenOverlord extends Overlord { const supplyTasks: Task[] = []; for (const request of supplyRequests) { // stop when carry will be full - const remainingAmount = queen.carryCapacity - _.sum(queenCarry); + const remainingAmount = queen.store.getCapacity() - _.sum(queenCarry); if (remainingAmount == 0) break; // figure out how much you can withdraw let amount = Math.min(request.amount, remainingAmount); @@ -219,7 +220,7 @@ export class BunkerQueenOverlord extends Overlord { const tasks: Task[] = []; const transferTarget = this.colony.terminal || this.colony.storage || this.batteries[0]; // Step 1: empty all contents (this shouldn't be necessary since queen is normally empty at this point) - if (_.sum(queen.carry) > 0) { + if (queen.store.getUsedCapacity() > 0) { if (transferTarget) { tasks.push(Tasks.transferAll(transferTarget)); } else { @@ -241,7 +242,7 @@ export class BunkerQueenOverlord extends Overlord { } for (const request of withdrawRequests) { // stop when carry will be full - const remainingAmount = queen.carryCapacity - _.sum(queenCarry); + const remainingAmount = queen.store.getCapacity() - _.sum(queenCarry); if (remainingAmount == 0) break; // figure out how much you can withdraw const amount = Math.min(request.amount, remainingAmount); @@ -317,7 +318,7 @@ export class BunkerQueenOverlord extends Overlord { // Do we need safemodes? else if (this.colony.level > 5 && this.colony.controller.safeModeAvailable < 3 && this.colony.terminal && this.colony.terminal.store[RESOURCE_GHODIUM] >= 1000 && - queen.carryCapacity >= 1000) { + queen.store.getCapacity() >= 1000) { // Only use 1 queen to avoid adding 2 safemodes if (queen.name == _.first(_.sortBy(this.queens, q => q.name)).name) { queen.task = Tasks.chain([ diff --git a/src/overlords/core/transporter.ts b/src/overlords/core/transporter.ts index 1a7cecbda..d0722388d 100644 --- a/src/overlords/core/transporter.ts +++ b/src/overlords/core/transporter.ts @@ -120,7 +120,7 @@ export class TransportOverlord extends Overlord { // If we need to go to a buffer first to get more stuff const buffer = deref(bestChoice.targetRef) as BufferTarget; const withdrawAmount = Math.min(buffer.store[request.resourceType] || 0, - transporter.carryCapacity - _.sum(transporter.carry), amount); + transporter.store.getFreeCapacity(request.resourceType), amount); task = task.fork(Tasks.withdraw(buffer, request.resourceType, withdrawAmount)); if (transporter.hasMineralsInCarry && request.resourceType == RESOURCE_ENERGY) { task = task.fork(Tasks.transferAll(buffer)); @@ -162,7 +162,7 @@ export class TransportOverlord extends Overlord { this.colony.logisticsNetwork.invalidateCache(transporter, request); } else { // If nothing to do, put everything in a store structure - if (_.sum(transporter.carry) > 0) { + if (transporter.store.getUsedCapacity() > 0) { if (transporter.hasMineralsInCarry) { const target = this.colony.terminal || this.colony.storage; if (target) { diff --git a/src/overlords/core/upgrader.ts b/src/overlords/core/upgrader.ts index 5891c3d0c..6bc052fe8 100644 --- a/src/overlords/core/upgrader.ts +++ b/src/overlords/core/upgrader.ts @@ -51,7 +51,7 @@ export class UpgradingOverlord extends Overlord { } private handleUpgrader(upgrader: Zerg): void { - if (upgrader.carry.energy > 0) { + if (upgrader.store.energy > 0) { // Repair link if (this.upgradeSite.link && this.upgradeSite.link.hits < this.upgradeSite.link.hitsMax) { upgrader.task = Tasks.repair(this.upgradeSite.link); diff --git a/src/overlords/core/worker.ts b/src/overlords/core/worker.ts index b5e47fa0a..e0c0fd88f 100644 --- a/src/overlords/core/worker.ts +++ b/src/overlords/core/worker.ts @@ -358,7 +358,7 @@ export class WorkerOverlord extends Overlord { } private handleWorker(worker: Zerg) { - if (worker.carry.energy > 0) { + if (worker.store.energy > 0) { // TODO Add high priority to block controller with ramparts/walls in case of downgrade attack // FIXME workers get stalled at controller in case of downgrade attack // Upgrade controller if close to downgrade or if getting controller attacked/was downgraded diff --git a/src/overlords/mining/miner.ts b/src/overlords/mining/miner.ts index 12605db98..0914d846f 100644 --- a/src/overlords/mining/miner.ts +++ b/src/overlords/mining/miner.ts @@ -306,7 +306,7 @@ export class MiningOverlord extends Overlord { if (this.container) { const transportCapacity = 200 * this.colony.level; const threshold = this.colony.stage > ColonyStage.Larva ? 0.8 : 0.5; - if (_.sum(this.container.store) > threshold * transportCapacity) { + if (this.container.store.getUsedCapacity() > threshold * transportCapacity) { this.colony.logisticsNetwork.requestOutput(this.container, { resourceType: 'all', dAmountdt : this.energyPerTick @@ -316,7 +316,7 @@ export class MiningOverlord extends Overlord { if (this.link) { // If the link will be full with next deposit from the miner const minerCapacity = 150; - if (this.link.energy + minerCapacity > this.link.energyCapacity) { + if (this.link.store.getUsedCapacity(RESOURCE_ENERGY) + minerCapacity > this.link.store.getCapacity(RESOURCE_ENERGY)) { this.colony.linkNetwork.requestTransmit(this.link); } } @@ -340,10 +340,10 @@ export class MiningOverlord extends Overlord { // Container mining if (this.container) { if (this.container.hits < this.container.hitsMax - && miner.carry.energy >= Math.min(miner.carryCapacity, REPAIR_POWER * miner.getActiveBodyparts(WORK))) { + && miner.store.energy >= Math.min(miner.store.getCapacity(), REPAIR_POWER * miner.getActiveBodyparts(WORK))) { return miner.goRepair(this.container); } else { - if (_.sum(miner.carry) < miner.carryCapacity) { + if (miner.store.getUsedCapacity(RESOURCE_ENERGY) < miner.store.getCapacity()) { return miner.goHarvest(this.source!); } else { return miner.goTransfer(this.container); @@ -353,7 +353,7 @@ export class MiningOverlord extends Overlord { // Build output site if (this.constructionSite) { - if (miner.carry.energy >= Math.min(miner.carryCapacity, BUILD_POWER * miner.getActiveBodyparts(WORK))) { + if (miner.store.energy >= Math.min(miner.store.getCapacity(), BUILD_POWER * miner.getActiveBodyparts(WORK))) { return miner.goBuild(this.constructionSite); } else { return miner.goHarvest(this.source!); @@ -363,7 +363,7 @@ export class MiningOverlord extends Overlord { // Drop mining if (this.allowDropMining) { miner.goHarvest(this.source!); - if (miner.carry.energy > 0.8 * miner.carryCapacity) { // try to drop on top of largest drop if full + if (miner.store.energy > 0.8 * miner.store.getCapacity()) { // try to drop on top of largest drop if full const biggestDrop = maxBy(miner.pos.findInRange(miner.room.droppedEnergy, 1), drop => drop.amount); if (biggestDrop) { miner.goDrop(biggestDrop.pos, RESOURCE_ENERGY); @@ -408,7 +408,7 @@ export class MiningOverlord extends Overlord { if (res == ERR_NOT_IN_RANGE) { // approach mining site if (this.goToMiningSite(miner)) return; } - if (miner.carry.energy > 0.9 * miner.carryCapacity) { + if (miner.store.energy > 0.9 * miner.store.getCapacity()) { miner.transfer(this.link, RESOURCE_ENERGY); } // If for whatever reason there's no reciever link, you can get stuck in a bootstrapping loop, so @@ -442,7 +442,7 @@ export class MiningOverlord extends Overlord { // Container mining if (this.container) { if (this.container.hits < this.container.hitsMax - && miner.carry.energy >= Math.min(miner.carryCapacity, REPAIR_POWER * miner.getActiveBodyparts(WORK))) { + && miner.store.energy >= Math.min(miner.store.getCapacity(), REPAIR_POWER * miner.getActiveBodyparts(WORK))) { return miner.repair(this.container); } else { return this.harvestOrSleep(miner, source); @@ -451,7 +451,7 @@ export class MiningOverlord extends Overlord { // Build output site if (this.constructionSite) { // standard miners won't have both a container and a construction site - if (miner.carry.energy >= Math.min(miner.carryCapacity, BUILD_POWER * miner.getActiveBodyparts(WORK))) { + if (miner.store.energy >= Math.min(miner.store.getCapacity(), BUILD_POWER * miner.getActiveBodyparts(WORK))) { return miner.build(this.constructionSite); } else { return this.harvestOrSleep(miner, source); @@ -461,13 +461,13 @@ export class MiningOverlord extends Overlord { // Drop mining if (this.allowDropMining) { this.harvestOrSleep(miner, source); - if (miner.carry.energy > 0.8 * miner.carryCapacity) { // move over the drop when you're close to full + if (miner.store.energy > 0.8 * miner.store.getCapacity()) { // move over the drop when you're close to full const biggestDrop = maxBy(miner.pos.findInRange(miner.room.droppedEnergy, 1), drop => drop.amount); if (biggestDrop) { miner.goTo(biggestDrop); } } - if (miner.carry.energy == miner.carryCapacity) { // drop when you are full + if (miner.store.energy == miner.store.getCapacity()) { // drop when you are full miner.drop(RESOURCE_ENERGY); } return; @@ -490,7 +490,7 @@ export class MiningOverlord extends Overlord { // Container mining if (this.container) { if (this.container.hits < this.container.hitsMax - && miner.carry.energy >= Math.min(miner.carryCapacity, REPAIR_POWER * miner.getActiveBodyparts(WORK))) { + && miner.store.energy >= Math.min(miner.store.getCapacity(), REPAIR_POWER * miner.getActiveBodyparts(WORK))) { return miner.repair(this.container); } else { return this.harvestOrSleep(miner, source); @@ -499,7 +499,7 @@ export class MiningOverlord extends Overlord { // Build output site if (this.constructionSite) { // standard miners won't have both a container and a construction site - if (miner.carry.energy >= Math.min(miner.carryCapacity, BUILD_POWER * miner.getActiveBodyparts(WORK))) { + if (miner.store.energy >= Math.min(miner.store.getCapacity(), BUILD_POWER * miner.getActiveBodyparts(WORK))) { return miner.build(this.constructionSite); } else { return this.harvestOrSleep(miner, source); @@ -509,13 +509,13 @@ export class MiningOverlord extends Overlord { // Drop mining if (this.allowDropMining) { this.harvestOrSleep(miner, source); - if (miner.carry.energy > 0.8 * miner.carryCapacity) { // move over the drop when you're close to full + if (miner.store.energy > 0.8 * miner.store.getCapacity()) { // move over the drop when you're close to full const biggestDrop = maxBy(miner.pos.findInRange(miner.room.droppedEnergy, 1), drop => drop.amount); if (biggestDrop) { miner.goTo(biggestDrop); } } - if (miner.carry.energy == miner.carryCapacity) { // drop when you are full + if (miner.store.energy == miner.store.getCapacity()) { // drop when you are full miner.drop(RESOURCE_ENERGY); } return; @@ -537,7 +537,7 @@ export class MiningOverlord extends Overlord { } else { miner.harvest(this.secondSource!); } - if (miner.carry.energy > 0.9 * miner.carryCapacity) { + if (miner.store.energy > 0.9 * miner.store.getCapacity()) { miner.transfer(this.link, RESOURCE_ENERGY); } return; @@ -548,7 +548,7 @@ export class MiningOverlord extends Overlord { // Container mining if (this.container) { if (this.container.hits < this.container.hitsMax - && miner.carry.energy >= Math.min(miner.carryCapacity, REPAIR_POWER * miner.getActiveBodyparts(WORK))) { + && miner.store.energy >= Math.min(miner.store.getCapacity(), REPAIR_POWER * miner.getActiveBodyparts(WORK))) { return miner.repair(this.container); } else if (this.source && this.source.energy > 0) { return miner.harvest(this.source!); @@ -559,7 +559,7 @@ export class MiningOverlord extends Overlord { // Build output site if (this.constructionSite) { - if (miner.carry.energy >= Math.min(miner.carryCapacity, BUILD_POWER * miner.getActiveBodyparts(WORK))) { + if (miner.store.energy >= Math.min(miner.store.getCapacity(), BUILD_POWER * miner.getActiveBodyparts(WORK))) { return miner.build(this.constructionSite); } else { return miner.harvest(this.source!); @@ -569,13 +569,13 @@ export class MiningOverlord extends Overlord { // Drop mining if (this.allowDropMining) { miner.harvest(this.source!); - if (miner.carry.energy > 0.8 * miner.carryCapacity) { // move over the drop when you're close to full + if (miner.store.energy > 0.8 * miner.store.getCapacity()) { // move over the drop when you're close to full const biggestDrop = maxBy(miner.pos.findInRange(miner.room.droppedEnergy, 1), drop => drop.amount); if (biggestDrop) { miner.goTo(biggestDrop); } } - if (miner.carry.energy == miner.carryCapacity) { // drop when you are full + if (miner.store.energy == miner.store.getCapacity()) { // drop when you are full miner.drop(RESOURCE_ENERGY); } return; diff --git a/src/overlords/powerMining/PowerHauler.ts b/src/overlords/powerMining/PowerHauler.ts index f9800e5c4..bea5921f6 100644 --- a/src/overlords/powerMining/PowerHauler.ts +++ b/src/overlords/powerMining/PowerHauler.ts @@ -45,7 +45,7 @@ export class PowerHaulingOverlord extends Overlord { } private handleHauler(hauler: Zerg) { - if (_.sum(hauler.carry) == 0) { + if (hauler.store.getUsedCapacity() === 0) { if (this.directive.memory.state >= 4) { // FIXME: Maybe ditch this and put it as a separate on-finishing method to reassign hauler.say('💀 RIP 💀', true); @@ -96,22 +96,22 @@ export class PowerHaulingOverlord extends Overlord { } else { // Travel to colony room and deposit resources if (hauler.inSameRoomAs(this.colony)) { - for (const [resourceType, amount] of hauler.carry.contents) { + for (const [resourceType, amount] of hauler.store.contents) { if (amount == 0) continue; if (resourceType == RESOURCE_ENERGY) { // prefer to put energy in storage - if (this.colony.storage && _.sum(this.colony.storage.store) < STORAGE_CAPACITY) { + if (this.colony.storage && this.colony.storage.store.getUsedCapacity() < STORAGE_CAPACITY) { hauler.task = Tasks.transfer(this.colony.storage, resourceType); return; - } else if (this.colony.terminal && _.sum(this.colony.terminal.store) < TERMINAL_CAPACITY) { + } else if (this.colony.terminal && this.colony.terminal.store.getUsedCapacity() < TERMINAL_CAPACITY) { hauler.task = Tasks.transfer(this.colony.terminal, resourceType); return; } } else { // prefer to put minerals in terminal - this.directive.memory.totalCollected += hauler.carry.power || 0; - if (this.colony.terminal && _.sum(this.colony.terminal.store) < TERMINAL_CAPACITY) { + this.directive.memory.totalCollected += hauler.store.power || 0; + if (this.colony.terminal && this.colony.terminal.store.getUsedCapacity() < TERMINAL_CAPACITY) { hauler.task = Tasks.transfer(this.colony.terminal, resourceType); return; - } else if (this.colony.storage && _.sum(this.colony.storage.store) < STORAGE_CAPACITY) { + } else if (this.colony.storage && this.colony.storage.store.getUsedCapacity() < STORAGE_CAPACITY) { hauler.task = Tasks.transfer(this.colony.storage, resourceType); return; } @@ -126,7 +126,7 @@ export class PowerHaulingOverlord extends Overlord { } checkIfStillCarryingPower() { - return _.find(this.haulers, hauler => hauler.carry.power != undefined && hauler.carry.power > 0); + return _.find(this.haulers, hauler => hauler.store.power != undefined && hauler.store.power > 0); } run() { diff --git a/src/overlords/situational/bootstrap.ts b/src/overlords/situational/bootstrap.ts index d51d759e0..72f2d56fa 100644 --- a/src/overlords/situational/bootstrap.ts +++ b/src/overlords/situational/bootstrap.ts @@ -134,7 +134,7 @@ export class BootstrappingOverlord extends Overlord { } private handleFiller(filler: Zerg) { - if (filler.carry.energy > 0) { + if (filler.store.energy > 0) { this.supplyActions(filler); } else { this.rechargeActions(filler); diff --git a/src/overlords/situational/hauler.ts b/src/overlords/situational/hauler.ts index 21e2c9e44..3d085d8be 100644 --- a/src/overlords/situational/hauler.ts +++ b/src/overlords/situational/hauler.ts @@ -28,7 +28,7 @@ export class HaulingOverlord extends Overlord { } init() { - if (!this.colony.storage || _.sum(this.colony.storage.store) > Energetics.settings.storage.total.cap) { + if (!this.colony.storage || this.colony.storage.store.getUsedCapacity() > Energetics.settings.storage.total.cap) { return; } // Spawn a number of haulers sufficient to move all resources within a lifetime, up to a max @@ -36,8 +36,8 @@ export class HaulingOverlord extends Overlord { // Calculate total needed amount of hauling power as (resource amount * trip distance) const tripDistance = 2 * (Pathing.distance((this.colony.storage || this.colony).pos, this.directive.pos) || 0); const haulingPowerNeeded = Math.min(this.directive.totalResources, - this.colony.storage.storeCapacity - - _.sum(this.colony.storage.store)) * tripDistance; + this.colony.storage.store.getCapacity() + - this.colony.storage.store.getUsedCapacity()) * tripDistance; // Calculate amount of hauling each hauler provides in a lifetime const haulerCarryParts = Setups.transporters.early.getBodyPotential(CARRY, this.colony); const haulingPowerPerLifetime = CREEP_LIFE_TIME * haulerCarryParts * CARRY_CAPACITY; @@ -48,7 +48,7 @@ export class HaulingOverlord extends Overlord { } private handleHauler(hauler: Zerg) { - if (_.sum(hauler.carry) == 0) { + if (hauler.store.getUsedCapacity() == 0) { // Travel to directive and collect resources if (hauler.inSameRoomAs(this.directive)) { // Pick up drops first @@ -64,7 +64,7 @@ export class HaulingOverlord extends Overlord { if (this.directive.storeStructure) { const store = this.directive.store!; let totalDrawn = 0; // Fill to full - for (const resourceType in store) { + for (const resourceType of Object.keys(store)) { if (store[resourceType] > 0) { if (hauler.task) { hauler.task = Tasks.withdraw(this.directive.storeStructure, resourceType).fork(hauler.task); @@ -72,7 +72,7 @@ export class HaulingOverlord extends Overlord { hauler.task = Tasks.withdraw(this.directive.storeStructure, resourceType); } totalDrawn += store[resourceType]; - if (totalDrawn >= hauler.carryCapacity) { + if (totalDrawn >= hauler.store.getCapacity()) { return; } } @@ -93,22 +93,22 @@ export class HaulingOverlord extends Overlord { // Travel to colony room and deposit resources if (hauler.inSameRoomAs(this.colony)) { // Put energy in storage and minerals in terminal if there is one - for (const [resourceType, amount] of hauler.carry.contents) { + for (const [resourceType, amount] of hauler.store.contents) { if (amount == 0) continue; if (resourceType == RESOURCE_ENERGY) { // prefer to put energy in storage - if (this.colony.storage && _.sum(this.colony.storage.store) < STORAGE_CAPACITY) { + if (this.colony.storage && this.colony.storage.store.getUsedCapacity() < STORAGE_CAPACITY) { hauler.task = Tasks.transfer(this.colony.storage, resourceType); return; - } else if (this.colony.terminal && _.sum(this.colony.terminal.store) < TERMINAL_CAPACITY) { + } else if (this.colony.terminal && this.colony.terminal.store.getUsedCapacity() < TERMINAL_CAPACITY) { hauler.task = Tasks.transfer(this.colony.terminal, resourceType); return; } } else { // prefer to put minerals in terminal if (this.colony.terminal && this.colony.terminal.my - && _.sum(this.colony.terminal.store) < TERMINAL_CAPACITY) { + && this.colony.terminal.store.getUsedCapacity() < TERMINAL_CAPACITY) { hauler.task = Tasks.transfer(this.colony.terminal, resourceType); return; - } else if (this.colony.storage && _.sum(this.colony.storage.store) < STORAGE_CAPACITY) { + } else if (this.colony.storage && this.colony.storage.store.getUsedCapacity() < STORAGE_CAPACITY) { hauler.task = Tasks.transfer(this.colony.storage, resourceType); return; } @@ -130,7 +130,7 @@ export class HaulingOverlord extends Overlord { hauler.run(); } // TODO: fix the way this is done - if (this.directive.memory.totalResources == 0 && this.haulers.filter(hauler => _.sum(hauler.carry) > 0).length == 0) { + if (this.directive.memory.totalResources == 0 && this.haulers.filter(hauler => hauler.store.getUsedCapacity() > 0).length == 0) { this.directive.remove(); } } diff --git a/src/overlords/situational/remoteUpgrader.ts b/src/overlords/situational/remoteUpgrader.ts index cb1d8c57d..232ca7c42 100644 --- a/src/overlords/situational/remoteUpgrader.ts +++ b/src/overlords/situational/remoteUpgrader.ts @@ -120,7 +120,7 @@ export class RemoteUpgradingOverlord extends Overlord { return; } // You're in the room, upgrade if you have energy - if (upgrader.carry.energy > 0) { + if (upgrader.store.energy > 0) { upgrader.task = Tasks.upgrade(this.upgradeSite.controller); return; } @@ -135,8 +135,8 @@ export class RemoteUpgradingOverlord extends Overlord { } // Recharge from transporter? const nearbyCarriers = _.filter(this.carriers, carrier => upgrader.pos.getRangeTo(carrier) <= 5); - const nearbyCarriersWaitingToUnload = _.filter(nearbyCarriers, carrier => carrier.carry.energy > 0); - const lowestEnergyCarrier = minBy(nearbyCarriersWaitingToUnload, carrier => carrier.carry.energy); + const nearbyCarriersWaitingToUnload = _.filter(nearbyCarriers, carrier => carrier.store.energy > 0); + const lowestEnergyCarrier = minBy(nearbyCarriersWaitingToUnload, carrier => carrier.store.energy); if (lowestEnergyCarrier) { upgrader.goTo(lowestEnergyCarrier); return; @@ -153,10 +153,10 @@ export class RemoteUpgradingOverlord extends Overlord { } // Get energy from the parent colony if you need it - if (carrier.carry.energy == 0) { + if (carrier.store.energy == 0) { // If you are in the child room and there are valuable resources in a storage/terminal that isn't mine, // then take those back before you go home - if (carrier.room == this.childColony.room && carrier.carry.getFreeCapacity() > 0) { + if (carrier.room == this.childColony.room && carrier.store.getFreeCapacity() > 0) { const storeStructuresNotMy = _.filter(_.compact([this.childColony.room.storage, this.childColony.room.terminal]), @@ -166,7 +166,7 @@ export class RemoteUpgradingOverlord extends Overlord { structure => structure.store.getUsedCapacity(resource) > 0); if (withdrawTarget) { const amount = Math.min(withdrawTarget.store.getUsedCapacity(resource), - carrier.carry.getFreeCapacity()); + carrier.store.getFreeCapacity()); carrier.task = Tasks.withdraw(withdrawTarget, resource, amount); return; } @@ -179,12 +179,12 @@ export class RemoteUpgradingOverlord extends Overlord { } const target = _.find(_.compact([this.parentColony.storage, this.parentColony.terminal]), - s => s!.store[RESOURCE_ENERGY] >= carrier.carryCapacity); + s => s!.store[RESOURCE_ENERGY] >= carrier.store.getCapacity()); if (!target) { log.warning(`${this.print}: no energy withdraw target for ${carrier.print}!`); return; } - if (carrier.carry.getUsedCapacity() > carrier.carry.getUsedCapacity(RESOURCE_ENERGY)) { + if (carrier.store.getUsedCapacity() > carrier.store.getUsedCapacity(RESOURCE_ENERGY)) { carrier.task = Tasks.transferAll(target); } else { carrier.task = Tasks.withdraw(target); @@ -202,9 +202,9 @@ export class RemoteUpgradingOverlord extends Overlord { // otherwise put in storage if you can const depositPos = this.upgradeSite.batteryPos || this.upgradeSite.pos; const carriersWaitingToUnload = _.filter(this.carriers, carrier => - carrier.carry.energy > 0 && carrier.pos.inRangeToPos(depositPos, 5)); + carrier.store.energy > 0 && carrier.pos.inRangeToPos(depositPos, 5)); const firstCarrierInQueue = minBy(carriersWaitingToUnload, carrier => - carrier.carry.energy + (carrier.ticksToLive || Infinity) / 10000); + carrier.store.energy + (carrier.ticksToLive || Infinity) / 10000); // Put in storage if you can if (this.childColony.storage && firstCarrierInQueue && firstCarrierInQueue != carrier) { diff --git a/src/overlords/~template/templateOverlord.ts b/src/overlords/~template/templateOverlord.ts index 1194674ed..555fe781c 100644 --- a/src/overlords/~template/templateOverlord.ts +++ b/src/overlords/~template/templateOverlord.ts @@ -143,7 +143,7 @@ export class TemplateOverlord extends Overlord { return; } // You're in the room, upgrade if you have energy - if (upgrader.carry.energy > 0) { + if (upgrader.store.energy > 0) { upgrader.task = Tasks.upgrade(this.colony.controller); return; } @@ -190,7 +190,7 @@ export class TemplateOverlord extends Overlord { private handleWorker(worker: Zerg): void { // Get energy if needed - if (worker.carry.energy == 0) { + if (worker.store.energy == 0) { worker.task = Tasks.recharge(); return; } diff --git a/src/prototypes/Structures.ts b/src/prototypes/Structures.ts index 522aff36f..2e6f2c3f0 100644 --- a/src/prototypes/Structures.ts +++ b/src/prototypes/Structures.ts @@ -45,46 +45,64 @@ OwnedStructure.prototype._isActive = OwnedStructure.prototype.isActive; // return this._isActiveValue; // }; -// Container prototypes ================================================================================================ +// Storage prototypes ================================================================================================ + +const StorageLikeStructures = [ + StructureContainer, + StructureExtension, + StructureLink, + StructureStorage, + StructureTerminal, + StructureSpawn, + Tombstone, + Ruin, +]; + +for (const structure of StorageLikeStructures) { + if (!structure.prototype.hasOwnProperty('energy')) { + Object.defineProperty(structure.prototype, 'energy', { + get(this: typeof structure.prototype) { + return this.store.getUsedCapacity(RESOURCE_ENERGY); + }, + configurable: true, + }); + } -Object.defineProperty(StructureContainer.prototype, 'energy', { - get() { - return this.store[RESOURCE_ENERGY]; - }, - configurable: true, -}); + Object.defineProperty(structure.prototype, 'isFull', { // if this container-like object is full + get(this: typeof structure.prototype) { + return this.store.getFreeCapacity() === 0; + }, + configurable: true, + }); + + Object.defineProperty(structure.prototype, 'isEmpty', { // if this container-like object is empty + get(this: StructureContainer) { + return this.store.getUsedCapacity() === 0; + }, + configurable: true, + }); +} -Object.defineProperty(StructureContainer.prototype, 'isFull', { // if this container-like object is full - get() { - return _.sum(this.store) >= this.storeCapacity; - }, - configurable: true, -}); -Object.defineProperty(StructureContainer.prototype, 'isEmpty', { // if this container-like object is empty - get() { - return _.sum(this.store) == 0; - }, - configurable: true, -}); +// Link prototypes ===================================================================================================== // Controller prototypes =============================================================================================== Object.defineProperty(StructureController.prototype, 'reservedByMe', { - get : function() { + get(this: StructureController) { return this.reservation && this.reservation.username == MY_USERNAME; }, configurable: true, }); Object.defineProperty(StructureController.prototype, 'signedByMe', { - get : function() { + get(this: StructureController) { return this.sign && this.sign.username == MY_USERNAME && Game.time - this.sign.time < 250000; }, configurable: true, }); Object.defineProperty(StructureController.prototype, 'signedByScreeps', { - get : function() { + get(this: StructureController) { return this.sign && this.sign.username == 'Screeps'; }, configurable: true, @@ -97,120 +115,28 @@ StructureController.prototype.needsReserving = function(reserveBuffer: number): // Extension prototypes ================================================================================================ -Object.defineProperty(StructureExtension.prototype, 'isFull', { // if this container-like object is full - get() { - return this.energy >= this.energyCapacity; - }, - configurable: true, -}); - -Object.defineProperty(StructureExtension.prototype, 'isEmpty', { // if this container-like object is empty - get() { - return this.energy == 0; - }, - configurable: true, -}); - // Link prototypes ===================================================================================================== -Object.defineProperty(StructureLink.prototype, 'isFull', { // if this container-like object is full - get() { - return this.energy >= this.energyCapacity; - }, - configurable: true, -}); - -Object.defineProperty(StructureLink.prototype, 'isEmpty', { // if this container-like object is empty - get() { - return this.energy == 0; - }, - configurable: true, -}); - -Object.defineProperty(StructureLink.prototype, 'storeCapacity', { // forwards-backwards compatibility - get() { - return this.energyCapacity; - }, - configurable: true, -}); - - // Nuker prototypes ==================================================================================================== // PowerSpawn prototypes =============================================================================================== // Spawn prototypes ==================================================================================================== -Object.defineProperty(StructureSpawn.prototype, 'isFull', { // if this container-like object is full - get() { - return this.energy >= this.energyCapacity; - }, - configurable: true, -}); - -Object.defineProperty(StructureSpawn.prototype, 'isEmpty', { // if this container-like object is empty - get() { - return this.energy == 0; - }, - configurable: true, -}); - // Storage prototypes ================================================================================================== + declare const Store: any; // Store prototype isn't included in typed-screeps yet Object.defineProperty(Store.prototype, 'contents', { - get() { - return Object.entries(this); + get(this: StoreDefinition) { + return Object.entries(this); }, configurable: true, }); // Storage prototypes ================================================================================================== -Object.defineProperty(StructureStorage.prototype, 'energy', { - get() { - return this.store[RESOURCE_ENERGY]; - }, - configurable: true, -}); - -Object.defineProperty(StructureStorage.prototype, 'isFull', { // if this container-like object is full - get() { - return _.sum(this.store) >= this.storeCapacity; - }, - configurable: true, -}); - -Object.defineProperty(StructureStorage.prototype, 'isEmpty', { // if this container-like object is empty - get() { - return _.sum(this.store) == 0; - }, - configurable: true, -}); - - // Terminal prototypes ================================================================================================= -Object.defineProperty(StructureTerminal.prototype, 'energy', { - get() { - return this.store[RESOURCE_ENERGY]; - }, - configurable: true, -}); - -Object.defineProperty(StructureTerminal.prototype, 'isFull', { // if this container-like object is full - get() { - return _.sum(this.store) >= this.storeCapacity; - }, - configurable: true, -}); - -Object.defineProperty(StructureTerminal.prototype, 'isEmpty', { // if this container-like object is empty - get() { - return _.sum(this.store) == 0; - }, - configurable: true, -}); - Object.defineProperty(StructureTerminal.prototype, 'isReady', { // the terminal is ready to send or deal get() { return this.cooldown == 0 && !this._notReady; @@ -237,28 +163,3 @@ StructureTerminal.prototype.send = function(resourceType: ResourceConstant, amou } return response; }; - -// Tower prototypes - -Object.defineProperty(StructureTower.prototype, 'isFull', { // if this container-like object is full - get() { - return this.energy >= this.energyCapacity; - }, - configurable: true, -}); - -Object.defineProperty(StructureTower.prototype, 'isEmpty', { // if this container-like object is empty - get() { - return this.energy == 0; - }, - configurable: true, -}); - -// Tombstone prototypes ================================================================================================ -Object.defineProperty(Tombstone.prototype, 'energy', { - get() { - return this.store[RESOURCE_ENERGY]; - }, - configurable: true, -}); - diff --git a/src/resources/Abathur.ts b/src/resources/Abathur.ts index 1e058f32d..eeb074485 100644 --- a/src/resources/Abathur.ts +++ b/src/resources/Abathur.ts @@ -72,7 +72,7 @@ export const REACTION_PRIORITIES = [ BOOST_TIERS.upgrade.T3, ]; -export const priorityStockAmounts: { [key: string]: number } = { +export const priorityStockAmounts = { XGHO2: 1000, // (-70 % dmg taken) XLHO2: 1000, // (+300 % heal) XZHO2: 1000, // (+300 % fat decr - speed) @@ -94,7 +94,7 @@ export const priorityStockAmounts: { [key: string]: number } = { G : 2000, // For nukes and common compounds }; -export const wantedStockAmounts: { [key: string]: number } = { +export const wantedStockAmounts = { UH : 3000, // (+100 % attack) KO : 3000, // (+100 % ranged attack) XGHO2: 10000, // (-70 % dmg taken) @@ -351,7 +351,7 @@ export class Abathur { // Compute the reaction queue for the highest priority item that you should be and can be making const stocksToCheck = [priorityStockAmounts, wantedStockAmounts]; for (const stocks of stocksToCheck) { - for (const resourceType in stocks) { + for (const resourceType of Object.keys(stocks)) { const amountOwned = colony.assets[resourceType]; const amountNeeded = stocks[resourceType]; if (amountOwned < amountNeeded) { // if there is a shortage of this resource @@ -433,8 +433,8 @@ export class Abathur { const requiredBasicMinerals = Abathur.getRequiredBasicMinerals(reactionQueue); if (verbose) console.log(`Required basic minerals: ${JSON.stringify(requiredBasicMinerals)}`); if (verbose) console.log(`assets: ${JSON.stringify(colony.assets)}`); - const missingBasicMinerals: { [resourceType: string]: number } = {}; - for (const mineralType in requiredBasicMinerals) { + const missingBasicMinerals = {}; + for (const mineralType of Object.keys(requiredBasicMinerals)) { const amountMissing = requiredBasicMinerals[mineralType] - colony.assets[mineralType]; if (amountMissing > 0) { missingBasicMinerals[mineralType] = amountMissing; diff --git a/src/resources/map_resources.ts b/src/resources/map_resources.ts index c8d82a453..91e33589e 100644 --- a/src/resources/map_resources.ts +++ b/src/resources/map_resources.ts @@ -354,4 +354,4 @@ export const DEPOSITS_ALL: ResourceConstant[] = [ RESOURCE_MIST, ]; -export const ALL_ZERO_ASSETS: { [resource: string]: number } = _.zipObject(RESOURCES_ALL, _.map(RESOURCES_ALL, i => 0)); +export const ALL_ZERO_ASSETS: StoreContents = _.zipObject(RESOURCES_ALL, _.map(RESOURCES_ALL, i => 0)); diff --git a/src/roomPlanner/RoomPlanner.ts b/src/roomPlanner/RoomPlanner.ts index 06a2c3eda..94aa2edb0 100644 --- a/src/roomPlanner/RoomPlanner.ts +++ b/src/roomPlanner/RoomPlanner.ts @@ -654,7 +654,7 @@ export class RoomPlanner { if (!this.colony.storage) { log.info(`${this.colony.name}: waiting until storage is built to remove terminal`); return; - } else if (this.colony.terminal && _.sum(this.colony.terminal.store) - this.colony.terminal.energy > 1000) { + } else if (this.colony.terminal && this.colony.terminal.store.getUsedCapacity() - this.colony.terminal.energy > 1000) { log.info(`${this.colony.name}: waiting on resources to evacuate before removing terminal`); return; } else if (this.colony.storage && this.structureShouldBeHere(STRUCTURE_STORAGE, this.colony.storage.pos) && diff --git a/src/tasks/instances/build.ts b/src/tasks/instances/build.ts index fa030c270..2c70d72c8 100644 --- a/src/tasks/instances/build.ts +++ b/src/tasks/instances/build.ts @@ -15,7 +15,7 @@ export class TaskBuild extends Task { } isValidTask() { - return this.creep.carry.energy > 0; + return this.creep.store.energy > 0; } isValidTarget() { diff --git a/src/tasks/instances/drop.ts b/src/tasks/instances/drop.ts index f1113be3c..aa7f0d5d1 100644 --- a/src/tasks/instances/drop.ts +++ b/src/tasks/instances/drop.ts @@ -28,7 +28,7 @@ export class TaskDrop extends Task { isValidTask() { const amount = this.data.amount || 1; - const resourcesInCarry = this.creep.carry[this.data.resourceType] || 0; + const resourcesInCarry = this.creep.store[this.data.resourceType] || 0; return resourcesInCarry >= amount; } diff --git a/src/tasks/instances/fortify.ts b/src/tasks/instances/fortify.ts index 04d3e074b..adeae64c2 100644 --- a/src/tasks/instances/fortify.ts +++ b/src/tasks/instances/fortify.ts @@ -21,7 +21,7 @@ export class TaskFortify extends Task { } isValidTask() { - return (this.creep.carry.energy > 0); // Times out once creep is out of energy + return (this.creep.store.energy > 0); // Times out once creep is out of energy } isValidTarget() { diff --git a/src/tasks/instances/generateSafeMode.ts b/src/tasks/instances/generateSafeMode.ts index 2888cbdbf..19465ff0f 100644 --- a/src/tasks/instances/generateSafeMode.ts +++ b/src/tasks/instances/generateSafeMode.ts @@ -12,7 +12,7 @@ export class TaskGenerateSafeMode extends Task { } isValidTask() { - return (this.creep.carry[RESOURCE_GHODIUM] >= 1000); + return (this.creep.store[RESOURCE_GHODIUM] >= 1000); } isValidTarget() { diff --git a/src/tasks/instances/harvest.ts b/src/tasks/instances/harvest.ts index 52f5336d7..4492cfdab 100644 --- a/src/tasks/instances/harvest.ts +++ b/src/tasks/instances/harvest.ts @@ -13,7 +13,7 @@ export class TaskHarvest extends Task { } isValidTask() { - return _.sum(this.creep.carry) < this.creep.carryCapacity; + return this.creep.store.getUsedCapacity() < this.creep.store.getCapacity(); } isValidTarget() { diff --git a/src/tasks/instances/pickup.ts b/src/tasks/instances/pickup.ts index 8d45b76b6..a8078eb72 100644 --- a/src/tasks/instances/pickup.ts +++ b/src/tasks/instances/pickup.ts @@ -13,7 +13,7 @@ export class TaskPickup extends Task { } isValidTask() { - return _.sum(this.creep.carry) < this.creep.carryCapacity; + return this.creep.store.getUsedCapacity() < this.creep.store.getCapacity(); } isValidTarget() { diff --git a/src/tasks/instances/recharge.ts b/src/tasks/instances/recharge.ts index 63921efa2..6a222d005 100644 --- a/src/tasks/instances/recharge.ts +++ b/src/tasks/instances/recharge.ts @@ -64,7 +64,7 @@ export class TaskRecharge extends Task { && (zerg.task.name == withdrawTaskName || zerg.task.name == pickupTaskName)); const resourceOutflux = _.sum(_.map(otherTargeters, other => other.store.getFreeCapacity())); - amount = minMax(amount - resourceOutflux, 0, creep.carryCapacity); + amount = minMax(amount - resourceOutflux, 0, creep.store.getCapacity()); const effectiveAmount = amount / (creep.pos.getMultiRoomRangeTo(obj.pos) + 1); if (effectiveAmount <= 0) { return false; diff --git a/src/tasks/instances/repair.ts b/src/tasks/instances/repair.ts index dff4e289f..974c7d655 100644 --- a/src/tasks/instances/repair.ts +++ b/src/tasks/instances/repair.ts @@ -15,7 +15,7 @@ export class TaskRepair extends Task { } isValidTask() { - return this.creep.carry.energy > 0; + return this.creep.store.energy > 0; } isValidTarget() { diff --git a/src/tasks/instances/transfer.ts b/src/tasks/instances/transfer.ts index b35c4795d..4a3994612 100644 --- a/src/tasks/instances/transfer.ts +++ b/src/tasks/instances/transfer.ts @@ -28,14 +28,14 @@ export class TaskTransfer extends Task { isValidTask() { const amount = this.data.amount || 1; - const resourcesInCarry = this.creep.carry[this.data.resourceType] || 0; + const resourcesInCarry = this.creep.store[this.data.resourceType] || 0; return resourcesInCarry >= amount; } isValidTarget() { const amount = this.data.amount || 1; // TODO: if you don't have vision of the creep (transferring to other creep?) - return !!this.target && this.target.store.getFreeCapacity(this.data.resourceType) >= amount; + return !!this.target && (this.target.store.getFreeCapacity(this.data.resourceType) ?? 0) >= amount; // LEGACY: diff --git a/src/tasks/instances/transferAll.ts b/src/tasks/instances/transferAll.ts index b93287aee..016a7ab08 100644 --- a/src/tasks/instances/transferAll.ts +++ b/src/tasks/instances/transferAll.ts @@ -20,7 +20,7 @@ export class TaskTransferAll extends Task { } isValidTask() { - for (const [resourceType, amount] of this.creep.carry.contents) { + for (const [resourceType, amount] of this.creep.store.contents) { if (this.data.skipEnergy && resourceType == RESOURCE_ENERGY) { continue; } @@ -32,12 +32,12 @@ export class TaskTransferAll extends Task { } isValidTarget() { - return !!this.target && _.sum(this.target.store) < this.target.store.getCapacity(); + return !!this.target && this.target.store.getUsedCapacity() < this.target.store.getCapacity(); } work() { if (!this.target) return ERR_INVALID_TARGET; - for (const [resourceType, amount] of this.creep.carry.contents) { + for (const [resourceType, amount] of this.creep.store.contents) { if (this.data.skipEnergy && resourceType == RESOURCE_ENERGY) { continue; } diff --git a/src/tasks/instances/upgrade.ts b/src/tasks/instances/upgrade.ts index 6f8b2cbb3..12e70c615 100644 --- a/src/tasks/instances/upgrade.ts +++ b/src/tasks/instances/upgrade.ts @@ -16,7 +16,7 @@ export class TaskUpgrade extends Task { } isValidTask() { - return (this.creep.carry.energy > 0); + return (this.creep.store.energy > 0); } isValidTarget() { diff --git a/src/tasks/instances/withdraw.ts b/src/tasks/instances/withdraw.ts index 0bffbdb73..11371b729 100644 --- a/src/tasks/instances/withdraw.ts +++ b/src/tasks/instances/withdraw.ts @@ -28,12 +28,12 @@ export class TaskWithdraw extends Task { isValidTask() { const amount = this.data.amount || 1; - return (_.sum(this.creep.carry) <= this.creep.carryCapacity - amount); + return (this.creep.store.getUsedCapacity() <= this.creep.store.getCapacity() - amount); } isValidTarget() { const amount = this.data.amount || 1; - return !!this.target && this.target.store.getUsedCapacity(this.data.resourceType) >= amount; + return !!this.target && (this.target.store.getUsedCapacity(this.data.resourceType) ?? 0) >= amount; // const target = this.target; // if (isTombstone(target) || isRuin(target) || isStoreStructure(target)) { diff --git a/src/tasks/instances/withdrawAll.ts b/src/tasks/instances/withdrawAll.ts index bd5187aa0..5b3a97ce1 100644 --- a/src/tasks/instances/withdrawAll.ts +++ b/src/tasks/instances/withdrawAll.ts @@ -18,11 +18,11 @@ export class TaskWithdrawAll extends Task { } isValidTask() { - return (_.sum(this.creep.carry) < this.creep.carryCapacity); + return (this.creep.store.getUsedCapacity() < this.creep.store.getCapacity()); } isValidTarget() { - return !!this.target && _.sum(this.target.store) > 0; + return !!this.target && (this.target.store.getUsedCapacity() ?? 0) > 0; } work() { diff --git a/src/utilities/utils.ts b/src/utilities/utils.ts index 61b976148..fef8310e1 100644 --- a/src/utilities/utils.ts +++ b/src/utilities/utils.ts @@ -73,7 +73,7 @@ export function minMax(value: number, min: number, max: number): number { return Math.max(Math.min(value, max), min); } -export function hasMinerals(store: { [resourceType: string]: number }): boolean { +export function hasMinerals(store: StoreDefinition): boolean { for (const resourceType in store) { if (resourceType != RESOURCE_ENERGY && (store[resourceType] || 0) > 0) { return true; @@ -186,14 +186,11 @@ export function toColumns(obj: { [key: string]: string }, opts = {} as ToColumnO /** * Merges a list of store-like objects, summing overlapping keys. Useful for calculating assets from multiple sources */ -export function mergeSum(objects: { [key: string]: number | undefined }[]): { [key: string]: number } { - const ret: { [key: string]: number } = {}; - for (const object of objects) { - for (const key in object) { - const amount = object[key] || 0; - if (!ret[key]) { - ret[key] = 0; - } +export function mergeSum(...stores: StoreContents[]): StoreContents { + const ret = {}; + for (const store of stores) { + for (const [key, amount] of <[ResourceConstant, number][]>Object.entries(store)) { + if (!ret[key]) ret[key] = 0; ret[key] += amount; } } diff --git a/src/zerg/AnyZerg.ts b/src/zerg/AnyZerg.ts index f8bd6b254..332b63d53 100644 --- a/src/zerg/AnyZerg.ts +++ b/src/zerg/AnyZerg.ts @@ -80,9 +80,7 @@ export abstract class AnyZerg { isAnyZerg: true; creep: AnyCreep; // The creep that this wrapper class will control // body: BodyPartDefinition[]; // These properties are all wrapped from this.creep.* to this.* - carry: StoreDefinition; // | store: StoreDefinition; // | - carryCapacity: number; // | effects: RoomObjectEffect[]; // fatigue: number; // | hits: number; // | @@ -108,9 +106,7 @@ export abstract class AnyZerg { // Copy over creep references this.creep = creep; // this.body = creep.body; - this.carry = creep.carry; this.store = creep.store; - this.carryCapacity = creep.carryCapacity; // this.fatigue = creep.fatigue; this.effects = creep.effects; this.hits = creep.hits; @@ -155,9 +151,7 @@ export abstract class AnyZerg { this.pos = creep.pos; this.nextPos = creep.pos; // this.body = creep.body; - this.carry = creep.carry; this.store = creep.store; - this.carryCapacity = creep.carryCapacity; // this.fatigue = creep.fatigue; this.hits = creep.hits; this.memory = creep.memory; @@ -284,7 +278,7 @@ export abstract class AnyZerg { // Carry methods get hasMineralsInCarry(): boolean { - for (const [resourceType, amount] of this.carry.contents) { + for (const [resourceType, amount] of this.store.contents) { if (resourceType != RESOURCE_ENERGY && amount > 0) { return true; } @@ -389,7 +383,7 @@ export abstract class AnyZerg { const fleeing = Movement.flee(this, avoidGoals, fleeOptions.dropEnergy, moveOptions) != undefined; if (fleeing) { // Drop energy if needed - if (fleeOptions.dropEnergy && this.carry.energy > 0) { + if (fleeOptions.dropEnergy && this.store.energy > 0) { const nearbyContainers = this.pos.findInRange(this.room.storageUnits, 1); if (nearbyContainers.length > 0) { this.transfer(_.first(nearbyContainers), RESOURCE_ENERGY); @@ -420,7 +414,7 @@ export abstract class AnyZerg { if (this.memory.avoidDanger) { if (this.memory.avoidDanger.timer > 0) { this.goToRoom(this.memory.avoidDanger.fallback); - if (opts.dropEnergy && this.carry.energy > 0) { + if (opts.dropEnergy && this.store.energy > 0) { this.drop(RESOURCE_ENERGY); // transfer energy to container check is only run on first danger tick } this.memory.avoidDanger.timer--; @@ -475,7 +469,7 @@ export abstract class AnyZerg { fallback: fallback, }; - if (opts.dropEnergy && this.carry.energy > 0) { + if (opts.dropEnergy && this.store.energy > 0) { const containersInRange = this.pos.findInRange(this.room.containers, 1); const adjacentContainer = _.first(containersInRange); if (adjacentContainer) { diff --git a/src/zerg/PowerZerg.ts b/src/zerg/PowerZerg.ts index 19d8436d5..0d8aaf2d5 100644 --- a/src/zerg/PowerZerg.ts +++ b/src/zerg/PowerZerg.ts @@ -55,9 +55,7 @@ export abstract class PowerZerg extends AnyZerg { this.creep = powerCreep; this.pos = powerCreep.pos; this.nextPos = powerCreep.pos; - this.carry = powerCreep.carry; this.store = powerCreep.store; - this.carryCapacity = powerCreep.carryCapacity; this.hits = powerCreep.hits; this.memory = powerCreep.memory; this.room = powerCreep.room as Room; // not actually as Room diff --git a/src/zerg/Zerg.ts b/src/zerg/Zerg.ts index 17bfce686..03c235f12 100644 --- a/src/zerg/Zerg.ts +++ b/src/zerg/Zerg.ts @@ -59,9 +59,7 @@ export class Zerg extends AnyZerg { isStandardZerg: true; creep: Creep; // The creep that this wrapper class will control body: BodyPartDefinition[]; // These properties are all wrapped from this.creep.* to this.* - carry: StoreDefinition; // | - store: StoreDefinition; // | - carryCapacity: number; // | + store: StoreDefinition; // | fatigue: number; // | hits: number; // | hitsMax: number; // |