Sarven Treasure - Please find my error


#1

I have been trying to make this work for hours. I was stuck at always getting 143/150 coins and scratched it and tried a new method. Currently, my guy just runs to the top, mid-right of the map OR he teleports once and then runs to the top, mid-right. I have NO idea why he is going to (x=48, y=62). I want him to just run around picking up silver/gold coins and running into a teleporter if an ogre gets too close or no coins are near him.

loop:
    minDistance = 20
    coinIndex = 0
    coins = self.findItems()
    ogres = self.findEnemies()
    ogre = self.findNearest(ogres)
    closestCoin = self.findNearest(coins)
    
    while coinIndex < len(coins):
        target = coins[coinIndex]
        coinIndex += 1
        distance = self.distanceTo(target)
        
        if distance < minDistance and target.value >= 2:
            minDistance = distance
            closestCoin = target
            
    if minDistance < 30 and closestCoin and not ogre:
        self.moveXY(closestCoin.pos.x, closestCoin.pos.y)
        
    if minDistance < 30 and closestCoin and ogre:
        ogreDistance = self.distanceTo(ogre)
        
        if ogreDistance >= 10 and closestCoin:
            self.moveXY(closestCoin.pos.x, closestCoin.pos.y)
            
    elif closestCoin:
        
        if self.pos.x > 43 and self.pos.y > 38:
            self.moveXY(75, 50)
        if self.pos.x > 43 and self.pos.y <= 38:
            self.moveXY(75, 20)
        if self.pos.x <= 43 and self.pos.y > 38:
            self.moveXY(5, 50)
        if self.pos.x <= 43 and self.pos.y <= 38:
            self.moveXY(5, 20) 
        self.moveXY(closestCoin.pos.x, closestCoin.pos.y)
        pass

I can’t get the self.moveXY(variable, variable) to work at all. It always says I need to put an integer in. But if I need to move to an integer, I’ll have no way of getting him to move to the coins?


#2

Nice approach. Basically, you don’t have enough elif and else statements, so instead of moving towards one coin in the loop, you are moving towards the coin, then moving over here, and then moving over there, and then moving back to that coin (which you already picked up).

This one is a bit tricky to debug, but I can tell you how to make it really easy to debug: only take one action per iteration of your loop. So only one move or attack or powerUp or whatever. Don’t let an if containing an action follow another if with an action–make sure it’s elif or else. Otherwise, your data (what coins there are, what ogres are where, what are the distances and values and such) will be stale when you take the second action, since you haven’t iterated up to the top of the loop again to refresh it.

This is a good strategy for most levels, by the way. Your job on each loop iteration is just to decide what to do next, not what to do after that.

Hope this helps!


#3

I copied & pasted your code and it works for me…

What glasses are you wearing? (This determines how far you can see)

your code has no “If I can’t see a coin…” put in an:

    else:
        self.say("Ack, pbht. I don't see any coins")

and see if that is what is happening. If so then either get better glasses or give him some where to go to look for more coins.

(Edit: sneaky nick poking save right before me.)


#4

A general tip for this level is simplify it a bit. One general strategy, for example:

if enemy is close:  # but how close?
   escape to portal  # but which portal?
else:
   pickup a coin

Maybe you can improve on that, but try to not have it be more complicated than that to begin with. You can add more details later, of course.

Also, when you find yourself repeating similar lines, try to recode:

if minDistance < 30 and closestCoin and not ogre:
   do stuff
if minDistance < 30 and closestCoin and ogre:
   do stuff

could be

if minDistance < 30 and closestCoin:
   if ogre:
      do stuff
   else:
      do stuff

Just some ideas, hope it helps.


#5

Thank you everyone for the replies! I was able to fix the bugs in it using your advice (though I still can’t pick up the 150 coins in time!). This is a really great community. Here is my fixed code, in case anyone stumbles upon this post due to a similar problem:

