What to do when there are no enemies to attack?


#1

Hi!

I know this is covered in the FAQ, but it doesn’t answer my question, hence why I am posting.

I am in The One Wizard challenge and this is my code so far;

while True:
    enemy = hero.findNearestEnemy()
    if enemy and hero.canCast("chain-lightning", enemy):
        hero.cast("chain-lightning", enemy)
    else:
        hero.attack(enemy)

I get the “target is null”-problem because after I kill the first 3 enemies it takes awhile for the next to spawn, which means that my hero.attack(enemy) turns up null.
So, how do I fix this? How do I code so that it only attacks IF there are enemies, and if there aren’t any enemeis then it does something else?

I tried this;

while True:
    enemy = hero.findNearestEnemy()
    if enemy and hero.canCast("chain-lightning", enemy):
        hero.cast("chain-lightning", enemy)
        if not enemy:
            hero.say("Waiting")
    else:
        hero.attack(enemy)

But I got the same issue. So, how do I solve this?

Edit: I solved the issue myself by changing the code into this -.

while True:
    enemy = hero.findNearestEnemy()
    if not enemy:
        hero.say("Waiting")
    else:
        hero.attack(enemy)
    if enemy and hero.canCast("chain-lightning", enemy):
        hero.cast("chain-lightning", enemy)

But I don’t understand why it makes a difference - Can someone explain it to me?


#2

Please learn to post your code properly. It’s really easy and only requires a very small amount of effort.

To post your code from the game, use the </> button or it won’t format properly. When you click the </> button, the following will appear:

Please paste ALL of your code inside the triple back tick marks.

``` <— Triple back tick marks.

Paste ALL of your code in here.

``` <— Triple back tick marks.

There are many people here willing and able to help. If you use the </> button correctly, then ALL of your code should look like this:

while True:
    enemy = hero.findNearestEnemy()
    if enemy:
        hero.attack(enemy)
    else:
        hero.say("My code is formatted properly")

If ALL of your code isn’t formatted like the code above, then you’re doing it wrong and we can’t see the structure of the code to troubleshoot whether or not that is the issue. Use the </> button and help us help you. This works when sending a private message as well.

Thank you.


#3
while True:
    # find enemy
    if enemy and enemy.health > 0:
        if hero.canCast("some-magic", enemy):
            # cast magic
        else:
            # attack enemy

But I don’t understand why it makes a difference?

       # 4 cases    
    if enemy and hero.canCast("chain-lightning", enemy):
        hero.cast("chain-lightning", enemy)
        # caseNo1  enemy available + lightning available - OK
    else:
        hero.attack(enemy)
    #caseNo2   enemy available + lightning  non available -OK
    #caseNo3   enemy non available  + lightning available - will produce the null-target error
    #caseNo4   enemy non available  + lightning non available - will produce the null-target error

#4

Thank you for your reply!

I am unsure I understand, though.

Why does

while True:
    enemy = hero.findNearestEnemy()
    if enemy and hero.canCast("chain-lightning", enemy):
        hero.cast("chain-lightning", enemy)
    else:
        hero.attack(enemy)

produce the null-targer error but

while True:
    # find enemy
    if enemy and enemy.health > 0:
        if hero.canCast("some-magic", enemy):
            # cast magic
        else:
            # attack enemy

does not? (I tested and you were right ofc).
I assume it has something to do where the “else” is parsed in the code?


#5

enemy = hero.findNearestEnemy() is an instance of a class and have his own code

each class can have their own destructor method to remove the object, the problem here is that the corpse of the enemy will remain a certain amount of time before being removed. Why? Because there is some features in the game using corpses.

So Enemy still exist.
When you go back on the line: enemy = hero.findNearestEnemy() you Re-assign again a new enemy.


#6

Thank you for your reply!
I still don’t get why the error appears. You say it is because there are still corpses - and these corpses are tagged as enemies - but why does my original code produce the error but not the code provide dby Xython? Both codes have enemy = hero.findNearestEnemy() in the while-true loop so both should be constantly reassigning new enemies, no?


#7

Gabriel_Dupuis is right, but in this particular case I think I gave the correct answer to your question.
@Calimahr
See these 2 code pieces. Can You see why they don’t work? You can test them in Bank Raid

while True:
    enemy = hero.findNearestEnemy()
    hasMagic = hero.canCast("chain-lightning")
    if enemy and hasMagic:
        hero.cast("chain-lightning", enemy)
    else:
        hero.attack(enemy)

and same code a bit modified:

while True:
    enemy = hero.findNearestEnemy()
    coin = hero.findNearestItem()
    if enemy and coin:
        hero.move(coin.pos)
    else:
        hero.attack(enemy)

#8

Thank you for your time ^^

while True:
    enemy = hero.findNearestEnemy()
    coin = hero.findNearestItem()
    if enemy and coin:
        hero.move(coin.pos)
    else:
        hero.attack(enemy)

I would assume that the if-statement contains the variable “enemy” and the variable “coin”, and implies that if neither of those are true (there are no enemies, and there are no coins) or if only one of them is true (there are enemies, but no coins, or vice versa) then the hero should attack the enemy. But since there are cases in which there are no enemies, the target becomes null and an error occurs. Am I right?

Would the null-error occur ONLY In the cases in which there are no enemies present, or does it occur in both cases because the code cares for all hypothethical cases? (i.e the code must be true in all possible worlds which the game/level can present, not only the actual ones which occur)?

In contrast, if we look at the code you provided

while True:
    # find enemy
    if enemy and enemy.health > 0:
        if hero.canCast("some-magic", enemy):
            # cast magic
        else:
            # attack enemy

Then there are no cases in which there exists an enemy with less that 0 health that can’t be attacked (since one can attack a dead enemy, even though it only yeilds the “…but it’s already dead response”.

If this is the case, then my original code

while True:
    enemy = hero.findNearestEnemy()
    if enemy and hero.canCast("chain-lightning", enemy):
        hero.cast("chain-lightning", enemy)
    else:
        hero.attack(enemy)

is faulty because there are cases in which “if enemy and hero.can cast” is false (there are no enemies, for example), which implies that the hero should attack the enemy. But there are no enemies, so the code fails.

I have a background in first order logic and analytical philosophy, which might explain how I approach these questions. I have zero programing background but I really want to learn, hence this excellent game.


#9

“But since there are cases in which there are no enemies, the target becomes null and an error occurs.” - You are absolutely right! You can see an example( maybe not the perfect one) of logic enemies/coins marauder.


#10

Thank you for your help!