Library Tactician Javascript Help

// 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!
var archerTarget = null;
// 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);
    var hushbaum = hero.findByType("libraian");
    if (soldier.health < 50) {
        hero.command(soldier, "move", hushbaum.pos);
    }
}
// Find the strongest target (most health)
// This function returns something! When you call the function, you will get some value back.
function findStrongestTarget() {
    var mostHealth = 0;
    var bestTarget = null;
    var enemies = hero.findEnemies();
    // Figure out which enemy has the most health, and set bestTarget to be that enemy.
    for (var i = 0; i < enemies.length; i++) {
        if (enemies[i].health > mostHealth) {
            mostHealth = enemies[i].health;
            bestTarget = enemies[i];
        }
    }
}
// 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.findNearestEnemy();
    if (archerTarget) {
        hero.command(archer, "attack", archerTarget);
    } else if (nearest) {
        hero.command(archer, "attack", nearest);
    }
}
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.
    for (var i = 0; i < soldiers.length; i++) {
        var soldier = soldiers[i];
        commandSoldier(soldier, i, soldiers.length);
    }
    // use commandArcher() to command your archers
    commandArcher();
}```

On line 35 it says “error: best Target is not defined”
What am I doing wrong?

LOL I’m stuck on the same level!
Python though…

Funny
Know anybody who could help?
When are they on?

The leaders are offline right now…

Hi sci12,

Three things:

  • Delete these lines - leave the function as it was written before:
    var hushbaum = hero.findByType("libraian");
    if (soldier.health < 50) {
        hero.command(soldier, "move", hushbaum.pos);
    }
  • Delete one of the } after ‘bestTarget = enemies[i]’, and put it in after the ‘return null’ instead. This will make those lines of code are included in the function.

  • At the bottom, write a for loop to go through archers, and run your commandArcher function for each of them.

Try these things, if you need more help then post your new code again.

Jenny

1 Like

Thank you for the tips.

1 Like
function findStrongestTarget() {
    var mostHealth = 0;
    var bestTarget = null;
}
var enemies = hero.findEnemies();
// Figure out which enemy has the most health, and set bestTarget to be that enemy.
for (var i = 0; i < enemies.length; i++) {
    if (enemies[i].health > mostHealth) {
        mostHealth = enemies[i].health;
        bestTarget = enemies[i];
    }
}
// Only focus archers' fire if there is a big ogre.
if (bestTarget && bestTarget.health > 15) {
    return bestTarget;
} else {
    return null;
}

The error still comes. Sorry I am posting a few days later.

You’ve just posted the function code. Can you post all of your code please?

Jenny

Sure

// 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!
var archerTarget = null;
// 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() {
    var mostHealth = 0;
    var bestTarget = null;
}
var enemies = hero.findEnemies();
// Figure out which enemy has the most health, and set bestTarget to be that enemy.
for (var i = 0; i < enemies.length; i++) {
    if (enemies[i].health > mostHealth) {
        mostHealth = enemies[i].health;
        bestTarget = enemies[i];
    }
}
// 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.findNearestEnemy();
    if (archerTarget) {
        hero.command(archer, "attack", archerTarget);
    } else if (nearest) {
        hero.command(archer, "attack", nearest);
    }
}
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 archer = hero.findByType("archer");
    for (var i = 0; i < soldiers.length; i++) {
        var soldier = soldiers[i];
        commandSoldier(soldier, i, soldiers.length);
    }
    // use commandArcher() to command your archers
    for (var i = 0; i < archer.length; i++) {
        var archer = archer[i];
        commandArcher(archer, i, archer.length);
    }
}

P.S how do you get rid of the red font?
Thanks @Deadpool198 for that change.

You’re using archer as a variable twice, which I suspect is confusing the code.

var archer = hero.findByType("archer");
var archer = archer[i];

Have another look at this bit. You’ve got { and } round it. Is that all the function?

1 Like

I tried that and the error didn’t come, but I still didn’t pass the level.

// 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!
var archerTarget = null;
// 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.
 var mostHealth = 0;
    var bestTarget = null;

function findStrongestTarget() {
   

var enemies = hero.findEnemies();
// Figure out which enemy has the most health, and set bestTarget to be that enemy.
for (var i = 0; i < enemies.length; i++) {
    if (enemies[i].health > mostHealth) {
        mostHealth = enemies[i].health;
        bestTarget = enemies[i];
    }
}
}
// 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.findNearestEnemy();
    if (archerTarget) {
        hero.command(archer, "attack", archerTarget);
    } else if (nearest) {
        hero.command(archer, "attack", nearest);
    }
}
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 archer = hero.findByType("archer");
    for (var i = 0; i < soldiers.length; i++) {
        var soldier = soldiers[i];
        commandSoldier(soldier, i, soldiers.length);
    }
    // use commandArcher() to command your archers
    for (var i = 0; i < archer.length; i++) {
         archer = archer[i];
        commandArcher(archer, i, archer.length);
    }
}

You do want both the variables, but just with different names! Have a look at

var soldiers = hero.findByType("soldier");
and then:
var soldier = soldiers[i];

For the findStrongestTarget function, you have 3 { brackets, and then

    }
}
}

which will end the function. You need to keep the next 4 lines inside the function! You don’t have to indent tidily with JavaScript, but it does make it easier to see chunks of code.

Jenny

1 Like

I tried that but It still says incomplete and I don’t pass @jka2706 .

// 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!
var archerTarget = null;
// 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.
var mostHealth = 0;
var bestTarget = null;
function findStrongestTarget() {
    var enemies = hero.findEnemies();
    // Figure out which enemy has the most health, and set bestTarget to be that enemy.
    for (var i = 0; i < enemies.length; i++) {
        if (enemies[i].health > mostHealth) {
            mostHealth = enemies[i].health;
            bestTarget = enemies[i];
        }
    }
    // 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.findNearestEnemy();
    if (archerTarget) {
        hero.command(archer, "attack", archerTarget);
    } else if (nearest) {
        hero.command(archer, "attack", nearest);
    }
}
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 < soldiers.length; i++) {
        var soldier = soldiers[i];
        commandSoldier(soldier, i, soldiers.length);
    }
    // use commandArcher() to command your archers
    for (var i = 0; i < archers.length; i++) {
        var archer = archers[i];
        commandArcher(archer, i, archer.length);
    }
}

Um… Is anybody online?

Yes I am but I can’t help I don’t understand enough JS :sob: :sob:

You’ve got this slightly confused. You want the:

var mostHealth = 0;
var bestTarget = null;

Inside the function. You don’t need to change anything else, just move them inside the findStrongestTarget() function.
The reason for this is that functions can’t access variables outside their code, so you have to write the variables inside the function.
Danny

4 Likes
// Edit: correct code is not allowed so, I removed it

Here is the new code and it still fails, but it takes longer to fail.
So sorry it doesn’t work and thanks for the help from everybody.

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);
}

How does the math part work? (just interested)

Your code works when I try it!
image

Do you want to try submitting it again, and see? If it doesn’t work, can you tell us what goes wrong?

In answer to your question about how does the function work, then it depends a bit on how much you know about sine, cosine and radians. If these are all new things to you, you might need to go and read up on them (search for trigonometry).

But…seeing as you asked. A radian is just a different way of measuring angles - there are 2π radians in a circle (so one radian is about 57 degrees). Python works in radians, so the angle variable is just working out what how far round the circle each soldier will be if there are numSoldiers number of soldiers. So if there were 4 soldiers, they would have quarter of the circle each and they’d be spaced 1.57 radians (= 90 degrees) round. If there were 12 they’d have a twelth of the circle each, so they’d be spaced 0.52 radians (= 30 degrees) round.

The defendPos position is the centre of the circle. For each soldier, a bit gets added on or taken away from the defendPos x and y to give that soldier’s x and y position. This means they all end up spaced around the circle. The bit that gets added on or taken away is the sine or cosine of the angle - these are formulae that describe the ratio between the length of the sides of a right angle triangle with different angles in the other corners. This picture maybe helps:

image

The blue line stays the same length for each soldier, but as the angles are different, the amount that gets added on or deducted from defendPos is different (ie the green and red lines are different lengths). This means the soldiers all get neatly spaced out.

I want this to be magic, but actually it’s maths :grin:.

2 Likes

Yay It worked!
Was the level “steelclaw gap” supposed to open?
To continue the main path do I do “The spy among us” or “uneasy truce”?
Thanks to everybody who helped me completed this level.
Thanks for the Math explanation, but I am still in 5th grade.
This topic is closed.