loop:
    minDistance = 20
    coinIndex = 0
    coins = self.findItems()
    ogres = self.findEnemies()
    ogre = self.findNearest(ogres)
    closestCoin = self.findNearest(coins)
    
    while coinIndex < len(coins):
        target = coins[coinIndex]
        coinIndex += 1
        distance = self.distanceTo(target)
        
        if distance < minDistance and target.value >= 2:
            minDistance = distance
            closestCoin = target

# If no ogre and a coin nearby, get it.
    if minDistance < 30 and closestCoin and not ogre:
        self.moveXY(closestCoin.pos.x, closestCoin.pos.y)

#If an ogre and a nearby coin, get the coin unless the ogre is close. If the ogre is close, teleport.       
    elif minDistance < 30 and closestCoin and ogre:
        ogreDistance = self.distanceTo(ogre)
        
        if ogreDistance >= 10 and closestCoin:
            self.moveXY(closestCoin.pos.x, closestCoin.pos.y)
            
        elif closestCoin:
        
            if self.pos.x > 43 and self.pos.y > 38:
                self.moveXY(75, 50)
            if self.pos.x > 43 and self.pos.y <= 38:
                self.moveXY(75, 20)
            if self.pos.x <= 43 and self.pos.y > 38:
                self.moveXY(5, 50)
            if self.pos.x <= 43 and self.pos.y <= 38:
                self.moveXY(5, 20) 
            pass

#Otherwise, say "no coin!".
    else:
        self.say("no coin!")

#6

Hmm, your “default” minDistance (20) is less than your “if minDistance < 30” so it can never be “>= 30”

You set closestCoin to the nearest coin “closestCoin = findNearest(coins)” then you loop through all the coins to find the nearest closer than 20… then check to see if the nearest is < 30…

SO, if the closest coin is >= 20 away you will still go to it (regardless of value).
the loop over all coins will find none so, minDistance will still be 20, and closestCoin will still be the one returned by findNearest…(no matter how far away)


#7

I have tinkered with my code, hoping to get my guy to pick up the coins faster. Sadly, I broke it again! This level is my curse. I get “Fix Your Code: It’s either really slow or has an infinite loop.” I want to understand my mistake so that I can get better. I have been modify it for hours and it’s been all over the place. I can’t find which part of my code is infinitely looping or using up all of the memory.

# Create my variables and indices.
loop:
    coinIndex = 0
    coins = self.findItems()
    ogres = self.findEnemies()
    ogre = self.findNearest(ogres)
    bestCoin = None
    bestRating = 0

    #Cycle through my array of coins and choose the best one based on coin
    # value and it's dstance from me. Give it the name "bestCoin" and a         
    # rating of "bestRating"
    while coinIndex < len(coins):
        currentCoin = coins[coinIndex]
        coinIndex += 1
        coinDistance = self.distanceTo(currentCoin)
        currentRating = 100 * currentCoin.value / coinDistance
        if currentRating > bestRating:
            bestRating = currentRating
            bestCoin = currentCoin
        else:
            pass

    # If I have a "bestCoin" and the rating is decent, we will do things.
    if bestCoin and bestRating > 10:
        # First let's see if there is an ogre.
        if ogre:
            ogreDistance = self.distanceTo(ogre)
            # The ogre is far away. Let's grab that coin!
            if ogreDistance > 15:
                self.move({"x": bestCoin.pos.x, "y": bestCoin.pos.y})

            # The ogre is too close. Let's run to a teleporter.
            else:
                if self.pos.x > 43 and self.pos.y > 38:
                    self.moveXY(77, 51)
                elif self.pos.x > 43 and self.pos.y <= 38:
                    self.moveXY(77, 19)
                elif self.pos.x <= 43 and self.pos.y > 38:
                    self.moveXY(5, 50)
                elif self.pos.x <= 43 and self.pos.y <= 38:
                    self.moveXY(5, 20) 
                    bestCoin = None
                else:
                    pass
        # Ok, there was no ogre. Let's grab that coin!
        else:
            self.move({"x": bestCoin.pos.x, "y": bestCoin.pos.y})
    # The closest "bestCoin" seems to be pretty far away. Let's use a           
    # teleporter.
    else:
        if self.pos.x > 43 and self.pos.y > 38:
            self.moveXY(77, 51)
        elif self.pos.x > 43 and self.pos.y <= 38:
            self.moveXY(77, 19)
        elif self.pos.x <= 43 and self.pos.y > 38:
            self.moveXY(5, 50)
        elif self.pos.x <= 43 and self.pos.y <= 38:
            self.moveXY(5, 20) 
            bestCoin = None
        else:
            pass

