Library Tactician python help


#1
# 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)
    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.
def findStrongestTarget():
    mostHealth = 0
    bestTarget = None
    enemies = hero.findEnemies()
    # Figure out which enemy has the most health, and set bestTarget to be that enemy.
    for enemy in enemies:
        if enemy.health > mostHealth:
            mostHealth = enemy.health
            bestTarget = enemy
    # 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:
        hero.command(archer, "attack", archerTarget)
    elif nearest:
        hero.command(archer, "attack", nearest)

archerTarget = None

while True:
    # 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 = hero.findFriends()
    soldiers = hero.findByType("soldier")
    # Create a variable containing your archers.
    archers = hero.findByType("archers")
    for i in range(len(soldiers)):
        soldier = soldiers[i]
        commandSoldier(soldier, i, len(soldiers));

    # use commandArcher() to command your archers
    for i in range(len(archers)):
        archer = archers[i]
        commandArcher(archer)

I always have one soldier that dies. Is there something not right with my code that I could fix to prevent that.


#2

@kiwiapple87 Yes I remember this challenge. You have done well with the code so far, as I did and ran into the same challenge.

I believe that we have properly identified the issue:

  1. Only one soldier dies each time.

So now the question is “how do I protect my soldiers so that if they are weak they don’t get killed” ?

I will give you a hint. commandSoldier is where we tell each soldier what to do, perhaps we can leverage this function and update it so that the injured soldiers protect themselves.


#3

One little tip, I don’t see archerTarget defined before it is used. :wink::wink::wink:


#4

Right before the While True loop it is set to ‘None’


#5

You need to set it before that.


#6

Why do I need to set it before that? I have no problem with my archers shooting.


#7

Oh ok. I have to do some developing things at the moment so I can’t help. Just wait a moment.


#8

I have tried a bunch of different things to try and protect that one soldier but I can’t seem to get him to survive. I have been stuck on this level for over 2 weeks now.


#9

Sometimes the best defense is a good retreat.


#10

I barely remember this level but i will try to help.


#11

I can’t get the retreat to work. I get the error saying that my code is taking to long to run or there is an infinite loop.

Also, I think I have figured out my issue but I have been unable to solve it. My archers don’t seem to be focusing on the ogre’s. I have changed the commandArcher function to:

def findStrongestTarget():
    bestTarget = None
    enemies = hero.findEnemies()
    # Figure out which enemy has the most health, and set bestTarget to be that enemy. or type ogre
    for enemy in enemies:
        if enemy.type == "ogre":
            bestTarget = enemy
    # Only focus archers' fire if there is a big ogre.
    if bestTarget and bestTarget.health > 15:
            return bestTarget

But even with changing it to go by type instead of health they still don’t focus on the ogre’s. After watching this about 40 times I know if I could solve that I would get past this level. Any help would be greatly appreciated.


#12

@kiwiapple87 the original code you had posted for the “findStrongestTarget” looked ok, you might try reverting to it.

For the retreat code you can update the “commandSoldier” code to check for the individual soldiers health. After you validate that the soldiers health is less than a certain number (near death) then command that soldier to retreat towards Hushbaum.

I think the original archer code detected the enemy with the greatest health and had the archers attack that target until it was vanquished… That should turn out to focus the attacks on the ogres.


#13

Using either Health or Type in the findStrongestTarget function results in the same problem. The archers aren’t focusing on the ogre’s until they are dead. Sometimes with will all focus on the ogre and then when they are almost dead switch to the nearest munchkin. Sometimes when a new ogre appears they won’t all start shooting him right away. They will be shooting at the nearest munchkin’s first then switch to him. And this is happening when I use either health detection or type detection. I am very confident that if I could get the archers to focus on the ogre’s till death and focus on the ogre’s immediately when they show up I would be able to pass this level. I just don’t understand why they aren’t focusing on them.


#14

@kiwiapple87 Ah! you are right. The reason that your archers are not attacking the right target is because there is a bug in your code. It was one I glanced over myself.

It’s an easy fix that is the good news!

Have you used " console.log() " before to debug the code? or even hero.say() ?

Hint: start with ensuring all the functions are being called by including a console.log() or hero.say() statement in the beginning of each.

.

if you have to use hero.say() then only have one hero.say() statement active in the code per test run as it can cause delays in the “hero.command()” statements. console.log() is more efficient in showing what is going on, but you will have to know how and where to read the web browser log output.


#15

One freaking letter :rage:. Thank you for the help .


#16

Those are the kinds of bugs that keep people up at night.