1 / 43

Game Programming Algorithms and Techniques

Game Programming Algorithms and Techniques. Chapter 9 Artificial Intelligence. Chapter 9 Objectives. "Real" vs. Game AI How AI needs for games differ from traditional AI Pathfinding How to represent the game world Heuristics Greedy Best-First and A* State-Based Behaviors

calebb
Download Presentation

Game Programming Algorithms and Techniques

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Game Programming Algorithms and Techniques Chapter 9 Artificial Intelligence

  2. Chapter 9Objectives • "Real" vs. Game AI • How AI needs for games differ from traditional AI • Pathfinding • How to represent the game world • Heuristics • Greedy Best-First and A* • State-Based Behaviors • Representing AI with state machines • State design pattern • Basics of Strategy and Planning • What is a strategy and a plan?

  3. "Real" vs. Game AI • Games typically do not use overly complex AI for the following reasons: • It's more about the perception of intelligence than actual intelligence. • Often "real" AI has emergent behavior that's not desired for games. • Computation time is limited.

  4. Pathfinding Two paths from A to B How to find an intelligent path from point A to B. Here are two paths, but we want the better one:

  5. Representing the Search Space • Pathfinding used for games relies on traversing the graph data structure. • A graph contains a set of nodes, and each node is connected to any number of adjacent nodes via edges. • Easiest way to represent a graph is via adjacency lists: • Each node has a linked list of pointers to adjacent nodes.

  6. Graph Example A sample graph

  7. Square Grid Skulls of the Shogun with its AI debug mode enabled to illustrate the square grid it uses for pathfinding In a square grid, each square is a node, and its adjacent nodes are the adjacent squares:

  8. Path Nodes Level designer places nodes where NPCs are allowed to travel. Code automatically generates edges between the nodes, checking for objects blocking them. NPCs can only trust that the nodes and the edges are valid locations; any other locations may not be valid.

  9. Navigation Mesh Each node is a convex polygon. Adjacent nodes are adjacent polygons. Much larger areas can be marked as safe with navigation meshes. Can also be entirely auto-generated.

  10. Path Nodes vs. Navigation Meshes Two representations of the same room

  11. Heuristic Represented by h(x). Is the estimate from a node to the end goal. To be considered admissible, the heuristic must be less than or equal to the actual cost.

  12. Heuristic, Cont'd Manhattan and Euclidean heuristics Two common heuristics:

  13. Manhattan Heuristic Akin to travelling city blocks Ignores diagonal distance

  14. Euclidean Distance Straight "as the crow flies" distance Can be calculated with the distance formula:

  15. Greedy Best-First A simple pathfinding algorithm Is considered greedy because it always picks the best answer "right now" without any amount of planning Can lead to sub-optimal paths

  16. Greedy Best-First, Cont'd Greedy best-first path Here's an example of a sub-optimal path:

  17. Node for Greedy Best-First In addition to adjacency information, we need to store the following: struct Node Nodeparent floath end parent tracks the node that was visited prior to this one. h stores the h(x) heuristic.

  18. Best-First, Step by Step Let's look at how we can solve this path. We will assume we can't travel diagonally, and use the Manhattan heuristic:

  19. BFS – Initialization Step currentNode = startNode add currentNode to closedSet do

  20. BFS – Main Loop, Step 1 foreach Node n adjacent to currentNode ifn is not in closedSet n.parent = currentNode ifn is not in openSet calculate n.h add n to openSet end end loop

  21. BFS – Main Loop, Step 2 ifopenSetis empty // Exit main loop break end

  22. BFS – Main Loop, Step 3 currentNode = Node with lowest h in openSet move currentNode from openSet to closedSet while currentNode != goalNode

  23. BFS – Main Loop, Step 1 foreach Node n adjacent to currentNode ifn is not in closedSet n.parent = currentNode ifn is not in openSet calculate n.h add n to openSet end end loop

  24. BFS – Main Loop, Step 2 ifopenSetis empty // Exit main loop break end

  25. BFS – Main Loop, Step 3 currentNode = Node with lowest h in openSet move currentNode from openSet to closedSet while currentNode != goalNode

  26. BFS End Result After many iterations, we will end up with the following: We then have a parent linked list from the goal to the start.

  27. But wait… • Don't we want a path from the start to the goal? • Two solutions: • Reverse the linked list using a stack. • RECOMMENDED: Calculate the initial path in reverse (for example, start at the goal node and travel to the start node).

  28. A* Will generally yield a much better path than best-first:

  29. A* Function • Instead of just using the heuristic, we also add a path-cost component g(x): • Actual cost from start node to the node in question. • The overall function then becomes: • Instead of selecting the lowest h(x) cost node, we now select the lowest f(x) cost node

  30. A* Node Need a few more parameters: structNode Node parent float f float g float h end Here, f/g correspond to the new parts of our equation.

  31. Node Adoption Current node adoption fails Rather than automatically overwriting the parent of an adjacent node in the open set, we must check which parent has a lower g(x) cost. In this case, the adoption fails:

  32. Full A* Algorithm currentNode = startNode add currentNode to closedSet do foreachNoden adjacent to currentNode ifclosedSet contains n continue else ifopenSet contains n// Check for adoption compute new_g// g(x) value for n with currentNode as parent ifnew_g < n.g n.parent = currentNode n.g = new_g n.f = n.g + n.h// n.h for this node will not change end else n.parent = currentNode compute n.h compute n.g n.f = n.g + n.h add n to openSet end loop ifopenSet is empty break end currentNode = Node with lowest f in openSet remove currentNode from openSet add currentNode to closedSet untilcurrentNode == endNode

  33. Dijkstra's Algorithm Equation for Dijkstra's is: Actually predates A*. Will find the same path as A*, but generally visits more nodes (less efficient). Only game use might be if there are multiple goal nodes, but it's unclear which one is closer.

  34. State Machines for AI More complex stealth AI state machine We usually want to have multiple states the AI can be in, such as:

  35. Basic State Machine Could simply have an enum of states: enumAIState Patrol, Death, Attack end

  36. Basic State Machine, Cont'd functionAIController.Update(floatdeltaTime) ifstate == Patrol // Perform Patrol actions else ifstate == Death // Perform Death actions else ifstate == Attack // Perform Attack actions end end functionAIController.SetState(AIStatenewState) // Exit actions ifstate == Patrol // Exit Patrol state else ifstate == Death // Exit Death state else ifstate == Attack // Exit Attack state end state = newState // Enter actions ifstate == Patrol // Enter Patrol state else ifstate == Death // Enter Death state else ifstate == Attack // Enter Attack state end end

  37. Basic State Machine: Problems • With many states, the code turns into spaghetti. • It's very inflexible: • If we want to share "patrol" behavior between multiple state machines, it’s very difficult to do so.

  38. State Design Pattern State design pattern

  39. AIState Class Create a base AIState class: classAIState AIControllerparent function Update(floatdeltaTime) function Enter() function Exit() end

  40. AIController Class Has a pointer to the current state: classAIController AIStatestate function Update(floatdeltaTime) function SetState(AIStatenewState) end

  41. AIController: Update/SetState Code becomes much cleaner in controller: functionAIController.Update(floatdeltaTime) state.Update(deltaTime) end functionAIController.SetState(AIStatenewState) state.Exit() state = newState state.Enter() end And state code is contained to a particular State class.

  42. Strategy and Planning • Strategy: AI's overall vision of how it should complete the game. • For example, in an RTS: • Aggressive or defensive? • Tech or rush? • Plan: How the AI intends to execute the strategy.

  43. Sample Plan for Expansion Scout for a suitable location for an expansion. Build enough units to be able to defend the expansion. Send a worker plus the defender units to the expansion spot. Start building the expansion.

More Related