Quiz: Issuing successive commands

Question A: Will the paladin heal oneself?
case 1:

        if paladin.health < paladin.maxHealth and paladin.canCast("heal"):
            hero.command(paladin,"cast", "heal", paladin)    
        hero.command(paladin, "move", {"x":paladin.pos.x + 3, "y":paladin.pos.y})

case 2:

        hero.command(paladin, "move",  {"x":paladin.pos.x + 3, "y":paladin.pos.y})  
        if paladin.health < paladin.maxHealth and paladin.canCast("heal"):
            hero.command(paladin,"cast", "heal", paladin)

Question B: How to do the two cases right?

Both cases look valid, it just depends on if you want your paladin healed before he moves, or after.

@dedreous : Both cases are invalid, but strangely one of them is working and I donā€™t know why. :face_with_raised_eyebrow: Do you have Boss Star IV to summon Paladins?

No, you need the Boss Star V to do that (not available to users yet, only to the devs). BS IV however, does allow you to command Paladins tho.

Speaking of which, how are you defining your ā€œpaladinā€? I tested your move code using one of the ā€˜1000 Flowersā€™ levels. I had to summon a soldier, instead of a paladin, but the move concepts are the same. My test soldier move where I told him to. However, it took me a couple of tries to get his definition correct.

I compared your paladin heal statement against one I used in another level and it looks fine.

That leaves the definition of your paladinā€¦in my test, I used:

hero.summon("soldier")
paladins = hero.findFriends()
paladin = paladins[0]

There a many other ways to do this, but I went for the quick/easy way, since I knew I would be working with just the one friend.

Boss Star IV, test code & picture:

hero.moveXY(10, hero.pos.y)
hero.summon("paladin")
paladin = hero.findByType("paladin")[0]
while True:
    if paladin and paladin.health > 0:
        hero.attack(paladin)
        if paladin.health < paladin.maxHealth and paladin.canCast("heal"):
            hero.command(paladin,"cast", "heal", paladin) 
        hero.command(paladin, "move",  {"x":paladin.pos.x + 3, "y":paladin.pos.y}) 

lolā€¦once I remembered to change weapons, your code worked fine. Of course, a soldier cannot heal, so that part is not truly tested yet.

For comparison, I borrowed code from ā€˜make-advancesā€™:

                if friend.health <= friend.maxHealth / 2:
                    hero.command(friend, "cast", "heal", friend)

Of course, substitute ā€˜paladinā€™ for ā€˜friendā€™ here. Ohā€¦and the ā€˜canCastā€™ part too.

There were so many errors in ā€œMake advancesā€ topicā€¦So will the soldier attack the hero?

hero.moveXY(10, hero.pos.y)
hero.summon("soldier")
soldier = hero.findByType("soldier")[0]
while True:
    if soldier and soldier.health > 0:
        hero.attack(soldier)
        if soldier.health > soldier.maxHealth/3 and  soldier.health < soldier.maxHealth/2:
            hero.command(soldier,"attack", hero) 
        hero.command(soldier, "move",  {"x":soldier.pos.x + 3, "y":soldier.pos.y}) 

Oops, I just realized I was incorrect on the summon paladin pointā€¦obviously, IV does give that ability. There was a thread about that, somewhere, and I mis-remembered.

Unless you command him to do so, he should not.

When I run the code, I follow the paladin all the way to the east edge and keep attacking until heā€™s dead, taking no damage myself.

And replacing with:

        hero.command(soldier, "move",  {"x":soldier.pos.x + 3, "y":soldier.pos.y})         
        if soldier.health > soldier.maxHealth/3 and  soldier.health < soldier.maxHealth/2:
            hero.command(soldier,"attack", hero) 

What do you get? Are these the results you have expected?

Staying with ā€˜paladinā€™, yes it performs as expected. Once the paladin got below 300 and stayed above 200, heā€™d swing back and attack.

where is the paladin going: left, right or staying at the same place?

hero.summon("paladin")
condition1 = True
condition2 = True
paladin = hero.findByType("paladin")[0]
hero.moveXY(hero.pos.x +5 , hero.pos.y +5 )
while True:
    if condition1:
        hero.command(paladin, "move", Vector(paladin.pos.x + 1, paladin.pos.y))
    if condition2:
        hero.command(paladin, "move", Vector(paladin.pos.x - 1, paladin.pos.y))
    #  the hero "movement" is obvious
    if condition1:
        hero.move(Vector(hero.pos.x , hero.pos.y + 1))
    if condition2:
        hero.move(Vector(hero.pos.x , hero.pos.y -1))

