Help: Library Tactician

I followed the instructions as close as I could, but I’m not sure I totally understand the code in the first place. It seems to work overall, but the archers aren’t prioritizing quite right, it seems like sometimes they’ll target the ogre properly and sometimes not, and I’m not sure where the problem is. I sometimes get very close to winning, but eventually the archers fail to target properly and one of the soldiers dies. Here’s the whole code, comments and all. Hopefully the formatting is correct:

# 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.
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);

# Find the strongest target (most health)
# This function returns something! When you call the function, you will get some value back.
def findStrongestTarget():
    mostHealth = 0
    bestTarget = None
    enemies = self.findEnemies()
    # Figure out which enemy has the most health, and set bestTarget to be that enemy.
    for enemy in enemies:
        if enemy.health > mostHealth:
            enemy.health = mostHealth
            enemy = bestTarget
        # Only focus archers' fire if there is a big ogre.
    if bestTarget and bestTarget.health > 15:
        return bestTarget
    else:
        return None


# If the strongestTarget has more than 15 health, attack that target. Otherwise, attack the nearest target.
def commandArcher(archer):
    nearest = archer.findNearestEnemy()
    if archerTarget:
        self.command(archer, "attack", archerTarget)
    elif nearest:
        self.command(archer, "attack", nearest)

archerTarget = None

loop:
    # If archerTarget is dead or doesn't exist, find a new one.
    if not archerTarget or archerTarget.health <= 0:
        # Set archerTarget to be the target that is returned by findStrongestTarget()
        archerTarget = findStrongestTarget()

    friends = self.findFriends()
    soldiers = self.findByType("soldier")

    for i, soldier in enumerate(soldiers):
        commandSoldier(soldier, i, len(soldiers));
    archers = self.findByType("archer")
    # use commandArcher() to command your archers
    for i, archer in enumerate(archers):
        commandArcher(archer, i, len(archers));

I am surprised this code even works as you pass your commandArcher function 3 variables and it only calls for 1…

Anyway your problem is here:

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

archerTarget = None

You define archer target as none, so there never is an archer target and you only attack the nearest enemy.

Welp. This seems obvious now that you mention it, but I’m pretty sure it’s part of the sample code and that’s why I left it in…

EDIT: Removing archerTarget = None doesn’t seem to change anything at all. I’m not seeing what you mean when you say that I’m passing commandArcher 3 variables, but I’m probably just being blind. Maybe the problem’s there?

archerTarget = None needs to stay to declare the variable before the loop, but
archerTarget = findStrongestTarget()
Should be in the commandArcher() function.

This is where you are passing 3 arguements, but as it works, it doesn’t need to be fixed:

Passing Three Arguments
def commandArcher(archer):
    foobar

for i, archer in enumerate(archers):
        commandArcher(archer, i, len(archers));

Oooh, I see. Thanks!

As for passing three arguments, yeah, I see what you mean, and I do find the formulation weird, but I copied it from the commandSoldiers function in the sample code. I had my own version at first that didn’t involve those two extra variables and everything seemed fine with it, but when I was trying to find out what was wrong I went with copying the code for commandSoldiers. I don’t really get why commandSoldiers works that way either, actually.

EDIT: Actually, that doesn’t solve it. I added "archerTarget = findStrongestTarget() in commandArcher() and it still behaves exactly the same and fails.

@Rykemasters can you show me your code.Ive been stuck on this level for days.

1 Like

can you show me your code.Ive been stuck on this level for days. thanks!

1 Like