Pathfind Random Path & Closest Object

Is there a somewhat “easy” way to make an object pathfind and choose any route instead of the shortest route? Have patience with me if you are going to talk hard core python. :yes:

Also, how would I get the closest object with a property out of a the scene objects list. I have Monster’s S2A and Agoose’s pathfind to closest enemy, but I want to learn how to do it with some explanation.

Monster’s seems fairly simple. . .
The getValueOfPositive isn’t included, I didn’t paste on here.

hitObjectList = getValueOfPositive(cont, "hitObjectList")    
     if hitObjectList == None:
        return    


    closestObject = hitObjectList[0]
    closestDistance = closestObject.getDistanceTo(cont.owner)
    for hitObject in hitObjectList:
        distance = hitObject.getDistanceTo(cont.owner)
        if distance < closestDistance:
            closestObject = hitObject
            closestDistance = distance

Thanks

What do you mean by “choose any route”? Do you mean for it to display a number of possible routes and let the player pick one, or just for it to pick a route at random (or something else entirely)?

I agree with Captain oblivion “choose and route” is very vague. Usually it means pick a random route. If you really mean “all” routes, you can let the character just randomly walk around it will always be a route = condition met.

You should define what set of routes to choose from. Common selections are: shortest, fastest, longest, with least sharp angles, with longer straights … . These are heuristics that prefer a specific kind of route.
Maybe you mean: select any route from the three (shortest) routes (like car navigators usually do)

The S2A could benefit from cleaning the code. Just now it is a bit dirty. I’m currently working on a new version with cleaner code.

Currently it does not support the steering actuator as the steering target game object is in attribute “target” and not in attribute “object” as in the other actuators. So the S2A needs to be extended to allow setting this attribute.

Right, you want a work-through of how to make a select closest?

Well, you have to get two things: the player object (or AI object) and a list of the things you want to track to. Generally this is:

own = cont.owner
enemy_list = [o for o in bge.logic.getCurrentScene().objects if 'Enemy' in o]

If you want an explanation of how that last line works, just ask.

Now you have them you have to find the closest one. I do this by creating a ‘dummy’ variable, called ‘minimum’ and another for the soon-to-be-selected target:

minimum = 10000
target = None

The reason it has a high value is because when you compare distances to it later, it has to be bigger than them.

Now you can create a loop that will find the distance to each potential target:


for enemy in enemy_list: #For each possible enemy
    dist = own.getDistanceTo(enemy) #Get the distance to it
    if dist < minimum: #If the distance is shorter than the previous minimum
        minimum = dist  #Adjust the minimum
        target = enemy #And set the target to the new enemy

Now you have a variable ‘Enemy’ that contains None if there are no close enough targets, or the game object reference to the closest enemy.

This is very easy to expand, by adding other elements into the loop and adding them together to create a ‘value’ for each enemy.
ie: distance + size + enemy_armour will target small, weak, close enemies.

Hope that helped.

Maybe it is more clear in this form?


    hitObjects = getHitObjectsFromSensors() 
   
    if not hitObjects:
        return    

    closestObject = getFirstObject(hitObjects)

    for hitObject in hitObjectList:
        closestObject = getObjectCloserToOwner(hitObject, closestObject):
 
    return closestObject 

(skipped the lower level functions)