Advertisement
Guest User

Untitled

a guest
Dec 30th, 2015
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.41 KB | None | 0 0
  1. package rpc.entities.pathfinder;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.PriorityQueue;
  5.  
  6. import org.newdawn.slick.Graphics;
  7. import org.newdawn.slick.SlickException;
  8.  
  9. import rpc.entities.EntityBase;
  10. import rpc.map.MapModule;
  11. import rpc.objects.ObjectBase;
  12. import rpc.objects.ObjectModule;
  13. import rpc.resources.ResourceModule;
  14. import rpc.resources.ResourceModule.ResourceType;
  15. import rpc.states.StateBase;
  16. import rpc.utilities.OrderedPair;
  17. import rpc.utilities.Utilities;
  18.  
  19. public class PathFinder {
  20. private MapModule map = StateBase.getMapModule();;
  21. private ResourceModule resource = StateBase.getResourceModule();
  22. private ObjectModule object = StateBase.getObjectModule();
  23.  
  24. private PriorityQueue<PathNode> openPathNodes = new PriorityQueue<PathNode>();
  25. private PriorityQueue<SearchNode> openSearchNodes = new PriorityQueue<SearchNode>();
  26. private PathNode basePathNode;
  27. private SearchNode baseSearchNode;
  28. private int mapWidth, mapHeight;
  29.  
  30. private PathNode[][] pathNodes;
  31. private SearchNode[][] searchNodes;
  32.  
  33. //For faster reading of entitylists, to find targets
  34. byte[][] entityMap;
  35.  
  36. public PathFinder() throws SlickException{
  37. mapWidth = map.getMapWidth();
  38. mapHeight = map.getMapHeight();
  39.  
  40. entityMap = new byte[mapWidth][mapHeight];
  41.  
  42. pathNodes = new PathNode[mapWidth][mapHeight];
  43. searchNodes = new SearchNode[mapWidth][mapHeight];
  44. for (int x = 0; x < pathNodes.length; x++){
  45. for (int y = 0; y < pathNodes[x].length; y++){
  46. pathNodes[x][y] = new PathNode();
  47. searchNodes[x][y] = new SearchNode();
  48. }
  49. }
  50. }
  51.  
  52. public ArrayList<OrderedPair> findPath(int startX, int startY, int goalX, int goalY, boolean allowBlocked) {
  53. if ((goalX < 0) || (goalX > map.getMapWidth()-1) || (goalY < 0) || (goalY > map.getMapHeight()-1))
  54. return null;
  55.  
  56. //We are already here, so just return the coordinates at your feet.
  57. if ((startX == goalX) && (startY == goalY)){
  58. ArrayList<OrderedPair> returnedPath = new ArrayList<OrderedPair>();
  59. returnedPath.add(OrderedPair.getOrderedPair(goalX, goalY));
  60. return returnedPath;
  61. }
  62.  
  63. boolean running = true;
  64. boolean searchBlocked = false;
  65.  
  66. int pathVariance = Utilities.randomInt(10)+1;
  67.  
  68. while (running){
  69. for (int x = 0; x < pathNodes.length; x++){
  70. for (int y = 0; y < pathNodes[x].length; y++){
  71. pathNodes[x][y].flagResettable();
  72. //pathNodes[x][y].resetNode(x, y, goalX, goalY, pathVariance);
  73. }
  74. }
  75.  
  76. openPathNodes.clear();
  77. basePathNode = pathNodes[startX][startY];
  78. openPathNodes.add(pathNodes[startX][startY]);
  79.  
  80. pathNodes[startX][startY].openNode();
  81. pathNodes[startX][startY].resetNode(startX, startY, goalX, goalY, pathVariance);
  82.  
  83. boolean foundPath = false;
  84.  
  85. while (!foundPath){
  86. //baseNode = openNodes.get(openNodes.size()-1);
  87. basePathNode = openPathNodes.poll();
  88.  
  89. //Check the values around the next ordered pair.
  90. int thisX = basePathNode.getX();
  91. int thisY = basePathNode.getY();
  92.  
  93. for (int x = -1; x < 2; x++) {
  94. y:
  95. for (int y = -1; y < 2; y++) {
  96. if ((x == 0) && (y == 0))
  97. continue;
  98.  
  99. int checkX = thisX+x;
  100. int checkY = thisY+y;
  101. if ((checkX > map.getMapWidth()-2) || (checkX < 2) || (checkY > map.getMapHeight()-2) || (checkY < 2))
  102. continue;
  103.  
  104. //If the node needs to be reset, reset it!
  105. if (pathNodes[checkX][checkY].isResettable())
  106. pathNodes[checkX][checkY].resetNode(checkX, checkY, goalX, goalY, pathVariance);
  107.  
  108. // If it's not on the closed list, add it to the checkList to look at later.
  109. if (pathNodes[checkX][checkY].isClosed())
  110. continue;
  111.  
  112. //If you're not allowed to pass blocked tiles, don't!
  113. if (map.getBlockMap()[checkX][checkY] > 0){
  114. if (searchBlocked){
  115. for (int l = 0; l < map.getMapLayers(); l++) {
  116. int tileID = map.getTileId(checkX, checkY, l);
  117. if (map.getMapTileLoader().isTileInvulnerable(tileID)){
  118. continue y;
  119. }
  120. }
  121. }else{
  122. continue y;
  123. }
  124. }
  125.  
  126. //TODO: This works for now, although there are situations where when the second pass to dig a path triggers,
  127. //it may cause a logical shortest path to be ignored.
  128. //Check the diagonal movement to see if it's valid.
  129. if ((checkX > thisX) && (checkY > thisY)
  130. && (map.getBlockMap()[checkX-1][checkY] > 0 || map.getBlockMap()[checkX][checkY-1] > 0)){
  131. continue;
  132. }else if ((checkX < thisX) && (checkY < thisY)
  133. && (map.getBlockMap()[checkX+1][checkY] > 0 || map.getBlockMap()[checkX][checkY+1] > 0)){
  134. continue;
  135. }else if ((checkX > thisX) && (checkY < thisY)
  136. && (map.getBlockMap()[checkX-1][checkY] > 0 || map.getBlockMap()[checkX][checkY+1] > 0)){
  137. continue;
  138. }else if ((checkX < thisX) && (checkY > thisY)
  139. && (map.getBlockMap()[checkX+1][checkY] > 0 || map.getBlockMap()[checkX][checkY-1] > 0)){
  140. continue;
  141. }
  142.  
  143. PathNode checkNode = pathNodes[checkX][checkY];
  144. //Calculate movement costs for this tile.
  145. //Remember terrain movement costs should also be increased on diagonals from their base, not just added.
  146. int movementCost = 0;
  147. int nodeMValue = checkNode.getM();
  148. if (((checkX > thisX) && (checkY > thisY))
  149. || ((checkX < thisX) && (checkY < thisY))
  150. || ((checkX > thisX) && (checkY < thisY))
  151. || ((checkX < thisX) && (checkY > thisY))){
  152. movementCost = (int)(10+nodeMValue+((10+nodeMValue)*0.4));
  153. }else{
  154. movementCost = 10+nodeMValue;
  155. }
  156.  
  157. // We are already on the open list.
  158. if (checkNode.isOpen()){
  159. int gValueCheck = basePathNode.getG()+movementCost;
  160. if (gValueCheck < checkNode.getG())
  161. checkNode.setParent(basePathNode);
  162. }else{
  163. //Open tile.
  164. checkNode.openNode();
  165.  
  166. //Assign parent to this tile, should be the original we're fetching
  167. checkNode.setParent(basePathNode);
  168.  
  169. //Calc gCost (NOTE: Incomplete. Is this where terrain would come in?)
  170. checkNode.setG(basePathNode.getG()+movementCost);
  171.  
  172. //Calc fCost
  173. checkNode.calcF();
  174.  
  175. openPathNodes.add(checkNode);
  176.  
  177. //Break if you find the goal.
  178. if ((checkX == goalX) && (checkY == goalY))
  179. return buildPath(checkNode);
  180. }
  181. }
  182. }
  183. //Close the node.
  184. basePathNode.closeNode();
  185.  
  186. //I've searched everywhere I could, and I've ran out of nodes.
  187. if (openPathNodes.size() <= 0)
  188. break;
  189. }
  190. if (allowBlocked && !searchBlocked){
  191. searchBlocked = true;
  192. }else{
  193. running = false;
  194. }
  195. }
  196. return null;
  197. }
  198.  
  199. /**
  200. * Get a list of valid coordinates that are within the movement cost of the starting position.
  201. *
  202. * @param startX - The X coordinate we will start on.
  203. * @param startY - The Y coordinate we will start on.
  204. * @param range - The maximum range in tiles. Note, that the value inputed will be multiplied by 10 internally
  205. * for proper movement cost calculations.
  206. * @param allowBlocked - If we are allowed to search through blocked tiles.
  207. *
  208. * @return The movement cost map to reach all the tiles in range.
  209. */
  210. public ArrayList<OrderedPair> getCoordinatesInRange(int startX, int startY, int range, boolean allowBlocked) {
  211. //Only reset nodes and maps in range, why bother with the rest?
  212. for (int x = startX-range; x < startX+range; x++){
  213. for (int y = startY-range; y < startY+range; y++){
  214. if ((x > 250) || (x < 2) || (y > 250) || (y < 2))
  215. continue;
  216. searchNodes[x][y].flagResettable();
  217. }
  218. }
  219.  
  220. int movementCostMax = range*10;
  221.  
  222. ArrayList<OrderedPair> list = new ArrayList<OrderedPair>();
  223.  
  224. openSearchNodes.clear();
  225. baseSearchNode = searchNodes[startX][startY];
  226. openSearchNodes.add(searchNodes[startX][startY]);
  227.  
  228. searchNodes[startX][startY].openNode();
  229. searchNodes[startX][startY].resetNode(startX, startY);
  230.  
  231. boolean foundPath = false;
  232.  
  233. while (!foundPath){
  234. //baseNode = openNodes.get(openNodes.size()-1);
  235. baseSearchNode = openSearchNodes.poll();
  236.  
  237. //Check the values around the next ordered pair.
  238. int thisX = baseSearchNode.getX();
  239. int thisY = baseSearchNode.getY();
  240.  
  241. for (int x = -1; x < 2; x++) {
  242. for (int y = -1; y < 2; y++) {
  243. if ((x == 0) && (y == 0))
  244. continue;
  245.  
  246. int checkX = thisX+x;
  247. int checkY = thisY+y;
  248. if ((checkX > map.getMapWidth()-2) || (checkX < 2) || (checkY > map.getMapHeight()-2) || (checkY < 2))
  249. continue;
  250.  
  251. //If the node needs to be reset, reset it!
  252. if (searchNodes[checkX][checkY].isResettable())
  253. searchNodes[checkX][checkY].resetNode(checkX, checkY);
  254.  
  255. // If it's not on the closed list, add it to the checkList to look at later.
  256. if (searchNodes[checkX][checkY].isClosed())
  257. continue;
  258.  
  259. SearchNode checkNode = searchNodes[checkX][checkY];
  260. //Calculate movement costs for this tile.
  261. //Remember terrain movement costs should also be increased on diagonals from their base, not just added.
  262. int movementCost = 0;
  263. int nodeMValue = checkNode.getM();
  264. if (((checkX > thisX) && (checkY > thisY))
  265. || ((checkX < thisX) && (checkY < thisY))
  266. || ((checkX > thisX) && (checkY < thisY))
  267. || ((checkX < thisX) && (checkY > thisY))){
  268. movementCost = (int)(10+nodeMValue+((10+nodeMValue)*0.4));
  269. }else{
  270. movementCost = 10+nodeMValue;
  271. }
  272.  
  273. // We are already on the open list.
  274. if (checkNode.isOpen()){
  275. int gValueCheck = baseSearchNode.getG()+movementCost;
  276. if (gValueCheck < checkNode.getG())
  277. checkNode.setParent(baseSearchNode);
  278. }else{
  279. //Open tile.
  280. checkNode.openNode();
  281.  
  282. //Assign parent to this tile, should be the original we're fetching
  283. checkNode.setParent(baseSearchNode);
  284.  
  285. //Calc gCost and add it to the nodelist if it's below range.
  286. if (baseSearchNode.getG()+movementCost <= movementCostMax){
  287. checkNode.setG(baseSearchNode.getG()+movementCost);
  288. openSearchNodes.add(checkNode);
  289. list.add(OrderedPair.getOrderedPair(checkX, checkY));
  290. }
  291. }
  292. }
  293. }
  294. //Close the node.
  295. baseSearchNode.closeNode();
  296.  
  297. //I've searched everywhere I could, and I've ran out of nodes.
  298. if (openSearchNodes.size() <= 0)
  299. break;
  300. }
  301.  
  302. return list;
  303. }
  304.  
  305. public ArrayList<OrderedPair> buildPath(PathNode node) {
  306. ArrayList<OrderedPair> returnedPath = new ArrayList<OrderedPair>();
  307. PathNode nextNode = node;
  308. OrderedPair nextPair = OrderedPair.getOrderedPair(node.getX(), node.getY());
  309. returnedPath.add(nextPair);
  310.  
  311. while (nextNode.getParent() != null){
  312. nextNode = nextNode.getParent();
  313. nextPair = OrderedPair.getOrderedPair(nextNode.getX(), nextNode.getY());
  314. returnedPath.add(nextPair);
  315. }
  316. return returnedPath;
  317. }
  318.  
  319. public ArrayList<OrderedPair> buildPath(SearchNode node) {
  320. ArrayList<OrderedPair> returnedPath = new ArrayList<OrderedPair>();
  321. SearchNode nextNode = node;
  322. OrderedPair nextPair = OrderedPair.getOrderedPair(node.getX(), node.getY());
  323. returnedPath.add(nextPair);
  324.  
  325. while (nextNode.getParent() != null){
  326. nextNode = nextNode.getParent();
  327. nextPair = OrderedPair.getOrderedPair(nextNode.getX(), nextNode.getY());
  328. returnedPath.add(nextPair);
  329. }
  330. return returnedPath;
  331. }
  332. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement