Help with Stranded In the Dunes


#1

Hi, I’m working on the new stage, really looking forward to trying out the new character! But I’m having some problems with my code. I’m just Javascript.

loop {
    var enemies = this.findEnemies();
    var enemyIndex = 0;
    var flag = this.findFlag("green");
    var soldiers = this.findFriends();
    var soldierIndex = 0;
     
    if (flag) {
        this.move(flag.pos);
        this.pickUpFlag(flag);
    }
    else if (this.gold > this.costOf("soldier")) {
       this.summon("soldier");
    }
    else {
        while (enemyIndex < enemies.length) {
            var enemy = enemies[enemyIndex];
            enemyIndex++;
             
            if (enemy.type !== "sand-yak") {
                while (enemy.health > 0) {
                    this.attack(enemy);
                    
                    while (soldierIndex < soldiers.length) {
                        var soldier = soldiers[soldierIndex];
                        soldierIndex++;
                        this.command(soldier, "attack", enemy);
                    }
                }//End WHILE attack loop
            }//End IF not sand-yak conditional
         }//End WHILE enemies loop
    }//End ELSE
    
}

How I see my code working is…

If there is a flag, move to it, pick it up
Also, if I have enough gold, then summon a solider (but only do this when not going after flag)
If there is no flag to move to, and if I dont have the gold to summon… THEN begin the enemy while loop
If the enemy is NOT a sand-yak, then attack it, and also command my soliders to attack it

The first problem I’m having is that my character will stop while moving to the flag, to attack an enemy. This causes problems in this level in the last zone, because she sees the enemies and tries to shoot them, but the wall prevents her from shooting them. So she just stands there blasting away at the wall.

Also, my soldiers are not attacking. I compared this to code from other levels but can’t figure out why they won’t attack.

Also, I guess since we travel from zone to zone, friends can’t follow along. So they just reappear in random locations in the next zone.

This seems like a fun level! Thanks for the help.


#2

What happens when there is no flag, an enemy and you place a flag?

Your problem is that before restarting the loop from the top, you kill every enemy present. This means before your code checks again for flags it will kill every enemy that was there when you entered the first while. What you actually want is probably:

this.findNearestNotYak = function (enemies){
    var score = 99999;
    var nearest = null;
    
    for (var i in enemies){
        if (enemies[i].type != "sand-yak" && this.distanceTo(enemies[i]) < score){
            nearest = enemies[i];
            score = this.distanceTo(enemies[i]);
        }
    }
    return nearest;
};

loop{
    // Everything before the if

    //------------------------------------------------------------------
    //            Flag Collection
    //------------------------------------------------------------------
    if (flag) {
        this.pickUpFlag(flag);     //no move needed, this already causes a move
        continue;
    }
    
    //------------------------------------------------------------------
    //            Soldier spawning
    //------------------------------------------------------------------
    while (/*gold>costOf*/){
        //spawn soldier
    }

    //------------------------------------------------------------------
    //            Enemy killing
    //------------------------------------------------------------------    
    var nearest = this.findNearestNotYak(enemies);
    if(nearest){
        /*
         * Order every soldier to attack as you did above
         */
        this.attack(nearest);
        continue;
    }
    
    //------------------------------------------------------------------
    //            Safety Waiting
    //------------------------------------------------------------------ 
    this.wait(0.1);
}

The method at the beginning (findNearestNoYak) is just a custom method. It finds the nearest enemy that is not a sand-yak or null if no such enemy exists.

Now to the strange continue in the Flag Collection-part. This causes your program to jump directly to the start of the innermost loop it is in (in this case the big loop). Why do we want that? Well, while you moved to collect the flag the world around you might have changed. New enemies, enemies that are now closer, allies that were alive and aren’t anymore… It is usually better to find everything again after you performed an action. Therefore we want to jump back to the beginning of the loop, and this is the easiest way to do so.

Soldier spawning is now a separate step. Remember, it will only be called if there is no flag, because if there is a flag we jump back to the beginning of the loop. Therefore we don’t have to put it in an else-clause. I also changed the if to a while to spawn multiple soldiers if possible. Just my own convenience usually.

Now for the Enemy Killing-part. You worked down the whole enemy-list. Well well, but this list is usually not ordered. You might spend most of your time running around. Much more convenient to just attack the nearest. The way I did it allows you to place a flag during an attack. Your hero hits the enemy, continues to the beginning, checks if their is a flag or new soldiers can be spawned and attacks again. This is much better than locking yourself in the desire to kill each and every enemy to the death.

The last part, the Safety Waiting-part is a bit special. If you take no action (move, attack, …), your code will run very, very often. You will quickly hit HEL, the Hard Execution Limit. This is a mechanism that stops your code from running to all eternity, for example in an infinite loop. To slow this down I built in a wait-timer of 0.1 seconds. This mean your loop will not idle more than 10 times per second, giving you a quick enough response time if something happens while still stopping you from reaching HEL.
Just remember that if you either find a flag or an enemy the code will continue to the beginning, thus skipping the wait part. This way of coding requires a bit more thinking, but it boils down to

Skip commands that can’t be executed until you find one that can, then start from the beginning.


#3

Wow, @J_F_B_M, this response was amazing. I’ve learned so much from your code and also your explanation of everything!

I really appreciate the effort! I’ll report back with my results!


#4

It worked! I got a bit tripped up on where to define my enemies variable, but finally figured it out, and it works great! There were a couple times in the final zone where my ranged character would still get stuck trying to fire on an enemy even when I had placed a flag, but she finally seemed to move along.

Thanks again, this was a very insightful answer to my question! I kind of want to post questions on stages that I’ve already passed just to see what else there is to learn!


#5

Feel free, though at the moment I’m a little occupied with University (IT, what else?). Just be sure to mention me with @J_F_B_M, otherwise I might miss it.