/******************************************************************************* * Copyright (c) 2013 Philip Collin. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Philip Collin - initial API and implementation ******************************************************************************/ package com.lyeeedar.Roguelike3D.Game.Level; import java.util.ArrayList; import java.util.Random; public class AStarPathfind { Random ran = new Random(); AbstractTile[][] grid; int startx; int starty; int endx; int endy; int currentx; int currenty; Node[][] nodes; ArrayList<Node> openList = new ArrayList<Node>(); ArrayList<Node> closedList = new ArrayList<Node>(); public AStarPathfind(AbstractTile[][] grid, int startx, int starty, int endx, int endy) { this.grid = grid; this.startx = startx; this.starty = starty; this.currentx = startx; this.currenty = starty; this.endx = endx; this.endy = endy; nodes = new Node[grid.length][grid.length]; nodes[startx][starty] = new Node(startx, starty, 0, 0, 0); openList.add(nodes[startx][starty]); while(currentx != endx || currenty != endy) { path(); } fillArray(); } public int[][] getPath() { int length = nodes[endx][endy].distance+1; int[][] path = new int[length][2]; path[length-1][0] = endx; path[length-1][1] = endy; int cx = endx; int cy = endy; for (int i = length-1; i > 0; i--) { if (cx-1 > 0 && nodes[cx-1][cy] != null && nodes[cx-1][cy].distance <= i) { cx--; } else if (cx+1 < grid.length && nodes[cx+1][cy] != null && nodes[cx+1][cy].distance <= i) { cx++; } else if (cy-1 > 0 && nodes[cx][cy-1] != null && nodes[cx][cy-1].distance <= i) { cy--; } else if (cy+1 < grid.length && nodes[cx][cy+1] != null && nodes[cx][cy+1].distance <= i) { cy++; } path[i-1][0] = cx; path[i-1][1] = cy; } return path; } public void fillArray() { for (Node n : closedList) { nodes[n.x][n.y] = n; } } private void path() { Node current = findBestNode(); currentx = current.x; currenty = current.y; if (currentx-2 > 0) { int tempx = currentx-1; int tempy = currenty; int heuristic = Math.abs(tempx-endx)+Math.abs(tempy-endy); Node tempn = new Node(tempx, tempy, heuristic, current.distance+1, grid[tempx][tempy].influence); addNodeToOpenList(tempn); } if (currentx+1 < grid.length) { int tempx = currentx+1; int tempy = currenty; int heuristic = Math.abs(tempx-endx)+Math.abs(tempy-endy); Node tempn = new Node(tempx, tempy, heuristic, current.distance+1, grid[tempx][tempy].influence); addNodeToOpenList(tempn); } if (currenty-2 > 0) { int tempx = currentx; int tempy = currenty-1; int heuristic = Math.abs(tempx-endx)+Math.abs(tempy-endy); Node tempn = new Node(tempx, tempy, heuristic, current.distance+1, grid[tempx][tempy].influence); addNodeToOpenList(tempn); } if (currenty+1 < grid.length) { int tempx = currentx; int tempy = currenty+1; int heuristic = Math.abs(tempx-endx)+Math.abs(tempy-endy); Node tempn = new Node(tempx, tempy, heuristic, current.distance+1, grid[tempx][tempy].influence); addNodeToOpenList(tempn); } } public boolean isNodeInClosedList(Node n) { for (Node nn : closedList) { if (nn.x == n.x && nn.y == n.y) return true; } return false; } public void addNodeToOpenList(Node n) { if (isNodeInClosedList(n)) return; if (openList.size() == 0) { openList.add(n); return; } Node less = openList.get(0); for (int i = 0; i < openList.size(); i++) { if (n.cost < less.cost) { openList.add(i, n); return; } } openList.add(n); } public void removeNodeFromOpenList(Node n) { int i = 0; for (Node nn : openList) { if (nn.x == n.x && nn.y == n.y) { openList.remove(i); return; } i++; } } public Node findBestNode() { if (openList.size() == 0) { System.err.println("No nodes in list!"); for (Node n : closedList) { System.err.printf(" %d %d ", n.x, n.y); } System.err.printf(" \n "); } Node best = openList.get(0); openList.remove(0); closedList.add(best); return best; } class Node { int x; int y; int cost; int heuristic; int distance; int influence; public Node(int x, int y, int heuristic, int distance, int influence) { this.influence = influence; this.x = x; this.y = y; this.heuristic = heuristic; this.distance = distance; this.cost = (heuristic*2) + distance + influence; } } }