Zero Sum item identification

here is my code:

def efficiency(item):
    return item.value / hd(item)

def fd(x):
    friend.distanceTo(x)

def hd(x):
    hero.distanceTo(x)

def fm(x):
    hero.command(friend, "move", x)

def fa(x):
    hero.command(friend, "attack", x)

def c20():
    a = 0
    x = 0
    while x < len(corpses):
        corpse = corpses[x]
        if corpse and hd(corpse) <= 20:
            a += 1
        x += 1
        if a >= 4:
            return True
            break

def e20():
    a = 0
    x = 0
    for enemy in enemies:
        enemy = enemies[x]
        if hd(enemy) <= 20:
            a += 1
        x += 1
        if a >= 4:
            return True
            break

def bestItem(items):
    a = 0
    besty = None
    x = 0
    while x < len(items):
        item = items[x]
        if a < efficiency(item):
            besty = item
            a = efficiency(item)
        x += 1
    return besty


def xxx(enemies):
    a = 0
    b = None
    x = 0
    while x < len(enemies):
        enemy = enemies[x]
        if a < enemy.maxHealth:
            a = enemy.maxHealth
            b = enemy
        x += 1
    return b


def skills():
    if hero.canCast("fear", leader) and hd(leader) <= 50 and leader.maxHealth > 200:
        hero.cast("fear", leader)
    if c and hero.canCast("raise-dead", c) and hd(c) <= 20 and c20():
        hero.cast("raise-dead", c)
    if hero.isReady("mana-blast") and hd(enemy) < 20 and e20():
        hero.manaBlast(enemy)
    if hero.isReady("reset-cooldown") and not hero.canCast("raise-dead"):
        hero.resetCooldown("raise-dead")
    elif hero.health < 1000 and hero.canCast("drain-life", enemy) and hero.distanceTo(enemy) <= 17 and hd(enemy) > 10:
        hero.cast("drain-life", enemy)


while True:
    enemies = hero.findEnemies()
    leader = xxx(enemies)
    t = hero.team
    a = hero.findFriends()
    corpses = hero.findCorpses()
    c = hero.findNearest(corpses)
    y = hero.findNearest(a)
    items = hero.findItems()
    coin = bestItem(items)
    hero.move(coin.pos)
    enemy = hero.findNearestEnemy()
    if hero.canCast("goldstorm"):
        hero.cast("goldstorm")
    if enemy and enemy.type != "yeti" and enemy.type != "cage" and hd(enemy) < 40:
        skills()
    if hero.gold >= 50:
        hero.summon("griffin-rider")
    for friend in a:
        fx = friend.findNearestEnemy()
        if fx and friend and friend.team == t:
            if fd(fx) > 35 or fd(fx) < 20 and hd(fx) >= 20 or fx.type == "cage":
                fm(hero.pos)
            elif fd(fx) <= 35:
                fa(fx)

Level: Zero Sum

I just changed this last part of the code which is irrelevant:

for friend in a:
        fx = friend.findNearestEnemy()
        if fx and friend and friend.team == t:
            if fd(fx) > 35 or fd(fx) < 20 and hd(fx) >= 20 or fx.type == "cage":
                fm(hero.pos)
            elif fd(fx) <= 35:
                fa(fx)

And then, it started to say that error in picture. Why and what is the solution? Thanks.

ok, that’s some weird bug, which happened to me either.Try using hero.moveXY(coin.pos.x, coin.pos.y)

moveXY is worse, it doesnt check other other codes until hero reaches the destination.

oh, then I’ll say, honestly, that I don’t know.I’ll ask some other guys.
@Eric_Tang , @098765432123 , @enPointe77 .
I have completely different way of passing, so Idk

2 Likes

The Minimal, Reproducable Example of your problem is the fact that this code does not work:

def hd(x): hero.distanceTo(x)

item = hero.findNearestItem()
hero.say(hd(item))

as the return value of hd is None. In a function, you need to explicitly return a value:

def hd(x): return hero.distanceTo(x)

and similar for your other utility functions.


My debugging process that led to the result:

  1. Notice item = bestItem(items) is not returning a coin, as your error reads “Cannot read property ‘pos’ of null”
  2. Add hero.say or print statements to the definition of bestItem to see why besty is not set.
  3. Notice that the return value of efficiency is always null.
  4. Notice efficiency relies on hd, which is always null.

Simpler code is easier to maintain, debug, and share. A suggestion: you make use of the pattern

x = 0
while x < len(items):
    item = items[x]
    ...
    x += 1

quite often, which is equivalent to a for-loop:

for item in items:
    ...
1 Like

Thanks so much! All of the problem was that i forgot to add “return”.
Because of that,

def hd(x):
    hero.distanceTo(x)

does not return anything and i was using in the most critical definition:

def efficiency(item):
    return item.value / hd(item)

So, as you said, besty was not coming out. Thanks so much :slight_smile:

Also, im new at the “for” loops. i understood how it works but not sure if it checks every one in the array. Thats why there is

enemy = enemies [x]
.
.
x += 1

in the while x < len(enemies) loop to apply the things to every person.
But i will give it a lot of tries for “for” loop and understand everything of it, no problem :smiley:

edit: Actually yes, it applies for everyone lol, lesson learned :smiley:

Exactly, well done!

Indeed, for loops are guarantee to iterate once over everything in a sequence. They are handy an a variety of cases where while loops would be a little clunky. A few examples:

for item in items: # Iterate across every item
    hero.move(item.pos)

for unitType in ["soldier", "archer", "paladin"]: # Iterate across each type
    hero.summon(unitType)

for char in "CodeCombat": # Iterate letter by letter
    hero.say("Give me a " + char + "!")

for i in range(3, 5): # Iterate across every integer 3 <= i < 5
    hero.move(items[i].pos)

for _ in range(5): # Iterate 5 times
    hero.spawnCollector()
1 Like

This topic was automatically closed 12 hours after the last reply. New replies are no longer allowed.