Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] improve carry recycling #403

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,13 @@ global.config = {
1800: [8, 15], // RCL 5
2300: [11, 21], // RCL 6
},
transferToCarry: false,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what the intention is.

The default behavior should be that carries transfer to carries. If I understand the implementation correct, that would be disabled here.
And there are two methods, something like transferToCreep which actually transferrs and something like checkForTransfer which lets the carry move in the other direction because it will get energy in this tick.

Both needs to be adapted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can swap carries' target when they transfer to each other.

// limit carry spawn rate when RCL < 4
minSpawnRate: 50,
// when ticksToLive > recycleThreshold, reuse carry
recycleThreshold: 200,
// keep at least one carry for a target
ensureOne: true,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't think up a better name...

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is fine, maybe ensureOnePerTarget ... :-)

// Percentage should increase from base to target room. Decrease may cause stack on border
carryPercentageBase: 0.1,
carryPercentageHighway: 0.2,
Expand Down Expand Up @@ -243,9 +249,9 @@ global.config = {
defender: 12,
defendranged: 13,
nextroomer: 15,
carry: 17,
reserver: 17,
sourcer: 18,
reserver: 19,
carry: 19,
},
},
};
Expand Down
26 changes: 14 additions & 12 deletions src/prototype_creep_harvest.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ Creep.prototype.spawnCarry = function() {
return false;
}

const baseRoom = Game.rooms[this.memory.base];

const foundKey = Object.keys(config.carry.sizes).reverse()
.find((key) => (key <= Game.rooms[this.memory.base].energyCapacityAvailable));
.find((key) => (key <= baseRoom.energyCapacityAvailable));
const carryCapacity = config.carry.sizes[foundKey][1] * CARRY_CAPACITY;

const workParts = this.body.filter((part) => part.type === WORK).length;

const waitTime = carryCapacity / (HARVEST_POWER * workParts);

let resourceAtPosition = 0;
const resources = this.pos.lookFor(LOOK_RESOURCES);
for (const resource of resources) {
Expand All @@ -63,15 +63,17 @@ Creep.prototype.spawnCarry = function() {
resourceAtPosition += _.sum(container.store);
}

const waitTime = carryCapacity / (HARVEST_POWER * workParts) *
Math.sqrt(carryCapacity / Math.max(resourceAtPosition, carryCapacity));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the approach, can you explain a bit more what the idea is here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reduce waitTime according to resourceAtPosition. I use Math.sqrt in the hope that it will reach an equilibrium quickly (not call/spawn too much carries).

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

K, cool, let's see

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like it


if (resourceAtPosition > carryCapacity) {
Game.rooms[this.memory.base].checkRoleToSpawn('carry', 0, this.memory.routing.targetId, this.memory.routing.targetRoom);
} else if (resourceAtPosition <= HARVEST_POWER * workParts) {
const nearCarries = this.pos.findInRangePropertyFilter(FIND_MY_CREEPS, 2, 'memory.role', ['carry'], false, {
filter: (creep) => creep.memory.routing.targetId === this.memory.routing.targetId,
});
if (nearCarries.length > 1) {
nearCarries[0].memory.recycle = true;
}
baseRoom.checkRoleToSpawn('carry', 0, this.memory.routing.targetId, this.memory.routing.targetRoom);
}

// limit carry spawn rate when RCL < 4
if (baseRoom.controller.level < 4) {
this.memory.wait = Math.max(waitTime, config.carry.minSpawnRate);
} else {
this.memory.wait = waitTime;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally, waitTime won't get too small because of Math.sqrt.

}
this.memory.wait = Math.max(waitTime, config.carry.minSpawnRate);
};
20 changes: 8 additions & 12 deletions src/prototype_creep_resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,8 @@ Creep.prototype.harvesterBeforeStorage = function() {
return true;
};

