Halps wit AI plz!!

So thanks to Social, I now have a great track-to-next-nearest Script. This script got me thinking about how it can be used for a simple AI where empties are used do define specific paths. For example, if an enemy is attacked it will track to the nearest empty with a property named “cover”, so he will try to hide from the shots. Another idea is for an enemy sniper who loves to camp (“it’s a legitimate strategy!”), you could program him so that if he is shot, he will track to the nearest empty with a property named “sniper_path”. Once near enough to that empty, he will track to the next nearest empty with a property named “sniper_path”. He will continue to do this until he reaches an empty named “snipe_spot”, where he will set up his tent, cook a pot of beans, and pick off your allies as if they were highway flies on a transport truck. This is where the problem comes in, He won’t fallow a path. He tracks to the first and the second ok, but after that he just sort of randomly decides where to go. Here’s an example. Hopefully you will have more luck!


Dumb_AI.blend (171 KB)

Hey Matt,

Maybe you should go for an all out node system. Something like this.

You could make them follow an organized path. That one works randomly.
Generate the list with a property listgenerated (bool false)
if own.listgenerated==0:
…for obj in obl:
…if hasattr(obj, “nodethingy”):
That should do it…

that’s basically what is going on, isin’t it? Anyway i got a bit working, the last node is being a jerk though. sub in this code where it says the (length - 1) stuff, and it seems to only work in apricot at the moment…

Check list length, and establish looping (or limits…whatever you want, but don’t go “out of bounds”):

length = len(relevant_pairs)
if own.sel == 3:
own.sel = 0

and jplur, I’ve tried out many different ways and they all seem to be more complex than they need to be. If my script works, path finding will be a lot easier to understand and edit, hopefully…

It works in 2.46 now, just change own.sel = 0 in the previous code to this:
own.sel = 1
still has some issues though, and it won’t work in apricot for some reason…

Thank you jplur for the link! IT got me thinking and i have a totally different system! Basically the nodes tell the bot where to go. if the bot rays a node, he will get a property on the node which tells him which node to track to next. It works great ( I even have a random actuator in intersections to randomly decide which direction to take). The main issue right now is that if the bot goes backwards, he will turn around. I’m trying to find a way to figure out which way he’s going…

Do you mean if it touches the last node to go back?
If not what do you mean?

I got it working, i’ll pload a blend when im done switching it over. Example: he is walking the wrong way down a long hallway, he hits a node, instead of turning left down the new hall, he’d turn all the way around and head back, dumb ai’s are dumb! but i fixed it!

Hey I’m glad your digging a little deeper with this. I’m going to try to implement node tree pathing for my project in a few weeks or so. Most references to pathing i see on the internet talk about A*, which I think is the same basic search algorithm but all nodes are in a grid, so they don’t actually have to store who their neighbors are.

Actually I have been having some good ideas for using blender as a level editor, then ‘baking’ the nodes into a python dict. Basically I would duplicate a node object around the map, then parent all the possible connections between nodes. Then run a little script to store a list of all nodes, their location, and their neighbors (by checking parent relations).

Then I could remove the actual nodes and have entities navigate the level by checking the list.

whew sorry got a little carried away with my train of thought :rolleyes:

mine won’t even need to search for nodes! I got thinking about paths and thought why does the character ned to define the path, when the path could define the path! when i get home, ill fix the intersections ad upload a file for you to see. So far it works miuh like the same movement systen in Unreal championship. Specific paths will also be easy to implement.

@ jplur: Actually, A* doesn’t need a grid to work, you can do it with any system of nodes. The difference between A* and what I think is going on here is that A* is a pathfinding algorithm; it’s used to calculate the node path which gives the shortest (and/or fastest, least dangerous etc) route to a goal. This on the other hand seems to be a system where the paths are pre-defined and the trick is in getting the actors to follow them, which is a different problem.

If anybody’s interested in doing AI that’s a bit more hardcore I recommend a book called ‘AI game programming wisdom’. It’s essentially a collection of articles by various professionals on not only how these AIs work in theory but also on the little tricks you can use to get them to work in practice.

I ordered the first Game Programming Gems book a couple days ago. I think it has a few articles on pathfinding in 3D spaces. I used A* for a project years ago, but had found the code and didn’t understand how it actually worked. I think it will be good to write something similar from scratch, just the searching without heuristics (AFAIK heuristics in these algorithms are basic assumptions – the shortest path to the goal is in a straight line, concave spaces are less likely to lead to the goal)

anyway I’ll be sure to post what I come up with

Ok so here’s a quick example of random pathing, much like unreal. I’m still working on intersections but the band-aid I have works for now . basically rats in a maze. it works in 2.46, but I would suggest using an apricot build, as some of the weird tracking glitches have been worked out. Ill be working on this for a while, so keep an eye out for updates


new_Dumb_AI.blend (309 KB)

@ Matt: It’s working pretty good, though eventually all the guys get stuck. I think that is because of the general crappiness of the Track brick, maybe try a function like:

def track(object, target, speed):
    from math import cos, sin
    # Target is a point[x,y]
    ownO = object.getOrientation()
    pos = object.getPosition()

    oriX = [ ownO[0][0], ownO[1][0], ownO[2][0] ]
    oriY = [ ownO[0][1], ownO[1][1], ownO[2][1] ]
    tvect = normalize([ target[0] - pos[0], target[1] - pos[1], target[2]-pos[2] ])
    oriY = [-oriY[1], oriY[0], oriY[2] ]  #get perpendicular 
    dot = dotprod(oriY, tvect)
    oriY = [oriY[1], -oriY[0], oriY[2] ]  #get perpendicular 
    cross = dotprod(oriY, tvect)
    ar = ( (cross-1)-.1 )*speed
    if dot > 0.004:
        ar = -ar
    elif dot < -.004:
        ar = ar
    elif cross < 0:
        ar = ar
        ar = 0

    rot_matrix = [[cos(ar), -sin(ar), 0],[sin(ar), cos(ar), 0],[0, 0, 1]]

    object.setOrientation( matMult(object.getOrientation(), rot_matrix))

It seems that has already been implemented in Apricot. I see the issues you are talking about in 2.46 (those guys remind me of the benny hill a bit), In apricot I accidentally left it running for a half an hour and they were still going fine. Finally! Trackers are ambi-turners!

haha awesome!

Interesting stuff Matt.

Ill have to dissect your scripts later to see how exactly youve done it. :eyebrowlift2:

Ive tryed it in 2.46 and an older apricot build, and they all manage to get stuck. Im guessing that the latest tracking fixes have been done before the 15606 build im using?
Ill have to download a 2.47RC sometime and give it a go on that.

Awesome work though.

I’m on 15939, so I guess they fixed it between them.