Misty Island Mine Ran Out of Time

I have recently tried the Misty Island Mine level. I have all of the code. The code works like a charm, but it says i run out of time before the peasants have 300 gold. I am even giving one of them haste every now and again. Nothing

That something wrong with your code. I’ve completed this level. Reply to me on a PM I’m going to send you and there I can help you.

1 Like

I am having problems with misty island mine. My code is working fine, but there seems to be logic problem in the code. Can you pm me what I should fix? My code is below.

// Collect gold efficiently by commanding peasants wisely!
// Peasants should collect coins and build decoys.
// The function should return the best item per target
// Use an array of ids to ensure no two peasants target the same item.
function findBestItem(friend, excludedItems) {
var items = friend.findItems();
var bestItemValue = 0;
var currentItemValue = 0;
var bestItem = items[0];
for (var i = 0; i < items.length; i++) {
var item = items[i];
// indexOf searches and array for a certain element:
var idx = excludedItems.indexOf(item);
// If the array doesn’t contain it, it returns -1
// In that case, skip over that item as another peasant is targeting it.
if (idx != -1) {
continue;
}
// Finish the function!
// Remember bestItemValue should be the highest item.value / distanceTo
currentItemValue = item.value / hero.distanceTo(item);
bestItemValue = bestItem.value / hero.distanceTo(bestItem);
if (currentItemValue > bestItemValue) {
bestItem = item;
}
}
return bestItem;
}
while (true) {
var peasants = hero.findByType(“peasant”);
// Create a new array every loop.
var claimedItems = [];
for (var i = 0; i < peasants.length; i++) {
var peasant = peasants[i];
var enemy = peasant.findNearestEnemy();
if (enemy) {
// If the peasant is the target of the enemy
// AND the hero has enough gold for a decoy
if (enemy.target == peasant && hero.gold >=peasant.costOf(“decoy”)){
hero.say(hero.gold);
hero.say(hero.costOf(“decoy”));
hero.command(peasant, “buildXY”, “decoy”, peasant.pos.x - 5, peasant.pos.y);
continue;
} // Command a peasant to build a “decoy”:
// Add a continue so the peasant doesn’t collect coins when building.
}
var item = findBestItem(peasant, claimedItems);
if (item) {
// After an item is claimed, stick it in the claimedItems array.
claimedItems.push(item);
// Command the peasant to collect the coin:
hero.command(peasant, “move”, item.pos);
}
}
}

Please format your code correctly. Then we can help.
Use triple backticks before and after your code.

Can send me the answer?

Hi Andro,
We do not share solutions in this forum. If you need assistance with a level, please create a new topic and post your code(With the correct format), and we’ll be more than happy to help!

Ok, so I helped you formatted the code and also found out a few mistakes, but here is your code formatted, and also sorry if my grammar is bad:

// Collect gold efficiently by commanding peasants wisely!
// Peasants should collect coins and build decoys.
// The function should return the best item per target
// Use an array of ids to ensure no two peasants target the same item.
function findBestItem(friend, excludedItems) {
    var items = friend.findItems();
    var bestItemValue = 0;
    var currentItemValue = 0;
    var bestItem = items[0];
    for (var i = 0; i < items.length; i++) {
       var item = items[i];
        // indexOf searches and array for a certain element:
        var idx = excludedItems.indexOf(item);
        // If the array doesn’t contain it, it returns -1
        // In that case, skip over that item as another peasant is targeting it.
        if (idx != -1) {
            continue;
        }
        // Finish the function!
        // Remember bestItemValue should be the highest item.value / distanceTo
        currentItemValue = item.value / hero.distanceTo(item);
        bestItemValue = bestItem.value / hero.distanceTo(bestItem);
        if (currentItemValue > bestItemValue) {
            bestItem = item;
        }
        return bestItem;
    }
}
while (true) {
    var peasants = hero.findByType("peasant");
    // Create a new array every loop.
    var claimedItems = [];
    for (var i = 0; i < peasants.length; i++) {
        var peasant = peasants[i];
        var enemy = peasant.findNearestEnemy();
        if (enemy) {
            // If the peasant is the target of the enemy
            // AND the hero has enough gold for a decoy
            if (enemy.target == peasant && hero.gold >=peasant.costOf("decoy")){
                hero.say(hero.gold);
                hero.say(hero.costOf("decoy"));
                hero.command(peasant, "buildXY", "decoy", peasant.pos.x - 5, peasant.pos.y);
                continue;
            } // Command a peasant to build a "decoy":
        // Add a continue so the peasant doesn’t collect coins when building.
        }
        var item = findBestItem(peasant, claimedItems);
        if (item) {
            // After an item is claimed, stick it in the claimedItems array.
            claimedItems.push(item);
            // Command the peasant to collect the coin:
            hero.command(peasant, "move", item.pos);
        }
    }
}

There are two problems:
The first problem, line 41, or hero.say(hero.costOf("decoy")); is wrong if you didn’t bring a building tool, which you probably didn’t. So scrap that line.Also, the hero doesn’t need to say anything, and saying things will probably make you lose. I can say that because I put your code into my level (don’t worry I copied my code), then deleted both line 40 (which is correct) and line 41 (and also what I will point out in line two), and your code worked like a charm. I also told the hero to say yeet instead of what you put in line, and it made the code not such a charm.
The second problem appears in line 42 of your original code, and I guess you forgot what they teach you in Kithgard Dungeon: Read the HINTS! Page 2 of the hints state that the building position should be peasant.pos.x - 2 (Y position remains the same). I removed your two lines of hero.say(something) and your code still failed, but I replaced peasant.pos.x - 5 with peasant.pos.x - 2, and it worked perfectly. Even I don’t understand why it wouldn’t work, as peasants building decoys at peasant.pos.x - 2 and peasant.pos.x - 5 both takes the peasant 0.2 seconds to build the decoy.
After I copied your code onto my level and done these modifications, the code worked. Hopefully it will help you.

