Summits gate infinite loop

function fullHeal() {
    hero.say("here");
    var paladins = hero.findByType("paladin", hero.findFriends());
    var p1 = paladins[0];
    var p2 = paladins[1];    
    while (hero.health < hero.maxHealth) {
        if (p1.canCast("heal") && p2.canCast("heal")) {            
            hero.command(p1, "cast", "heal", hero);
            hero.command(p2, "cast", "heal", hero);
        }
        //hero.say("1");        
    }    
}

I’ve made this function to fully heal my hero using my 2 paladins. But for some reason this function results in an infinite loop unless i uncomment the “hero.say(“1”)” part. The weird thing is the function is not even executed if i dont have the hero.say part, but still causes an infinite loop elsewhere in my code.

This is my full code. So far i only call stageOne() and fullHeal()

// Fight your way into the Inner Sanctum of the ogre chieftain, and defeat her.
var stage = 1;
function lowestHealthPaladin() {
    var lowestHealth = 99999;
    var lowestFriend = null;
    if (hero.health < hero.maxHealth / 2)
        return hero;
    var friends = hero.findFriends();
    for (var f = 0; f < friends.length; f++) {
        var friend = friends[f];
        if (friend.health < lowestHealth && friend.health < friend.maxHealth) {
            lowestHealth = friend.health;
            lowestFriend = friend;
        }
    }
    return lowestFriend;
}
function 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")
    // And don't forget, they can attack, too!
    var low = lowestHealthPaladin();
    if (paladin.heatlh < paladin.maxHealth / 3) {
        //hero.say("shield");
        hero.command(paladin, "shield");
    } else if (low && paladin.canCast("heal")) {
        hero.command(paladin, "cast", "heal", low);
    } else
        hero.command(paladin, "attack", paladin.findNearestEnemy());
}
function commandArcher(friend) {
}
function commandSoldier(friend) {
}
function commandFriends() {
    // Command your friends.
    var friends = hero.findFriends();
    for (var i = 0; i < friends.length; i++) {
        var friend = friends[i];
        if (friend.type == "archer") {
            commandArcher(friend);
        } else if (friend.type == "soldier") {
            commandSoldier(friend);
        } else if (friend.type == "paladin") {
            commandPaladin(friend);
        }
    }
}
function heroAttack() {
    var enemy = hero.findNearestEnemy();
    if (hero.isReady("jump")) {
        hero.jumpTo(enemy);
    }
    if (enemy && hero.canCast("chain-lightning", enemy)) {
        hero.cast("chain-lightning", enemy);
    }
    if (enemy && hero.isReady("bash"))
        hero.bash(enemy);
    if (enemy)
        hero.attack(enemy);
}
function stageOne() {
    var catapults = hero.findByType("catapult", hero.findEnemies());
    var friends = hero.findFriends();    
    commandFriends(friends, "defend", {
            "x": 1,
            "y": 38
        }); 
    while (catapults[0] && catapults[0].health > 0) {
        hero.attack(catapults[0]);
    }
    while (catapults[1] && catapults[1].health > 0) {
        hero.attack(catapults[1]);
    }
    while (true) {
        var enemy = hero.findNearestEnemy();
        if (enemy && enemy.type != "door") {
            if (hero.canCast("chain-lightning", enemy)) {                
                hero.cast("chain-lightning", enemy);
            } 
            else
                hero.attack(enemy);
        } else {            
            break;
        }
    }
    
    hero.moveXY(92, 34);
    commandFriends(friends, "move", hero.pos);        
}

function fullHeal() {
    //hero.say("here");
    var paladins = hero.findByType("paladin", hero.findFriends());
    var p1 = paladins[0];
    var p2 = paladins[1];    
    while (hero.health < hero.maxHealth) {
        if (p1.canCast("heal") && p2.canCast("heal")) {            
            hero.command(p1, "cast", "heal", hero);
            hero.command(p2, "cast", "heal", hero);
        }
        hero.say("1");        
    }    
}

function commandFriends(friends, command, target) {
    for (var i=0; i < friends.length; i++) {
        hero.command(friends[i], command, target);
    }    
}
stageOne();
fullHeal();
hero.say("full");

Hi Skoll,

Try changing the ‘while’ into an ‘if’ for the function. Also try splitting the paladins, so that if p1 can cast heal then she heals, and if p2 can heal then she heals. I suspect the problem is that if one of them can’t heal then the while loops flicks around lots of times which is detected as an infinite loop.

Jenny

Try submitting it, then skip

But if i change the while into an if, then the paladins would only heal once each right? I tried splitting the paladins but that didnt change anything.

In the case where your hero is not at full health and at least one paladin is unable to heal, your while loop has no action in it, and thus will spin forever in an infinite loop. When you include the hero.say statement, instead CodeCombat blocks for a few frames every iteration as your hero says something, preventing an infinite loop. Nick comments on the exact behavior here.

How you want to solve this issue is up to you. The hero.wait command may come in handy as a replacement for an awkward hero.say.


(A side note- I’d suggest generalizing fullHeal() with a for loop over paladins so it’s able to utilize more or less than exactly two paladins. for-of loops are worth learning about)

1 Like

This topic was automatically closed 12 hours after the last reply. New replies are no longer allowed.