Grim Determination Stuck


#1

Hi, guys!

I have troubles with Grim Determination level.

What are the main ideas for building right strategy?

My current code

# Your goal is to protect Reynaldo

# Find the paladin with the lowest health.
def lowestHealthPaladin():
    lowestHealth = 99999
    lowestFriend = None
    friends = self.findFriends()
    for friend in friends:
        if friend.type != "paladin":
            continue
        if friend.health < lowestHealth and friend.health < friend.maxHealth:
            lowestHealth = friend.health
            lowestFriend = friend

    return lowestFriend



paladinPoint = {'x': 88, 'y': 43}

def commandPaladin(paladin):
    # Heal the paladin with the lowest health using lowestHealthPaladin()
    # You can use paladin.canCast("heal") and command(paladin, "cast", "heal", target)
    # Paladins can also shield: command(paladin, "shield")
    
    lowestFriend = lowestHealthPaladin()
    healingThreshold = 0.8 * paladin.maxHealth
    warlocks = self.findByType('warlock')
    nearestWarlock = paladin.findNearest(warlocks)
    nearestEnemy = paladin.findNearest(self.findEnemies())
#    if nearestWarlock:
#        dx = nearestWarlock.pos.x - paladin.pos.x
#        dy = nearestWarlock.pos.y - paladin.pos.y
#        dist = dx**2 + dy**2
    
    if lowestFriend and paladin.canCast('heal') and lowestFriend.health < healingThreshold:
        self.command(paladin, 'cast', 'heal', lowestFriend)    
        
    elif nearestWarlock:
        self.command(paladin, 'attack', nearestWarlock)
    
    elif nearestEnemy:
        self.command(paladin, 'attack', nearestEnemy)
        
    else:        
        self.command(paladin, 'defend', paladinPoint)




def commandGriffin(griffin):
    warlocks = self.findByType('warlock')
    nearestWarlock = griffin.findNearest(warlocks)
    nearestEnemy = griffin.findNearest(self.findEnemies())
    
    if nearestWarlock:
        self.command(griffin, 'attack', nearestWarlock)
        
    elif nearestEnemy:
        self.command(griffin, 'attack', nearestEnemy)
        
    else:
        self.command(griffin, 'defend', paladinPoint)



def commandPeasant(peasant):
    peasants = self.findByType('peasant')
    
    for i, pes in enumerate(peasants):
        if pes is peasant:
            break
    
    coins = self.findItems()
    nearestCoin = peasant.findNearest(coins)
    
    if i == 0 and nearestCoin.pos.y <= 43:
        self.command(peasant, 'move', nearestCoin.pos)
    elif i == 1 and nearestCoin.pos.y > 43:
        self.command(peasant, 'move', nearestCoin.pos)


def commandFriends():
    # Command your friends.
    friends = self.findFriends()
    for friend in friends:
        if friend.type == "peasant":
            commandPeasant(friend)
            
        elif friend.type == "griffin-rider":
            commandGriffin(friend)
            
        elif friend.type == "paladin":
            commandPaladin(friend)


def summonGriffin():
    if self.gold >= self.costOf('griffin-rider'):
        self.summon('griffin-rider')



loop:
    commandFriends()
    # Summon griffin riders!
    summonGriffin()



#2

You are chasing the warlocks too hard, even if they are miles away or blocked by hordes of enemies.

I passed with your code by deleting the lines 39 and 40:
[...]elif nearestWarlock:[...]

Even with bonus, cause it’s good code besides that.


#3

It seems that once I kill a warlock another one or two spawn in a couple of seconds.
So, without prioritizing them, I summon only 2 instead of 15 during the combat.

That’s amazing! Thank you.


#4

Your goal is to protect Reynaldo

Find the paladin with the lowest health.

def lowestHealthPaladin():
lowestHealth = 99999
lowestFriend = None
friends = self.findFriends()
for friend in friends:
if friend.type != “paladin”:
continue
if friend.health < lowestHealth and friend.health < friend.maxHealth:
lowestHealth = friend.health
lowestFriend = friend
return lowestFriend

paladinPoint = {‘x’: 88, ‘y’: 43}

def commandPaladin(paladin):
# Heal the paladin with the lowest health using lowestHealthPaladin()
lowestFriend = lowestHealthPaladin
healingThreshold = 0.8 * paladin.maxHealth
nearestEnemy = paladin.findNearest(self.findEnemies())

if lowestFriend and paladin.canCast("heal") and lowestFriend.health < healingThreshold:
    self.command(paladin, "cast", "heal", lowestFriend)
