A java PacMan game application for A.U.TH (data structures class)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

366 lines
11 KiB

  1. package gr.auth.ee.dsproject.pacman;
  2. import java.util.ArrayList;
  3. import gr.auth.ee.dsproject.node.Globals;
  4. import gr.auth.ee.dsproject.node.Tree;
  5. import gr.auth.ee.dsproject.node.Node89978445;
  6. /**
  7. * <p>
  8. * Title: DataStructures2011
  9. * </p>
  10. *
  11. * <p>
  12. * Description: Data Structures project: year 2011-2012
  13. * </p>
  14. *
  15. * <p>
  16. * Copyright: Copyright (c) 2011
  17. * </p>
  18. *
  19. * <p>
  20. * Company: A.U.Th.
  21. * </p>
  22. *
  23. * @author Michael T. Tsapanos
  24. * @version 1.0
  25. */
  26. public class Creature implements gr.auth.ee.dsproject.pacman.AbstractCreature
  27. {
  28. public String getName ()
  29. {
  30. return "Mine";
  31. }
  32. private int step = 1;
  33. private boolean amPrey;
  34. public Creature (boolean isPrey) {
  35. amPrey = isPrey;
  36. }
  37. /**
  38. *
  39. */
  40. public int calculateNextPacmanPosition (Room[][] Maze, int[] currPosition)
  41. {
  42. int [] bestPos = {-1, -1}; // Best position in maze to play
  43. Node89978445 bestNode; // The node with the best evaluation
  44. Node89978445 cur = new Node89978445 (Maze, currPosition); // The node with the current position
  45. //make the tree
  46. createSubTreePacman (cur.getDepth (), cur, Maze, currPosition);
  47. // min-max to find best node and consequently the best position
  48. bestNode = Tree.minmaxAB (cur, Globals.MINMAXTREE_MAX_DEPTH-1, Globals.EVAL_MIN - 1, Globals.EVAL_MAX + 1, true);
  49. bestPos = bestNode.getCurrentPacmanPos();
  50. // convert back to move encoding
  51. return Node89978445.moveConv (bestPos, currPosition);
  52. }
  53. /**
  54. *
  55. */
  56. void createSubTreePacman (int depth, Node89978445 parent, Room[][] Maze, int[] curPacmanPosition)
  57. {
  58. if (depth >= Globals.MINMAXTREE_MAX_DEPTH-1)
  59. /*<
  60. * As the depth starts from 0 and MINMAXTREE_MAX_DEPTH
  61. * is strictly even, with this comparison we accept that there
  62. * is no need for a max-depth layer of ghosts-evaluation based nodes.
  63. * As soon as we accept the depth-1 layers max evaluated node.
  64. */
  65. return;
  66. else {
  67. Node89978445 newNode;
  68. Room[][] newMaze;
  69. int[] nextPosition = {-1, -1};
  70. // scan possible valid moves
  71. for (int move=0 ; move<4 ; ++move) {
  72. if ((nextPosition = Node89978445.pacmanValidMove (parent, move)) != Globals.FALSE_POS) {
  73. // Make a copy of the maze in order to simulate next move and move Pacman
  74. newMaze = PacmanUtilities.copy (Maze);
  75. PacmanUtilities.movePacman (newMaze, parent.getCurrentPacmanPos(), nextPosition);
  76. // Create a node for the move in the new stated game maze
  77. newNode = new Node89978445 (newMaze, nextPosition);
  78. Tree.grow (newNode, parent); // add node to the min-max tree
  79. // call the recursive ranch creator
  80. createSubTreeGhosts (newNode.getDepth (), newNode, newMaze, newNode.getCurrentGhostPos());
  81. }
  82. }
  83. }
  84. }
  85. /**
  86. *
  87. */
  88. void createSubTreeGhosts (int depth, Node89978445 parent, Room[][] Maze, int[][] currGhostsPosition)
  89. {
  90. if (depth >= Globals.MINMAXTREE_MAX_DEPTH-1)
  91. /*<
  92. * As the depth starts from 0 and MINMAXTREE_MAX_DEPTH
  93. * is strictly even, with this comparison we accept that there
  94. * is no need for a max-depth layer of ghosts-evaluation based nodes.
  95. * As soon as we accept the depth-1 layers max evaluated node.
  96. */
  97. return;
  98. else {
  99. Node89978445 newNode;
  100. Room[][] newMaze;
  101. ArrayList<int[][]> ghostMoves;
  102. // Get all possible ghost moves
  103. ghostMoves = PacmanUtilities.allGhostMoves(Maze, currGhostsPosition);
  104. // loop all ghost moves
  105. for (int i=0 ; i<ghostMoves.size() ; ++i) {
  106. // Make a copy of the maze in order to simulate next move and move ghosts
  107. newMaze = PacmanUtilities.copy (Maze);
  108. PacmanUtilities.moveGhosts(newMaze, currGhostsPosition, ghostMoves.get(i));
  109. // Create a node for the move in the new stated game maze
  110. newNode = new Node89978445 (newMaze, parent.getCurrentPacmanPos());
  111. Tree.grow (newNode, parent); // add node to the min-max tree
  112. //recursive call for the rest of the tree
  113. createSubTreePacman (newNode.getDepth (), newNode, newMaze, parent.getCurrentPacmanPos());
  114. }
  115. }
  116. }
  117. public int[] getPacPos (Room[][] Maze)
  118. {
  119. int[] pacmanPos = new int[2];
  120. for (int i = 0; i < PacmanUtilities.numberOfRows; i++) {
  121. for (int j = 0; j < PacmanUtilities.numberOfColumns; j++) {
  122. if (Maze[i][j].isPacman()) {
  123. pacmanPos[0] = i;
  124. pacmanPos[1] = j;
  125. return pacmanPos;
  126. }
  127. }
  128. }
  129. return pacmanPos;
  130. }
  131. public boolean[] comAvPos (Room[][] Maze, int[][] currentPos, int[] moves, int currentGhost)
  132. {
  133. boolean[] availablePositions = { true, true, true, true };
  134. int[][] newPos = new int[4][2];
  135. for (int i = 0; i < 4; i++) {
  136. if (Maze[currentPos[currentGhost][0]][currentPos[currentGhost][1]].walls[i] == 0) {
  137. availablePositions[i] = false;
  138. continue;
  139. }
  140. if (PacmanUtilities.flagColision(Maze, currentPos[currentGhost], i)) {
  141. availablePositions[i] = false;
  142. }
  143. else if (currentGhost == 0)
  144. continue;
  145. else {
  146. switch (i) {
  147. case Room.WEST:
  148. newPos[currentGhost][0] = currentPos[currentGhost][0];
  149. newPos[currentGhost][1] = currentPos[currentGhost][1] - 1;
  150. break;
  151. case Room.SOUTH:
  152. newPos[currentGhost][0] = currentPos[currentGhost][0] + 1;
  153. newPos[currentGhost][1] = currentPos[currentGhost][1];
  154. break;
  155. case Room.EAST:
  156. newPos[currentGhost][0] = currentPos[currentGhost][0];
  157. newPos[currentGhost][1] = currentPos[currentGhost][1] + 1;
  158. break;
  159. case Room.NORTH:
  160. newPos[currentGhost][0] = currentPos[currentGhost][0] - 1;
  161. newPos[currentGhost][1] = currentPos[currentGhost][1];
  162. }
  163. for (int j = (currentGhost - 1); j > -1; j--) {
  164. switch (moves[j]) {
  165. case Room.WEST:
  166. newPos[j][0] = currentPos[j][0];
  167. newPos[j][1] = currentPos[j][1] - 1;
  168. break;
  169. case Room.SOUTH:
  170. newPos[j][0] = currentPos[j][0] + 1;
  171. newPos[j][1] = currentPos[j][1];
  172. break;
  173. case Room.EAST:
  174. newPos[j][0] = currentPos[j][0];
  175. newPos[j][1] = currentPos[j][1] + 1;
  176. break;
  177. case Room.NORTH:
  178. newPos[j][0] = currentPos[j][0] - 1;
  179. newPos[j][1] = currentPos[j][1];
  180. // break;
  181. }
  182. if ((newPos[currentGhost][0] == newPos[j][0]) && (newPos[currentGhost][1] == newPos[j][1])) {
  183. availablePositions[i] = false;
  184. continue;
  185. }
  186. if ((newPos[currentGhost][0] == currentPos[j][0]) && (newPos[currentGhost][1] == currentPos[j][1]) && (newPos[j][0] == currentPos[currentGhost][0])
  187. && (newPos[j][1] == currentPos[currentGhost][1])) {
  188. availablePositions[i] = false;
  189. }
  190. }
  191. }
  192. }
  193. return availablePositions;
  194. }
  195. public int comBestPos (boolean[] availablePositions, int[] pacmanPosition, int[] currentPos)
  196. {
  197. int[] newVerticalDifference = new int[2];
  198. for (int i = 0; i < 2; i++)
  199. newVerticalDifference[i] = currentPos[i] - pacmanPosition[i];
  200. int[] distanceSquared = new int[4];
  201. for (int i = 0; i < 4; i++) {
  202. if (availablePositions[i] == true) {
  203. switch (i) {
  204. case Room.WEST:
  205. newVerticalDifference[1]--;
  206. break;
  207. case Room.SOUTH:
  208. newVerticalDifference[0]++;
  209. break;
  210. case Room.EAST:
  211. newVerticalDifference[1]++;
  212. break;
  213. case Room.NORTH:
  214. newVerticalDifference[0]--;
  215. break;
  216. }
  217. distanceSquared[i] = newVerticalDifference[0] * newVerticalDifference[0] + newVerticalDifference[1] * newVerticalDifference[1];
  218. } else
  219. distanceSquared[i] = PacmanUtilities.numberOfRows * PacmanUtilities.numberOfRows + PacmanUtilities.numberOfColumns * PacmanUtilities.numberOfColumns + 1;
  220. }
  221. int minDistance = distanceSquared[0];
  222. int minPosition = 0;
  223. for (int i = 1; i < 4; i++) {
  224. if (minDistance > distanceSquared[i]) {
  225. minDistance = distanceSquared[i];
  226. minPosition = i;
  227. }
  228. }
  229. return minPosition;
  230. }
  231. public int[] calculateNextGhostPosition (Room[][] Maze, int[][] currentPos)
  232. {
  233. int[] moves = new int[PacmanUtilities.numberOfGhosts];
  234. int[] pacmanPosition = new int[2];
  235. pacmanPosition = getPacPos(Maze);
  236. for (int i = 0; i < PacmanUtilities.numberOfGhosts; i++) {
  237. moves[i] = comBestPos(comAvPos(Maze, currentPos, moves, i), pacmanPosition, currentPos[i]);
  238. }
  239. return moves;
  240. }
  241. public boolean[] checkCollision (int[] moves, int[][] currentPos)
  242. {
  243. boolean[] collision = new boolean[PacmanUtilities.numberOfGhosts];
  244. int[][] newPos = new int[4][2];
  245. for (int i = 0; i < moves.length; i++) {
  246. if (moves[i] == 0) {
  247. if (currentPos[i][1] > 0) {
  248. newPos[i][0] = currentPos[i][0];
  249. newPos[i][1] = currentPos[i][1] - 1;
  250. } else {
  251. newPos[i][0] = currentPos[i][0];
  252. newPos[i][1] = PacmanUtilities.numberOfColumns - 1;
  253. }
  254. } else if (moves[i] == 1) {
  255. if (currentPos[i][0] < PacmanUtilities.numberOfRows - 1) {
  256. newPos[i][0] = currentPos[i][0] + 1;
  257. newPos[i][1] = currentPos[i][1];
  258. } else {
  259. newPos[i][0] = 0;
  260. newPos[i][1] = currentPos[i][1];
  261. }
  262. } else if (moves[i] == 2) {
  263. if (currentPos[i][1] < PacmanUtilities.numberOfColumns - 1) {
  264. newPos[i][0] = currentPos[i][0];
  265. newPos[i][1] = currentPos[i][1] + 1;
  266. } else {
  267. newPos[i][0] = currentPos[i][0];
  268. newPos[i][1] = 0;
  269. }
  270. } else {
  271. if (currentPos[i][0] > 0) {
  272. newPos[i][0] = currentPos[i][0] - 1;
  273. newPos[i][1] = currentPos[i][1];
  274. } else {
  275. newPos[i][0] = PacmanUtilities.numberOfRows - 1;
  276. newPos[i][1] = currentPos[i][1];
  277. }
  278. }
  279. collision[i] = false;
  280. }
  281. for (int k = 0; k < moves.length; k++) {
  282. }
  283. for (int i = 0; i < moves.length; i++) {
  284. for (int j = i + 1; j < moves.length; j++) {
  285. if (newPos[i][0] == newPos[j][0] && newPos[i][1] == newPos[j][1]) {
  286. collision[j] = true;
  287. }
  288. if (newPos[i][0] == currentPos[j][0] && newPos[i][1] == currentPos[j][1] && newPos[j][0] == currentPos[i][0] && newPos[j][1] == currentPos[i][1]) {
  289. collision[j] = true;
  290. }
  291. }
  292. }
  293. return collision;
  294. }
  295. }