Iā€™m asking @dedreous, @Deadpool198, @brooksy125 because almost all answers to questions about issuing successive commands are a mess ( example: Grim determination level)

That is a pretty good question! Iā€™m going to pose: while the ā€˜moveā€™ command is prevalent in both the paladin and hero statements, the methods are different. It appears that once the paladin move fires, it is forgotten (code is ignored).

Check out this test:

while True:
    #  the hero "movement" is obvious
    if condition1:
        hero.move(Vector(hero.pos.x , hero.pos.y + 1))
        hero.command(paladin, "move", Vector(paladin.pos.x + 1, paladin.pos.y))
    if condition2:
        hero.move(Vector(hero.pos.x , hero.pos.y - 1))
        hero.command(paladin, "move", Vector(paladin.pos.x - 1, paladin.pos.y))
#    if condition1:
#        hero.command(paladin, "move", Vector(paladin.pos.x + 1, paladin.pos.y))
#    if condition2:
#        hero.command(paladin, "move", Vector(paladin.pos.x - 1, paladin.pos.y))

In my initial test, I moved the hero conditions above the paladin and result was identical. With this next test, I combined the move statementsā€¦both are dancing now.

Get rid of hero code - it is for comparison only. Focus only on the paladin - where is she/he going and why?

Okā€¦I can only guess at the method. Iā€™m thinking that the hero.command move is actually leveraging the moveXY method.

Try swapping the +1 and -1ā€¦the paladin then moves to the right. And, if you add another condition1 (or 2) statement, reversing that last paladin moveā€¦that is the direction he goes. Itā€™s stopping at the final condition statement, in spite of the loop. Since it does not do this for the hero moves, the methods must differ.

Beyond that, I donā€™t have an answerā€¦perhaps Danny or Brooksy might.


Make this search. User htrnblr was maybe the first to show how to issue successive commands - itā€™s in the ā€œGrim Determination - paladin problemā€ , but I think all these topics show the right solution.

I guess Iā€™m not understanding the question then. As was stated in that post, ā€œif, elif, else is already understoodā€. That was my assumption too.

Are you asking why only the last statement is being fired in a stacked series? If yes, then you might need Nick for that oneā€¦no, I wonā€™t give him a shout :wink:

a sample from last posts:

if paladin.canCast("heal"): 
    hero.command(paladin, "cast", "heal", target) 
hero.command(paladin, "shield") 
hero.command(paladin, "attack", enemy) 
##############################################
        if enemy:
            hero.command(friend, "attack", enemy)
            if friend.health < friend.maxHealth:
                hero.command(friend, "move", {'x':44, 'y':44})
######################################################
        hero.command(friend, "move", {"x": 40,"y": 35})
        if enemy:
            hero.command(friend, "attack", enemy)
###############################################
## and this code is accepted as solution
    if enemy:
        hero.command(paladin, 'attack', enemy)
        inNeed = lowestHealthPaladin()
        if inNeed and paladin.canCast('heal'):
            hero.command(paladin, 'cast', 'heal', inNeed)
        if paladin.health < paladin.maxHealth * 0.5:
            hero.command(paladin, 'shield')    

``` Can you foresee what piece of code will be executed and why? This kind of errors are almost never spotted and corrected, because the code somehow works...

I never realized you couldnā€™t layer the commands for your friends like that, especially when using conditional if statements. I do remember some times when I couldnā€™t understand why it wasnā€™t working like I expected and this may have been part of that issue.

Now I just know to use if-elif-else to determine the condition before commanding. I recognize the 2nd one on your list. I commented on that one today. I didnā€™t run the code they had, just gave the suggestion to build your checks so you only run one command. Now that I run their code, I see my comment wasnā€™t accurate, the code jumps to the second if command.

So essentially, you can only command each ally once in a loop and the last command is the one it will follow. These are the details that need to be explained better in the levels. The specific commands could use more detail. hero.command ("move") seems to act more like hero.moveXY() instead of hero.move() as @dedreous puts it fire and forget.

Lack of documentation would be my biggest complaint about CodeCombat.

1 Like

Same. I first came across this properly, and realised what was going on in Kelvintaph defiler; I always found they just went with the last command, if the conditions of the two actions they had to choose from were both true.
Now, like brooksy, I use if-elif-else.

I think youā€™re on to something here.
Iā€™m afraid I canā€™t really add anything to that.