elif nearestEnemy:
    self.command(paladin, "attack", nearestEnemy)
else:
    self.command(paladin, "defend", paladinPoint)
# You can use paladin.canCast("heal") and command(paladin, "cast", "heal", target)
# Paladins can also shield: command(paladin, "shield")
# And don't forget, they can attack, too!

def commandGriffin(griffin):
warlocks = self.findByType(“warlock”)
nearestWarlock = griffin.findNearest(warlocks)
nearestEnemy = griffin.findNearest(self.findEnemies())

elif nearestEnemy:
    self.command(griffin, "attack", nearestEnemy)

def commandPeasant(peasant):
peasants = self.findByType(“peasant”)

for i, pes in enumerate(peasants):
    if pes is peasant:
        break
    
coins = self.findItems()
nearestCoin = peasant.findNearest(coins)

if i == 0 and nearestCoin.pos.y <= 43:
    self.command(peasant, "move", nearestCoin.pos)
elif i == 1 and nearestCoin.pos.y > 43:
    self.command(peasant, "move", nearestCoin.pos)

def commandFriends():
# Command your friends.
friends = self.findFriends()
for friend in friends:
if friend.type == “peasant”:
commandPeasant(friend)
if friend.type == “griffin-rider”:
commandGriffin(friend)
elif friend.type == “paladin”:
commandPaladin(friend)

def summonGriffin():
if self.gold >= self.costOf(“griffin-rider”):
self.summon(“griffin-rider”)

loop:
commandFriends()
summonGriffin()

con some one help me
sorry about the FAQ it wouldn’t work


#5

To format your code correctly, please highlight it and click the </> button. This lets others check the indentation and makes the code much easier to read.

What is your problem?


#6

simple problem but huge.my griffins attack and the peasants collect coins but the griffins don’t block them enough. my paladins die and break through is there something wrong or what


#7

the enemy break through easily


#8

Are your paladins healing? To call a function you must add the argument list ( ) after its name:

lowestFriend = lowestHealthPaladin()

#9

what do mean and where do i add it. i tried myself with the info. i kow and it said “maximum stack exceeded”


#10

my paladins either heal or attack, but if they heal they attack for a few minutes then stop attacking and just heal. Same if I choose to shield.

def commandPaladin(paladin):
    friends = self.findFriends()
    for friend in friends:
        if friend.type == "paladin":
            target = lowestHealthPaladin()
            enemy = friend.findNearest(friend.findEnemies())
            if target:
                if friend.canCast("heal", target):
                    self.command(friend, "cast","heal", target)
            elif enemy:
                self.command(friend, "attack", enemy)
            #else:
                #self.command(friend, "shield")


#11

What happens if there’s a target but the paladin can’t cast heal again yet?


#12

If you use combined if structures you must count all the possible paths your code can take. Each if instruction adds 1 extra branch on top of the one branch a normal code has. So 4 if’s will generate 5 branches (elif counts as an if also)

if friend.type == "paladin":
            if target:
                if friend.canCast("heal", target):
                    # 1st branch: paladin, someone to help, heal spell ready
                else:
                    # 2nd branch: paladin, someone to help, spell not ready
           else:
                if enemy:
                   # 3rd branch: paladin, none to help, enemy found
                else:
                   # 4th branch: paladin, none to help, no enemy 
else:
          #5th branch, not a paladin

Ugggh! So many branches! And in the #2 and #3 branch you may have to right similar code. No one wants to write code twice. The solution is to add an extra variable which catches all the untreated branches:

if friend.type == "paladin":
            busy = False 
            #busy must be set to False every time before the if structure starts
            if target:
                if friend.canCast("heal", target):
                    # 1st branch: paladin, someone to help, heal spell read
                    #We do something here
                    busy = True
                #else:
                    # we do not write this branch at all, it will be caught
           # No we start a second if structure instead of putting ifs inside each other
           if not busy:
                if enemy:
                    # 2rd branch: paladin, not busy = has not cast heal this turn, enemy found
                    #we do something  here
                    busy = True 
                #else:
                   # 3rd branch: paladin, not busy, not enemy
                   # maybe move or shield
                   busy = True
          #else
                 #paladin, busy 
                # well, he is already busy doing something, leave him alone, no need to write  
else:
          #not a paladin
          #4th branch
          busy = False   
          #if we have something else to command we start again the same structure

It looks more complicated but you actually need to write less paths and it is easier to verify


#13

thanks just one more question.should i replace the code i have for the paladins right now or add it in
and Catsync, paladins don’t heal at all