diff --git a/src/prototype_room_mineral.js b/src/prototype_room_mineral.js index ed0ad13dd..5443dfae7 100644 --- a/src/prototype_room_mineral.js +++ b/src/prototype_room_mineral.js @@ -221,3 +221,89 @@ Room.prototype.handleTerminal = function() { delete this.memory.mineralOrder[roomOtherName]; return true; }; + +Room.prototype.cleanupNotEnoughResources = function() { + if (!this.memory.reaction) { + return false; + } + const lab1 = Game.getObjectById(this.memory.reaction.labs[1]); + const lab2 = Game.getObjectById(this.memory.reaction.labs[2]); + const findCreep = this.findMyCreepsOfRole('mineral'); + const mineralCreep = findCreep.length ? findCreep[0] : false; + if (mineralCreep && this.memory.reaction && this.memory.reaction.result) { + if (!mineralCreep.checkLabEnoughMineral(lab1, this.memory.reaction.result.first) || !mineralCreep.checkLabEnoughMineral(lab2, this.memory.reaction.result.second)) { + roles.mineral.cleanUpLabs(mineralCreep); + } + } + return true; +}; + +Room.prototype.handleReaction = function() { + if (!this.memory.reaction) { + return false; + } + + const labsToReact = this.findStructuresOfStructureType(STRUCTURE_LAB).filter((lab) => { + if (lab.store[this.memory.reaction.result.first] > 0 || lab.store[this.memory.reaction.result.second] > 0) { + return false; + } + return true; + }); + + if (labsToReact.length === 0) { + return false; + } + + const lab0 = Game.getObjectById(this.memory.reaction.labs[0]); + const lab1 = Game.getObjectById(this.memory.reaction.labs[1]); + const lab2 = Game.getObjectById(this.memory.reaction.labs[2]); + if (lab0 === null || lab1 === null || lab2 === null) { + delete this.memory.reaction; + return false; + } else { + const labsToReactResponse = labsToReact.map((lab0) => { + const inRange = lab0.pos.getRangeTo(lab1) < 3 && lab0.pos.getRangeTo(lab2) < 3; + if (lab0.cooldown === 0 && inRange) { + if (lab0.mineralAmount > lab0.mineralCapacity - 100 && this.memory.reaction) { + this.memory.fullLab = 1; + return 'ERR_FULL_LAB'; + } + if (lab0.mineralAmount < 100) { + this.memory.fullLab = 0; + } + const returnCode = lab0.runReaction(lab1, lab2); + if (returnCode === ERR_NOT_ENOUGH_RESOURCES) { + this.cleanupNotEnoughResources(); + return 'ERR_NOT_ENOUGH_RESOURCES'; + } + if (returnCode === ERR_NOT_IN_RANGE) { + return 'ERR_NOT_IN_RANGE'; + } + if (returnCode === OK) { + return 'OK'; + } + } else { + return false; + } + }).reduce((a, t) => a || t, false); + + if (this.memory.reaction.result) { + const resultLab = labsToReact.filter((s) => s.cooldown === 0 && s.store[this.memory.reaction.result.result]); + if (config.debug.mineral && typeof labsToReactResponse !== 'undefined' && labsToReactResponse !== false && labsToReact.length > 1) { + this.debugLog(this.memory.reaction.result.result, labsToReactResponse, resultLab); + } + } + this.checkMineralToSpawn(); + } +}; + +Room.prototype.checkMineralToSpawn = function() { + if (Game.time % 150 && this.isRoomReadyForMineralHandling()) { + let amount = 1; + // room has a lot energy in terminal; move energy to storage + if (this.getEnergy() * 0.7 <= this.terminal.store.getUsedCapacity(RESOURCE_ENERGY)) { + amount = 2; + } + this.checkRoleToSpawn('mineral', amount); + } +}; diff --git a/src/prototype_room_my.js b/src/prototype_room_my.js index 32d497386..2096d7eb0 100644 --- a/src/prototype_room_my.js +++ b/src/prototype_room_my.js @@ -357,8 +357,28 @@ Room.prototype.handleReputation = function() { } }; +/** + * todo move this to prototype_room_resources.js ? + * + * @return {number} + */ +Room.prototype.getEnergy = function() { + let amount = 0; + if (this.terminal) { + amount += this.terminal.store[RESOURCE_ENERGY]; + } + if (this.storage) { + amount += this.storage.store[RESOURCE_ENERGY]; + } + return amount; +}; + Room.prototype.getBuilderAmount = function(constructionSites) { let amount = 1; + const energyInRoom = this.getEnergy(); + if (energyInRoom > (config.terminal.minEnergyAmount / 2)) { + amount = 2; + } if (this.controller.level >= 4 && this.memory.misplacedSpawn) { amount = 3; } @@ -430,15 +450,13 @@ Room.prototype.checkForMineral = function() { return false; } - // const labs = this.findPropertyFilter(FIND_MY_STRUCTURES, 'structureType', [STRUCTURE_LAB]); - // if ((!this.memory.cleanup || this.memory.cleanup <= 10) && (_.size(labs) > 2)) { + if (this.memory.reaction) { + this.handleReaction(); + } + if (this.isHealthy() && ((this.data.mineralLastRecyled || Game.time) + 1500 > Game.time)) { this.checkRoleToSpawn('mineral'); } - // } - // if ((Game.time + this.controller.pos.x + this.controller.pos.y) % 10000 < 10) { - // this.memory.cleanup = 0; - // } }; Room.prototype.handleEconomyStructures = function() { @@ -485,8 +503,7 @@ Room.prototype.isHealthy = function() { if (this.isStruggling()) { return false; } - // TODO extract as config variable - if (this.storage.store.energy < config.room.isHealthyStorageThreshold) { + if (this.getEnergy() < config.room.isHealthyStorageThreshold) { return false; } return true; diff --git a/src/role_mineral.js b/src/role_mineral.js index f670bb2c5..efbb7c880 100644 --- a/src/role_mineral.js +++ b/src/role_mineral.js @@ -146,6 +146,9 @@ const handleWithdrawResponse = function(creep, target, resource, amount, returnC } creep.log('get: ' + returnCode + ' target: ' + target + ' resource: ' + resource + ' amount: ' + amount); creep.log(target.mineralAmount + ' ' + (creep.carryCapacity - _.sum(creep.carry))); + delete creep.data.mode; + delete creep.data.state; + return false; }; @@ -155,11 +158,11 @@ const handleWithdrawResponse = function(creep, target, resource, amount, returnC * @param {object} creep - The creep to interact with. * @param {object} target - The target to get the resource from. * @param {string} resource - The resource to get. - * @return {boolean|void} If it was an success + * @return {boolean} If it was an success */ function get(creep, target, resource) { if (getFullCapacity(creep, target, resource)) { - return; + return false; } if (creep.carry[resource]) { @@ -167,7 +170,7 @@ function get(creep, target, resource) { creep.log('next state already carrying' + target); } nextState(creep); - return; + return false; } if (target instanceof StructureTerminal && !target.store[resource]) { @@ -175,7 +178,7 @@ function get(creep, target, resource) { creep.log('next state terminal no resource' + target); } nextState(creep); - return; + return false; } if (target instanceof StructureLab && target.mineralAmount === 0) { @@ -183,7 +186,7 @@ function get(creep, target, resource) { creep.log('next state lab no mineral' + target); } nextState(creep); - return; + return false; } const amount = getAmount(creep, target, resource); @@ -193,7 +196,7 @@ function get(creep, target, resource) { creep.log('next state no amount' + target); } nextState(creep); - return; + return false; } const returnCode = creep.withdraw(target, resource, amount); @@ -207,7 +210,7 @@ function get(creep, target, resource) { * @param {object} creep - The creep to interact with. * @param {object} target - The target to transfer the resource to. * @param {string} resource - The resource to transfer. - * @return {boolean|void} If it was an success + * @return {boolean} If it was an success */ function transfer(creep, target, resource) { if (target instanceof StructureTerminal) { @@ -224,39 +227,44 @@ function transfer(creep, target, resource) { if (!creep.carry[resource]) { nextState(creep); - return; + return false; } const returnCode = creep.transfer(target, resource); if (returnCode === OK) { nextState(creep); - return; + return false; } if (returnCode === ERR_FULL) { nextState(creep); - return; + return false; } if (returnCode === ERR_NOT_IN_RANGE) { - return; + return false; } creep.log('Transfer to: ' + target + 'failed with: ' + returnCode); + if (returnCode === ERR_INVALID_TARGET) { + delete creep.data.mode; + delete creep.data.state; + } + return false; } /** - * checkForSuicide + * checkForRecycle * * @param {object} creep * @return {boolean} */ -function checkForSuicide(creep) { +function checkForRecycle(creep) { if (!creep.room.terminal) { - creep.suicide(); + creep.memory.recycle = true; return true; } if (creep.ticksToLive < 50 && _.sum(creep.carry) === 0) { // early suicide to not waste minerals - creep.suicide(); + creep.memory.recycle = true; return true; } return false; @@ -268,7 +276,7 @@ function checkForSuicide(creep) { * @param {object} creep - The creep to handle. * @return {boolean} If a lab was found. */ -function cleanUpLabs(creep) { +roles.mineral.cleanUpLabs = function(creep) { creep.say('cleanup'); creep.memory.cleanup = creep.memory.cleanup || 0; // if 2 / 3 of the creep live time is cleanup stop spawning them for 10000 ticks @@ -301,33 +309,6 @@ function cleanUpLabs(creep) { creep.moveToMy(lab.pos); creep.withdraw(lab, lab.mineralType); } -} - - -const handleReactions = function(creep, room) { - const lab0 = Game.getObjectById(room.memory.reaction.labs[0]); - const lab1 = Game.getObjectById(room.memory.reaction.labs[1]); - const lab2 = Game.getObjectById(room.memory.reaction.labs[2]); - - if (lab0 === null || lab1 === null || lab2 === null) { - delete room.memory.reaction; - } else { - if (lab0.cooldown === 0) { - const returnCode = lab0.runReaction(lab1, lab2); - if (returnCode === ERR_NOT_ENOUGH_RESOURCES) { - if (!creep.checkLabEnoughMineral(lab1, room.memory.reaction.result.first) || !creep.checkLabEnoughMineral(lab2, room.memory.reaction.result.second)) { - cleanUpLabs(creep); - } - } - } - } - if (lab0.mineralAmount > lab0.mineralCapacity - 100 && room.memory.reaction) { - room.memory.fullLab = 1; - } - - if (lab0.mineralAmount < 100) { - room.memory.fullLab = 0; - } }; /** @@ -485,16 +466,12 @@ function checkNuke(creep) { } const execute = function(creep) { - if (checkForSuicide(creep)) { - return true; + if (checkForRecycle(creep)) { + return false; } const room = Game.rooms[creep.room.name]; - if (room.memory.reaction) { - handleReactions(creep, room); - } - updateStateWithFullLab(creep); if (room.memory.boosting && Object.keys(room.memory.boosting).length > 0) { @@ -510,7 +487,9 @@ const execute = function(creep) { creep.memory.state = creep.memory.state || 0; if (!room.memory.reaction) { - cleanUpLabs(creep); + creep.say('cleanUpLabs'); + roles.mineral.cleanUpLabs(creep); + creep.room.reactionsWithoutReaction(); return true; } @@ -522,7 +501,7 @@ const execute = function(creep) { } else if (state.destination === STRUCTURE_STORAGE) { target = creep.room.storage; } - + creep.creepLog('target', target, target.structureType); creep.moveToMy(target.pos); let resource = RESOURCE_ENERGY; @@ -542,7 +521,7 @@ const execute = function(creep) { * setStateFillTowers * * @param {object} creep - * @return {bool} + * @return {boolean} */ function setStateFillTowers(creep) { const towers = creep.room.findTowers(); @@ -551,6 +530,7 @@ function setStateFillTowers(creep) { return false; } creep.data.state = { + name: 'FillTowers', getResource: () => RESOURCE_ENERGY, source: creep.room.storage.id, target: fillableTower.id, @@ -563,13 +543,14 @@ function setStateFillTowers(creep) { * setStateFillTerminalEnergy * * @param {object} creep - * @return {bool} + * @return {boolean} */ function setStateFillTerminalEnergy(creep) { - if (creep.room.terminal.store.energy > config.terminal.minEnergyAmount) { + if (creep.room.terminal && creep.room.terminal.store.energy > config.terminal.minEnergyAmount) { return false; } creep.data.state = { + name: 'FillTerminalNrg', getResource: () => RESOURCE_ENERGY, source: creep.room.storage.id, target: creep.room.terminal.id, @@ -582,13 +563,14 @@ function setStateFillTerminalEnergy(creep) { * setStateGetEnergyFromTerminal * * @param {object} creep - * @return {bool} + * @return {boolean} */ function setStateGetEnergyFromTerminal(creep) { if (creep.room.terminal.store.energy < config.terminal.maxEnergyAmount) { return false; } creep.data.state = { + name: 'NrgFromTerminal', getResource: () => RESOURCE_ENERGY, source: creep.room.terminal.id, target: creep.room.storage.id, @@ -602,14 +584,19 @@ function setStateGetEnergyFromTerminal(creep) { * setStateEmptyCreepStore * * @param {object} creep - * @return {bool} + * @return {boolean} */ function setStateEmptyCreepStore(creep) { if (creep.store.getUsedCapacity() === 0) { return false; } + const targetId = _.sum(creep.room.terminal.store) > _.sum(creep.room.storage.store) ? creep.room.storage.id : creep.room.terminal.id; creep.data.state = { - action: 'empty', + name: 'EmptyCreepStore', + getResource: () => RESOURCE_ENERGY, + source: creep.id, + target: targetId, + action: 'transfer', }; return true; } @@ -618,7 +605,7 @@ function setStateEmptyCreepStore(creep) { * setStateFillLabsWithEnergy * * @param {object} creep - * @return {bool} + * @return {boolean} */ function setStateFillLabsWithEnergy(creep) { const labs = creep.room.findLabs(); @@ -627,6 +614,7 @@ function setStateFillLabsWithEnergy(creep) { return false; } creep.data.state = { + name: 'FillLabsWithNrg', getResource: () => RESOURCE_ENERGY, source: creep.room.storage.id, target: fillableLab.id, @@ -639,13 +627,14 @@ function setStateFillLabsWithEnergy(creep) { * setStateTransferResourcesToTerminal * * @param {object} creep - * @return {bool} + * @return {boolean} */ function setStateTransferResourcesToTerminal(creep) { if (!Object.keys(creep.room.storage.store).find((resource) => resource !== RESOURCE_ENERGY)) { return false; } creep.data.state = { + name: 'TransResourcesToTerminal', getResource: (storage) => Object.keys(storage.store).find((resource) => resource !== RESOURCE_ENERGY), source: creep.room.storage.id, target: creep.room.terminal.id, @@ -654,11 +643,48 @@ function setStateTransferResourcesToTerminal(creep) { return true; } +/** + * setStateClearLabs + * + * @param {object} creep + * @param {boolean} all clear all labs + * @return {boolean} + */ +function setStateClearLabs(creep, all = true) { + const labs = creep.room.findLabs(); + let fillableLab; + if (all) { + fillableLab = labs.find((s) => _.sum(s.store) > 0 && Object.keys(s.store).find((resource) => resource !== RESOURCE_ENERGY)); + } else { + let input1 = RESOURCE_ENERGY; + let input2 = RESOURCE_ENERGY; + if (creep.room.memory.reaction && creep.room.memory.reaction.result) { + input1 = creep.room.memory.reaction.result.first || RESOURCE_ENERGY; + input2 = creep.room.memory.reaction.result.second || RESOURCE_ENERGY; + } + const filterNonNeededResourcesInLab = (lab) => Object.keys(lab.store).find((resource) => resource !== RESOURCE_ENERGY && resource !== input1 && resource !== input2); + fillableLab = labs.find(filterNonNeededResourcesInLab); + } + if (!fillableLab) { + return false; + } + + creep.data.state = { + name: 'ClearLabs', + getResource: (lab) => Object.keys(lab.store).find((resource) => resource !== RESOURCE_ENERGY), + source: fillableLab.id, + target: creep.room.terminal.id, + action: 'transfer', + }; + return true; +} + /** * setState + * todo: add actions form old exec * * @param {object} creep - * @return {bool} + * @return {boolean} */ function setState(creep) { if (setStateEmptyCreepStore(creep)) { @@ -679,6 +705,9 @@ function setState(creep) { if (setStateTransferResourcesToTerminal(creep)) { return true; } + if (setStateClearLabs(creep)) { + return true; + } return false; } @@ -686,7 +715,7 @@ function setState(creep) { * handleState * * @param {object} creep - * @return {bool} + * @return {boolean} */ function handleState(creep) { if (!creep.data.state) { @@ -695,13 +724,8 @@ function handleState(creep) { } creep.log(`Set state: ${JSON.stringify(creep.data.state)}`); } - if (creep.data.state.action === 'empty') { - creep.moveToMy(creep.room.storage.pos); - creep.transfer(creep.room.storage, Object.keys(creep.store)[0]); - if (creep.store.getUsedCapacity() === 0) { - delete creep.data.state; - } - } else if (creep.data.state.action === 'transfer') { + + if (creep.data.state.action === 'transfer') { if (creep.store.getUsedCapacity() > 0) { const target = Game.getObjectById(creep.data.state.target); creep.moveToMy(target.pos); @@ -713,21 +737,52 @@ function handleState(creep) { const source = Game.getObjectById(creep.data.state.source); creep.moveToMy(source.pos); const resource = creep.data.state.getResource(source); - creep.withdraw(source, resource); + if (resource) { + creep.withdraw(source, resource); + } else if (typeof resource === 'undefined') { + delete creep.data.state; + } } } - creep.say('new state'); + if (creep.data.state && creep.data.state.name) { + creep.say(creep.data.state.name); + } return true; } +roles.mineral.preMove = function(creep) { + creep.pickupWhileMoving(); +}; + roles.mineral.action = function(creep) { - creep.say('mineral'); - if (handleState(creep)) { - return true; + if (!creep.room.isRoomReadyForMineralHandling()) { + creep.memory.recycle = true; + creep.room.data.mineralLastRecyled = Game.time; + } + + if (creep.ticksToLive < 50) { + creep.memory.recycle = true; + creep.room.data.mineralLastRecyled = Game.time; } - creep.memory.recycle = true; - creep.room.data.mineralLastRecyled = Game.time; - creep.say('old'); - return execute(creep); + if (typeof creep.data.mode === 'undefined') { + creep.data.mode = true; + } + + if (creep.data.mode) { + if (handleState(creep)) { + return true; + } else { + creep.data.mode = false; + return true; + } + } else { + creep.say('old exec'); + const execRes = execute(creep); + if (!execRes) { + creep.data.mode = true; + return false; + } + return true; + } };