Summit's Gate: code help


#1

I’m almost at the Glacier. All I’ve got left is Summit’s Gate, that’s all. (Note cheerfully sarcastic tone…)

Where I’m stuck at right now is that I can’t get the code to progress past the Beam Towers. I can defeat them, but I can’t figure out how to word the code to trigger the next phase of my code. I hope this makes sense, because I don’t know the technical jargon.

To try to explain a bit better: I made an if bTower or bTower1 clause to get the soldiers and hero to attack them (I defined the variables beforehand), figuring that once their health is <= 0, they’ll be false. (That worked for the catapults.) Nope. Even after the Towers are ‘dead’, they just stand around, instead of the code passing into the else or elif (I debugged this with hero.say() just to be sure, putting a comment in the beginning of the elif, and it never got said.) I tried to use bTower.health > 0 or bTower1.health > 0, but it’s no better, which is really puzzling, because I can clearly see that they’re below zero. I’m throwing in a picture for good measure.

PS - For some reason the hero isn’t saying the cheeky debug I put in (if hero.time > 45: on line 147-148). Do I have to start hero.time somehow before I can use it? I seem to remember being able to use it fine in other levels.


#2

Hmm. If you have those glasses with infinite range and doesn’t need line-of-sight to find enemies, maybe you’re checking for the health of towers that are found later on in the level. I haven’t played through this stage yet, so I don’t know for sure if there are more than 2 towers.

Maybe you can check for the closest 2 towers (dead or alive) using this
    #...
    elif stage == 2:
        bTowers = hero.findByType("tower")
        
        # if bTower doesn't exist yet, get the nearest tower.
        if not bTower: 
            bTower = hero.findNearest(bTowers)
        # remove the nearest tower from the list of towers.
        bTowers.remove(bTower)
        
        # if bTower1 doesn't exist yet, get the nearest tower from the remaining towers.
        if not bTower1:
            bTower1 = hero.findNearest(bTowers)
        # bTowers.remove(bTower1)
        
        # then do your bTower and bTower1 health checks

(I haven’t tested this lol so make adjustments if you get bugs)


#3

Can you post you whole code so I can inspect what’s wrong?


#4

There are only two beam towers.


#5

Try using different flags for different tactics.


#6

Try splitting each stage into individual functions and piecing them together, or use flags as @Chaboi_3000 mentioned.


#7

I used Senik for this level. My gift of the trees has scattershot which does great damage.


#8

Don’t say I didn’t warn you…

I’m working on refactoring. I’ll probably adopt @Hellenar’s idea of breaking the stages into functions. I’m very open to additional suggestions for refactoring from anyone energetic enough to wade through this.

(@Chaboi_3000, you’ll see I tried using flags, too. That usually didn’t work, though there was one time where I was running on the small screen (not submitting), and a flag I had placed the last time I had submitted came on as my hero was attacking the towers, and that time, it actually went in to stage 3, causing her to stop attacking the towers and getting zapped up.)

A Whole Lot of Code
summonTypes = ['soldier', 'soldier', 'archer', 'archer']
tactic = 'defend'
stage = 1


def summonTroops():
    type = summonTypes[len(hero.built) % len(summonTypes)]
    if hero.gold > hero.costOf(type):
        hero.summon(type)


def lowestHealthPaladin():
    lowestHealth = 99999
    lowestFriend = None
    friends = hero.findFriends()
    for friend in friends:
        if friend.health < lowestHealth and friend.health < friend.maxHealth:
            lowestHealth = friend.health
            lowestFriend = friend
    return lowestFriend


def commandPaladin(paladin):
    if (paladin.canCast("heal")):
        if (hero.health < hero.maxHealth * 0.8):
            target = self
        else:
            target = lowestHealthPaladin()
        if target:
            hero.command(paladin, "cast", "heal", target)
    elif (paladin.health < 100):
        hero.command(paladin, "shield")
    else:
        target = hero.findNearestEnemy()
        if warlock:
            target = warlock
        if target:
            hero.command(paladin, "attack", target)


def SoldierAttack(soldier):
    target = hero.findNearestEnemy()
    if warlock:
        target = warlock
    
    if target:
        if stage != 2 or soldier.type != 'archer':
            hero.command(soldier, "attack", target)
        else:
            if target.type == 'tower':
                if target.pos.y < 35:
                    hero.command(soldier, "move", {'x': 110, 'y': 28})
                    hero.command(soldier, "attack", target)
                else:
                    hero.command(soldier, "move", {'x': 110, 'y': 37})
                    hero.command(soldier, "attack", target)
    
    if stage == 1:
        if soldier.pos.x > 81:
            hero.command(soldier, "defend", {'x': 70, 'y': 34})

        
            
def SoldierDefend(soldier):
    if stage == 1:
        hero.command(soldier, "defend", {'x': 1, 'y': 40})
    elif stage == 2:
        hero.command(soldier, "defend", {'x': 92, 'y': 34})
    elif stage == 3:
        hero.command(soldier, "defend", {"x": 277, "y": 34})
    elif stage == 4:
        hero.command(soldier, "defend", {'x': 278, 'y': 34})
    else:
        hero.command(soldier, "defend", hero)

