Setting creep spawn que priority order



  • I am having a lot of trouble the game spawning less important creeps before harvesters which thereby results in my population dying out. I have tried to formulate a priority order in my code but it has no worked so far. Would someone be able to help me with what I am doing wrong? I tried nesting 'if' and 'else if' statements before my code but this did not work. I also tried:

    let stage1 = _(Game.creeps).filter( { memory: { role: 'harvester' } } ).size(4);

    let stage2 = _(Game.creeps).filter( { memory: { role: 'extender' } } ).size(2);

     if(stage1 === false) {
    if(harvesters.length < 4) {
        var newName = 'harvester' + Game.time;
        console.log('Spawning new harvester: ' + newName);
        Game.spawns['Spawn1'].spawnCreep([WORK,WORK,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE,MOVE,MOVE], 
     newName, 
            {memory: {role: 'harvester'}});
    }}
    
     else if (stage1 === true) {   
    if(extenders.length < 0) {
        var newName = 'extender' + Game.time;
        console.log('Spawning new extender: ' + newName);
        Game.spawns['Spawn1'].spawnCreep([CARRY,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE,MOVE,MOVE], 
       newName, 
            {memory: {role: 'extender'}});
    }}
    
    if(stage1 & stage2 === true) {
            if(southharvesters.length < 0) {
        var newName = 'southharvester' + Game.time;
        console.log('Spawning new southharvester: ' + newName);
        Game.spawns['Spawn1'].spawnCreep([WORK,WORK,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE,MOVE], newName, 
            {memory: {role: 'southharvester'}});        
    }}   
    

    This pattern I continued on through all my different creep roles in order of priority but it did not work although no error message came up. Is there a particular way in javascript which is best to create priority ques? Thanks for your help.



  • I just want to point out that none of the roles were set at .length < 0 when I actually tried the code.



  • @nanocraft I'm quite a noob, and would be better if a more skilled person helps you, but i use that nested if/else system you mention and it works perfectly for me.

    First i count every creep that belongs to a room and split them into roles. And then...

    if(totalRefillers < desiredRefillers){                CreateCreep.run(thisRoom, 'refiller',   {});
    }else if(totalMiners < desiredMiners){                            CreateCreep.run(thisRoom, 'miner',      {});
    }else if(totalLinkManagers < desiredLinkManagers){          CreateCreep.run(thisRoom, 'linkManager',{});
    }else if(totalScavengers < desiredScavengers){              CreateCreep.run(thisRoom, 'scavenger',  {});
    }else if(totalBuilders < desiredBuilders){                  CreateCreep.run(thisRoom, 'builder',    {});
    }else if(totalRepairers < desiredRepairers){                CreateCreep.run(thisRoom, 'repairer',   {});
    }else if(totalUpgraders < desiredUpgraders){                CreateCreep.run(thisRoom, 'upgrader',   {});
    }
    

    So as soon as it finds one that this room lacks of, will spawn it and ignore the rest.



  • @Calfa OK first lets cleanup your formatting a little to get more readability:

    NanoCraft:

    if (stage1 === false) {
        if (harvesters.length < 4) {
            var newName = 'harvester' + Game.time;
            console.log('Spawning new harvester: ' + newName);
            Game.spawns['Spawn1'].spawnCreep([WORK, WORK, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE],
                newName, {
                    memory: {
                        role: 'harvester'
                    }
                });
        }
    } else if (stage1 === true) {
        if (extenders.length < 0) {
            var newName = 'extender' + Game.time;
            console.log('Spawning new extender: ' + newName);
            Game.spawns['Spawn1'].spawnCreep([CARRY, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE],
                newName, {
                    memory: {
                        role: 'extender'
                    }
                });
        }
    }
    
    if (stage1 & stage2 === true) {
        if (southharvesters.length < 0) {
            var newName = 'southharvester' + Game.time;
            console.log('Spawning new southharvester: ' + newName);
            Game.spawns['Spawn1'].spawnCreep([WORK, WORK, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE], newName, {
                memory: {
                    role: 'southharvester'
                }
            });
        }
    }
    

    Calfa:

    if (totalRefillers < desiredRefillers) {
        CreateCreep.run(thisRoom, 'refiller', {});
    } else if (totalMiners < desiredMiners) {
        CreateCreep.run(thisRoom, 'miner', {});
    } else if (totalLinkManagers < desiredLinkManagers) {
        CreateCreep.run(thisRoom, 'linkManager', {});
    } else if (totalScavengers < desiredScavengers) {
        CreateCreep.run(thisRoom, 'scavenger', {});
    } else if (totalBuilders < desiredBuilders) {
        CreateCreep.run(thisRoom, 'builder', {});
    } else if (totalRepairers < desiredRepairers) {
        CreateCreep.run(thisRoom, 'repairer', {});
    } else if (totalUpgraders < desiredUpgraders) {
        CreateCreep.run(thisRoom, 'upgrader', {});
    }
    

    This might looks like a minor detail but it helps if you ask people for a code review, nobody wants to deal with a confuse formatting.
    Its best practice to use beautifier tools for that. There are plenty to chose from, even online versions.
    Oh and you will thank yourself for that if you revisit your code after a while.

    @NanoCraft so the first problem I see is that you use a === true instead of a == true and the second one a & b === true is a complete disaster 😉
    Lets fix that, js uses i.e. &, && and &&& for completely different kinds of comparison:

    • A single one is used for a bit wise comparison <- this is where you can make your code efficient if you are confident with binary stuff
    • A double one is used for a logical comparison <- the most used one and the one you need
    • A tripple one checks if it is exactly the same object <- you need this very rare

    Now some other advice, even corrected if(a == true) you would do almost unnecessary stuff.
    A if statement only cares if it is true or not, that means simply if(a){do true stuff}else{do false stuff} would suffice but is is safer to compare it to a bool in case it isn't a bool.
    So your last statement could look like: if(stage1 && stage2)but if you still want to use the bool comparison it gets a bit tricky,
    since you need to make that check first: if((stage1 == true) && (stage2 == true)) the parenthesis force the execution order.

    A note on Calfas solution: The nice thing is the priority is from top to bottom and easily adjustable by moving the lines around.

    Here is a version of his solution where the priority is from bottom to top

    let creepToSpawn = "none";
    if (totalRefillers < desiredRefillers) {
        creepToSpawn = 'refiller';
    }
    if (totalMiners < desiredMiners) {
        creepToSpawn = 'miner';
    }
    if (totalLinkManagers < desiredLinkManagers) {
        creepToSpawn = 'linkManager';
    }
    if (totalScavengers < desiredScavengers) {
        creepToSpawn = 'scavenger';
    }
    if (totalBuilders < desiredBuilders) {
        creepToSpawn = 'builder';
    }
    if (totalRepairers < desiredRepairers) {
        creepToSpawn = 'repairer';
    }
    if (totalUpgraders < desiredUpgraders) {
        creepToSpawn = 'upgrader';
    }
    if (creepToSpawn != "none") {
        CreateCreep.run(thisRoom, creepToSpawn, {});
    }
    

    The creepToSpawn avoids unnecessary calls and saves CPU but be aware that this will only spawn one creep even if you have more spawns.


    Output finished insert input below 😄



  • @mrfaul said in Setting creep spawn que priority order:

    This might looks like a minor detail but it helps if you ask people for a code review, nobody wants to deal with a confuse formatting.

    Actually it isn't a minor detail for me. I always try to write readable and clean code everytime i ask for help, so i apologize (even if it's not me asking for help this time, but still).

    Its best practice to use beautifier tools for that. There are plenty to chose from, even online versions.

    Looking for one right now!! I always do it, and it's not easy in this forum to format code manually hehe

    A if statement only cares if it is true or not, that means simply if(a){do true stuff}else{do false stuff} would suffice but is is safer to compare it to a bool in case it isn't a bool.

    A different but related question i have is when i have a bool in a creep's memory.

    If i ask for...

    if(creep.memory.isReady){
        //Do stuff
    }
    

    Am i asking if creep.memory.isReady actually exists? Or am i asking if it equals true? This is something i sometimes wonder 🙂

    A note on Calfas solution: It has a flaw that he already fixed in a round about way, if multiple categories are missing it will create a call for each. If you directly call spawnCreep you create a lot of unused creep memory since the instant you call it the memory gets created.

    I don't understan this part. Don't know if it's due to my knowledge of the english language, but Google Translator doesn't help at all 😂

    The nice thing is the priority is from bottom to top and easily adjustable by moving the lines around.

    When nesting ifs/elses, isn't the priority from top to bottom? 😓

    I'm in the need to say how grateful i am people like you spends his time on awesome help and answers like that!

    Cheers!!



  • This post is deleted!


  • @Calfa
    A elseif is nothing other than a short hand, let me elaborate that:

    if(bla){
    	//...do
    }elseif(blup){
    	//... stuff
    }elseif(blop){
    	//...or
    }else{
    	//...the last thing if nothing works
    }
    

    is the same as:

    if(bla){
    	//... Do
    }else{
    	if(blup){
    		//... Stuff
    	}else{
    		if(blop){
    			//... Or
    		}else{
    			//... The last thing if nothing works
    		}
    	}
    }
    

    and I just noted that I completely messed up it was late xD correcting that sry 🙂 read it again

    OK now to your other question:
    if(creep.memory.isReady) will work for your creeps, assuming that you set that flag on birth,
    otherwise it will be undefined and return false.
    On hostile creeps it will throw an error since you don't have access to the memory.



  • @mrfaul Ohh ok, so if i ask for...

    if(creep.memory.isReady) it will return false if either it doesn't exist or equals false, and will return true if it exists and/or it equals true?

    Regarding the if/else nesting, i knew this, but you said above thet the priority is from bottom to top. Isn't it the opposite? from top to bottom? 😕



  • Yes, and read the post again I corrected it with additional changes to demonstrate bottom to top.



  • @mrfaul Before i read it (again), when you say that the priority is from bottom to top, do you mean that the bottom has the least priority and the top has the most? This is how i understand it, but thought you were saying the opposite:

    if(true){
        //do 1
    }else if(true){
        //do 2
    }else if(true){
        //do 3
    }
    //....
    

    For me, in this example, "1" has the highest piority and that's why it's checked first, and bottom ("3"), has the least and that's why it's at the bottom. This is the logic i followed to spawn creeps: The most important roles like haulers or miners at the top.

    EDIT: @MrFaul Now i finally understand what you meant when you said the priority was from bottom to top, and why i solved it without even being conscious about it. @W4rl0ck made me realize when he told me that....

    ... but if you have two calls calling to spawn a creep on the same spawn the last one will get executed.