# 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?

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

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!

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:

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 .

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.