def commandSoldiers():
    soldiers = hero.findFriends()
    for soldier in soldiers:   
        if soldier.type == "paladin":
            commandPaladin(soldier)
        elif tactic == 'attack':
            SoldierAttack(soldier)
        elif tactic == 'defend':
            SoldierDefend(soldier)


def moveTo(position):
    if hero.isReady("jump"):
        hero.jumpTo(position)
    else:
        hero.move(position)


def attack(target):
    if target:
        if hero.distanceTo(target) > 45:
            moveTo(target.pos)
        else:
            hero.attack(target)

def announceStage():
    hero.say("STAGE " + stage + "!!!")

def pickUpNearestItem():
    nearestItem = hero.findNearest(hero.findItems())
    if nearestItem:
        moveTo(nearestItem.pos)


commandSoldiers()
hero.moveXY(31, 56)
while True:
    greenFlag = hero.findFlag("green")
    if stage == 1:
        catapults = hero.findByType('catapult')
        catapult = catapults[0]
        catapult1 = catapults[1]
        warlock = hero.findNearest(hero.findByType('warlock'))
        target = hero.findNearestEnemy()
        nearestItem = hero.findNearestItem()
        
        if catapult or catapult1:
            attack(hero.findNearest(catapults))
        elif stage == 1:
            global tactic
            tactic = 'attack'
            commandSoldiers()
            if target:
                hero.attack(target)
            
            if target.type == 'tower':
                global stage
                stage = 2
                
                global tactic
                tactic = 'defend'
                commandSoldiers()
    elif stage == 2:
        bTowers = hero.findByType("tower")
        bTower = bTowers[0]
        bTower1 = bTowers[1]
        
        
        if bTower or bTower1:
            if hero.pos.x < 108:
                hero.moveXY(129, 34)
            target = hero.findNearestEnemy()
            
            if hero.canCast("chain-lightning", target):
                hero.cast("chain-lightning", target)
            hero.attack(target)
            hero.attack(target)
            hero.attack(target)
            global tactic
            tactic = 'attack'
            commandSoldiers()
            if greenFlag:
                global stage
                stage = 3
                announceStage()
                commandSoldiers()
                hero.pickUpFlag(greenFlag)
        
        else:
            
            global stage
            stage = 3
            announceStage()
            commandSoldiers()
            hero.moveXY(270, 34)
    elif stage == 3:
        global tactic
        tactic = 'defend'
        commandSoldiers()
        hero.moveXY(270, 34)
        if hero.pos.x >= 267 and hero.pos.x < 290:
            pet.moveXY(277, 65)
            pet.moveXY(261, 60)
            pet.moveXY(263, 56)
            pet.moveXY(276, 54)
            pet.moveXY(275, 13)
            pet.moveXY(262, 9)
            pet.moveXY(269, 3)
            pet.moveXY(277, 33)
            pickUpNearestItem()

#9

I have figured out that using a lack of targeted enemies to trigger the next phase is no good, because there’s always the next door, which counts as an enemy.

I have, on the other hand, refactored my strategy to the point where I can get by the beam towers without losing any troops…


#10

Hmm… I’ve made it to what I’d call stage 4, namely the warlocks right before the last chamber with the chieftain in it. My big problem now is that my hero is targeting a nearest enemy on the other side of the closed door. Is there a way to use hero.findNearest with a restriction on the x-coordinate? I thought of putting the if-clause in the same line, like a ternary clause, but I can’t nail it.


#11
def findNearestEnemyInXRange(xmin, xmax, enemies = hero.findEnemies()):
    enemiesInXRange = []
    # iterate through each enemy in enemies
        # if the enemy is within the x-range, append that enemy to enemiesInXRange
    # find the nearest enemy from enemiesInXRange
    # return that enemy

# example usage
enemy = findNearestEnemyInXRange(85, 100)
if enemy:
    hero.say(enemy.id)
Instead of using a for loop

Instead of going through a for loop, you can make a generator or list comprehension to find enemies within the x-range.
Info about generators and list comprehensions:
https://www.codementor.io/djangostars/python-list-comprehensions-generator-expressions-6dnzuh12c
Example code:

enemiesWithHighHealth = [enemy for enemy in enemies if enemy.health > 200]
# or
enemiesWithHighHealth = (enemy for enemy in enemies if enemy.health > 200)

#12

Couldn’t you remove your twilight glasses and replace them with something like enchanted lenses(those have infinity range without seeing through walls) or check the type of the enemy and if it’s type "warlock" or "skeleton" (summoned by warlocks)?


#13

I would like to thank the community (and my i7 cores):

Thanks for all the help, guys. And that means we’re one more player closer to lavaland…


#14

can you show your code


#15

No one on this board just gives out code. That’s not what this board is for so please don’t ask. The purpose of this board is to help you figure out the solution yourself so you can learn. Simply providing solutions/code for the purpose of passing a level and moving on to the next one is counterproductive to the main goal and you’re just going to get stuck on the next level.


#16

I did it later on my own apparently my internet was slow.