Another note: The modified code originally worked but after a few more tries it failed. The reason to that is because the peasants are huddled together, causing them to get not enough coins to build a decoy. And that I actually need help on.
Sorry

Hi @3nterpris3, thank you very much for helping on the forum! Unfortunately I don’t think Toxic Reaper is around any more to see your reply, so it might not be very helpful to him/her. And you probably spent quite a long time writing your reply. I would recommend before you reply to someone, check how recently they’ve visited the forum, and how much time they’ve spent reading topics recently. You can do this by visiting their profile.
And if you look here:
Screen Shot 2020-02-21 at 10.40.13
So that means they haven’t been here for around 8 months.
Thanks
Danny

1 Like

Thx for that. I don’t mind it and also somebody else might come and take a look for hints too.

1 Like

Alright I found the issue:
These lines have the same error that leads to all the peasants going for the same coin.

currentItemValue = item.value / hero.distanceTo(item);
bestItemValue = bestItem.value / hero.distanceTo(bestItem);

If you used hero.distanceTo(whatever);, all the peasants will go for the same coin as the distance to the coin isn’t from the peasants’ prospective, but the hero’s.
You should replace “hero” with “friend”.

Another problem:
Random coin placement means sometimes ogres will go for peasants that do not have adequate coins to build a decoy. In that case, you might want to submit the levels a few times before changing your code. I learnt that by having to attempt six times, and five of them failed.

@3nterpris3
Will you launch a manned rocket to Mars if you know only one of six crew will survive the adventure? Better post your code to see where you fail so miserably.

This is the code that failed so miserably:

// Collect gold efficiently by commanding peasants wisely!
// Peasants should collect coins and build decoys.
// The function should return the best item per target
// Use an array of ids to ensure no two peasants target the same item.
function findBestItem(friend, excludedItems) {
    var items = friend.findItems();
    var bestItem = null;
    var bestItemValue = 0;
    for (var i = 0; i < items.length; i++) {
        var item = items[i];
        // indexOf searches and array for a certain element:
        var idx = excludedItems.indexOf(item);
        // If the array doesn't contain it, it returns -1
        // In that case, skip over that item as another peasant is targeting it.
        if (idx != -1) {
            continue;
        }
        // Finish the function!
        // Remember bestItemValue should be the highest item.value / distanceTo
        var currentItemValue = item.value / friend.distanceTo(item);
        if (currentItemValue > bestItemValue) {
            bestItem = item;
            bestItemValue = currentItemValue;
        }
    }
    return bestItem;
}
// This function checks if you have enough gold for a decoy.
function enoughGoldForDecoy() {
    return hero.gold >= 25;
}
while (true) {
    var peasants = hero.findByType("peasant");
    // Create a new array every loop.
    var claimedItems = [];
    for (var i = 0; i < peasants.length; i++) {
        var peasant = peasants[i];
        var enemy = peasant.findNearestEnemy();
        if (enemy) {
            // If the peasant is the target of the enemy
            // AND the hero has enough gold for a decoy
            if (enemy.target == peasant && enoughGoldForDecoy) {
                // Command a peasant to build a "decoy":
                hero.command(peasant, "buildXY", "decoy", peasant.pos.x - 2, peasant.pos.y);
                // Add a continue so the peasant doesn't collect coins when building.
                continue;
            }
        }
        var item = findBestItem(peasant, claimedItems);
        if (item) {
            // After an item is claimed, stick it in the claimedItems array.
            claimedItems.push(item);
            // Command the peasant to collect the coin:
            hero.command(peasant, "move", item.pos);
        }
    }
}

I submitted it 20 times today without changing the code, and submitting means the coins’ placements are random. I have a 75% success chance, failing at attempt 4, 5, 13, 14 and 17.
Try it. The main issue is that when a peasant is walking to the coin with the highest value / distance, another one with an even higher value / distance spawns, so the peasants heads for that, and then another, and another, until the peasant got killed by the ogres.

1 Like

Your code is following the default one and it’s perfectly right. I admire you tested it so thoroughly. I admit was extremely lucky when passed long time ago the level, even without using the very helpful hints. Tried your code, but instead of heading the decoys toward the towers I pointed them toward the “aliens”. I have 10/10 “success” rate’. In 9/10 cases all my peasants survive. I don’t notice indigenous casualties. One submission is very unfortunate - 3 peasants perish, only one finishes the goal and I think this is inadmissible if this is a mission to Mars. So the code can be improved…

var buildDecoyPaysant = function (peasant, goalPoint){
    var goal = Vector.subtract( peasant.pos, goalPoint);
    goal = Vector.normalize(goal);
    var buildatPos = Vector.subtract(peasant.pos, goal);
    hero.command(peasant, "buildXY", "decoy", buildatPos.x, buildatPos.y);
};
// I replaced:
                 hero.command(peasant, "buildXY", "decoy", peasant.pos.x - 2, peasant.pos.y);
// with
                 buildDecoyPaysant (peasant, enemy.pos) 
1 Like