[SOLVED] Toil and trouble....certainly toil for me!


#1
# Ogre Witches have some unpleasant surprises ready for you.
def chooseTarget(friend):
    friends = hero.findFriends()
    for friend in friends:
        soldier = hero.findNearest(hero.findByType("soldier")
        if friend and friend.type == "soldier":
            return "witch"
        else:
            return "enemy" 
    

    
# Define a chooseTarget function which takes a friend argument
# Returns the a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
while True:
    friends = hero.findFriends()
    enemy = hero.findNearestEnemy()
    for friend in friends:
        hero.command(friend, "attack", chooseTarget())
        
       
        pass

Been messing with various code on this level and cannot get through it. My latest code above seems to have some kind of parsing t colon error? Help!


#2

Put

chooseTarget(friend)

instead of

hero.command(friend, "attack", chooseTarget())
        
       
        pass

#3

In the def choose target you need to put

hero.command(friend, "attack", witch)
hero.command(friend, "attack", enemy)

You also need to find the nearest witch and the nearest enemy.


#4
# Ogre Witches have some unpleasant surprises ready for you.
def chooseTarget(friend):
    friends = hero.findFriends()
    witch = friend.findNearest(hero.findByType("witch"))
    enemy = friend.findNearestEnemy()
    soldier = hero.findNearest(hero.findByType("soldier"))
    for friend in friends:
        if friend.type == "soldier":
            hero.command(friend, "attack", witch)
        else:
            hero.command(friend, "attack", enemy)
    

    
# Define a chooseTarget function which takes a friend argument
# Returns the a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
while True:
    friends = hero.findFriends()
    enemy = hero.findNearestEnemy()
    if enemy:
        hero.attack(enemy)
    for friend in friends:
        chooseTarget(friend)
        
       
        pass

I’m getting closer! thanks. They target correctly now, but the soldiers all attack one witch. Not sure how to split them out - friend.findNearest works but then friend.findByType does not…


#5
def chooseTarget(friend): # a single friend enters the function
    friends = hero.findFriends()  # then you redefine this friend
    for friend in friends:
# code
while True:
    friends = hero.findFriends()   
# code
    for friend in friends:
        chooseTarget(friend) # you are passing a single friend to the function

You have a mismatch of friend in friends and a friend. You have to get rid of some code.


#6
# Ogre Witches have some unpleasant surprises ready for you.
def chooseTarget(friend):
    
    witch = friend.findNearest(hero.findByType("witch"))
    enemy = friend.findNearestEnemy()
    soldier = hero.findNearest(hero.findByType("soldier"))
    for friend in friends:
        if friend.type == "soldier":
            hero.command(friend, "attack", witch)
        else:
            hero.command(friend, "attack", enemy)
    

    
# Define a chooseTarget function which takes a friend argument
# Returns the a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
while True:
    friends = hero.findFriends()
    enemy = hero.findNearestEnemy()
    if enemy:
        hero.attack(enemy)
    for friend in friends:
        chooseTarget(friend)
        
       
        pass

Took the redefinition line out but exactly the same thing happens. All the soldiers run to one witch…


#7

Try doing witch health > 0


#8

Try getting rid of

if friend.type == "soldier":

and put

if friend.type is "soldier" and enemy and witch and witch.health > 0

and change the

else:

to

if friend and friend.type is "archer" and enemy:

#9

Get rid of for friend in friends in def chooseTarget. And in the beginning get rid of
soldier = hero.findNearest etc
and put enemy = friend.findNearestEnemy() at the top
you also want to add enemies.findNearestEnemies() at the top to.
You have to add witches = hero.findByType("witch", enemies) and witch = friend.findNearest (witches). Get rid of if enemy: and hero.attack(enemy) but keep enemy = hero.findNearestEnemy()


#10

And before making any changes answer yourself what of the two following schemes you want to follow:

def warriorIsGoingToFight( warrior): # scheme 1
    # hero or warrior finds the enemy
    # hero commands warrior

def warriorsAreGoingToFight( warriors):  # scheme 2
    for warrior in warriors:
        # hero or warrior finds the enemy
        # hero commands warrior

while True:   # scheme 2
    friends = hero.findFriends()
    warriorsAreGoingToFight(friends) 
#   or
while True:  # scheme 1
    friends = hero.findFriends()
    for friend in friends:
        warriorIsGoingToFight(friend)

#11

It looks to me like your function is trying to do too much. If you reset the code on this level, the for loop in the while True loop is where you should be commanding the troops to attack, not the function. The function should just define which type of enemy the soldiers and archers should attack. See the comments:

# Define a chooseTarget function which takes a friend argument
# Returns the a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.

Use the function to return witch or enemy based upon the type of friend. Then use the while True loop to command your troops. Also, in your function you’ve only defined one type of friend; soldier. You need to define archers as well.


#12

Thanks for reply. In my first post this is what I had but then others’ advise changed it to how it is now. I will change back to my original post and include a definition of archers. I was hoping that because they are not soldiers it would just follow the else path.


#13
# Ogre Witches have some unpleasant surprises ready for you
def chooseTarget(friend):
    for friend in friends:
        soldier = hero.findNearest(hero.findByType("soldier"))
        archer = hero.findNearest(hero.findByType("archer"))
        if friend and friend.type == "soldier":
            return witch
        if friend and friend.type == "archer":
            return enemy 
# Define a chooseTarget function which takes a friend argument
# Returns the a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
while True:
    friends = hero.findFriends()
    enemy = hero.findNearestEnemy()
    witch = hero.findNearest(hero.findByType("witch"))
    for friend in friends:
        hero.command(friend, "attack", chooseTarget())
        
       
        pass

Now everyone just goes forward… I am literally going round in circles!


#14

thanks for reply but commanding in the function disagrees with MunkeyShynes post and the instructions as far as I can see :S


#15

That’s much closer but you need to get rid of the for loop in the function. It doesn’t belong there. The rest of the function is good.

In your while True loop, you don’t do a check for the existence of an enemy, nor do you use the variable enemy or witch, so they don’t need to be there. It will work without defining enemy and using if enemy, but when the enemies aren’t there in the end you’ll get a null error. The correct way to do it would be to define the variable enemy as the output of your function and then do an ```if enemy`` conditional inside the for loop. Then command the attack but by using enemy as the object to attack. Since it’s defined as the output of your function, it will send the troops to their respective targets.


#16
# Ogre Witches have some unpleasant surprises ready for you
def chooseTarget(friend):
    
        soldier = hero.findNearest(hero.findByType("soldier"))
        archer = hero.findNearest(hero.findByType("archer"))
        if friend and friend.type == "soldier":
            return witch
        if friend and friend.type == "archer":
            return enemy 
# Define a chooseTarget function which takes a friend argument
# Returns the a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
while True:
    friends = hero.findFriends()
    enemy = chooseTarget()
    
    for friend in friends:
        if enemy:
            hero.command(friend, "attack", enemy)
        
       
        pass

Fairly sure this replicates your direction. I think I have reached my programming limit for now! Because this still doesn’t work!


#17

did you tab back all the lines in the function so they are properly aligned? They should just be one tab or four spaces over from the left. It doesn’t look like it. Also, put your enemy definition inside the for loop, just before the if enemy: conditional. Make these corrections and it should work.

One more thing I just noticed. You have defined soldier and archer so they are variables, but then you use them as strings. Either use them as strings as you presently have and do away with the variable definition, or change the strings to use the variables. Either should work.

And one more, you don’t define witch as a variable in your function.


#18
# Ogre Witches have some unpleasant surprises ready for you
def chooseTarget(friend):
    
    soldier = hero.findNearest(hero.findByType("soldier"))
    archer = hero.findNearest(hero.findByType("archer"))
    witch = hero.findNearest(hero.findByType("witch"))
    if friend and friend.type == soldier:
        return witch
    if friend and friend.type == archer:
        return enemy 
# Define a chooseTarget function which takes a friend argument
# Returns the a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
while True:
    friends = hero.findFriends()
    for friend in friends:
        enemy = chooseTarget()
        if enemy:
            hero.command(friend, "attack", enemy)
        
       
        pass

I think I made the recommended changes but it still doesn’t work. They all die!


#19

You don’t have a definition for the variable, enemy, in your function.

Also, it definitely works better with the archers and soldiers used as strings instead of variables in the function. I’m not sure why but it probably has something to do with how the methods defining them are processed. Just use them as strings and do away with the variables.

One more thing, you are using hero.findNearest for the method to define witch. Who should be finding the witch? The same goes for the method used in the enemy definition. Read this hint again:
Toil%26Trouble


#20

Noticed that the friend should be doing the finding before but it never lets me do it?