Use of findNearest with created objects - Python


#1

I was trying a different solution to one of the problems and I did something wrong. I have access to self.findNearest() and can use it for things like peasantA.findNearest([Array of vectors]). What I’d like to do/am trying to do is to do things a little backwards:

Hypothetical python code:

XVector  = Vector(40, 40)
XVector.findNearest(peasant.findItems()) 

or (in a while loop):

P = Peasants[whileIndex]
if P:
     coin = AssignedPoints[whileIndex].findNearest(P.findItems())

where AssignedPoints is an array of vectors and P is a nearby peasant who is supposed to be collecting near his/her associated AssignedPoints. Currently, I get an error on the last line above, so I’m guessing I’m not using the right or variable type to start the findNearest.

I think I know how to iterate through P.findItems() and test which coin is the best (based on distance), but I’d prefer more elegant code. That being said, the brute force method below has certain advantages to it.

Where AP is the appropriate assigned point/position, P is the associated peasant, find the minimum value as follows:

# ok - this is pushing it, but I love how elegantly this populates any gold+ coins in 25 feet (?) or so.
coins = [coin for coin in P.FindItems() if ((coin.value > 2) and P.distanceTo(coin) < 25]
# if the above test came up empty, let's use a slightly modified test to populate coins
if not(len(coins)>0): 
    coins = [coin for coin in self.FindItems() if (P.distanceTo(coin) < 50)]
# ok - I give up.  Any coins in line of sight to my peasant will do.
if not(len(coins)>0): 
    coins = P.findItems()
if len(coins)>0 :     #Making sure there are coins out there as one last safety check.
    currentcoin = P.findNearest(coins) 
    evalValue = ((currentcoin.pos.x - AP.x)^2 + (currentcoin.pos.y - AP.y)^2)^0.5 + ((currentcoin.pos.x - P.pos.x)^2 + (currentcoin.pos.y - P.pos.y)^2)^0.5    #distance to P + distance to AP
    for c in coins:
        checkValue =  ((c.pos.x - AP.x)^2 +(c.pos.y-AP.y)^2 )^0.5 + ((c.pos.x - P.pos.x)^2 + (c.pos.y - P.pos.y)^2)^0.5  
        if checkValue < evalValue:
            currentcoin = c
            evalValue = checkValue
    # sigh - I actually miss putting in Next c here.  And I keep typing "for each c" automatically.
    self.command(P, "move", currentcoin.pos)
else:
    self.command(P, "move", AP)     #if there are no coins, start P moving back towards AP.

Thoughts/suggestions? All appreciated … :wink:
Edit: Ugh, went HEL towards end and had terminal confusion before that. Need to store more, not use fancier for…in, etc.


#2

First, I don’t see the reason for creating a set of coins within 25m, but if none then within 50m, etc. Why bother with all that?

Second, I didn’t try to figure out if the coordinate calculations are correct, but why not use vectors? The distance between two points (=positions, vectors) can be simply calculated with Vector.distance(A, B) where A and B can be e.g. something.pos or Vector(x, y)

OR

use the distance() method as explained here

Third, if you want to find the closest peasant (or whatever) to a specific coin, you could use the coin’s methods coin.distanceTo() and coin.findNearest()

Happy coding!


#3

After I posted above, I too had found the distance() method. I’ve never been able to get it to work with a Vector as the initial object, however. That being said, I just got this code to give the expected result on a test level:
V1 = Vector(40,50)
V2 = Vector(50, 50)
d = V1.distance(v2)
self.say(d)
[my character says “10”]

so I must have done something wrong previously each time I’ve tried to use distance().

With respect to the alternative code above, it didn’t work as well as I would like per the note above - so feel free to disregard it. Turns out that brute force method was too computationally painful.