Play Home Contribute Github Join Us! Discourse Staff Members Github Contribution Guides Team

Library Tactician - JS - Archers leave position?

Hi. I have been working on library tactician and can’t figure out why my archers leave their spots all of sudden 10 seconds in. The array is not looping or something like that? I am teaching this level (even though I do not currently have a teacher’s license) so any strategies on how to explain this concept would be appreciated greatly! Code below. Thank you

function findStrongestTarget() {
        var mostHealth = 0;
        var bestTarget = null;
        var enemies = hero.findEnemies();
        var enemyIndex = 0;
        while(enemyIndex < enemies.length) {
        var enemy = enemies[enemyIndex];
            if (enemy.health > mostHealth) {
            bestTarget = enemy;
            mostHealth = enemy.health;
        }
    enemyIndex++;
    }
    // Only focus archers' fire if there is a big ogre.
    if (bestTarget && bestTarget.health > 15) {
        return bestTarget;
    } else {
        return null;
    }
}



// If the strongestTarget has more than 15 health, attack that target. Otherwise, attack the nearest target.
function commandArcher(archer) {
    var nearest = archer.findNearest(hero.findEnemies());
    if(archerTarget) {
        hero.command(archer, "attack", archerTarget);
    } else if(nearest) {
        hero.command(archer, "attack", enemy);
    }


var archerTarget = null;
while(true) {
    // If archerTarget is defeated or doesn't exist, find a new one.
    if(!archerTarget || archerTarget.health <= 0) {
        // Set archerTarget to be the target that is returned by findStrongestTarget()
       archerTarget = findStrongestTarget();
    }
    var friends = hero.findFriends();
    var soldiers = hero.findByType("soldier");
    // Create a variable containing your archers.
    var archers = hero.findByType("archer");
    for(var i=0; i < archers.length; i++) {
        archer = archers[i];
        commandArcher(archer, i, archers.length);
    }
    // use commandArcher() to command your archers
    commandArcher(archer);
}
}

Hi 2Flowers, welcome to the Forum. Brilliant that you’re using CoCo to teach :smile:

    for(var i=0; i < archers.length; i++) {
        archer = archers[i];
        commandArcher(archer, i, archers.length);

I think the problem is the last of these lines. If you look back to where you defined the function, it only had one input (ie one thing in the brackets); and you’re now calling the function with 3 inputs. So delete the “, i, archers.length”, so that the function can run.

Try that, post again if you want more help or a longer explanation!

2 Likes

Actually, since the function is expecting a single argument, only the first one is accepted…the other two are simply ignored. However, it is best practice to ‘clean up’ your code wherever possible.

2 Likes

There you go, useful to know :slight_smile:. Thanks @dedreous.

The other thing I noticed was that:

checks nearest and then attacks enemy.

2 Likes

Hmm. I tended to each of those recommendations. Thank you all. The archers still move and leave Hushbaum exposed, which summons the extra baddies. Can I ask which part of this very long piece of code would affect the archers staying in place? Do I need to create some kind of mathematical function as exists for the soldiers at the top?

1 Like

Can you show me your recent code?

Andrei

1 Like
// Hushbaum has been ambushed by ogres!
// She is busy healing her soldiers, you should command them to fight!
// The ogres will send more troops if they think they can get to Hushbaum or your archers, so keep them inside the circle!
// Soldiers spread out in a circle and defend.
function commandSoldier(soldier, soldierIndex, numSoldiers) {
    var angle = Math.PI * 2 * soldierIndex / numSoldiers;
    var defendPos = {
        x: 41,
        y: 40
    };
    defendPos.x += 10 * Math.cos(angle);
    defendPos.y += 10 * Math.sin(angle);
    hero.command(soldier, "defend", defendPos);
}
// Find the strongest target (most health)
// This function returns something! When you call the function, you will get some value back.
function findStrongestTarget() {
    // Figure out which enemy has the most health, and set bestTarget to be that enemy.
    var mostHealth = 0;
    var bestTarget = null;
    var enemies = hero.findEnemies();
    var enemyIndex = 0;
    while (enemyIndex < enemies.length) {
        var enemy = enemies[enemyIndex];
        if (enemy.health > mostHealth) {
            bestTarget = enemy;
            mostHealth = enemy.health;
        }
        enemyIndex++;
    }
    // Only focus archers' fire if there is a big ogre.
    if (bestTarget && bestTarget.health > 15) {
        return bestTarget;
    } else {
        return null;
    }
}
// If the strongestTarget has more than 15 health, attack that target. Otherwise, attack the nearest target.
function commandArcher(archer) {
    var nearest = archer.findNearest(hero.findEnemies());
    if (archerTarget) {
        hero.command(archer, "attack", archerTarget);
    } else if (nearest) {
        hero.command(archer, "attack", nearest);
    }
    var archerTarget = null;
    while (true) {
        // If archerTarget is defeated or doesn't exist, find a new one.
        if (!archerTarget || archerTarget.health <= 0) {
            // Set archerTarget to be the target that is returned by findStrongestTarget()
            archerTarget = findStrongestTarget();
        }
        var friends = hero.findFriends();
        var soldiers = hero.findByType("soldier");
        // Create a variable containing your archers.
        var archers = hero.findByType("archer");
        for (var i = 0; i < archers.length; i++) {
            archer = archers[i];
            commandArcher(archer);
        }
        // use commandArcher() to command your archers
        commandArcher(archer);
    }
}

Can you please resend the code, but first press the U button from the workspace from the level and then send it so it will be better formated?

Andrei

1 Like

I updated the code in the post above

1 Like

Do you need this since you commanded all of the archers before this line?

Andrei

I will help you later more (after aprox. 2 hours).

Andrei

1 Like

This section is the complete function. At the moment you’ve got the code beneath being run as part of the function as well. Put another } at the end of the function above.

Also, looking at the code I wrote for the level, I’ve got a for loop for my soldiers which is very similar to the for loop for the archers - ie it runs the commandSoldier function for each of the soldiers. It appears the instructions for the level don’t tell you this!

2 Likes

Jenny’s fix will also result in an extra } at the end of the code…need to account for that, too.

What about:

            archer = archers[i];

Looks kind of barren…

2 Likes

I’m not sure what barren means! Can you clarify how you use that word? Something is missing from that line or the variable assignment is null/barren?

3 Likes

heh…good question actually! In this case:

barren = empty; missing something; not properly defined

4 Likes

@jka2706 I don’t understand why this variable assignment is outside of any loop or function?

var archerTarget = null;

I guess I felt like this level requires a coding logic I didn’t learn from the other levels

Edit: oops, I didn’t scroll up and missed the commandSoldier block.

Think of each section of your code as ‘blocks’ (this is actually what they are referred to as). Your first block is the commandSoldier function…and so on. An outline of it looks like this:

commandSoldier block
findStrongestTarget block
commandArcher block

archerTarget block (even if it is only a single line)

while true block

Placing ‘archerTarget = null’ outside of the other blocks means that you want this line of code to run independently of any other block. It also ensures that the variable you are defining is ‘clean’, or, equals nothing, so you start with a clean slate.

4 Likes

Thank you, I will think on this and work on it.