3If we need to design an AI… That is able to calculate a suitable route through the game level to get from where it currently is to its goal……and that route is to be as short or rapid as possible, or at least, looks smart enough (!) …
4PathfindingSometimes called path planning (but pathfinding is still the usual term used)Simple task: Work out where to move to reach a goalIn Millington’s model – sits on the border between decision-making and movement.GOAL is decided by decision-making AIPathfinding simply works out HOW to get thereMovement AI GETS the character there
5Using PathfindingVast majority of games use pathfinding solutions that are efficient and easy to implement – BUT pathfinding AI cannot work directly with game level data.Requires game level to be represented in a certain data structure: A directed non-negative weighted graph
7Graph Formal representation: Each node represents A set of nodesA set of connections (an unordered pair of nodes)Each node representsA region of the game level (room, section of corridor, platform, etc.)Connections representsWhich locations (nodes) are connectedIf a room adjoins a corridor?Split whole game level into regions which are connected
8Weighted GraphsIn addition to having nodes and connections, a numerical value or “weight” is used to label each connection with an associated cost value
9Graphs in games: Weights? In games, what can we use the weights to represent?
10Graphs in games: Nodes/Connections? How shall we overlay a weighted graph onto game level geometry?Suggest some ways to place nodes/connections correctly…
11Now, what’s the whole idea? So, back to the original idea of pathfinding: How shall we use a weighted graph (like below) to find paths in the game?
12More things to consider… Can we have negative weights in a graph?Can certain nodes be only connected one way (just like a one-way street)?
13Directed Weighted Graphs Connections of graph are directed, or allows movement between 2 nodes to be from one direction only
14Directed Weighted Graph Can be useful in 2 special situations:Reachability between two locations (node A can reach node B, but node B cannot reach node A)Allow both connections in opposite directions to have different weights (the cost to move from node A to node B is different from the cost to move from node B to node A)
15Representing Graphs in Code Graph class – store an array of connection objects for any nodeConnection class – store cost, ‘from’ node, ‘to’ node
16Dijkstra’s Algorithm Named after Edsger Dijkstra, a mathematician Originally designed to solve a problem in mathematical graph theory called “shortest path”, NOT for gamesIdea: Finding the shortest path from one start point to one goal pointDijkstra’s Algorithm is designed to find the shortest routes to everywhere from an initial point – Wasteful?
17The ProblemAim: Given a graph and two nodes (start and goal), generate a path such that the total path cost of that path is minimal among all possible paths from start to goalThere may be any number of paths with the same minimal cost Just return any one will doMany games do not consider having more than one connection between any pair of nodes (only one possible path?)With many connections between any pair of nodes, an optimum path is needed to make the AI look smart!
19The Algorithm Spread out from the start node along its connections Each time, keep a record of the direction it came from with “arrows”Eventually, the goal is reached, follow the “arrows” back to its start point to generate the complete minimal routeWorks in iterationsEach iteration: consider one node of the graph and follow outgoing connectionsEach iteration’s node is called the “current node”
20The Algorithm Processing the Current Node at each iteration Consider outgoing connections from current nodeFor each connection, finds the end node and stores the total cost of the path so far “cost-so-far”Each connected node stores a) cost-so-far and b) which connection
21The Algorithm After the 1st iteration Cost-so-far = Sum of connection cost + cost-so-far of current node
22Node List Keeps track of all the nodes seen so far in 2 lists: Open ListRecords all nodes seen, but haven’t been processed in its own iteration yetClosed ListRecords all nodes that have been processed in its own iterationNodes in neither list are “unvisited”At each iteration, a node from the open list with smallest cost-so-far is chosen (processed), then removed from the open list and placed in the closed listDid we miss out anything?
23Cost-so-far for Open and Closed Nodes What happens when we arrive at an open or close node (again) during an iteration?Check if the new route we found has a lower cost-so-far compared to the earlier found route.If higher cost, then don’t update earlier costIf lower cost, update it to this new cost (then this node should be removed from the closed list and back to open list!)
24A few iterations later… Notice the updating done on node D
25Terminating the Algorithm Basic Dijkstra’s Algorithm – terminates when open list is empty (no more nodes to process), and all nodes are in closed listIn practical pathfinding, we can terminate earlier once we have processed the goal node AND the goal node is the smallest node on the open list (added heuristic)Why do we add this heuristic rule?
27Retrieving the Path Final step Start from goal node, look back at the connections that were used to arrive there. Continue until reach start goalThe list of connections need to be reversed to obtain the right path order
29Data Structures & Interfaces Simple ListNot performance critical, use a basic linked list (list) or resizable array (vector) in your languagePathfinding ListLarge Open and Closed lists can affect performance. Need optimization to perform these operations adding entry, removing entry, finding smallest element, finding entry in list corresponding to a particular node
30Practical Performance of Dijkstra’s Depends mostly on performance of operations in pathfinding list data structureTheoretically (n nodes, m connections):Time complexity (execution speed): O(nm)Space complexity (memory): O(nm) worst-case
31Weaknesses Searches whole graph indiscriminately for shortest path Wasteful for point-to- point pathfindingSuffers from terrible amount of “fill” (nodes that were considered but never made part of the final route)
32A* Algorithm Most widely used for pathfinding in games Simple to implementEfficientMany scopes for optimizationUnlike Dijkstra algorithm, A* is designed for point-to-point pathfinding, NOT for solving shortest path problem in graph theory.Always returns a single path from source to goalThe “best” possible path
33A* Algorithm – The Problem Given a graph (a directed non-negative weighted graph) and two nodes in that graph (a start and goal node)Generate a path the total path cost of the path is minimal among all paths from start to goalIf there are more than one possible solution, any minimal path will doPath should consist of a list of connections from the start goal to goal nodeStartGoal
34A* Algorithm – Difference from Dijkstra Dijkstra Always considered the open node with lowest cost-so-far for processingA* Consider node that most likely to lead to shortest overall path“most likely” controlled by a “heuristic”, an estimated rule of thumbIf accurate heuristic used: EfficientIf bad heuristic used: May perform worse than Dijkstra!
35How to estimate “heuristic” for A* A* also stores another 2 values – heuristic value and estimated total cost
36We can observe that…Estimated total cost = Cost so far + Heuristic costThe heuristic cost cannot be negative (obviously!)Just like Dijkstra, A* also keeps an open list of nodes and closed list of nodesNodes are moved to open list as they are found at end of connectionsNodes are moved to closed list as they are processed in their own iterationUnlike Dijkstra, node with smallest estimated total cost is selected NOT node with smallest cost-so-far
37How to estimate “heuristic” for A* Think about how an “estimated total cost” should be calculated?...Think of a good heuristic to use?How to estimate total cost from start to end for this node?StartGoal
38How to estimate “heuristic” for A* A node with smallest estimated total cost should haveA relatively small cost-so-far (Dijkstra only have this)A relatively small estimated distance to go to reach goalStartGoal
39Calculating CostsCost-so-far is calculated by the total cost of the path travelled so farIf there are new values that are lower than existing value of node, update is needed
41Updating CostsTo update: Compare cost-so-far NOT estimated total cost (with heuristic added)This is the only reliable “real” value. Heuristic involves estimationOpen nodes that have their values revised simply stay out on the open listHow to revised values of closed nodes?Simple way to force algorithm to recalculate and re- propagate new values:Remove node from closed list, place back into open listIt will be processed once again and have its connections reconsidered
42Terminating the Algorithm A* terminates when the goal node is the smallest node on the open list (smallest estimated total cost)This does not guarantee that shortest path is found. WHY?It is natural for A* to run a bit longer to generate a guaranteed optimal resultOne way: Require that A* terminates when node in open list with smallest cost-so-far has a cost-so-far greater than cost of path found to goal (almost like Dijkstra)Drawback: Same fill problem as Dijkstra!!
43Tampering with heuristic function A* can theoretically produce non-optimal resultsChoice of heuristic function can determine outcome of resultsUse a good heuristic function (with additional termination rules) to ensure better optimal resultsDeliberately allow sub-optimal results (by using a mediocre heuristic) to give faster execution
44Algorithm Performance Depends on data structure usedTime complexity, O(lm)Space complexity, O(lm)l: number of nodes whose total estimated path cost is less than that of goal, > n from Dijkstram: average number of outgoing connections from each nodeHeuristic calculation is usually O(1) execution time and memory, so no effect on overall performance. Call be even calculated offline.Refer to textbook for more detail on the pseudocode and data structures involved
45Choosing a HeuristicThe more accurate the heuristic, the less fill A* experiences, the faster it will runPerfect heuristic correct answerUnderestimating heuristicBiased towards cost-so-far, Increases running timeBest if accuracy more important than performanceOverestimating heuristicBiased towards heuristic value, faster search towards goalDefinitely sub-optimalBest if performance and speed is more important than accuracy
46Heuristic – Euclidean Distance Or “bird’s flight distance” or “straight-line distance”Guaranteed to be underestimating
47Heuristic – Cluster Heuristic Works by grouping nodes together in clustersNodes in a cluster represent some region of level (room, building, etc.) that is highly interconnectedClustering can be done by some graph clustering algorithms (beyond scope of this course)Create a lookup table with the smallest path length between each pair of clusters. An offline step.In game,If start and goal nodes are in same cluster, Euclidean distance (or some other simpler fallback) is used to get resultOtherwise, look up the table for the distance between clusters
52World Representations Tile GraphsDirichlet DomainsPoints of VisibilityPolygonal Meshes
53Hierarchical Pathfinding Divide world into many plansGroup locations together to form clusters. E.g. Individual locations for a whole room can be grouped together. In a higher level plan, the room can be treated as a single node in a larger world.Each level is considered a “node” in the next higher level, and so onProcess can be repeated as many time as neededFinal product is a hierarchical graph. At each level of hierarchy, graph acts just like any other pathfinding graph