Design and Implementation of Heap
data structure for A* Pathfinding in
Computer Games
SRM University
Department of Software Engineering
Final Year Project in Software Engineering, 2016
Project group: Swapnika Pasunuri,Siddharth Gupta
Supervisor: Mrs. Alice Nithya
ABSTRACT
The project documents the implementation of the famous pathfinding algorithm A* using a
Heap data structure to increase the performance of a 2D Pacman game. In order to add fun
and make a game interesting the AI should be challenging enough to the player. An efficient
algorithm guarantees quick and accurate responses from the AI players. The application has
been solely programmed with Unity Game Engine utilizing C# language and a Mono-develop
Editor. The current trends in A* pathfinding utilize the stack structure tostore the nodes. The
heap data structure would increase the flexibility and decrease the time to perform the
calculation. The application has been programmed with a degree of success and in conclusion
the A* search algorithm in conjunction with the heap data structure has made it possible for
Games utilizing artificial intelligence to be indeed challenging.
SECTION 1
INTRODUCTION
The project investigates the aspects of implementing an efficient pathfinding algorithm to
make the current Real Time Strategy (RTS) PC games more challenging and interesting. The
application has been developed with the intention of being implemented in these games to
increase the efficiency of responses of the bots in these games. The project originated from
the observation of sloppy enemy AI in a mobile game - Clash of Clans. The idea was to
increase the swiftness in responses of enemy AI so that the game gives you a challenging
time.
On the basis of this we proceeded to develop a PC Clone of all time famous Pacman Game
and sought to enhance the algorithm efficiency of the enemy AI to make the game a lot more
capable of making the users addictive. Thus, we started small and thought of improvising the
pathfinding technique in the basic game of Pacman. Our idea was to improvise the usage of
existing algorithm to make performance leaps.
Currently Djikstra algorithm and A* algorithm are widely used in pathdfinding in Computer
Games. Djikstra algorithm uses uniform cost strategy to find the optimal path while A*
algorithm combines both strategies thereby minimizing the total cost. Due to the optimal
nature of A* in term of both cost and efficiency it is always chosen above Djikstra algorithm
and that is one of the prime reason we sought to chose A* algorithm.
The paper outlines the following sections:
Section 2 - Proposed methodology
Section 3 - Experimental Methods and Results
Section 2 – Proposed Methodology
A*
A* pathfinding is a directed algorithm, meaning that it does not blindly search for a path.
Instead it assesses the best direction to explore, sometimes backtracking to try alternatives.
This means that A* will not only find a path between two points but will also find the shortest
path if one exists and do so relatively quickly.
How It Works
The game map has to be prepared or pre-processedbefore the A* algorithmcan work.
This involvesbreakingthe map into differentpointsor locations,which are called
nodes.These can be waypoints, the polygons ofa navigation meshor the polygonsof
an area awarenesssystem.These nodesare usedto record the progress of the search.
In additionto holdingthe map locationeach node has three other attributes. These are
fitness,goal and heuristiccommonlyknown as f,g, and h respectively.Different
valuescan be assignedto paths betweenthe nodes.Typicallythese values would
representthe distances betweenthe nodes.The attributes g, h, and f are definedas
follows:
· g is the cost of gettingfrom the start node to the current node i.e. the sum of
all the values inthe path betweenthe start and the current node
· h stands for heuristicwhich is an estimatedcost from the current node to the
goal node (usuallythe straight line distance from this node to the goal)
· f is the sum of g and h and is the bestestimate of the cost of the path going
through the current node.In essence the lowerthe value of f the more efficient
the path
The purpose of f, g, and h is to quantifyhow promising a path isup to the present
node.AdditionallyA* maintains two lists,an Openand a Closedlist. The Openlist
contains all the nodes inthe map that have not beenfullyexploredyet,whereasthe
Closedlistconsists ofall the nodesthat have beenfullyexplored.A node is
consideredfullyexploredwhenthe algorithmhas lookedat every node linkedto it.
Nodestherefore simplymark the state and progress of the search.
The A* Algorithm
The pseudo-code forthe A* Algorithmis as follows:
1. Let P = starting point.
2. Assignf, g and h valuesto P.
3. Add P to the Openlist.At this point,P is the onlynode on the Open list.
4. Let B = the bestnode from the Openlist (i.e.the node that has the lowest
f-value).
a. If B is the goal node,then quit – a path has beenfound.
b. If the Openlistis empty, thenquit – a path cannot be found
5. Let C = a valid node connectedto B.
a. Assign f, g,and h valuesto C.
b. Check whetherC is on the Open or Closedlist.
i. If so, checkwhether the new path is more efficient(i.e.has
a lowerf-value).
1. If so update the path.
ii.Else, add C to the Openlist.
c. Repeat step5 for all valid childrenofB.
6. Repeatfrom step 4.
Optimizing A* - Heap Data Structure
While calculating the shortest path, A* takes in account , all the nodes in the Open List and
thus reduces the speedof executing the algorithm. Each iteration has to search the entire
open set. Thus in order to overcome such a performance drawback we implemented the A*
algorithm with the Heap Data structure.
Design- Heap Data Structure
A heap data structure is analogous to a binary tree wherein each node can have at most 2
child nodes. However in such a Heap structure the parent node must always be smaller
than the child nodes.
Heap Structure
When we are inserting a node into the structure we check if the parent node is less than the
child node. If it is greater we swap the nodes. With this process we don’t have to process all
the nodes in the given open list. Thus we gain speedin executing the algorithm.
When we delete a node from the structure we replace the node from the leaf node and
check if it is smaller than the child nodes and repeat the same process again.
Parent Node = (n - 1)/ 2
Child Node Left = 2n + 1;
Child Node Right = 2n + 2;
Implementationof Heap Data Structure using C#
1. using UnityEngine;
2. using System.Collections;
3. using System;
4.
5. public class Heap<T> where T : IHeapItem<T> {
6.
7. T[] items;
8. int currentItemCount;
9.
10. public Heap(int maxHeapSize) {
11. items = new T[maxHeapSize];
12. }
13.
14. public void Add(T item) {
15. item.HeapIndex = currentItemCount;
16. items[currentItemCount] = item;
17. SortUp(item);
18. currentItemCount++;
19. }
20.
21. public T RemoveFirst() {
22. T firstItem = items[0];
23. currentItemCount--;
24. items[0] = items[currentItemCount];
25. items[0].HeapIndex = 0;
26. SortDown(items[0]);
27. return firstItem;
28. }
29.
30. public void UpdateItem(T item) {
31. SortUp(item);
32. }
33.
34. public int Count {
35. get {
36. return currentItemCount;
37. }
38. }
39.
40. public bool Contains(T item) {
41. return Equals(items[item.HeapIndex], item);
42. }
43.
44. void SortDown(T item) {
45. while (true) {
46. int childIndexLeft = item.HeapIndex * 2 + 1;
47. int childIndexRight = item.HeapIndex * 2 + 2;
48. int swapIndex = 0;
49.
50. if (childIndexLeft < currentItemCount) {
51. swapIndex = childIndexLeft;
52.
53. if (childIndexRight < currentItemCount) {
54. if (items[childIndexLeft].CompareTo(items[childIndexRigh
t]) < 0) {
55. swapIndex = childIndexRight;
56. }
57. }
58.
59. if (item.CompareTo(items[swapIndex]) < 0) {
60. Swap (item,items[swapIndex]);
61. }
62. else {
63. return;
64. }
65.
66. }
67. else {
68. return;
69. }
70. }
71. }
72.
73. void SortUp(T item) {
74. int parentIndex = (item.HeapIndex-1)/2;
75.
76. while (true) {
77. T parentItem = items[parentIndex];
78. if (item.CompareTo(parentItem) > 0) {
79. Swap (item,parentItem);
80. }
81. else {
82. break;
83. }
84. parentIndex = (item.HeapIndex-1)/2;
85. }
86. }
87.
88. void Swap(T itemA, T itemB) {
89. items[itemA.HeapIndex] = itemB;
90. items[itemB.HeapIndex] = itemA;
91. int itemAIndex = itemA.HeapIndex;
92. itemA.HeapIndex = itemB.HeapIndex;
93. itemB.HeapIndex = itemAIndex;
94. }
95. }
96.
97. public interface IHeapItem<T> : IComparable<T> {
98. int HeapIndex {
99. get;
100. set;
101. }
Section 3 - Experimental Methods and Results:
A: Before Implementing Heap Structure
B: After Implementing Heap Structure
Conclusion
The reason that games developers have not researched machine learning for pathfinding is that it
would take to much time to do so and time is money! Games developers are also very reluctant to
experiment with machine learning, as it could be unpredictable. Future work will involve setting up a
test bed to test the practicality of using machine learning to perform pathfinding. Pacman is the game
chosen for the test bed, as it is a real-time game that uses pathfinding algorithms to navigate around a
2D maze
References
[Alexander02] Alexander, Thor,. “GoCap: Game Observation Capture”, AI Game Programming
Wisdom, Charles River Media, 2002
[Alexander02a] Alexander, Thor,. “Optimized Machine Learning with GoCap”, Game Programming
Gems 3, Charles River Media, 2002
[Board & Ducker02] Board, Ben., Ducker, Mike., “Area Navigation: Expanding the Path-
Finding Paradigm”, Game Programming Gems 3, Charles River Media, 2002
[Cain02] Cain, Timothy, “Practical Optimizations for A*”, AI Game Programming Wisdom, Charles
River Media, 2002

Game Paper

  • 1.
    Design and Implementationof Heap data structure for A* Pathfinding in Computer Games SRM University Department of Software Engineering Final Year Project in Software Engineering, 2016 Project group: Swapnika Pasunuri,Siddharth Gupta Supervisor: Mrs. Alice Nithya ABSTRACT The project documents the implementation of the famous pathfinding algorithm A* using a Heap data structure to increase the performance of a 2D Pacman game. In order to add fun and make a game interesting the AI should be challenging enough to the player. An efficient algorithm guarantees quick and accurate responses from the AI players. The application has been solely programmed with Unity Game Engine utilizing C# language and a Mono-develop Editor. The current trends in A* pathfinding utilize the stack structure tostore the nodes. The heap data structure would increase the flexibility and decrease the time to perform the calculation. The application has been programmed with a degree of success and in conclusion the A* search algorithm in conjunction with the heap data structure has made it possible for Games utilizing artificial intelligence to be indeed challenging. SECTION 1 INTRODUCTION The project investigates the aspects of implementing an efficient pathfinding algorithm to make the current Real Time Strategy (RTS) PC games more challenging and interesting. The application has been developed with the intention of being implemented in these games to increase the efficiency of responses of the bots in these games. The project originated from
  • 2.
    the observation ofsloppy enemy AI in a mobile game - Clash of Clans. The idea was to increase the swiftness in responses of enemy AI so that the game gives you a challenging time. On the basis of this we proceeded to develop a PC Clone of all time famous Pacman Game and sought to enhance the algorithm efficiency of the enemy AI to make the game a lot more capable of making the users addictive. Thus, we started small and thought of improvising the pathfinding technique in the basic game of Pacman. Our idea was to improvise the usage of existing algorithm to make performance leaps. Currently Djikstra algorithm and A* algorithm are widely used in pathdfinding in Computer Games. Djikstra algorithm uses uniform cost strategy to find the optimal path while A* algorithm combines both strategies thereby minimizing the total cost. Due to the optimal nature of A* in term of both cost and efficiency it is always chosen above Djikstra algorithm and that is one of the prime reason we sought to chose A* algorithm. The paper outlines the following sections: Section 2 - Proposed methodology Section 3 - Experimental Methods and Results Section 2 – Proposed Methodology A* A* pathfinding is a directed algorithm, meaning that it does not blindly search for a path. Instead it assesses the best direction to explore, sometimes backtracking to try alternatives. This means that A* will not only find a path between two points but will also find the shortest path if one exists and do so relatively quickly. How It Works The game map has to be prepared or pre-processedbefore the A* algorithmcan work. This involvesbreakingthe map into differentpointsor locations,which are called nodes.These can be waypoints, the polygons ofa navigation meshor the polygonsof an area awarenesssystem.These nodesare usedto record the progress of the search. In additionto holdingthe map locationeach node has three other attributes. These are fitness,goal and heuristiccommonlyknown as f,g, and h respectively.Different valuescan be assignedto paths betweenthe nodes.Typicallythese values would
  • 3.
    representthe distances betweenthenodes.The attributes g, h, and f are definedas follows: · g is the cost of gettingfrom the start node to the current node i.e. the sum of all the values inthe path betweenthe start and the current node · h stands for heuristicwhich is an estimatedcost from the current node to the goal node (usuallythe straight line distance from this node to the goal) · f is the sum of g and h and is the bestestimate of the cost of the path going through the current node.In essence the lowerthe value of f the more efficient the path The purpose of f, g, and h is to quantifyhow promising a path isup to the present node.AdditionallyA* maintains two lists,an Openand a Closedlist. The Openlist contains all the nodes inthe map that have not beenfullyexploredyet,whereasthe Closedlistconsists ofall the nodesthat have beenfullyexplored.A node is consideredfullyexploredwhenthe algorithmhas lookedat every node linkedto it. Nodestherefore simplymark the state and progress of the search. The A* Algorithm The pseudo-code forthe A* Algorithmis as follows: 1. Let P = starting point. 2. Assignf, g and h valuesto P. 3. Add P to the Openlist.At this point,P is the onlynode on the Open list. 4. Let B = the bestnode from the Openlist (i.e.the node that has the lowest f-value). a. If B is the goal node,then quit – a path has beenfound. b. If the Openlistis empty, thenquit – a path cannot be found 5. Let C = a valid node connectedto B. a. Assign f, g,and h valuesto C. b. Check whetherC is on the Open or Closedlist. i. If so, checkwhether the new path is more efficient(i.e.has a lowerf-value). 1. If so update the path. ii.Else, add C to the Openlist. c. Repeat step5 for all valid childrenofB. 6. Repeatfrom step 4.
  • 4.
    Optimizing A* -Heap Data Structure While calculating the shortest path, A* takes in account , all the nodes in the Open List and thus reduces the speedof executing the algorithm. Each iteration has to search the entire open set. Thus in order to overcome such a performance drawback we implemented the A* algorithm with the Heap Data structure. Design- Heap Data Structure A heap data structure is analogous to a binary tree wherein each node can have at most 2 child nodes. However in such a Heap structure the parent node must always be smaller than the child nodes. Heap Structure When we are inserting a node into the structure we check if the parent node is less than the child node. If it is greater we swap the nodes. With this process we don’t have to process all the nodes in the given open list. Thus we gain speedin executing the algorithm. When we delete a node from the structure we replace the node from the leaf node and check if it is smaller than the child nodes and repeat the same process again. Parent Node = (n - 1)/ 2 Child Node Left = 2n + 1; Child Node Right = 2n + 2;
  • 5.
    Implementationof Heap DataStructure using C# 1. using UnityEngine; 2. using System.Collections; 3. using System; 4. 5. public class Heap<T> where T : IHeapItem<T> { 6. 7. T[] items; 8. int currentItemCount; 9. 10. public Heap(int maxHeapSize) { 11. items = new T[maxHeapSize]; 12. } 13. 14. public void Add(T item) { 15. item.HeapIndex = currentItemCount; 16. items[currentItemCount] = item; 17. SortUp(item); 18. currentItemCount++; 19. } 20. 21. public T RemoveFirst() { 22. T firstItem = items[0]; 23. currentItemCount--; 24. items[0] = items[currentItemCount]; 25. items[0].HeapIndex = 0; 26. SortDown(items[0]); 27. return firstItem; 28. } 29. 30. public void UpdateItem(T item) { 31. SortUp(item); 32. } 33.
  • 6.
    34. public intCount { 35. get { 36. return currentItemCount; 37. } 38. } 39. 40. public bool Contains(T item) { 41. return Equals(items[item.HeapIndex], item); 42. } 43. 44. void SortDown(T item) { 45. while (true) { 46. int childIndexLeft = item.HeapIndex * 2 + 1; 47. int childIndexRight = item.HeapIndex * 2 + 2; 48. int swapIndex = 0; 49. 50. if (childIndexLeft < currentItemCount) { 51. swapIndex = childIndexLeft; 52. 53. if (childIndexRight < currentItemCount) { 54. if (items[childIndexLeft].CompareTo(items[childIndexRigh t]) < 0) { 55. swapIndex = childIndexRight; 56. } 57. } 58. 59. if (item.CompareTo(items[swapIndex]) < 0) { 60. Swap (item,items[swapIndex]); 61. } 62. else { 63. return; 64. } 65. 66. } 67. else { 68. return;
  • 7.
    69. } 70. } 71.} 72. 73. void SortUp(T item) { 74. int parentIndex = (item.HeapIndex-1)/2; 75. 76. while (true) { 77. T parentItem = items[parentIndex]; 78. if (item.CompareTo(parentItem) > 0) { 79. Swap (item,parentItem); 80. } 81. else { 82. break; 83. } 84. parentIndex = (item.HeapIndex-1)/2; 85. } 86. } 87. 88. void Swap(T itemA, T itemB) { 89. items[itemA.HeapIndex] = itemB; 90. items[itemB.HeapIndex] = itemA; 91. int itemAIndex = itemA.HeapIndex; 92. itemA.HeapIndex = itemB.HeapIndex; 93. itemB.HeapIndex = itemAIndex; 94. } 95. } 96. 97. public interface IHeapItem<T> : IComparable<T> { 98. int HeapIndex { 99. get; 100. set; 101. }
  • 8.
    Section 3 -Experimental Methods and Results: A: Before Implementing Heap Structure B: After Implementing Heap Structure
  • 9.
    Conclusion The reason thatgames developers have not researched machine learning for pathfinding is that it would take to much time to do so and time is money! Games developers are also very reluctant to experiment with machine learning, as it could be unpredictable. Future work will involve setting up a test bed to test the practicality of using machine learning to perform pathfinding. Pacman is the game chosen for the test bed, as it is a real-time game that uses pathfinding algorithms to navigate around a 2D maze References [Alexander02] Alexander, Thor,. “GoCap: Game Observation Capture”, AI Game Programming Wisdom, Charles River Media, 2002 [Alexander02a] Alexander, Thor,. “Optimized Machine Learning with GoCap”, Game Programming Gems 3, Charles River Media, 2002 [Board & Ducker02] Board, Ben., Ducker, Mike., “Area Navigation: Expanding the Path- Finding Paradigm”, Game Programming Gems 3, Charles River Media, 2002 [Cain02] Cain, Timothy, “Practical Optimizations for A*”, AI Game Programming Wisdom, Charles River Media, 2002