Determination (grim and otherwise) - js

hello everyone,
I’m stuck in the grim determination level. I wrote a really elaborate code with a lot of functions, so I cut out what I think that has the problem. the rest of the code works fine, it’s just that the peasant don’t collect enough coins. they keep trying to go for the same coin. I tried to change that but it still doesn’t work. what is the problem?

here’s my code (regarding this):

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 distance = friend.distanceTo(item);
        if ((item.value/hero.distanceTo(item)) > bestItemValue) {
            excludedItems.push(item);
            bestItem = item;
            bestItemValue = bestItem.value;
        }
    }
    return bestItem;
}
function commandPeasants(){
    var peasants = hero.findByType("peasant");
    for (var peasantIndex = 0; peasantIndex<peasants.length;peasantIndex++){
        var peasant = peasants[peasantIndex];
        var claimedItems = [];
        var coin = findBestItem(peasant,claimedItems);
        if (coin) {
        hero.command(peasant, "move", coin.pos);
    }
    } 
}

Hi, @foxfire!Could you please send me a link to this level?

hello @Anonym! sorry for the long waiting time. here’s the link!

1 Like

no problem, I’ll take a look now!

can you please send me your full code, @foxfire .Cuz’ I don’t have enough info

I disagree, all the information necessary to debug the reported problem (collecting coins) is present. Thanks for identifying where the problem is and not dumping your entire code base!


You have several bugs in your code, which I’ll enumerate here:

The first bug that stands out to me is that peasants are going for a far-off coin instead of picking the nearest value over distance one. This suggests a bug in your findBestItem not related to your logic attempting to prevent peasants from chasing the same coin.

  1. You’re confusing hero with friend in your findBestItem function. Remember, this code is supposed to return the best item for that individual friend, which means it should probably not care about the hero, other friends (with the exception of excludedFriends, etc). You’re mistakenly using the distance from the hero in your value over distance calculation instead of distance from the friend.

  2. Your code is comparing incompatible values when trying to find the best coin. You define bestItemValue not as the value of the coin but as the value over distance of the coin: if ((item.value/hero.distanceTo(item)) > bestItemValue) { ... } but, instead of carrying on with this definition, you set bestItemValue = bestItem.value. You want to use value over distance both times. Make sure it’s the distance to the peasant!

And finally, your excludedItems code is incorrect. Given your implementation, I’m not convinced you’re clear on how the concept of excludedItems relates to your code, so I’ll reiterate:

If we made no attempt to prevent peasants from stacking on top of each other, they may waste a lot of time chasing the exact same coin, when it would be more efficient for the peasants to split up and chase separate coins. One simple way to solve this is to build a list of already assigned items and have other peasants ignore them. Each peasant picks what they think is the best coin that hasn’t already been picked.

The pseudo-code for such an algorithm is as so:

claimedItems = []
for each peasant:
    # choose the best item for `peasant` that is not in `claimedItems`
    item = findBestItem(peasant, claimedItems)

    if item:
        move peasant to item pos
        claimedItems.push(item) # Claim this coin so no other peasants chase it

Note that no part of my findBestItem function modifies claimedItems, it only reads from it. The responsibility of managing claimedItems is left entirely to the command-loop. This is just to reduce confusion for the reader: after all, why would a function named find change anything?

Your current code makes these mistakes:

  1. It does not persist claimedItems between peasants
  2. It adds more items to claimedItems than it should; you only want to add the chosen coin

In programming, simpler is usually better. You might not need a super-advanced peasant collecting algorithm to pass the level! Or, if you do, another method of implementing more efficient coin collection would be to command one peasant to only collect from the top half of the coin field and the other from the bottom half.

Hopefully this is helpful! Good luck!

3 Likes