Created
March 20, 2016 15:54
-
-
Save derofim/72b7a5e1a57b77877892 to your computer and use it in GitHub Desktop.
Path cache for screeps
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = (function () { // store and reuse often used paths | |
function addPath(from, to, path) { | |
var key = getPathKey(from, to); | |
var cache = Memory.pathCache || {}; | |
var cachedPath = { | |
path: path, | |
uses: 1 | |
} | |
cache[key] = cachedPath; | |
Memory.pathCache = cache; | |
} | |
function getPath(from, to) { | |
var cache = Memory.pathCache; | |
if(cache) { | |
var cachedPath = cache[getPathKey(from, to)]; | |
if(cachedPath) { | |
cachedPath.uses += 1; | |
Memory.pathCache = cache; | |
return cachedPath; | |
} | |
} | |
} | |
function cleanCache() { | |
//cleanCacheByUsage(1); | |
} | |
function cleanCacheByUsage(usage) { | |
if(Memory.pathCache && _.size(Memory.pathCache) > 1500) { //1500 entries ~= 100kB | |
console.log('Cleaning path cache (usage == '+usage+')...'); | |
var counter = 0; | |
for (var key in Memory.pathCache) { | |
var cached = Memory.pathCache[key]; | |
if(cached.uses === usage) { | |
Memory.pathCache[key] = undefined; | |
counter += 1; | |
} | |
} | |
Game.notify('Path cache of usage '+usage+' cleaned! '+counter+' paths removed', 6 * 60); | |
cleanCacheByUsage(usage + 1); | |
} | |
} | |
// require('pathCache').showCacheUsage(); | |
function showCacheUsage() { | |
var usageCountCounter = {}; | |
var howManyTimesCacheUsed = 0; | |
for (var key in Memory.pathCache) { | |
var cached = Memory.pathCache[key]; | |
usageCountCounter['used'+cached.uses] = usageCountCounter['used'+cached.uses] + 1 || 1; | |
howManyTimesCacheUsed += cached.uses; | |
} | |
console.log(JSON.stringify(usageCountCounter)); | |
console.log('howManyTimesCacheUsed: ' + howManyTimesCacheUsed); | |
console.log('cache size: ' + _.size(Memory.pathCache)); | |
} | |
function getPathKey(from, to) { | |
//console.log("getPathKey= "+getPosKey(from) + '$' + getPosKey(to)); | |
return getPosKey(from) + '$' + getPosKey(to); | |
} | |
function getPosKey(pos) { | |
return pos.x + 'x' + pos.y + pos.roomName; | |
} | |
return { | |
add: addPath, | |
get: getPath, | |
clean: cleanCache, | |
showCacheUsage: showCacheUsage | |
} | |
}()); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var pathCache = require('path_cache'); | |
var MINE_FLAG = 1, MINE_FIND =2; | |
module.exports = { | |
PATH_FAIL : -1, | |
PATH_FOUND : 1, | |
PATH_CHANGED : 2, | |
PATH_WALKING : 3, | |
PATH_END : 4, | |
PATH_ERROR : 5, | |
onSpawn: function(creep) { | |
this.creep = creep; | |
creep.memory.onSpawned = true; | |
creep.memory.last_path_broken_wait = 0; | |
creep.memory.broken_attemts = 0; | |
creep.memory.curTask = MINE_FIND; | |
}, | |
run : function (creep) { | |
if (creep.memory.onSpawned === undefined) this.onSpawn(creep); | |
if(creep.memory.curTask==MINE_FLAG) { | |
this.goFlag(creep, FIND_FLAGS, COLOR_GREEN); | |
} else if(creep.carry.energy < creep.carryCapacity) { | |
this.collectEnergy(creep, FIND_SOURCES_ACTIVE); | |
} | |
else { | |
this.storeEnergy(creep, FIND_MY_SPAWNS); | |
} | |
}, | |
collectEnergy: function ( creep, target ) // example target: FIND_SOURCES_ACTIVE | |
{ | |
var aim = creep.pos.findClosestByPath(target); | |
if(aim){ | |
var path_result = this.moveByMemoryPathTo(creep, aim, 1); //console.log("path result: "+ result); | |
if(path_result == this.PATH_END && creep.harvest(aim) == ERR_NOT_IN_RANGE) console.log("bug_path"); | |
} | |
}, | |
goFlag: function ( creep, target, color ) // example {target: FIND_FLAGS, color:COLOR_GREEN} | |
{ | |
var aim = creep.pos.findClosestByRange(target, { | |
filter: function(x) { | |
if(x.color == color) return true; | |
return null; | |
} | |
}); | |
if(aim){ | |
creep.memory.curTask=MINE_FLAG; | |
var path_result = this.moveByMemoryPathTo(creep, aim, 1); //console.log("path result: "+ result); | |
if(path_result == this.PATH_END) creep.memory.curTask=MINE_FIND; | |
} | |
}, | |
storeEnergy: function ( creep, target ) // example target: FIND_MY_SPAWNS | |
{ | |
//console.log(1); | |
var aim = creep.pos.findClosestByRange(target, { | |
filter: function(x) { | |
if(x.energy < x.energyCapacity) return true; | |
return null; | |
} | |
}); | |
if(aim){ | |
//console.log(2); | |
// | |
// | |
// | |
// | |
// | |
var path_result = this.moveByMemoryPathTo(creep, aim, 1); //console.log("path result: "+ result); | |
if(path_result == this.PATH_END && creep.transfer(aim, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) console.log("bug_path"); | |
} else this.goFlag(creep, FIND_FLAGS, COLOR_GREEN); | |
}, | |
/** | |
/* Use for moving to almost static target (flag, source, e.t.c.) | |
/* distance: min allowed final distance between creep and target (for example, 1 if target is source) | |
/* Note: Stuck ticks: if creep is moving by target path and dont move N ticks, than path refreshes. | |
/* Note: If distance not correct, than creep may stay harvesting/building/e.t.c and stuck ticks will increase! | |
/* findPathTo: If the target is in another room, then the corresponding exit will be used as a target => recreate path! | |
**/ | |
moveByMemoryPathTo : function ( creep, target, distance ) | |
{ | |
if( !creep || creep.spawning || creep.fatigue>0 ) return this.PATH_FAIL; | |
if ( creep.pos.getRangeTo(target)<=distance) return this.PATH_END; // if at position | |
if( !creep.memory.path || !creep.memory.path[creep.memory.path.length-1] || creep.memory.ticks_stuck && creep.memory.ticks_stuck > creep.memory.path.length) // if no path or stuck for N ticks | |
{ | |
creep.memory.path = this.setPathTo(creep, target, distance); | |
if(creep.memory.path) return this.PATH_FOUND; // if new path created | |
else return this.PATH_FAIL; // if cant find path | |
} else if ( !target.pos.isEqualTo( creep.memory.path[creep.memory.path.length-1].x, creep.memory.path[creep.memory.path.length-1].y ) ) { // path changed | |
creep.memory.path = this.setPathTo(creep, target, distance); | |
return this.PATH_CHANGED; | |
} else if ( creep.pos.getRangeTo(target)>distance) { // if not at position | |
if(creep.fatigue==0) creep.memory.prev_pos = creep.pos; | |
if(creep.moveByPath(creep.memory.path)<0) { | |
creep.memory.ticks_stuck = 99999; | |
return this.PATH_ERROR; | |
} | |
if( creep.pos.isEqualTo(creep.memory.prev_pos) && creep.fatigue==0) { | |
//console.log("stuck ticks" + creep.memory.ticks_stuck); | |
creep.memory.ticks_stuck++; // increases every move too! Check like (stuck > creep.memory.path.length-2) | |
} else { | |
creep.memory.ticks_stuck = 0; | |
} | |
return this.PATH_WALKING; | |
} | |
// if strage thing happens 0_o | |
creep.memory.ticks_stuck = 99999; | |
return this.PATH_ERROR; | |
}, | |
setPathTo : function(creep, target, distance){ | |
// check if path marked as broken | |
if(creep.memory.path_target_id == target.id && creep.memory.last_path_broken_wait!==undefined && creep.memory.last_path_broken_wait>0) | |
{ | |
creep.memory.last_path_broken_wait--; | |
//console.log("skipping broken path for "+creep.memory.last_path_broken_wait); | |
return; | |
} | |
// create new path | |
if(Memory.pathCache.length>500) { | |
console.log("total clean of Memory.pathCache"); | |
delete Memory.pathCache; | |
} | |
if(!Memory.pathCache) Memory.pathCache = {}; // ToDo: Startup init | |
var path,uses; | |
if(Memory.pathCache[this.getPathKey(creep.pos,target.pos)]!==undefined) | |
{ | |
path = Memory.pathCache[this.getPathKey(creep.pos,target.pos)].path; | |
uses = Memory.pathCache[this.getPathKey(creep.pos,target.pos)].uses || 0; | |
} else { | |
path = creep.pos.findPathTo(target); | |
uses = 0; | |
console.log(creep.name + ' pathfind..' + ' key: ' + this.getPathKey(creep.pos,target.pos)); | |
} | |
if( path ) // if radius to target very small, than path may be reused | |
{ | |
Memory.pathCache[this.getPathKey(creep.pos,target.pos)] = { path: path, uses: ++uses }; | |
console.log(creep.name + ' using time ' + uses + ' key: ' + this.getPathKey(creep.pos,target.pos)); | |
if(uses>30) { // clean some cache | |
console.log("before"+_.size(Memory.pathCache)); | |
delete Memory.pathCache[this.getPathKey(creep.pos,target.pos)]; | |
for (var key in Memory.pathCache) { | |
var cached = Memory.pathCache[key]; | |
if(cached.uses<5) delete Memory.pathCache[key]; | |
} | |
console.log("after"+_.size(Memory.pathCache)); | |
} | |
} | |
creep.memory.path = path; | |
//console.log("found path to creep " + creep.id + ", length" + creep.memory.path.length); | |
creep.memory.path_target_id = target.id; | |
creep.memory.ticks_stuck = 0; | |
creep.memory.prev_pos = creep.pos; | |
if(creep.memory.path && creep.memory.path[creep.memory.path.length-1] && target.pos.isEqualTo( creep.memory.path[creep.memory.path.length-1].x, creep.memory.path[creep.memory.path.length-1].y ) ){ | |
creep.memory.last_path_broken_wait = 0; | |
creep.memory.broken_attemts = 0; | |
return creep.memory.path; | |
} | |
// if final path does not exist | |
creep.memory.last_path_broken_wait = 5; // ticks to wait for next check | |
creep.memory.broken_attemts++; | |
console.log("creep.memory.broken_attemts for "+creep.name+" = "+creep.memory.broken_attemts); | |
if(creep.memory.broken_attemts>1) { // Maybe creeps blocked each other, send them home | |
creep.memory.ticks_stuck = 99999; | |
this.goFlag(creep, FIND_FLAGS, COLOR_GREEN); | |
} | |
return null; | |
}, | |
getPathKey : function(from, to) { | |
return this.getPosKey(from) + '$' + this.getPosKey(to); | |
}, | |
getPosKey : function (pos) { | |
return pos.x + 'x' + pos.y + pos.roomName; | |
}, | |
}; |
Author
derofim
commented
Mar 22, 2016
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment