Search code examples
javascriptalgorithmloopsscreeps

Finding structure with highest energy screeps


So I have this creep role called storer that is supposed to go fetch energy from containers and bring it to the storage. However, currently, it finds the container closest by Path and with an energy level greater to a certain threshold so that it doesn't wait there for hours every time a miner refills the container.

The problem I have is if I lower the threshold, the storer will run back and forth to the same containers, ignoring any containers further in the room and letting them fill up.
And raising the threshold will make him sit out and wait for too long, not giving him enough time to empty containers and thus the storage will be empty almost all the time.

I need a way for the creep to determine the container with the highest energy and fill up from there.

Here's the code its running:

if ((source = creep.pos.findClosestByPath(FIND_STRUCTURES, {filter: (s) => {return (s.structureType == STRUCTURE_CONTAINER && s.store[RESOURCE_ENERGY] >= 150)}})) != undefined) {
    if (creep.withdraw(source, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
        creep.moveTo(source);
    }
}

EDIT: here's the code I tried, but I feel like it is using too much CPU power and can be done in a better way:

for (let i = 2000; i>=0; i=i-100) {
    source = creep.pos.findClosestByPath(FIND_STRUCTURES, {filter: (s) => {return s.structureType == STRUCTURE_CONTAINER && s.store[RESOURCE_ENERGY] >= i}});
        if (source != undefined) {
            break;
        }
    }
    if (creep.withdraw(source, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
        creep.moveTo(source);
    }
}

Solution

  • What you can do is loop trough all the containers once, get their energy level and pick the highest one. Set a value when the creep is working so the creep dosen't move to another container if he get higher.

    This is the code i made for the storer role:

    module.exports = {
    
      run: function( creep ) {
    
        // Setting the working variable so the creep focus
        // on getting the ressource or returning it.
        if ( creep.memory.working && creep.carry.energy == 0 ) {
            creep.memory.working = false;
        }
    
        if ( ! creep.memory.working && creep.carry.energy == creep.carryCapacity ) {
            creep.memory.working = true;
            creep.memory.targetContainer = false;
        }
    
        if ( creep.memory.working ) {
    
            // Bring the ressources to the storage.
            var theStorage = creep.pos.findClosestByRange(FIND_MY_STRUCTURES, {
                filter: (structure) => {
                    return (structure.structureType == STRUCTURE_STORAGE );
                }
            });
    
            if ( creep.transfer( theStorage, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
                creep.moveTo( theStorage );
            }
    
        } else {
    
            // If the creep have a target.
            if ( creep.memory.targetContainer ) {
    
                // Go to the container.
                var theContainer = Game.getObjectById( creep.memory.targetContainer );
    
                if ( creep.withdraw( theContainer, RESOURCE_ENERGY ) == ERR_NOT_IN_RANGE ) {
                    creep.moveTo( theContainer );
                }
    
            } else {
    
                // Find the container with the most energy.
                var target = creep.room.find( FIND_STRUCTURES, {
                    filter: (structure) => {
                        return (structure.structureType == STRUCTURE_CONTAINER );
                    }
                });
    
                if ( target.length ) {
    
                    var allContainer = [];
    
                    // Calculate the percentage of energy in each container.
                    for ( var i = 0; i < target.length; i++ ) {
    
                        allContainer.push( { energyPercent: ( ( target[i].store.energy / target[i].storeCapacity ) * 100 ), id: target[i].id } );
    
                    }
    
                    // Get the container containing the most energy.
                    var highestContainer = _.max( allContainer, function( container ){ return container.energyPercent; });
    
                    console.log( 'Going for the container id "' + highestContainer.id + '" at ' + highestContainer.energyPercent + '% full.' );
    
                    // set the target in memory so the creep dosen't
                    // change target in the middle of the room.
                    creep.memory.targetContainer = highestContainer.id;
    
                }
            }
        }
      }
    };