# Ogre Witches have some unpleasant surprises ready for you.
# Define a chooseTarget function which takes a friend argument
# Returns a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
def chooseTarget(friend):
enemies = self.findEnemies()
enemy = self.findNearest(enemies)
witches = self.findByType("witch", enemies)
witch = self.findNearest(witches)
if friend.type is soldier:
self.command(soldier, "attack", witch)
if friend.type is archer:
self.command(archer, "attack", enemy)
loop:
friends = self.findFriends()
soldier = self.findByType("soldier", friends)
archer = self.findByType("archer", friends)
for friend in friends:
# Use your chooseTarget function to decide what to attack.
target = chooseTarget(friend)
if target:
if target.type is witch:
self.command(friend, "attack", target)
if target.type is enemy:
self.command(friend, "attack", target)
I don’t get how this does not work. Please help me!!!
findEnemies and findByType may return empty lists. Passing an empty list to findNearest returns None. You should check if the enemy exists before ordering your units to attack them—either by checking the length of the list returned by findEnemies / findByType or whether findNearest actually returned an unit.
The type values are strings so they should be quoted—i.e. you should compare target.type with "witch" instead of witch.
Your chooseTarget function does not return an enemy, it already orders the unit to attack it. So you can remove the target = part in target = chooseTarget(friend), and remove the whole if target: block as well.
These lines are dead code (unused code), you can safely remove them:
# When no enemies
enemies = findEnemies() # enemies is []
enemy = findNearest(enemies) # enemy == None, because no enemy in enemies
command(friend, "attack", enemy) # enemy == None, error occurs
You seem to already know this, as you account for the issue in the main loop. The main modification you’ll really need to make is to change chooseTarget() such that you aren’t commanding a friend, but rather using return to return the appropriate enemy target.
# Ogre Witches have some unpleasant surprises ready for you.
# Define a chooseTarget function which takes a friend argument
# Returns a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
def chooseTarget(friend):
enemies = self.findEnemies()
if len(enemies) is not 0:
enemy = self.findNearest(enemies)
if friend and friend.type is "soldier" and enemy and enemy.type is "witch":
self.command("soldier", "attack", "witch")
elif enemy:
self.command("soldier", "attack", enemy)
if friend and friend.type is "archer" and enemy:
self.command("archer", "attack", enemy)
loop:
friends = self.findFriends()
for friend in friends:
# Use your chooseTarget function to decide what to attack.
chooseTarget(friend)
“soldier” is a string, a piece of text. You need an object to order just like you need an object to attack.
Only the name of the action “attack” is a string.
# Ogre Witches have some unpleasant surprises ready for you.
# Define a chooseTarget function which takes a friend argument
# Returns a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
def chooseTarget(friend):
enemies = self.findEnemies()
enemy = self.findNearest(enemies)
if friend and friend.type is "soldier" and enemy and enemy.type is "witch":
self.command(friend, "attack", enemy)
if friend and friend.type is "archer" and enemy:
self.command(friend, "attack", enemy)
loop:
friends = self.findFriends()
for friend in friends:
# Use your chooseTarget function to decide what to attack.
chooseTarget(friend)
You are only ever commanding your friends to attack the nearest enemy to your hero. You will need to re-add the logic to find witches from the enemies array, or use the self.findByType('witch') method.
# Define a chooseTarget function which takes a friend argument
# Returns a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
def chooseTarget(friend):
enemies = friend.findEnemies()
enemy = friend.findNearest(enemies)
targets = friend.findByType("witch")
if friend and friend.type is "soldier" and enemy and enemy.type is "witch":
self.command(friend, "attack", enemy)
if friend and friend.type is "archer" and enemy:
self.command(friend, "attack", enemy)
loop:
friends = self.findFriends()
for friend in friends:
# Use your chooseTarget function to decide what to attack.
chooseTarget(friend)
Because it isn’t working. @UltCombo Are you there?
IT DIDN’T WORK. I just can’t believe it. The archers can’t kill the ogres quickly enough and all the troops die leaving the ogres and witches alive. However, the soldiers go for only one witch and since the witches heal each other that witch doesn’t die.
Here is my code:
# Ogre Witches have some unpleasant surprises ready for you.
# Define a chooseTarget function which takes a friend argument
# Returns a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
def chooseTarget(friend):
enemies = friend.findEnemies()
enemy = friend.findNearest(enemies)
witches = self.findByType("witch", enemies)
witch = self.findNearest(witches)
if friend and friend.type is "soldier" and enemy and witch and witch.health > 0:
self.command(friend, "attack", witch)
if friend and friend.type is "archer" and enemy:
self.command(friend, "attack", enemy)
loop:
friends = self.findFriends()
for friend in friends:
# Use your chooseTarget function to decide what to attack.
chooseTarget(friend)
Only one problem remains: you are telling all soldiers to attack the same witch (the nearest one to your hero). Command your soldiers to attack the nearest witch to them—that is, change self.findNearest(witches) to friend.findNearest(witches). After making this small change, your code should be able to win. Congratulations!
Actually Toil and Trouble may have a bug because this:
# Ogre Witches have some unpleasant surprises ready for you.
# Define a chooseTarget function which takes a friend argument
# Returns a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
def chooseTarget(friend):
enemies = friend.findEnemies()
enemy = friend.findNearest(enemies)
witches = self.findByType("witch", enemies)
witch = friend.findNearest(witches)
if friend and friend.type is "soldier" and enemy and witch and witch.health > 0:
self.command(friend, "attack", witch)
else:
self.command(friend, "attack", enemy)
if friend and friend.type is "archer" and enemy:
self.command(friend, "attack", enemy)
loop:
friends = self.findFriends()
for friend in friends:
# Use your chooseTarget function to decide what to attack.
chooseTarget(friend)
# I have to say that these witches are tough to kill
And this:
# Define a chooseTarget function which takes a friend argument
# Returns a target to attack, depending on the type of friend.
# Soldiers should attack the witches, archers should attack nearest enemy.
def chooseTarget(friend):
enemies = friend.findEnemies()
enemy = friend.findNearest(enemies)
witches = self.findByType("witch", enemies)
witch = friend.findNearest(witches)
if friend and friend.type is "soldier" and enemy and witch and witch.health > 0:
self.command(friend, "attack", witch)
else:
self.command(friend, "attack", enemy)
if friend and friend.type is "archer" and enemy:
self.command(friend, "attack", enemy)
loop:
friends = self.findFriends()
for friend in friends:
# Use your chooseTarget function to decide what to attack.
chooseTarget(friend)
# I have to say that these witches are tough to kill
Both work! Unless you can persuade me that it isn’t a bug I have no other issues with it.