Grim Determination Stuck

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()


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 Likes

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.

1 Like

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

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?

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

the enemy break through easily

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

lowestFriend = lowestHealthPaladin()

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

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")

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

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

1 Like

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