Creep.prototype.checkEnergyTransfer = function(otherCreep) {
Creep.prototype.checkEnergyTransfer = function(offset = 0) {
// TODO duplicate from role_carry, extract to method
let offset = 0;
if (otherCreep) {
offset = otherCreep.carry.energy;
}

// define minimum carryPercentage to move back to storage
let carryPercentage = config.carry.carryPercentageHighway;
Expand Down Expand Up @@ -65,7 +61,7 @@ Creep.prototype.findCreepWhichCanTransfer = function(creeps) {
if (otherCreep.checkHelperNoTransfer(this)) {
continue;
}
return this.checkEnergyTransfer(otherCreep);
return this.checkEnergyTransfer(otherCreep.carry[RESOURCE_ENERGY]);
}
continue;
}
Expand All @@ -79,10 +75,7 @@ Creep.prototype.checkForTransfer = function(direction) {

const adjacentPos = this.pos.getAdjacentPosition(direction);

if (adjacentPos.x < 0 || adjacentPos.y < 0) {
return false;
}
if (adjacentPos.x > 49 || adjacentPos.y > 49) {
if (!adjacentPos.isValid()) {
return false;
}

Expand All @@ -106,7 +99,7 @@ Creep.prototype.pickupWhileMoving = function(reverse) {
if (resources.length > 0) {
const resource = resources[0];
const amount = this.pickupOrWithdrawFromSourcer(resource);
return _.sum(this.carry) + amount > 0.5 * this.carryCapacity;
return this.checkEnergyTransfer(amount);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

if (this.room.name === this.memory.routing.targetRoom) {
Expand All @@ -118,7 +111,7 @@ Creep.prototype.pickupWhileMoving = function(reverse) {
}
if (container.store[RESOURCE_ENERGY]) {
this.withdraw(container, RESOURCE_ENERGY);
return container.store[RESOURCE_ENERGY] > 9;
return this.checkEnergyTransfer(container.store[RESOURCE_ENERGY]);
}
}
}
Expand Down Expand Up @@ -297,6 +290,9 @@ const checkCreepForTransfer = function(creep) {
if (Game.creeps[creep.name].memory.role === 'powertransporter') {
return false;
}
if (!config.carry.transferToCarry && Game.creeps[creep.name].memory.role === 'carry') {
return false;
}
if (creep.carry.energy === creep.carryCapacity) {
return false;
}
Expand Down
10 changes: 8 additions & 2 deletions src/prototype_creep_routing.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,15 @@ Creep.prototype.followPath = function(action) {
return action(this);
}
const prepareData = this.moveByPathPrepare(route, routePos, 'pathStart', this.memory.routing.targetId);
let routeLength;
let pathLength;
if (prepareData.pathPos) {
this.memory.routing.pathPos = prepareData.pathPos;
routeLength = route.length;
pathLength = prepareData.path.length;
}
if (prepareData.unit.preMove) {
if (prepareData.unit.preMove(this, prepareData.directions)) {
if (prepareData.unit.preMove(this, prepareData.directions, routeLength, pathLength)) {
return true;
}
}
Expand Down Expand Up @@ -206,7 +213,6 @@ Creep.prototype.moveByPathMy = function(route, routePos, start, target, action,

if (pathPos < 0) {
// this.say('R:pos -1');
this.memory.routing.pathPos = pathPos;
if (path.length === 0) {
this.log('config_creep_routing.followPath no pos: ' + JSON.stringify(path));
return false;
Expand Down
71 changes: 66 additions & 5 deletions src/role_carry.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,44 @@ roles.carry.updateSettings = function(room, creep) {
}
};

roles.carry.reset = function(creep) {
// TODO check new routing. if carry is on the new path, reset carry, otherwise move to pathStart
const queue = Memory.rooms[creep.memory.base].queue || [];
for (let i = 0; i < queue.length; i++) {
if (queue[i].role === 'carry' && !queue[i].helper) {
creep.memory.routing = queue[i].routing;
queue.splice(i, 1);
return true;
}
}
return false;
};

roles.carry.ensureOne = function(creep) {
if (config.carry.ensureOne) {
const nearCarries = creep.pos.findInRangePropertyFilter(FIND_MY_CREEPS, 1, 'memory.role', ['carry'], false, {
filter: (otherCreep) => !otherCreep.resetTarget && otherCreep.memory.routing.targetId === creep.memory.routing.targetId,
});
if (nearCarries.length < 2) {
creep.memory.resetTarget = false;
}
}
};

roles.carry.checkHelperEmptyStorage = function(creep) {
// Fix blocked helpers due to empty structure in the room where we get the energy from
if (creep.room.name === creep.memory.routing.targetRoom) {
const targetStructure = Game.getObjectById(creep.memory.routing.targetId);
if (targetStructure === null) {
creep.suicide();
creep.memory.resetTarget = true;
return;
}

if (targetStructure.structureType === STRUCTURE_STORAGE) {
creep.say('storage');
if (targetStructure.store.energy === 0) {
creep.log('Suiciding the storage I should get the energy from is empty');
creep.suicide();
creep.log('the storage I should get the energy from is empty');
creep.memory.resetTarget = true;
}
}
}
Expand All @@ -67,6 +91,8 @@ roles.carry.handleMisplacedSpawn = function(creep) {
// TODO Somehow ugly and maybe better somewhere else
if (creep.inBase() && (creep.room.memory.misplacedSpawn || creep.room.controller.level < 3)) {
// creep.say('cmis', true);
// don't recycle carry
creep.memory.resetTarget = false;
if (creep.carry.energy > 0) {
const structure = creep.pos.findClosestByRange(FIND_MY_STRUCTURES, {
filter: (object) => object.energy < object.energyCapacity,
Expand Down Expand Up @@ -94,7 +120,7 @@ roles.carry.handleMisplacedSpawn = function(creep) {
}
};

roles.carry.preMove = function(creep, directions) {
roles.carry.preMove = function(creep, directions, routeLength, pathLength) {
roles.carry.checkHelperEmptyStorage(creep);

if (roles.carry.handleMisplacedSpawn(creep)) {
Expand Down Expand Up @@ -122,7 +148,9 @@ roles.carry.preMove = function(creep, directions) {

let reverse = false;
if (!creep.memory.routing.reverse) {
reverse = creep.checkForTransfer(directions.forwardDirection);
if (config.carry.transferToCarry) {
reverse = creep.checkForTransfer(directions.forwardDirection);
}
if (!reverse && creep.isStuck() && directions.backwardDirection) {
const adjacentPos = creep.pos.getAdjacentPosition(directions.backwardDirection);
if (adjacentPos.isValid()) {
Expand Down Expand Up @@ -164,6 +192,35 @@ roles.carry.preMove = function(creep, directions) {
}

reverse = creep.pickupWhileMoving(reverse);

// recycle carry
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not like the recycling idea sooo much.

If there is a problem with too many carries, the call carry logic should be improved.
But fine until the call carry logic is better.

Copy link
Contributor Author

@kahojyun kahojyun Sep 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ultimate solution to call carry logic would be #294. My solution is making use of 'negative feedback'. The latter one is not as efficient as the former one, but it's easier to be implemented, and, in my opinion, their performance difference is not quite significant.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with adding this one and I'm also not so sure about the perfect solution, especially due to the fact that paths should be shared over multiple sources, which makes it more tricky.

if (pathLength) {
const routing = creep.memory.routing;
if (routing.routePos === routeLength - 1 && routing.pathPos === pathLength - 2) {
if (creep.isStuck() && !reverse) {
creep.memory.resetTarget = true;
}
roles.carry.ensureOne(creep);
}
}
if (creep.memory.resetTarget) {
reverse = true;
creep.say('reset');
if (creep.inBase()) {
if (creep.ticksToLive > config.carry.recycleThreshold && roles.carry.reset(creep)) {
creep.memory.resetTarget = false;
} else {
const spawn = creep.pos.findClosestByRangePropertyFilter(FIND_MY_STRUCTURES, 'structureType', [STRUCTURE_SPAWN]);
if (spawn && spawn.recycleCreep(creep) === 'OK') {
return true;
} else if (creep.memory.routing.pathPos === 0) {
creep.memory.recycle = true;
return true;
}
}
}
}

if (reverse) {
// creep.log('reverse');
directions.direction = directions.backwardDirection;
Expand Down Expand Up @@ -249,6 +306,10 @@ roles.carry.action = function(creep) {

creep.memory.routing.reached = false;
creep.memory.routing.reverse = true;
if (!creep.memory.helper) {
creep.memory.resetTarget = true;
roles.carry.ensureOne(creep);
}

return true;
};
Expand Down