/* * public functions */ /// <summary> /// A*, modified to find a nearest path in case of failure /// </summary> /// <param name="map">The Map</param> /// <param name="startNode">The starting Node</param> /// <param name="endNode">The ending Node</param> /// <returns>The path as a list of waypoints</returns> public static List<Node> findPath(NodeMap map, Node startNode, Node endNode) { // initialize data PQueue open = new PQueue(); open.enqueue(startNode); List<Node> adjacentNodes = new List<Node>(); // good ol' A* while (open.Count > 0) { // find the open Node with the lowest Fscore and remove it from the open PQueue Node current = open.dequeue(); // if this is our destination Node, we're done; otherwise, close it so we don't travel to it again if (current == endNode) return reconstruct(endNode); current.close(); // find every valid Node adjacent to the current Node adjacentNodes = map.getAdjacentNodes(current); // iterate over all of them for (int i = 0; i < adjacentNodes.Count; i++) { // grab an adjacent Node and calculate a new GScore and HScore for it Node adjacent = adjacentNodes[i]; int tempGScore = current.Gscore + map.pathDistance(current, adjacent); int tempHScore = map.pathDistance(adjacent, endNode); // if we have not opened this Cell, give it new stats and open it if (!adjacent.isOpen) { setAdjacentStats(adjacent, current, tempGScore, tempHScore); open.enqueue(adjacent); } // otherwise, if we have opened it but the new path to it is shorter than the old one, give it new stats and reset its position in the open PQueue else if (tempGScore < adjacent.Gscore) { setAdjacentStats(adjacent, current, tempGScore, tempHScore); //open.resetPosition(adjacent); } } } // no valid path exists, so find the nearest path List<Node> closed = createClosed(map); Node nearestNode = closed[0]; // find the closed Node with the lowest Hscore (distance from the intended end); return a path to that Node if (closed.Count > 0) { for (int i = 1; i < closed.Count; i++) { if (closed[i].Hscore < nearestNode.Hscore) nearestNode = closed[i]; } } return reconstruct(nearestNode); }
/* * public functions */ /// <summary> /// A*, modified to find a nearest path in case of failure /// </summary> /// <param name="map">The Map</param> /// <param name="startCell">The starting Cell</param> /// <param name="endCell">The ending Cell</param> /// <returns>The path as a list of waypoints</returns> public static List<Cell> findPath(Map map, Cell startCell, Cell endCell) { /* * Terminology * Gscore cumulative calculated distance from the start Cell to the given Cell * Hscore estimated distance from the given Cell to the end Cell. * Overestimating this can result in the calculation of an incorrect (inefficient) path, * but the more it is underestimated, the longer correct path calculation will take * Fscore Gscore + Hscore; estimated total distance from start to end on a path through the given Cell. * Priority queues (PQueues) are ordered by ascending Fscore, so shortest estimated paths are examined first * open list A PQueue of Cells to be examined. Initially contains the start Cell * closed list A List<Cell> of Cells that have been examined * adjacent list A PQueue of Cells adjacent to the current Cell */ // initialize the lists PQueue open = new PQueue(); open.enqueue(startCell); List<Cell> closed = new List<Cell>(); PQueue adjacentCells = new PQueue(); iterations = 0; // good ol' A* while (open.count() > 0) // iterate until we have examined every appropriate Cell { //open.print("Open", true); Cell currentCell = open.dequeue(); // look at the Cell with the lowest Fscore and remove it from the open list if (currentCell == endCell) // if this is our destination Cell, we're done! return reconstruct(endCell); // so return the path closed.Add(currentCell); // otherwise, close this Cell so we don't travel to it again adjacentCells = getAdjacentCells(map, open, closed, currentCell); // now find every valid Cell adjacent to the current Cell //adjacentCells.print("Adjacent", false); while (adjacentCells.count() != 0) // iterate over all of them, from lowest to highest Fscore { Cell adjacentCell = adjacentCells.dequeue(); // grab the current adjacent Cell int tempGScore = currentCell.Gscore + pathDistance(currentCell, adjacentCell); // calculate a temporary Gscore as if we were traveling to this Cell from the current Cell if (!open.contains(adjacentCell) || tempGScore < adjacentCell.Gscore) // if this Cell has not been added to the open list, or if tempGscore is less than the Cell's current Gscore { int h = pathDistance(adjacentCell, endCell); // estimate the Cell's Hscore adjacentCell.prev = currentCell; // set the Cell's prev pointer to the current Cell adjacentCell.Hscore = h; // set the Cell's Hscore adjacentCell.Gscore = tempGScore; // set the Cell's Gscore adjacentCell.Fscore = tempGScore + h; // set the Cell's Fscore } if (!open.contains(adjacentCell)) // if the adjacent Cell we just examined is not yet on the open list, add it open.enqueue(adjacentCell); } iterations++; } // no valid path exists, so find the nearest path closed.RemoveAt(0); // remove the start Cell from the closed List if (closed.Count > 0) // if there are still Cells on the closed list { Cell nearestCell = closed[0]; // find the closed Cell with the lowest Hscore; for (int i = 1; i < closed.Count; i++) // this should be the Cell closest to the desired destination, { // so return a path ending with that Cell. if (closed[i].Hscore < nearestCell.Hscore) nearestCell = closed[i]; } return reconstruct(nearestCell); } else { List<Cell> path = new List<Cell>(); // otherwise, our only path was the start Cell (i.e. we are completely trapped); path.Add(endCell); // so return a path with just that Cell. return path; } }
/* * public functions */ /// <summary> /// A*, modified to find a nearest path in case of failure /// </summary> /// <param name="map">The Map</param> /// <param name="startNode">The starting Node</param> /// <param name="endNode">The ending Node</param> /// <returns>The path as a list of waypoints</returns> public static List <Node> findPath(NodeMap map, Node startNode, Node endNode) { // initialize data PQueue open = new PQueue(); open.enqueue(startNode); List <Node> adjacentNodes = new List <Node>(); // good ol' A* while (open.Count > 0) { // find the open Node with the lowest Fscore and remove it from the open PQueue Node current = open.dequeue(); // if this is our destination Node, we're done; otherwise, close it so we don't travel to it again if (current == endNode) { return(reconstruct(endNode)); } current.close(); // find every valid Node adjacent to the current Node adjacentNodes = map.getAdjacentNodes(current); // iterate over all of them for (int i = 0; i < adjacentNodes.Count; i++) { // grab an adjacent Node and calculate a new GScore and HScore for it Node adjacent = adjacentNodes[i]; int tempGScore = current.Gscore + map.pathDistance(current, adjacent); int tempHScore = map.pathDistance(adjacent, endNode); // if we have not opened this Cell, give it new stats and open it if (!adjacent.isOpen) { setAdjacentStats(adjacent, current, tempGScore, tempHScore); open.enqueue(adjacent); } // otherwise, if we have opened it but the new path to it is shorter than the old one, give it new stats and reset its position in the open PQueue else if (tempGScore < adjacent.Gscore) { setAdjacentStats(adjacent, current, tempGScore, tempHScore); //open.resetPosition(adjacent); } } } // no valid path exists, so find the nearest path List <Node> closed = createClosed(map); Node nearestNode = closed[0]; // find the closed Node with the lowest Hscore (distance from the intended end); return a path to that Node if (closed.Count > 0) { for (int i = 1; i < closed.Count; i++) { if (closed[i].Hscore < nearestNode.Hscore) { nearestNode = closed[i]; } } } return(reconstruct(nearestNode)); }
/* * public functions */ /// <summary> /// A*, modified to find a nearest path in case of failure /// </summary> /// <param name="map">The Map</param> /// <param name="startCell">The starting Cell</param> /// <param name="endCell">The ending Cell</param> /// <returns>The path as a list of waypoints</returns> public static List <Cell> findPath(Map map, Cell startCell, Cell endCell) { /* * Terminology * Gscore cumulative calculated distance from the start Cell to the given Cell * Hscore estimated distance from the given Cell to the end Cell. * Overestimating this can result in the calculation of an incorrect (inefficient) path, * but the more it is underestimated, the longer correct path calculation will take * Fscore Gscore + Hscore; estimated total distance from start to end on a path through the given Cell. * Priority queues (PQueues) are ordered by ascending Fscore, so shortest estimated paths are examined first * open list A PQueue of Cells to be examined. Initially contains the start Cell * closed list A List<Cell> of Cells that have been examined * adjacent list A PQueue of Cells adjacent to the current Cell */ // initialize the lists PQueue open = new PQueue(); open.enqueue(startCell); List <Cell> closed = new List <Cell>(); PQueue adjacentCells = new PQueue(); iterations = 0; // good ol' A* while (open.count() > 0) // iterate until we have examined every appropriate Cell { //open.print("Open", true); Cell currentCell = open.dequeue(); // look at the Cell with the lowest Fscore and remove it from the open list if (currentCell == endCell) // if this is our destination Cell, we're done! { return(reconstruct(endCell)); // so return the path } closed.Add(currentCell); // otherwise, close this Cell so we don't travel to it again adjacentCells = getAdjacentCells(map, open, closed, currentCell); // now find every valid Cell adjacent to the current Cell //adjacentCells.print("Adjacent", false); while (adjacentCells.count() != 0) // iterate over all of them, from lowest to highest Fscore { Cell adjacentCell = adjacentCells.dequeue(); // grab the current adjacent Cell int tempGScore = currentCell.Gscore + pathDistance(currentCell, adjacentCell); // calculate a temporary Gscore as if we were traveling to this Cell from the current Cell if (!open.contains(adjacentCell) || tempGScore < adjacentCell.Gscore) // if this Cell has not been added to the open list, or if tempGscore is less than the Cell's current Gscore { int h = pathDistance(adjacentCell, endCell); // estimate the Cell's Hscore adjacentCell.prev = currentCell; // set the Cell's prev pointer to the current Cell adjacentCell.Hscore = h; // set the Cell's Hscore adjacentCell.Gscore = tempGScore; // set the Cell's Gscore adjacentCell.Fscore = tempGScore + h; // set the Cell's Fscore } if (!open.contains(adjacentCell)) // if the adjacent Cell we just examined is not yet on the open list, add it { open.enqueue(adjacentCell); } } iterations++; } // no valid path exists, so find the nearest path closed.RemoveAt(0); // remove the start Cell from the closed List if (closed.Count > 0) // if there are still Cells on the closed list { Cell nearestCell = closed[0]; // find the closed Cell with the lowest Hscore; for (int i = 1; i < closed.Count; i++) // this should be the Cell closest to the desired destination, { // so return a path ending with that Cell. if (closed[i].Hscore < nearestCell.Hscore) { nearestCell = closed[i]; } } return(reconstruct(nearestCell)); } else { List <Cell> path = new List <Cell>(); // otherwise, our only path was the start Cell (i.e. we are completely trapped); path.Add(endCell); // so return a path with just that Cell. return(path); } }