Library Tactician Dec '15/ Apr '21

Why isn’t this working??? I’m getting no errors and I seemed to have done all the reqs.

def commandSoldier(soldier, soldierIndex, numSoldiers):
    angle = Math.PI * 2 * soldierIndex / numSoldiers
    defendPos = {"x": 41, "y": 40}
    defendPos.x += 10 * Math.cos(angle)
    defendPos.y += 10 * Math.sin(angle)
    self.command(soldier, "defend", defendPos);

def findStrongestTarget():
    mostHealth = 0
    bestTarget = findStrongestTarget()
    enemies = self.findEnemies()
    enemyIndex = 0
    while len(enemies) > enemyIndex:
        enemy = enemies[enemyIndex]
        if enemy:
            enemyIndex += 1
            if enemy.health > mostHealth:
                mostHealth = enemy.health
                bestTarget = enemy
    
    if bestTarget and bestTarget.health > 15:
        return bestTarget
    else:
        return None



def commandArcher(archer):
    nearest = archer.findNearestEnemy()
    if archerTarget:
        self.command(archer, "attack", archerTarget)
    elif nearest:
        self.command(archer, "attack", nearest)
        
archerTarget = None

loop:
    if self.gold > self.costOf("soldier"):
        self.summon("soldier")
    

    if not archerTarget or archerTarget.health <= 0:
   
        archerTarget = findStrongestTarget()

    friends = self.findFriends()
    soldiers = self.findByType("soldier")
    archers = self.findByType("archers")
    for i, soldier in enumerate(soldiers):
        commandSoldier(soldier, i, len(soldiers));


    for i in range(len(archers)):
        archer = archers[i]
        commandArcher(archer)

My only problem is one guy dies.

Try resubmitting a few times. You get a new random seed every time you submit, so perhaps you just need a bit of luck.

If I recall correctly, I also had this problem in this level. It might be worth checking if this level needs some adjustments or re-balancing.

@nick Please help out here. My code is correct.

1 Like
[quote="Wiilli, post:1, topic:6072"]
enemyIndex = 0
    while len(enemies) > enemyIndex:
        enemy = enemies[enemyIndex]
        if enemy:
            enemyIndex += 1
            if enemy.health > mostHealth:
                mostHealth = enemy.health
                bestTarget = enemy
[/quote]

The problem is somewhere in here. When I paste this section into my code people die. You are using python, just replace it with a for loop and make your life happy.

    for enemy in enemies:
        if enemy.health > mostHealth:
            bestTarget = enemy
            mostHealth = enemy.health

I did, still loosing :frowning:
Now I’m getting a maximum call stack size exceeded error.

Omg That wasn’t my error!
I was putting bestTarget= FindStrongest before I defined findStrongest.
Ayyyyy

I also have a code as well, however the error that pops out is “Too much recursion” and I am not sure why…
Here is my code:

    // 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.
    this.commandSoldier = function(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);
        this.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.
    this.findStrongestTarget = function() {
        var mostHealth = 0;
        var bestTarget = null;
        var enemies = this.findEnemies();
        // Figure out which enemy has the most health, and set bestTarget to be that enemy.
        var archerTarget = this.findStrongestTarget();
        // 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.
    this.commandArcher = function(archer) {
        var nearest = archer.findNearestEnemy();
        if(archerTarget) {
            this.command(archer, "attack", archerTarget);
        } else if(nearest) {
            this.command(archer, "attack", nearest);
        }
    };

    var archerTarget = null;
    loop {
        // If archerTarget is dead 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 = this.findStrongestTarget();
        }
        var friends = this.findFriends();
        var soldiers = this.findByType("soldier");
        for(var i=0; i < soldiers.length; i++) {
            var soldier = soldiers[i];
            this.commandSoldier(soldier, i, soldiers.length);
        }
        // use commandArcher() to command your archers
        this.commandArcher(archer);
        
    }

Please help!!!:sob:

The reason for the error “too much recursion” is that you call the function findStrongestTarget inside itself, which is not supposed to be done.

Do you happen to have any suggestions on what I can do?

Reload the level. findStrongestTarget is already fully defined in the sample code.

Reloaded it, but now there’s an error with the sample code, and I changed no part of it!


this.commandArcher = function(archer) { var nearest = archer.findNearestEnemy(); if(archerTarget) { this.command(archer, "attack", archerTarget); } else if(nearest) { this.command(archer, "attack", nearest); } };


The var nearest = archer.findNearestEnemy(); part has a “tmp72[tmp73] is not a function” error. Whereas if I change it to var nearest = archer.findNearest(archer.findEnemies));, it says “tmp75[tmp76] is not a function”…
Where am I going wrong?!

The error message say that during the code execution the value of “archer” does not have a method called
"findNearestEnemy"

This happened because the value you used to call this.commandArcher(archer); was not an ally or was null
For example calling:

this.commandArcher(null);
this.commandArcher(25);

Use archer=this.findNearestFriend();

What if I used var archer =this.findbyType("archer")?

That would not work, because then you would be trying to get the nearest enemy of a list, which is impossible.

I used var archer = this.findNearest(friends);, but now one soldier keeps dying, and archers still won’t focus their fire on ogres.

You have to loop over all the archers using a for-loop. Right now you are just commanding the nearest archer to target an ogre.

for (var i = 0, i < this.findByType("archer").length, i++) {
    // Insert your commandArcher function here

At this part, now it says “Expected ‘}’ to match ‘{’ from line 56 and instead saw’;’.”
// use commandArcher() to command your archers var archer = this.findNearest(friends); for (var i = 0, i < this.findByType("archer").length, i++) { this.commandArcher(archer); } }

Why is there two ending brackets?

It’s for the loop { higher up the code.

It looks you are using JavaScript
Replace the commas by semicolons in the for instruction (that is the correct syntax):

for (var i = 0; i < this.findByType("archer").length; i++) 

There might be some trailing brackets. Count your opened { and closed } brackets and make sure they match.

I run a test and it is going better, but the soldiers will still die because they run too far away from the archers.

Make sure they attack only if the enemy is near and that they are running next to librarian.pos if the enemy is far:

//at the beginning:
librarian=this.findByType("librarian");

if (distance_to_nearest_enemy_too_big)
    // soldier should go back to librarian.pos