Running out of time on Sarven Teasure

Hi folks.

I’m having some trouble with Sarven Treasure. I don’t think there’s much wrong with my strategy: basically, run around collecting coins unless an ogre gets too close, then run towards teleport that is furthest from the approaching ogre (thus ensuring I’m running away from the ogre). I experimented a bit with the safety range, and 12 seems to get the best results, but I’m just running out of time before I get to 150 gold. I tried adding in an invisibility spell, but that just made things worse, so I commented it out. Any suggestions?

def goTowardsTeleporter(n):
    if n ==1:
        hero.move({"x": 5, "y": 49})
    elif n == 2:
        hero.move({"x": 5, "y": 19})
    elif n == 3:
        hero.move({"x": 76, "y": 51})
    elif n == 4:
        hero.move({"x": 77, "y": 19})
    return

while True:
    targetPortal = 0
    safetyDistance = 12
    enemy = hero.findNearestEnemy()
    if enemy:
        distance = hero.distanceTo(enemy)
        if distance >= safetyDistance:
            coin = hero.findNearestItem()
            if coin:
                hero.moveXY(coin.pos.x, coin.pos.y)
        elif distance < safetyDistance:
            #castable = hero.canCast("invisibility", hero)
            #if castable:
            #    hero.cast("invisibility", hero)
            if enemy.pos.x < hero.pos.x and enemy.pos.y < hero.pos.y:
                targetPortal = 3
            elif enemy.pos.x < hero.pos.x and enemy.pos.y >= hero.pos.y:
                targetPortal = 4
            elif enemy.pos.x >= hero.pos.x and enemy.pos.y >= hero.pos.y:
                targetPortal = 2
            elif enemy.pos.x >= hero.pos.x and enemy.pos.y < hero.pos.y:
                targetPortal = 1
            goTowardsTeleporter(targetPortal)

Have you thought about finding the best value coin to distance?

highest = 0
bestCoin = null
coins = ???

if coin.value / hero.distanceTo(coin) > bestCoin:
bestCoin = coin
highest = coin.value / hero.distanceTo(coin)

Hi brotherofall,

thanks for the suggestion. I already tried implementing something very similar (see the , bestValueCoin(coins) method in my alternative code, below) but I found that I ran out of time with even fewer gold collected (79, versus 143 without). I’ve had similar problems with code executing very slowly on other levels, so I wonder if it’s just a [my computer] problem?

# Collect 150 gold while evading ogres with teleporters.
# If you win, it gets harder (and more rewarding).
# If you lose, you must wait a day before you can resubmit.
# Remember, each submission gets a new random seed.

def goTowardsTeleporter(n):
    if n ==1:
        hero.move({"x": 5, "y": 49})
    elif n == 2:
        hero.move({"x": 5, "y": 19})
    elif n == 3:
        hero.move({"x": 76, "y": 51})
    elif n == 4:
        hero.move({"x": 77, "y": 19})
    return

def valueOverDistance(coin):
    return coin.value / hero.distanceTo(coin)


def bestValueCoin(coins):
    bestCoin = coins[0]
    for coin in coins:
        if valueOverDistance(coin) > valueOverDistance(bestCoin):
            bestCoin = coin
    return bestCoin

while True:
    targetPortal = 0
    enemy = hero.findNearestEnemy()
    if enemy:
        distance = hero.distanceTo(enemy)
        if distance >= 12:
            coins = hero.findItems()
            if coins[0]:
                bestCoin = bestValueCoin(coins)
                hero.moveXY(bestCoin.pos.x, bestCoin.pos.y)
        elif distance < 12:
            castable = hero.canCast("invisibility", hero)
            if castable:
                hero.cast("invisibility", hero)
            if enemy.pos.x < hero.pos.x and enemy.pos.y < hero.pos.y:
                targetPortal = 3
            elif enemy.pos.x < hero.pos.x and enemy.pos.y >= hero.pos.y:
                targetPortal = 4
            elif enemy.pos.x >= hero.pos.x and enemy.pos.y >= hero.pos.y:
                targetPortal = 2
            elif enemy.pos.x >= hero.pos.x and enemy.pos.y < hero.pos.y:
                targetPortal = 1
            goTowardsTeleporter(targetPortal)

@middleagedspread I think I found the solution to your problem. I noticed a something you can change which is to move to coins before the enemies show up. Also the for statement is better to execute the best coin. Below is how it would look in Javascript if you can look at it and change to Python it should work after those changes.

            var highest = 0;
            var bestCoin = null;
            var coins = hero.findItems();

        for (var i = 0; i < coins.length; i++) {
            var coin = coins[i];

            if (coin.value / hero.distanceTo(coin) > highest) {
            highest = coin.value / hero.distanceTo(coin);
            bestCoin = coin
            hero.moveXY(bestCoin.pos.x, bestCoin.pos.y)
            }
         }

Hi brotherofall,

thanks again. Good spot on collecting coins before the enemy shows up, I’ll give modify that. I think I’m already implementing my bestCoin algorithm in the same way you are (i.e. with a for loop), but I’m comparing coin values directly without an additional ‘highest’ variable.

I’ve pulled the code out of the methods and added comments to make it clearer:

bestCoin = coins[0] # set bestCoin to be first coin in array of coins
    for coin in coins: #this is the python syntax for looping through every value in the coins array
        if coin.value / hero.distanceTo(coin) > bestCoin.value / hero.distanceTo(bestCoin) #compare the next item in the array to the current bestCoin
:
            bestCoin = coin #assign the new best value coin to bestCoin
    return bestCoin #once out of the loop, I return the best value coin in the array, which is the one the hero then goes to
  var highest = 0;
            var bestCoin = null;
            var coins = hero.findItems();

        for (var i = 0; i < coins.length; i++) {
            var coin = coins[i];

            if (coin.value / hero.distanceTo(coin) > highest) {
            highest = coin.value / hero.distanceTo(coin);
            bestCoin = coin
            hero.moveXY(bestCoin.pos.x, bestCoin.pos.y)
            }
         }

Other little details to consider: which hero are you using and what fast gear? Using a ranger will let you attack the ogres at a safe distance. Also, do you have the ability to call in friends to distract the enemies? Flags can help with this level if you want to help direct the hero away manually (I prefer to stick to code, more challenging).

1 Like

Replace in your original code:

                hero.moveXY(coin.pos.x, coin.pos.y)
# with                
                hero.move(coin.pos) 

Thanks brooksy125. I’m not a subscriber yet, so I’ve just been using the basic warrior hero. I did add some fast boots, and now I’ve also added the speed ring (as well as the one-ring and painted steel armour all round): that got me through the first level, but no farther. Like you I want to do it with code only.

Thanks xython, I’ll do that.