Target priorisation function not returning lists as expected


#1

I’m trying to work on a function to help better target enemy units, based on their type. So far, I’m trying the following on the Grim Determination level:

def chooseEnemyTarget():
    enemies = hero.findEnemies()
    warlocks = hero.findByType("warlock", enemies)
    skeletons = hero.findByType("skeleton", enemies)
    munchkins = hero.findByType("munchkin", enemies)
    
    if warlocks:
        return warlocks
    elif munchkins:
        return munchkins
    elif skeletons:
        return skeletons
    else: 
        return enemies

This function gets used by the combat function, which selects the target from the provided array. However, it seems that the arrays are returning empty and as a result, the friendly units stand won’t attack.

I’ve also tried iterating over the enemies list to build the unit type lists, but that doesn’t seem to do anything either:

...
enemies = hero.findEnemies()
    warlocks = []
    skeletons = []
    munchkins = []
    
    if enemies:
        for enemy in enemies:
            if enemy.type == "warlock":
                warlocks.append(enemy)
            elif enemy.type == "skeletons":
                skeletons.append(enemy)
            elif enemy.type == "munchkins":
                munchkins.append(enemy)
...

If I comment out everything but the return enemies line, they’ll happily go off chopping things as intended.

Does anyone have any ideas?

Full Code:
## Functions
def commandGriffin(griffin):
    enemies = chooseEnemyTarget()
    #enemy = hero.findNearest(chooseEnemyTarget())
    enemy = griffin.findNearest(enemies)
    if enemy:
        hero.command(griffin,"attack",enemy)
    else:
        friend = hero.findNearest(hero.findByType("paladin"))
        hero.command(griffin,"move",friend.pos)

def commandPaladin(paladin):
    healTarget = lowestHealthPaladin()
    enemies = chooseEnemyTarget()
    enemy = paladin.findNearest(enemies)

    if healTarget and paladin.canCast("heal", healTarget):
        hero.command(paladin,"cast","heal",healTarget)
    elif paladin.health < paladin.maxHealth / 0.666:
        hero.command(paladin,"shield")
    elif enemy:
        hero.command(paladin,"attack",enemy)


def commandPeasant(peasant):
    item = friend.findNearestItem()
    
    if item:
        hero.command(peasant,"move",item.pos)

def commandFriends():
    # Command your friends.
    friends = hero.findFriends()

    for friend in friends:
        if friend.type == "peasant":
            commandPeasant(friend)
        elif friend.type == "griffin-rider":
            commandGriffin(friend)
        elif friend.type == "paladin":
            commandPaladin(friend)

def lowestHealthPaladin():
    lowestHealth = 99999
    lowestFriend = None
    friends = hero.findFriends()
    for friend in friends:
        if friend.type != "paladin":
            continue
        if friend.health < lowestHealth and friend.health < friend.maxHealth:
            lowestHealth = friend.health
            lowestFriend = friend

    return lowestFriend

def chooseEnemyTarget():
    enemies = hero.findEnemies()
    warlocks = hero.findByType("warlock", enemies)
    skeletons = hero.findByType("skeleton", enemies)
    munchkins = hero.findByType("munchkin", enemies)
    
    return enemies
    
    if warlocks:
        return warlocks
    elif munchkins:
        return munchkins
    elif skeletons:
        return skeletons
    
def summonGriffins():
    if hero.gold > hero.costOf("griffin-rider"):
        hero.summon("griffin-rider")

## Execute
while True:
    commandFriends()
    summonGriffins()
    hero.say(chooseEnemyTarget())
#    self.wait(1)

#2

I’m afraid that the python interpreter is not 100% python compatible, meaning that if enemies: may not be properly evaluated. Try something else, like if len(enemies) or if enemies[0]. Also, try debugging by adding some lines like hero.say("warlocks found!") after the if/elif statements. Otherwise your code seems to be correct…


#3

An empty array is considered true in CodeCombat, so even if there are no warlocks you wil hit the line of code return warlocks As ant said, checking for len(warlocks) will solve this.

It is also important to know that returning ends a function.

def number():
  while(True):
    return 1
    hero.say('This code will never happen')

Will return the number 1 exactly one time and then stop before the hero says anything.