I'm over 3,000,000 - Python - Cavern Survival


#1

Below is my code. I’ll admit I’m working a little over my head here but it has me perplexed and I was hoping to have discussion about it and possibly learn. :smile:

loop:
    enemies = self.findEnemies()
    enemyIndex = 0  # Devise your own strategy. Be creative!
    if enemies:
        enemyDistance = self.distanceTo(self.findNearest(enemies))
    while enemyIndex < len(enemies):
#        enemy = enemies[enemyIndex]
#        while enemyDistance:
#            self.attack(enemy)
#        if len(enemies) >= 2 and enemyDistance < 10:
#           self.cleave(enemy)
#        else:
#            self.attack(enemy)
#    while len(enemies) == 0:
#             self.moveXY(49, 62)
#             self.shield()

So what I think i am doing here is…build an index of enemies that my guy can see… if he sees enemies, set the distance to the variable…verifying that there are enemies by checking the number of enemies. This is where it breaks. I’ve commented out the rest of what I had going on.


#2

You are using Python, correct? Well, in Python, a list is always truthy. Therefore, if enemies will always be true, even if the list enemies is empty. You don’t need the if-check, so delete it.

Also, while enemyDistance will result in an infinite loop, because there is a variable enemyDistance and so the loop amounts to while True. Try while enemy.health > 0:

I think those are your main problems. Fix those and come back.


#3

Thanks for the pointers.

while enemy.health > 0:

Returns an error for me. There are more problem than just that. I got the code running but my guy ignored the munchkins and went straight for the doors and the other player. In an attempt to make him not do that, he just stands there and gets hit in the face.

I’m going to take a break and come back to it in a bit with a solution more geared to my basic understanding.


#4
Decided to work with what I already know and came up with...

[spoiler]

loop:
    enemy = self.findNearest(self.findEnemies())
    enemyDistance = self.distanceTo(enemy)
    if enemy and self.isReady("cleave"):
        self.cleave(enemy)
    elif enemy and self.isReady("bash"):
        self.bash(enemy)
    elif enemy and enemyDistance > 3:
        enemyPos = enemy.pos
        enemyX = enemyPos.x 
        enemyY = enemyPos.y
        self.moveXY(enemyX, enemyY)
    elif enemy:
        self.attack(enemy)
    elif enemy = 0:
        self.shield()

works decently well.
Thanks for the help @ChronistGilver


#5

Hi @Berohn! You say that the code works decently enough, but let me show a few points which you could improve (on this and/or later levels).

First of all, you could reorganise all those if enemy and ... statements into something like this:

if enemy:
    if ...:
        # do this
    elif ...:
        # do that
    else:
        # do something else

I also wanted to say that it’s good to check the distance for all actions (cleave, bash). But to be honest, you don’t have to check it for direct attacks: if the enemy is too far away, your hero will first walk to it and then attack. And that’s the reason why you don’t really have to walk to the enemy: just attack, and your hero does the walking alone…


One error that I noticed is the elif enemy = 0: statement. In python you use one equal sign is to give a value to variable, and two equal signs for comparison:

# give a value:
myVar = 123

# compare:
if myVar == 123:

Furthermore, if there is no enemy, then enemy is equal to None (note that it’s case sensitive!), not 0 or Null. So the correct check should be something like this:

if enemy == None:

# or simply:
if not enemy:

So here is a sample pseudo-code, with the above-mentioned things in mind:

loop:
    enemy = ...
    if enemy: # if there is an enemy
        if cleave is ready:
            cleave
        elif bash is ready:
            bash
        else: # if cleave or bash is not ready
            attack

    # this part is optional:
    else: # if there are no enemies
        do something else

#6

@ant thanks for taking the time to respond.

Thank you for the pointers! Always appreciate code review.

I cleaned up my code using your pointers.
loop:
    enemy = self.findNearest(self.findEnemies())
    if enemy and self.isReady("cleave"):
        self.cleave(enemy)
    elif enemy and self.isReady("bash"):
        self.bash(enemy)
    elif enemy and enemyDistance > 3:
        enemyDistance = self.distanceTo(enemy)
        thrower = self.findByType("thrower")
        enemyPos = thrower.pos
        enemyX = enemyPos.x 
        enemyY = enemyPos.y
        self.moveXY(enemyX, enemyY)
        self.attack(thrower)
    elif enemy:
        self.attack(enemy)

Trying to be able to identify enemies.

I’m sure you’ll see more of me :smile:

Thanks,
Berohn


#7

Well, you can still clean it up more. You don’t need all these if enemy: checks. You just need one, right after your definition of enemy, then you can put the rest in without the check.

Technically, you can’t attack a list, which is what self.findByType(type) returns. It would be better to attack the nearest thrower, with something like thrower = self.findNearest(self.findByType("thrower")). Also, you don’t check if there is a thrower in the first place, so add that, or it could break your code.

Also, why do you define enemyDistance? You don’t seem to use it, so what is it for?

If you make these changes, then I’d say your code would be rather solid.


#8

Thank you @ChronistGilver!