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
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!
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.
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?
// 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);
}
}
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!
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.