Enemy AI: chasing a player without Navigation2D or A* pathfinding
abitawake.com
abitawake.com
1. You only need to do the path generation once, and it scales very well with the number of monsters. 2. It's really good at combining several concerns, because you can generate a couple of heat maps for different concerns and add them up. For example one heat map is about proximity to player. Another could be about proximity to health pickups, or proximity to cover, or proximity to open space if a monster likes to keep distance and shoot. If a gas trap is triggered, you can use a "danger" heat map. Then a monster can easily get closer to player and at the same time choose the path which has fewer harmful effects.
That's why centaur archers in Brogue are so annoying, monsters avoid traps intelligently, monster groups avoid wasting their numerical advantage by chasing player through a corridor.
He described it in detail in this article: http://www.roguebasin.com/index.php?title=The_Incredible_Pow...
And in case you're wondering, Brogue source code is licensed on AGPLv3.
The algorithm is summarized in the article as: "When an enemy enters the Chase state it tries to raycast to the player and if nothing is in the way - chase em! If something is in the way, it goes through the scent trail in order and tries to raycast to each scent until it can see one, then - chase it!"
With complex geometry, this will frequently lead to a non-optimal route, and is probably more fun to play against.
This gives you a value (distance to player) for every square on the board; you can do a lot of things with that data, like choose between multiple "best steps" based on some other preference, or choose "best steps" for a large number of monsters efficiently.
If the player's route is not straight, some squares with "fresher scent" may be physically more distant from the player than squares with less fresh scent.
https://news.ycombinator.com/item?id=22849522
https://donhopkins.com/home/archive/emacs/mw/display.c
https://donhopkins.com/home/documents/EmacsRedisplayAlgorith...
7. Acknowledgements
The people who did the real work behind this paper are Mike Kazar, Charles Liescrson and Craig Everhart; all from CMU.
Bibliography
1. Kevin Q. Brown. Dynamic Programming in Computer Science. CMU, February, 1979.
There's no point filling an entire level if monsters only react when the player gets within say 30 tiles. Even line of sight should have limits.
You could add something like an A* heuristic on top where monsters are drawn to the general direction of the player based on a vector, but switch to shortest-path when they're close. (but then you worry about getting stuck I guess)
Consider a semi-open map with 30 tiles sides, we're talking a thousand tiles in total and/or paths a hundred tiles long. For the effect to propagate to the 30th tile away, the propagation algorithm has to iterate more than 30 times.
Graph algorithms are generally slow (whole milliseconds on large graphs) but repeated many times over they can get truly horrendous.
SimCity has several layers like pollution, land value, etc, which slowly diffuse over time. But it only does that computation every so often, not every frame. It has a 16 phase simulation clock, and it scans the cells of the map in eight stripes over eight steps, then scans different layers like taxes, traffic and rate of growth decay, power, pollution and land value, police coverage and crime, population density, fire coverage and disasters, and the RCI valves. (That made it possible to run on a C64!)
Chaim Gingold's SimCity Reverse Diagrams show how the different phases of "Simulate()" perform different kinds of analysis over time, and how the different map layers interact with each other.
https://lively-web.org/users/Dan/uploads/SimCityReverseDiagr...
>SimCity reverse diagrams, by Chaim Gingold (2016).
>These reverse diagrams map and translate the rules of a complex simulation program into a form that is more easily digested, embedded, disseminated, and and discussed (Latour 1986).
>If we merge the reverse diagram with an interactive approach—e.g. Bret Victor’s Nile Visualization (Victor 2013), such diagrams could be used generatively, to describe programs, and interactively, to allow rich introspection and manipulation of software.
>Latour, Bruno (1986). “Visualization and cognition”. In: Knowledge and Society 6 (1986), pp. 1– 40.
>Librande, Stone (2010). “One-Page Designs”. Game Developers Conference. 2010.
>Victor, Bret (2013). “Media for Thinking the Unthinkable”. MIT Media Lab, Apr. 4, 2013.
I think this is also how 3D printers work (effectively). They do a form of scan-line filling to minimise the number of jumps between sections of filament.
At first I thought I would apply a pathfinding algorithm like A* to route each stream but given that it was an arbitrary graph and not a 2D map there was no obvious heuristic to guide the algorithm, so it devolved into an exhaustive search.
But then I realized that I had relatively few nodes (a dozen at most) and many more streams to route, so it made more sense to compute the distance between every pair of nodes once (n^2 with the number of nodes using a trivial implementation, less if you optimize it but I didn't even need to) and then I could lookup the path between any two nodes in linear time. Given that this was all running on an underpowered embedded system it made a significant difference in performance when routing hundreds of streams.
https://en.wikipedia.org/wiki/Gosling_Emacs
>Gosling Emacs was especially noteworthy because of the effective redisplay code, which used a dynamic programming technique to solve the classical string-to-string correction problem. The algorithm was quite sophisticated; that section of the source was headed by a skull-and-crossbones in ASCII art, warning any would-be improver that even if they thought they understood how the display code worked, they probably did not.
https://donhopkins.com/home/archive/emacs/skull-and-crossbon...
Trivia: That "Skull and Crossbones" ASCII art is originally from Brian Reid's Scribe program, and is not copyrighted.
https://donhopkins.com/home/archive/emacs/mw/display.c
/* 1 2 3 4 .... Each Mij represents the minumum cost of
+---+---+---+---+----- rearranging the first i lines to map onto
1 | | | | | the first j lines (the j direction
+---+---+---+---+----- represents the desired contents of a line,
2 | | \| ^ | | i the current contents). The algorithm
+---+---\-|-+---+----- used is a dynamic programming one, where
3 | | <-+Mij| | M[i,j] = min( M[i-1,j],
+---+---+---+---+----- M[i,j-1]+redraw cost for j,2
4 | | | | | M[i-1,j-1]+the cost of
+---+---+---+---+----- converting line i to line j);
. | | | | | Line i can be converted to line j by either
. just drawing j, or if they match, by moving
. line i to line j (with insert/delete line)
*/
https://donhopkins.com/home/documents/EmacsRedisplayAlgorith...https://dl.acm.org/doi/10.1145/1159890.806463
A redisplay algorithm, by James Gosling.
Abstract
This paper presents an algorithm for updating the image displayed on a conventional video terminal. It assumes that the terminal is capable of doing the usual insert/delete line and insert/delete character operations. It takes as input a description of the image currently on the screen and a description of the new image desired and produces a series of operations to do the desired transformation in a near-optimal manner. The algorithm is interesting because it applies results from the theoretical string-to-string correction problem (a generalization of the problem of finding a longest common subsequence), to a problem that is usually approached with crude ad-hoc techniques.
[...]
6. Conclusion
The redisplay algorithm described in this paper is used in an Emacs-like editor for Unix and a structure editor. It's performance has been quite good: to redraw everything on the screen (when everything has changed) takes about 0.12 seconds CPU time on a VAX 11/780 running Unix. Using the standard file typing program, about 0.025 seconds of CPU time are needed to type one screenful of text. Emacs averages about 0.004 CPU seconds per keystroke (with one call on the redisplay per keystroke).
Although in the interests of efficency we have stripped down algorithm 5 to algorithm 6 the result is still an algorithm which has a firm theoretical basis and which is superior to the usual ad-hoc approach.
Also, it seems like this might also be useful for computing minimal diffs, eh?
It's based on the "string-to-string correction problem" (edit distance / Levenshtein distance), combined with "dynamic programming" (finding the best cost path through a cost matrix), which is (kind of) how diff works, on a line-by-line basis for inserted and deleted lines, and then on a character-by-character basis between changed lines. Each "edit" has a "cost" determined by the number of characters you have to send to the terminal (length of the escape codes to perform an edit in multiple possible ways, versus just redrawing the characters). Emacs computes its way through a twisty maze of little escape codes each time it updates the screen.
H. M. Wagner and M. J. Fischer. "The string-to-string correction problem." JACM 21, 1 (January 1974), 168-173
Citation: https://dl.acm.org/doi/10.1145/321796.321811
PDF: https://dl.acm.org/doi/pdf/10.1145/321796.321811?download=tr...
https://en.wikipedia.org/wiki/String-to-string_correction_pr...
>In computer science, the string-to-string correction problem refers to determining the minimum number of edit operations necessary to change one string into another (i.e., computing the shortest edit distance). A single edit operation may be changing a single symbol of the string into another, deleting, or inserting a symbol. The length of the edit sequence provides a measure of the distance between the two strings.
https://en.wikipedia.org/wiki/Diff
>In computing, the diff utility is a data comparison tool that calculates and displays the differences between two files. Unlike edit distance notions used for other purposes, diff is line-oriented rather than character-oriented, but it is like Levenshtein distance in that it tries to determine the smallest set of deletions and insertions to create one file from the other. The diff command displays the changes made in a standard format, such that both humans and machines can understand the changes and apply them: given one file and the changes, the other file can be created.
https://en.wikipedia.org/wiki/Levenshtein_distance
>In information theory, linguistics and computer science, the Levenshtein distance is a string metric for measuring the difference between two sequences. Informally, the Levenshtein distance between two words is the minimum number of single-character edits (insertions, deletions or substitutions) required to change one word into the other. It is named after the Soviet mathematician Vladimir Levenshtein, who considered this distance in 1965.
https://en.wikipedia.org/wiki/Edit_distance
>In computational linguistics and computer science, edit distance is a way of quantifying how dissimilar two strings (e.g., words) are to one another by counting the minimum number of operations required to transform one string into the other. Edit distances find applications in natural language processing, where automatic spelling correction can determine candidate corrections for a misspelled word by selecting words from a dictionary that have a low distance to the word in question. In bioinformatics, it can be used to quantify the similarity of DNA sequences, which can be viewed as strings of the letters A, C, G and T.
Here's a Levenshtein demo that shows you the cost matrix with the shortest path highlighted. Try calculating the distance between "fotomat" and "tomato", and you can see the shortest path which has a cost of 3 edits (1: delete f at beginning, 2: delete o at beginning, 3: insert o at end):
http://www.let.rug.nl/kleiweg/lev/
>Levenshtein distance is obtained by finding the cheapest way to transform one string into another. Transformations are the one-step operations of (single-phone) insertion, deletion and substitution. In the simplest versions substitutions cost two units except when the source and target are identical, in which case the cost is zero. Insertions and deletions costs half that of substitutions. This demonstration illustrates a simple algorithm which basically looks at all of the different ways for operations to transform one string to another.
Another unrelated thing I found very useful is Floyd Warshall. It's a graph algorithm to compute efficiently ALL shortest paths between any 2 nodes. Real time pathfinding was too slow to use, had to precompute wherever possible, turns out most of the world is fixed and can be precomputed.
https://gameschoolgems.blogspot.com/2009/12/influence-maps-i...
https://gameschoolgems.blogspot.com/2010/03/influence-maps-i...
https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorit...
http://zhar.net/projects/gameai/influence_map.html
My contribution was to use heat transfer calculations to model the battlefield as a conductive plate with units as heat constraints.
Fun times. I always wondered if that thread inspired any real world games.
In SimAirport we use flow fields, they're great for crowds & they scale incredibly well with agent count. We use them for "long distance" traversals, and then we use "local" A-star like grid search for the "last-mile" of an agent's journey.
For flow-fields, we start by dividing everything up into "sectors" based on game logic -- and then further, into "sub-sectors", essentially just basic abstractions of the graph with smaller node counts. It does have an impact on path quality but for the scale we operate at in SimAirport the trade-off is a no brainer. The abstractions then limit the flow-field's graph size & the destination-count that any given subsector (abstracted-node) can have -- essentially it's a hierarchical (pseudo HPA-star) approach to flowfield pathfinding / navigation, and the abstraction also has major benefits for reachability queries & game-logic driven "rules" (ie load-balancing of capacity-constrained paths [stairs/escalators], one-way paths [ie directed graph algos], etc).
> Basically it's about generating a heatmap for all the squares on the level.
> You can start with 0 at player position, and from that point use a simple floodfill algorithm, putting down increasing numbers with each step.
I’ve always called this Lee’s algorithm https://en.m.wikipedia.org/wiki/Lee_algorithm
It's too bad because games like F.E.A.R. have shown that even simple AI heuristics can lead to very interesting emergent behavior. TFA demonstrates that very simple AI tweaks can make the enemies feel more organic and realistic.
I suppose that some of the problem is that good IA doesn't make for nice trailers and ads (since you can just script those to do whatever you want anyway).
Problem with AI is even if you spend a lot of time trying to get it right, it can make choices that are confusing to us humans and illicit ridicule from the player base.
To me, that's a huge part of our game -- catering to the NPCs, specifically figuring out "why are they missing X? Oh, because they're walking Z distance to the nearest bathroom!". I think the AI is fantastic but, when functioning perfectly as [we would have] expected, we still get complaints about why the 'dumb AI' will do X or Y. Part of that is defintiely a UI/UX issue on our part -- but another part is that players generally aren't used to it and they expect much more "robotic" or obvious/easy behaviors from agents/NPCs.
Emergent & opportunistic behaviors are awesome (IMO at least), but a lesson we learned is that they may not always provide players with the desired or expected gameplay experience. It'll of course always be game-specific, but it's something we will keep in mind & likely simplify further in our next game.
This is really not so hard to implement, simple games could do this for ages.
Or at least basic tactics, I think in Far Cry 1 enemies did not run away, but were smart enough to sneak and circle around you, later in Crysis or the other Far Cry titles, they were just cannon fooder. Makes everthing more hollywood kaboom
A lot of making the experience of a game is in managing perception and belief - in making the player agree that the game is doing "what I expected" - and when a feeling of realism is aimed for, the amount of falsified behavior needed to get that result goes up dramatically. The games where belief is easy to achieve are mostly stuff where the ruleset is abstracted, empirically tested and legible to all - board games, physics games, puzzle games, etc. Things where the decision making itself is the intelligence. In contrast making soldiers that are satisfying opponents requires a blend of assets: carefully managing their positioning, animation states and voice callouts so that their decision making is something that players can identify, respond to and overcome.
I am not saying it is easy. But today, we got some more cpu power to throw at the problem. And even if you simplify a lot, you would still get better results, than plain cheating, which breaks immersion for me too, when they all storm my position, they could not know exactly.
"In contrast making soldiers that are satisfying opponents requires a blend of assets: carefully managing their positioning, animation states and voice callouts"
And here is the crux: there are tons of ressources thrown at the animation states and voice callouts, which is even more frustrating, when their behavior is as dumb as allways.
And not everything is expensive to simulate: in allmost every game with stealth elements for example: you can kill some enemies and the others are looking for you for some time - and then they go back to their default state with "ah, it must have been nothing", even though they might have been already wounded by you and witnessed comrades fallen.
Here you would not need more cpu power, but simply a third state: where they can still give up the search, but remain on guard. (And tend to their wounds, etc. )
If an enemy sneaks around the player, gets in cover and concealment, and shoots them while the player does not understand where the fire is coming from, is it an enjoyable experience?
Smarter and more realistic does not necessarily mean better. We don't write enemy AI for the purpose of it being effective in fighting, it's there to provide entertainment for the player.
It's also about creating the intended emotions. Games are intentionally designed to create a particular set of experiences. There's a niche of games that relies on gratification of overcoming some frustration (e.g. Dark Souls series) but the majority of gamer market prefers a 'power fantasy' emotional experience, so many games are intentionally targeting that. If we want the player to feel powerful, then we design so that their character can defeat many enemies; if we want the player to feel smart, then we design enemies so that their behavior has exploitable weaknesses that they player can discover and feel satisfied while 'outsmarting' or 'tricking' the opponents. In most game genres we don't want the player to feel outsmarted by the computer unless they have made a substantial mistake that the average player is able to notice and correct.
A good game mode does not require finding and hunting down all enemies. It has targets, like "go there"(story continues), "blow up X", "clear area Y"
"if an enemy sneaks around the player, gets in cover and concealment, and shoots them while the player does not understand where the fire is coming from, is it an enjoyable experience?"
If the game gets the graphics and gameplay right, for sure! (I still have memories from Vietcong, where you get ambushed in the jungle and don't see anything and just die, until you learn to move in cover and watch the terrain)
And you have the muzzle flash for example. And if you do not see it ... the fun is in getting scared and rushing to cover. Where the enemy cannot see you anymore (if the KI is not cheating) and then move to a different position to find him. Or you can have the kill cam, where you see upon death, where the enemy was, that killed you.
"If we want the player to feel powerful, then we design so that their character can defeat many enemies"
True, but there are various ways to implement this, without ZombieKI. Like in crysis for example, where you have superior tech. Or more hitpoints, because you play a badass. Or in general, you as a player have quicksave and load. The computer does not.
So yeah, I know that the target audience is dumb and wants fast food, so to say, but they also consume what is avaiable. And the standard is mostly ZombieKI, or ultra hardcore realism like in Arma, which is clearly not for everyone, but I really don't see, why the "AAA" games could not invest a tiny bit more in KI that does not break immersion.
Sure, but after a while, after seeing that in 100000 permutations, some people kinda move on from that and don't look back.
https://www.youtube.com/watch?v=h3rKmTFP9f4&t=8m50s
If it's just that essentially, but dressed up more nicely, I neither want to play it or make it. Personally I even got bored of collecting items for the sake of collecting them, or getting high scores for the sake of getting them, and exactly because every day 1000 games are made that follow all those patterns I feel perfectly free to ignore every one of them.
I still probably will never make a good game, but I learned a lot through trying, and I can feel good about what I tried, too. For me it's just something I do when I feel like coding, but have nothing "useful" to work on, after all.
As an example the alien game released a few years back had both interesting yet an AI that didn't feel like cheating. In this context an AI that does intersting things is accepted since the goal is to strike fear, whereas with a modern shooter most enemies are made to bring some challenge but eventually be killed.
https://www.youtube.com/watch?v=7YWbY7kWesI
>How This Blob Solves Mazes | WIRED
>Physarum polycephalum is a single-celled, brainless organism that can make “decisions,” and solve mazes. Anne Pringle, who is a mycologist at the University of Wisconsin-Madison, explains everything you need to know about what these slime molds are and how they fit into our ecosystem.
The first time I've seen this technique in use was in the classic SimAnt game by Maxis, in the 90s; in research it was also explored in the ALife community. It's a cool trick, but by itself it's not quite enough, it's good for insect behavior but not much more.
But what has been useful is combining standard pathfinding with this. For example, imagine if one of your units dies and drops some "scent of death" into the surrounding area - and that scent gets incorporated into A* as a large cost value for traversing this terrain. Now all your other units will "smartly" start avoiding the dangerous area for a while, without having to do any expensive analysis of why the unit died there, e.g. was there an ambush there or some such.
(Google for "potential fields" and "flow fields" in games for more examples from commercial games.)
If you are far enough away there is a big hole in this wherein they can’t get to your position before their maximum-amount-of-time-in-search-mode timer fires off and they go back to their normal location and behavior, though.
The PacBot only has a limited local view down the roads a few cells, and can't see around corners.
Even though they're extremely simple and stupid and short-sighted, they still have interesting emergent behavior when multiple PacBots are competing for the same traffic, like how PacBot will give up and turn around when its competitors eat the cars it was wok-a-wok-a-ing towards.
There is a good example of lots of competing PacBots around 0:55:
https://www.youtube.com/watch?v=8snnqQSI0GE
>Now you have some good, uuh, there's some traffic here. There's this thing called a PacBot. It's this PacMan that follows the road around looking for traffic. And then he eats it. So that's good for your city. And you can have a lot of different PacMans on the thing, and you know, just editing the road gives the PacMan somewhere to go. So their score is how many cars they've eaten. So it's an "agent", and it woks all around, and he follows roads. And you can put a lot of them on the map to keep the traffic low.
MicropolisRobot.scanRoads looks down the road in a given direction for a given distance, and counts the number of cars (in the traffic density layer), attenuated by distance (further away cars don't count as much).
https://github.com/SimHacker/micropolis/blob/b0c5a3f495ebabb...
Then the PacBot simulator calls scanRoads in all possible different directions to get a score, and moves in the direction of the best score.
https://github.com/SimHacker/micropolis/blob/b0c5a3f495ebabb...
As it turns out, the PacBot is actually the God of the Church of PacMania (each Polytheistic PacMania Church spawns up to four PacBot God Agents, if it's connected to a road), and the church zone itself generates a LOT of traffic, in the hopes of attracting the PacBots. The emergent behavior is that followers of the Church of PacMania happily drive back and forth between church, home, work, and shopping, again and again, in the hopes of sacrificing themselves to their God, PacBot. And the PacBot Gods hang out around the Church of PacMania, eating their followers, and raising their scores -- everybody's happy!
class MicropolisZone: def generateRobots(self):
https://github.com/SimHacker/micropolis/blob/b0c5a3f495ebabb...
class MicropolisZone_ChurchOfPacMania(MicropolisZone):
https://github.com/SimHacker/micropolis/blob/b0c5a3f495ebabb...
https://www.ri.cmu.edu/wp-content/uploads/2018/08/SMC2018.pd...
I was playing around with my lil asteroid sim[1] and I wanted to trace the trajectories of the asteroids, so I put a particle generator in the asteroid "base class" and set it to emit sixty particles with lifetime set sixty seconds, zero momentum and velocity, and unaffected by gravity. I bet you could adapt that to make a "scent trail", eh?
[1] https://git.sr.ht/~sforman/SpaceGame but it seems I deleted the experiment. The commit that has it is https://git.sr.ht/~sforman/SpaceGame/commit/7cc3981631db22be... FWIW.
If you ever move to large non-convex obstacles, like a maze -- there will be mounting problems until it would have made more sense to use a navigation or path-finding.
- split a map into convex polygons - use pathfinding to find out which polygins you have to traverse (either by making each polygon a node in the pathfinding graph or by selecting points on the polygon's edges and using those as nodes) - move in a straight line inside a polygon.
It seems, especially for "almost convex" maps, this could move a good deal of pathfinding computation into the build phase.
The latter is useful to open up extra gameplay.
Subset Games, the makers of FTL and 'Into the Breach' have talked about this extensively. 'Into the Breach' deliberately has the enemies telegraph their plans one turn ahead of time, and the game is all about interfering with those plans.
The rest of the game's design carefully reinforces the message that the enemy units are not intelligent. The backstory has them as basically oversized insects.
If you have a game that pretends to give you realistic human antagonists, but they behave mechanically dumb and predictable, that breaks immersion like you suggest.
One big problem is that having very smart AI that's purely there to oppose you in a zero sum game ain't fun to play against for most people. The handicaps a modern chess or Go engine would have to give you a normal human for a fair fight are ludicrous. And people seldom want fair fights in their games. They want a feeling of accomplishment, but without actually putting in all that much work.
Even hardcore games like XCom cheat in your favour behind the scenes.
There are at least two ways out of this while still avoiding the boring repetition:
- carefully make the NPC make believable human-like (or animal-like) mistakes, instead of easily exploitable repetitive mistakes - give the NPC goals that are in conflict with the player, but not 100% so.
A silly example of the second option:
Take a game like Thief that's all about sneaking around stealthily and stealing stuff. Now realistically, most of the guards are just hired goons. They don't want to die, but they don't particularly care about protecting the place. They do care about being seen doing their job, so they don't get fired.
So your job as a player could be, in addition to staying unseen, to provide plausible distractions and reasons for the guards not too investigate to closely.
Higher ranked guards, and owners, would be under higher pressure to perform and won't get away with excuses. So they would be more alert.
Using the same trick over and over again would lower it's effectivity: guards can't plausible claim to their higher ups to have been tricked again and again.
If you are starting to become aggressive to a guard, or he learns that you called one of his friends, the guard's priorities will change towards more self-preservation.
A pacifist run might even earn you respect and admiration from the lower level guards. Just like cat burglars are often admired in real life.
Seen a bit more abstract, the game now becomes one of three factions: the thief (that's you), the low level guards and their employers. All with partially overlapping, partially conflicting goals.
You can throw insurance companies into the mix, if you want to make it even more complicated.
Thanks to the non-zero sum nature of the partial conflict, you can crank up how smart everyone acts, without overwhelming the player:
Eg smarter guards might figure out a way to de-escalate that still looks like a plausible and even courageous move to their employers.
As an aside, unrelated to your reply, I just remembered another common excuse, which is that the enemies only exist for X seconds before the player shoots them, so effort on smarts would be wasted on them. For some games, I think its for sure the case, but I also feel that in many cases the enemy only exists for a few seconds because they are dumb and uninteresting.
Both 'dumb' and 'interesting' AI can be useful in a game, it all depends on your game's design.
To give another silly example: Tetris by default has very 'dumb' AI that just gives you pieces at random. You could imagine variants of Tetris with more interesting piece selection.
For example, an AI that makes pieces as unhelpful as possible while keeping their distribution statistically indistinguishable from true random selection.
Or there was an inversion of the 2048 game, where an AI plays the normal game, and your task is to give them unhelpful numbers.
Of course at this point you probably end up with something that's actually more CPU-intensive than a naive A* so it can't be used as an optimization. I think the cleverness of TFA is that it combines both a performance optimization and makes the enemies look smarter than omniscient bots doing A* perfectly every time.
This is how a scent dog tracks prey it cannot see.
I recommend the author hang out at the dog park and watch other kinds of working dogs, like retrievers and herd dogs. Very, very different behavior.
In fact I've heard that dogs can make a pretty nearly accurate guess about shortest path when dealing with terrain that has two different speeds. If, for instance, your dog is trying to get to you in the water and you are diagonal to his position, they will use two angles to triangulate on you, staying on the sand longer (but not until perpendicular with you) to minimize travel time.
One of my dogs definitely uses the Wayne Gretzky approach (go where the puck will be) but sometimes arrives before her target, resulting in collisions or acrobatics.
I wouldn't fault the authors too much, they just looked for an easy to remember name and the metaphor holds up well enough for that.
Really, if you wanna do path finding, a dog park will give you tons and tons of food for thought.
Some dogs are very clever. Others dumb as a post.
Insects and other animals are also good for inspiration. Even microbes!
There are some microbes that essentially follow this small program to find sugars:
- swim forward - wiggle around randomly - repeat
When the concentration of sugars is increasing, spend more time swimming forward. Otherwise, spend less time swimming between wiggles.
In a game, you would have the player leave a scent trail, and some of the other critters could behave like above.
You leave a trail for the enemy to follow, and they follow it.
It's not even path-finding, it's path-following. Which is pretty much an if-then statement.
It's a neat, simple approach, and fun to watch. But there isn't any learning, or knowledge, or other AI.
AI does not require ML.
"It's part of the history of the field of artificial intelligence that every time somebody figured out how to make a computer do something—play good checkers, solve simple but relatively informal problems—there was a chorus of critics to say, 'that's not thinking'."
A lot of modern work has focused on procedural animation versus behaviour but the two are quite intertwined: https://youtu.be/JZKaqQKcAnw
It's not claiming to be "academic AI".
Games have been using this terminology for decades.
People simply have no clue what AI actually means and think it is only about sci-fi robots and ML.
My stronger claim is that this falls so squarely within the bounds of "game AI" that it's fairly ludicrous to say it's not AI.
For years (but even now) Artificial Intelligence meant understanding how intelligent behaviors worked, and then understand what is the sequence of "if-then"s that could express those behaviors in an artificial setting. Use statistical inference is a "hack" (unavoidable, often) to cover the cases in which such behaviors seem to be too complex to be grasped - and then expressed - by one simple and/or comprehensive algorithm, but the (possibly unattainable) ideal would be having everything expressed as "pretty much an if-then statement" indeed.
This is flatly incorrect - the point of AI is to have a machine achieve intelligent behaviors without explicit programming.
If an "if-then" must be written by a programmer for every single behavior, then this is called "programming". It is not called "artificial intelligence".
Yes, there are many explicit if-else style programs in Russel & Norvig, & other books - but those are the 'training wheels', until better methods are developed. For actual AI, the training wheels are supposed to come off, and the agent learns and acts on its own.
You are talking about ML, not AI.
BASIC, for example, would be considered merely a training wheel in any book on programing languages but it is nonetheless a programing language.
>In computer science, artificial intelligence (AI), sometimes called machine intelligence, is intelligence demonstrated by machines, in contrast to the natural intelligence displayed by humans and animals. Leading AI textbooks define the field as the study of "intelligent agents": any device that perceives its environment and takes actions that maximize its chance of successfully achieving its goals.
Hence the 'or' in my statement. Neither are present here.
This does exactly that.
I would say that the more a program thinks on its own which actions to take to maximize its chances of success, the closer to AI it is.
If it's doing exactly what it's explicitly told, then it's not really intelligent, is it?
>Every program that has ever existed does this.
No, not every program is self-tuning, nor do they all take inputs.
You seem to acknowledge a distinction between ML and AI, but I'm not able to understand in your categorization, what would AI be?
We don't need mathematical optimization to call it "AI", but there SHOULD be more than a simple if-then.
At least show me that you're path-finding. That's not even being done here - this is just path-following.
"I leave a trail, you follow it." Explain to me how that qualifies as AI. Simple BFS/DFS achieves a lot more than this - which is considered by most to not even really be AI.
if (ai.x - pad > ball.x)
move_ai(-max_speed);
else if (ai.x + pad < ball.x)
move_ai(max_speed);
... or something like that, with some bounds checking and some logic for smaller moves. Bottom line, "just an if/then statement" can be sufficient to make a playable game with a challenging (or even unbeatable) computer player. Tic tac toe is another example of this.