IT ACTUALLY WORKED ONCE! And then the next game my guy just stood in the corner and was beaten to death :’(


#8

Honestly, the code doesn’t have to be this complicated. Try just grabbing the nearest coin (as long as nearest enemy is some distance away) and see how that works. I think you will be pleasantly surprised…


#9

The “Devourer” is the hunt for bestCoin. it runs EVERY time you take a step. This is the achilles heel of “move()” (nick is working on it). The only thing that can be done about it is to not do it . . . either at all (as Eiler13 suggests) or less often (by some means, say? time passage, move distance, need new best coin, etc).


#10

I tried the suggestion of eiler13, but this doesn’t work at all. I never come close to 150 gold. I think the most I got was 122. Grabbing the nearest coin without additional smarts just isn’t fast enough. I thought of trying what Elthran was doing (it was actually my first thought of what to do), but I actually got fewer coins.
What do I try next? I don’t have slow boots or anything, but I kill the ogres first because it takes two hits and then they’re dead.

loop {
    var enemy = this.findNearest(this.findEnemies());
    if (enemy) {
        while (enemy.health > 0) {
            this.attack(enemy);
        }
    }
    var item = this.findNearest(this.findItems());
    if (item) {
        var goldDistance = this.distanceTo(item);
        if (goldDistance > 15) {
            var x; var y;
            if (this.pos.x > 40) {x = 75;}
            else {x = 5;}
            if (this.pos.y > 35) {y = 50;}
            else {y = 20;}
            this.moveXY(x, y);
        }
        else {this.moveXY(item.pos.x, item.pos.y);}
    }
}

#11

It might make sense to use a while-loop to kill the ogres first instead of killing one at a time and fetching coins in between.


#12

there is no time =\

x = self.pos.x
y = self.pos.y
a = (5,48)
b = (5,19)
c = (75,51)
d = (75,20)
lista = [a,b,c,d]
def distancia(x1,y1,x2,y2):
    return (((x1-x2)**2 + (y1-y2)**2 )**(1/2))
loop:
    item = self.findNearest(self.findItems())
    enemy = self.findNearest(self.findEnemies())
    if enemy:
        if self.distanceTo(enemy)<=5:
            self.shield()            
            menor = 9999
            vez = a
            for lugar in lista:
                dist = distancia(lugar[0],lugar[1],self.pos.x,self.pos.y)
                if dist < menor:
                    menor = dist
                    vez = lugar                                
            x = vez[0]
            y = vez[1]
        elif item:
            x = item.pos.x
            y = item.pos.y
    elif item:
        x = item.pos.x
        y = item.pos.y
    self.moveXY(x, y)

#13

I’m afraid I’m having a hard time understanding your variables. Could you please explain what they are?


#14

It doesn’t have to be that complicated. Here is how i did it:

[redacted, we don’t post correct code]
This is my first post so i can’t figure out how to get the indentation right sorry.


#15

You realize that there is a topic that says “FAQ – read before posting”. If you had read it, then you would know how to format your code. Also we don’t post correct code to begin with. It provides easy answer without providing the learning experience.


#16

sorry about that! I haven’t been on here much i didn’t realize that. Won’t happen again. And i’ll read the FAQ.


#17

doesn’t work???


#18

@Tailin.Chen

If you click on D0rm1nd0’s name from his post, you’ll see that the person you are replying to hasn’t been logged into this board for over two years. If you’re having problems with a level, it’s best to start a new post or at least post your code here so we can assist you.