001    import java.io.*;
002    import java.lang.*;
003    import java.util.*;
004    
005    /**
006     *      An implementation of the A* algoritm. It is goal directed and only returns 
007     *      full paths.
008     */
009    public class AStar {
010            
011            /**
012             *      The main method. 
013             *      @param world Nodelist containing a world
014             *      @param nGoal The goal node
015             *      @param pStartInit the start node
016             *      @return A NodeList with Nodes forming the path
017             */
018            public static NodeList run(NodeList world, Node nGoal, Node nStartInit) {
019                    System.out.println("***In AStar");
020                    Node nStart = new Node();
021                    nStart = world.get(world.nodeExist(nStartInit.getX(), nStartInit.getY()));
022                    nStart.setH(getManhattanDist(nStart, nGoal));
023                    Node n = new Node();
024                    
025                    //System.out.println("Start: " + nStart);
026                    //System.out.println("Goal:  " + nGoal);
027                    
028                    NodeList openList = new NodeList();
029                    NodeList closedList = new NodeList();
030                    NodeList neighbourList = new NodeList();
031                    NodeList path = new NodeList(); 
032                    
033                    openList.add(nStart);
034    
035                    while(openList.isNotEmpty()){
036                            n = openList.popNodeWithLowestF();
037                            closedList.add(n);
038                            if(nGoal.isPointEqual(n)){
039                                    path.add(n);
040                                    fetchFamily(n, nStart, path);
041                                    break;
042                            }                       
043                            neighbourList = getNeighbours(world, n, nGoal);
044                            for(int i = 0; i < neighbourList.size();i++){
045                                    if(openList.beenThereDoneThat(neighbourList.get(i))){
046                                            continue;
047                                    }
048                                    if(closedList.beenThereDoneThat(neighbourList.get(i))){
049                                            continue;
050                                    }
051                                    openList.removeEqualPoints(neighbourList.get(i));
052                                    closedList.removeEqualPoints(neighbourList.get(i));
053                                    openList.add(neighbourList.get(i));
054                            }
055                    }
056                    //System.out.println("PATH: " + path);
057                    return path;
058            }
059            
060            /**
061             *      Recursive method that fetches all the nodes, starting 
062             *      with the goal and following the parents.
063             */
064            public static void fetchFamily(Node n, Node nStart, NodeList path){
065                    if(!n.isPointEqual(nStart)){
066                            path.add(n.getParent());
067                            fetchFamily(n.getParent(),nStart,path);
068                    }
069            }
070            
071            /**
072             *      Calculates the manhattan-distance between two nodes
073             */
074            public static int getManhattanDist(Node nA, Node nB) {  
075                    return (int)( Math.abs(nA.getX() - nB.getX()) + Math.abs(nA.getY() - nB.getY()) );
076            }
077            
078            /**
079             *      Makes a NodeList holding all the neighbour Nodes using 4-connectivity.
080             *      @param world Nodelist containing a world
081             *      @param nCurrent The currentnode
082             *      @param nGoal the goal node
083             */
084            public static NodeList getNeighbours(NodeList world, Node nCurrent, Node nGoal){
085                    NodeList neighbourList = new NodeList();
086                    Node[] anTemp = new Node[4];
087                    
088                    int iX = nCurrent.getX();
089                    int iY = nCurrent.getY();
090                    int iG = nCurrent.getG();
091                    
092                    anTemp[0] = new Node(iX,iY+1);
093                    anTemp[1] = new Node(iX,iY-1);
094                    anTemp[2] = new Node(iX+1,iY);
095                    anTemp[3] = new Node(iX-1,iY);
096    
097                    int location;
098                    for(int i = 0; i < 4; i++) {
099                            location = world.nodeExist(anTemp[i].getX(), anTemp[i].getY());
100                            if(location >= 0){
101                                    if (    ((anTemp[i].getY() > iY) && (nCurrent.getTop() == 0)) ||
102                                                    ((anTemp[i].getX() > iX) && (nCurrent.getRight() == 0)) ||
103                                                    ((anTemp[i].getY() < iY) && (nCurrent.getBottom() == 0)) ||
104                                                    ((anTemp[i].getX() < iX) && (nCurrent.getLeft() == 0))
105                                            ) {
106                                            Node temp = new Node();
107                                            temp = (Node)world.get(location);
108                                            anTemp[i].setG(iG+1);
109                                            anTemp[i].setH(getManhattanDist(anTemp[i], nGoal));
110                                            anTemp[i].setParent(nCurrent);
111                                            anTemp[i].setTop(temp.getTop());
112                                            anTemp[i].setRight(temp.getRight());
113                                            anTemp[i].setBottom(temp.getBottom());
114                                            anTemp[i].setLeft(temp.getLeft());
115                                            neighbourList.add(anTemp[i]);
116                                    }
117                            }
118                    }
119                    //System.out.println("Neighbour of " + nCurrent + ": " + neighbourList);
120                    return neighbourList;
121            }
122    }