Help on improving code : Looting coins

So, I’ve taken the code into my own Zero Sum to experiment with it. Not surprisingly, only checking coins when coins are added or removed helps a lot and I haven’t reached the HEL once. Of course, the AI dies after 1 min, but considering you were having problems at 30sec, this is a good indicator.

Regarding your second condition:

Looking at your code and conditions, this appears to be the most important consideration, but doesn’t actually save your code any work. As it stands, the code runs through all coins twice. If you were to check for your second condition in the first loop, you can save yourself a lot of processing.

Here’s what I have tweaked to:

**Tweak: Main Loop (throttling by length)**
loop {
    coins = this.findByType("coin");
    if (nCoins != coins.length) {
        nCoins = coins.length;
        nextCoin = findNextCoin(this);
    }
    this.move(nextCoin.pos);
}

In discriminating algorithms, it is generally best to eliminate early whenever possible. With this code, virtually 1/2 of the field is eliminated before we even start moving. As position updates, the number of options for comparison increase and decrease naturally. In tense situations (opposing pender controlling more field), this makes things much faster. In relaxed situations, there is better chance to pick the best value.

**Tweak: findNext - 1st Loop (move condition 2)**
    myCloser = [];
    nCoins = coins.length;
    for (var i = 0; i < nCoins; i++){
        coin = coins[i];
    
    // Get Barycentric Sums
        var currValue = coin.value;
        tempX += coin.pos.x * currValue;
        tempY += coin.pos.y * currValue;
        totalValue += currValue;
        
    // First Elimination (Second Condition)
    // Is it closer to me or her?
        if (self.distanceTo(coin) <= coin.distanceTo(pender)) {
            myCloser.push(coin);
        }
    }
**Tweak: findNext - 2nd Loop (use new array)**
    nCoins = myCloser.length;
    for (i = 0; i < nCoins; i++) {
         currCoin = myCloser[i];
         ...
         // Rest of Barycenter code
         ...
    }

I haven’t tweaked the rest of the code, but this seems to help a lot without worrying about micro-optimizations (which should be discouraged until absolutely needed).

Udpate: After running the original vs these changes

This actually grabs coins faster for the same level seed. Your code was winning against AI @ 1:05 with 502 gold. These changes win against AI @ 1:05 with 558 gold.

Update 2: With the next change

I got to thinking that perhaps the barycenter should also change according to the second condition. In other words, the vector will change according to the most value that your hero can access. After running tests, win is at 1:08 with 615 gold.

First Loop: Adjusted Barycenter
    for (var i = 0; i < nCoins; i++){
        coin = coins[i];
        
    // First Elimination
        if (self.distanceTo(coin) <= coin.distanceTo(pender)) {
        // Add to new array
            myCloser.push(coin);
        // Get Barycentric Sums
            var currValue = coin.value;
            tempX += coin.pos.x * currValue;
            tempY += coin.pos.y * currValue;
            totalValue += currValue;
        }
    }

Final Update: Serious Flaw

While the code works, the algorithm as you coded it has a serious flaw and fails to accomplish what you wished it to. This is dues to your last condition:

Second Loop:

    for (i = 0; i < nCoins; i++) {
        ...
        if (currCoinDistWeighted < leastCoinDistWeighted) {
            if (pender && currCoin.distanceTo(pender) > currCoinDist) {
                ...
                if (leastCoinDistWeighted < 15) {
                    ...
                } 
                else {
                    nextCoin = currCoin;
                }
            }
        }
    }

When this executes, anytime any coin doesn’t meet the weighted distance, it overwrites any previously found optimal coin. So, this means that if the last coin is not optimal, it becomes the chosen coin. It additionally means that each optimal coin is often compared against coins that are already not optimal (rather than compared against other potentially optimal coins). I fixed this with the following:

**Code: Fixed Loop**
    for (i = 0; i < nCoins; i++) {
        ...
        if (currCoinDistWeighted < leastCoinDistWeighted) {
            if (pender && currCoin.distanceTo(pender) > currCoinDist) {
                ...
                if (leastCoinDistWeighted < 15) {
                    ...
                } 
            // If we already have an optimal coin, don't overwrite it
                else if (!nextCoin) {  
                    nextCoin = currCoin;
                }
            }
        }
    }