Rilcon42
Rilcon42

Reputation: 9763

Screeps- How to make path calculation consistent?

I have a prototype to create a room layout. I am trying to calculate the location to place a container as:

the closest point between the spawn and the controller that is one unit away from the controller

For some reason it appears to give me multiple values (possibly due to the pathing algorithm) which is Jump Point according to the API. How can I get the same result every time, not three different points?

Room.prototype.layoutRoom=function(){
    var s:Spawn=this.spawns()[0]
    var c:Controller=this.controller;

    //get path from spawn to controller
    var path = this.findPath(s.pos, c.pos, {ignoreDestructibleStructures: true});

    //place container on last part of path -3 to stay 1 away from controller, and closest to spawn
    //length-1= on endpoint, -2 is one step away, -3 is two steps away 
    var loc=path[path.length-3]
    console.log('layout room, put container: '+loc.x+' '+loc.y)
    this.createConstructionSite(loc.x, loc.y, STRUCTURE_CONTAINER);
}

Running the code above multiple times (which is required) results in multiple construction sites:

enter image description here

Upvotes: 0

Views: 732

Answers (2)

Jake
Jake

Reputation: 11

So the other answer covers this, it would be consistent if you changed your findPath to something more like var path = this.findPath(s.pos, c.pos, {ignoreDestructibleStructures: true, ignoreCreeps: true});

However, since the name of the game is to save CPU, you really don't want to be calculating this path every tick.

You could save the container location in memory, or first check that a container has been built within one tile of the controller.


Option A - Saving the location in memory

This would be my personally preferred option as I make use of memory quite often. Keep in mind, to this solution I added a lot of extra code that you don't need to make it work, but will keep your code safer and less error prone within this context.

Room.prototype.layoutRoom=function(forceUpdate: boolean){
    var s: Spawn = this.spawns()[0];
    var c: Controller = this.controller;
    
    // Adding this to check that this spawn/controller exists (or code will error out if one doesn't exist)
    if(!s || !c){
        return;
    }
    // Check if a memory value has been set for this container already, and we aren't forcing the location to update via parameter; we can end early otherwise
    if(this.memory.controllerContainer && !forceUpdate){
        // you could uncomment this out to have it place a site on the same location if we find the location is saved in memory already
        // var loc = this.memory.controllerContainer;
        // this.createConstructionSite(controllerContainer.x, controllerContainer.y, STRUCTURE_CONTAINER);
        return;
    }

    //get path from spawn to controller
    var path = this.findPath(s.pos, c.pos, {
        ignoreDestructibleStructures: true, ignoreCreeps: true
    });

    //place container on last part of path -3 to stay 1 away from controller, and closest to spawn
    //length-1= on endpoint, -2 is one step away, -3 is two steps away 
    var loc=path[path.length-3];
    console.log('layout room, put container: '+loc.x+' '+loc.y);
    
    // Note that I am not saving the RoomPosition object into memory, when the JSON parses 
    // your memory back out you won't be able to use it as a RoomPosition object, so its safer 
    // to save as a custom object that mimics Room position and have a function available to convert 
    // it to one if you need to use it as one for the purpose of passing as a parameter to something
    this.memory.controllerContainer = {x: loc.x, y: lox.y};
    this.createConstructionSite(loc.x, loc.y, STRUCTURE_CONTAINER);
}

Option B - Without using memory

This option would have the same affect, as if the container site or the container exists already by the controller, it won't attempt to build another site.

Room.prototype.layoutRoom=function(){
    var s: Spawn = this.spawns()[0];
    var c: Controller = this.controller;
    
    // Adding this to check that this spawn/controller exists (or code will error out if one doesn't exist)
    if(!s || !c){
        return;
    }

    // Check if a construction site or container exists near the controller, exit if so
    // For brevity, i will include here, but normally I would pull this into its own function
    var numConstructionSites = room.find(FIND_CONSTRUCTION_SITES, { filter: (site) => 
        site.isNearTo(c) && site.structureType === STRUCTURE_CONTAINER
    }).length;
    var numExistingContainers = room.find(FIND_STRUCTURES, { filter: (struct) => 
        struct.isNearTo(c) && struct.structureType === STRUCTURE_CONTAINER
    }).length;
    if(numConstructionSites > 0 || numExistingContainers > 0) {
        return;
    }

    //get path from spawn to controller
    var path = this.findPath(s.pos, c.pos, {
        ignoreDestructibleStructures: true, ignoreCreeps: true
    });

    //place container on last part of path -3 to stay 1 away from controller, and closest to spawn
    //length-1= on endpoint, -2 is one step away, -3 is two steps away 
    var loc=path[path.length-3];
    console.log('layout room, put container: '+loc.x+' '+loc.y);
    this.createConstructionSite(loc.x, loc.y, STRUCTURE_CONTAINER);
}

Upvotes: 1

Chawit.O
Chawit.O

Reputation: 53

By default path finding will treat creeps as impassable tile. To fix this you add this to the option:

ignoreCreeps: true

Upvotes: 1

Related Questions