Play Home Contribute Github Join Us! Discourse Staff Members Github Contribution Guides Team

Need help on Harrowland

Hello. I am very new to python and decided to try out using the def function. Here is what I ended up with:

def findHp(edible):
    edible = None
    enemies = hero.findEnemies()
    enemyIndex = 0
    while enemyIndex != len(enemies):
        enemy = enemies[enemyIndex]
        if enemy.health > 100 and enemy.health < 200:
            edible = enemy
            return edible
        enemyIndex += 1
    enemyIndex = 0
    while enemyIndex != len(enemies):
        enemy = enemies[enemyIndex]
        if enemy.health < 200:
            edible = enemy
            return edible

while True:
    enemy = hero.findNearestEnemy()
    mhp = hero.maxHealth
    hp = hero.health
    corpse = hero.findCorpses()
    flag = hero.findFlag("green")
    food = findHp(edible)
    if hero.canCast("summon-undead"):
        hero.cast("summon-undead")
        hero.cast("sacrifice", hero.findNearestFriend(), hero)
    elif hero.canCast("raise-dead"):
        hero.moveXY(41, 33)
        hero.cast("raise-dead")
    elif hp < 200 and food:
        if hero.canCast("invisibility", hero):
            hero.cast("invisibility", hero)
        hero.moveXY(food.pos.x, food.pos.y)
        hero.devour(food)
        hero.say("omnomnom")
    elif hp < (mhp / 10) * 9 and hero.distanceTo(enemy) < 15:
        hero.cast("drain-life", enemy)
    elif hp < mhp / 3:
        hero.cast("drain-life", enemy)

for some reason it doesn’t find the “edible enemy” ( enemy with 100-200 hp or at least less than 200) and drops an error.

Thanks in advance, help with this and ANY other tips would be appreciated (since this is my first couple of weeks on this, I am happy to hear on how I could improve my code).

A couple quick tips. (I didn’t test these though)

When you call the function using a parameter, the parameter needs to be defined before the function. If you won’t be using that parameter directly in your function, you don’t need to set one. I see you look for a new enemy set within the function, so I don’t see a need for the edible parameter.

food = findHp(edible) #edible is not defined
def findHp(): # if there isn't a need for a parameter don't define one in the function

The main problem you have with the code is your return statement is in the while loop. The first enemy that meets the criteria in the while loop will return and the function will end. Keep the return outside of the while loops to make sure you check every enemy.
Here is another suggestion, instead of having two while condition loops that are identical, just add an elif statement to the first one. I changed your second range so it isn’t duplicating the first range, but has the same effect.

    while enemyIndex != len(enemies):
        enemy = enemies[enemyIndex]
        if enemy.health > 100 and enemy.health < 200: #range of 100-200
            edible = enemy
        elif enemy.health <= 100: # no need to check for 100-200 again, so less than 100
            edible = enemy
        enemyIndex += 1
    return edible # indented on the first indent to allow the while loop to run completely before assigning edible variable
  

Thanks for the reply.
The reason I have put the return statement inside the first loop, so if it would find me an enemy that i can devour, it would ignore the second loop that looks for an enemy with less than 100 hp ( which would make casting devour less useful). At least thats what i want it to do, but i might not understand the def function properly and something doesnt work.

No, you are correct. It would give you the first enemy that met that criteria and exit out of the function. I realized that on my drive into work.

Later on you will want to consider how to create your functions to return the best option to maximize your strategy. That is when you want to have the return outside of the while loop to make sure you have evaluated every enemy to identify the optimal target. One detail you might want to add to get the closest enemy that met that criteria is a distance check. Then you can return the enemy closest to you with the health range. Otherwise the first enemy you get might be the farthest away opening you up to some extra damage.

One last detail, do you have the ability to use better boots with the move()? The moveXY() prevents any other code from running while you move. As much as possible, you will want to use move() which moves one step at a time.

Yes, I believe the best way to do it would be to loop through current enemies that hero can find and make an array of the compatible ones, then loop through that array to find the closest one from the compatible targets. I just have no idea how to do that.

Also maybe thats the problem with my current code. Hero starts walking towards the compatible target and the target dies, so there is nothing to devour anymore. Is it possible that this is the reason of this error?

About the boots, I didnt know the difference so I never invested in them. They just made it on my buylist :smiley:

What error are you getting? A screenshot or snip of the error is a good way for us to see the error in the context. Otherwise, you can just type it all out.

Using your original code with these few changes below, I was able to beat the Medium level opponent. Although, I might not have the same gear that you do. I figured out that you are using Nalfar with one of the Unholy Tome spell books.

Did you fix findHp() function so there isn’t edible in it?

food = findHp()
def findHp():

Also, you didn’t add the enemyIndex to the second while loop in the function so you are getting an infinite loop.

Lastly, I got an error on this line of code.

hero.cast("sacrifice", hero.findNearestFriend(), hero) #error here 
hero.findNearestFriend() # not an acceptable method
hero.findNearest(hero.findFriends()) # replace with this

I actually removed both of the parameters, I think it works now.

Regarding the hero.findNearestFriend() and the code that you suggested for me to replace with - why is that not an acceptable method? Doesnt it do exactly the same? It is shown in the available methods.

Interesting, I just checked all of the glasses and the Mahogany glasses does have that method. It is the only one that has it. I was under the impression the higher level glasses inherited all the methods from the lower level ones, but I find out today that it is not true.

Twilight Glasses.

Same, that’s weird, I never noticed that either. I think it’s because when you get to a higher level, you’d usually make an array of friends with hero.findFriends() then use hero.findNearest(friends) to get the equivalent friend. It’s for the lower levels where you just need to find one.
Good spot! I wonder if there are any others :mag_right:
Danny