Is there a better way to make peasants target different coins?


#1

In some levels it is helpful to command multiple peasants to pick up coins. The generic ‘go to nearest coin’ doesn’t work very well when multiple peasants try to go to the same coin.
There was one level that shows a way to make them target different coins: Make an array that contains all the coins that were ever targeted and check this array every time when considering a coin (in order to not go after a coin that was already targeted).
This method doesn’t seem very efficient and I was wondering if there is a better approach.


#2

Actually, I believe the level uses an array of the coins currently on screen so as to not send two+ peasants toward the same coin. Which is already more efficient than the way you worded it. :wink:

Current - find closest coin not claimed.
Improvement - of course change “nearest” to “nearest-bestest” (consider distance and value).
Possible improvement - make sure “first” peasant to “see” coin is actually the closest???

Are there other ways, sure. What are some of the things you have thought of (good or bad), and then we can discuss and (maybe) add to your list…


#3

In this case I’m not looking for a method to find the best coin to get. I just want to make sure the same coin isn’t sought after by more than one peasant.

One possibility I considered is after finding a potential coin, checking each peasant to see if another one is already targeting it. There tends to be less peasants than coins so this should be better. I haven’t implemented a way to do this yet.
It might be possible to make an array containing coins/coordinates where each value corresponds to a different peasant. This might have to rely on findFriends() ordering the peasants in the same order each time though. Or perhaps I could just store them in a specific order in a more permanent array.
An alternative could be to check if another peasant is closer to the coin and moving towards it, but that is more complicated.

Edit: The first possibility sounds like it could work. I’ll try implementing it tomorrow.


#4

There is a simple solution for this: make your peasants work in “zones”. I tried multiple approaches:

a) Simpler version: set a limit for your peasants and if the coin is behind this limit, skip it. Sample python code:

nextCoin = peasant.findNearestItem()
# if coin is above the middle of the field
if nextCoin.pos.y > middle:
    # ...pick up the coin
    self.command(peasant, "move", nextCoin.pos)
# ...otherwise move away from the middle
else:
    self.command(peasant, "move", {"x": peasant.pos.x, "y": peasant.pos.y+2})

b) More elegant version: create separate coinlists for the zones and pick your next coin from the appropriate list:

coins = self.findItems()
coins1 = [] # upper zone
coins2 = [] # lower zone

for coin in coins:
    if coin.pos.y > middle:
        coins1.append(coin)
    else:
        coins2.append(coin)

nextCoin = peasant.findNearest(coins1) # or (coins2)

Of course, you can make these much more elaborate, these are just basic ideas.

Finding the optimal next coin can also be improved: you can make a weighted list of coins (e.g. based on value and distance) or calculate the “center” of the coins and head towards that, etc. You can find such topics here on the forum:
http://discourse.codecombat.com/t/help-on-improving-code-looting-coins/3359
http://discourse.codecombat.com/t/vectors-facingtowards-and-looting-coins/3330