private int GetHeuristic(HexTile node, HexTile end) { return(Math.Abs(node.GridIdx.X - end.GridIdx.X) + Math.Abs(node.GridIdx.Y - end.GridIdx.Y)); }
// pseudo: http://en.wikipedia.org/wiki/A*_search_algorithm /// <summary> /// Uses A-star algorithm. WORK IN PROGRESS! DOESNT WORK YET! /// reconstruct_path() needs work /// Also the BaseCost is not included now. But when I include it, it will also move backwards because those have a lower cost of course -.- /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <returns>The list of nodes or null if no route was found.</returns> public List <HexTile> GetRoute(HexTile start, HexTile end) { if (start == end) { return new List <HexTile>() { end } } ; List <HexTile> closedList = new List <HexTile>(); // The set of nodes already evaluated. List <HexTile> openList = new List <HexTile>() { start }; // The set of tentative nodes to be evaluated, initially containing the start node List <HexTile> cameFrom = new List <HexTile>(); // The map of navigated nodes. // F = G + H // Which square do we choose? The one with the lowest F cost. // G = the movement cost to move from the starting point A to a given square on the grid, following the path generated to get there. // H = the estimated movement cost to move from that given square on the grid to the final destination, point B. // This is often referred to as the heuristic, which can be a bit confusing. The reason why it is called that is // because it is a guess. We really don’t know the actual distance until we find the path, because all sorts of // things can be in the way (walls, water, etc.). start.AStar.G = 0; // G: Cost from start along best known path. start.AStar.H = GetHeuristic(start, end); // H: Heuristic. // F: Estimated total cost from start to goal through y. while (openList.Count > 0) { openList.Sort(new HexTileMoveCostComparer()); // Refactor note: this sorting every loop costs a lot of CPU. This can be optimized. HexTile currentNode = openList[0]; if (currentNode.GridIdx == end.GridIdx) // If true then we found the ending node { cameFrom.Add(end); // Add the desination itself also to the route. return(reconstruct_path(ref cameFrom, cameFrom.Last())); } openList.Remove(currentNode); closedList.Add(currentNode); List <HexTile> neighboars = currentNode.GetPassableneigboars(); foreach (HexTile neighboar in neighboars) { if (closedList.Contains(neighboar)) { continue; } int tentative_g_score = currentNode.AStar.G + neighboar.AStar.G; // tentative_g_score := g_score[x] + dist_between(x,y) bool tentativeIsBetter = false; if (!openList.Contains(neighboar)) { openList.Add(neighboar); tentativeIsBetter = true; } else if (tentative_g_score < neighboar.AStar.G) { tentativeIsBetter = true; } if (tentativeIsBetter) { cameFrom.Add(currentNode); neighboar.AStar.G = tentative_g_score; neighboar.AStar.H = GetHeuristic(neighboar, end); } } } return(null); // No possible route was found. }
/// <summary> /// The recursive procedure /// </summary> /// <param name="result"></param> /// <param name="pathwalked"></param> /// <param name="currentTile"></param> /// <param name="movespeedLeft"></param> private void FindMoveArea(ref List <HexTile> result, ref LinkedList <HexTile> pathwalked, HexTile currentTile, int movespeedLeft) { List <HexTile> neighboars = currentTile.GetPassableneigboars(); result.Add(currentTile); pathwalked.AddLast(currentTile); foreach (HexTile tile in neighboars) { if (movespeedLeft != 0 && !pathwalked.Contains(tile)) { int moveSpeedCost = (int)Math.Ceiling(tile.AStar.G / (float)100); if (movespeedLeft >= moveSpeedCost) { FindMoveArea(ref result, ref pathwalked, tile, movespeedLeft - moveSpeedCost); } } } pathwalked.RemoveLast(); // Remove itself from the list before returning. }