public Path ComputeInternalPathFromTo(Tile _StartTile, Tile _EndTile) { List <PathLinkHeuristic> openList = new List <PathLinkHeuristic>(); HashSet <Tile> closeSet = new HashSet <Tile>(); openList.Add(new PathLinkHeuristic(_StartTile, Tile.GetManhattanDistance(_StartTile, _EndTile))); CustomComparer <PathLinkHeuristic> comparer = new CustomComparer <PathLinkHeuristic>(false); while (openList.Count > 0) { PathLinkHeuristic linkToExtend = openList.Last(); if (linkToExtend.Tile == _EndTile) { return(Path.CreatePath(linkToExtend)); } openList.RemoveAt(openList.Count - 1); Tile tileToExtend = linkToExtend.Tile; if (closeSet.Contains(tileToExtend)) { continue; } closeSet.Add(tileToExtend); for (int i = 0; i < tileToExtend.Neighbors.Count; i++) { Tile neighbor = tileToExtend.Neighbors[i]; if (!neighbor.IsAccessible || !IsTileInside(neighbor) || closeSet.Contains(neighbor)) { continue; } //PathLinkHeuristic extension = new PathLinkHeuristic(linkToExtend, neighbor, Tile.GetManhattanDistance(neighbor, _EndTile)); PathLinkHeuristic extension = linkToExtend.MakeExtensionWith(neighbor, Tile.GetManhattanDistance(neighbor, _EndTile)); int indexInsertion = openList.BinarySearch(extension, comparer); if (indexInsertion < 0) { indexInsertion = ~indexInsertion; } openList.Insert(indexInsertion, extension); } } return(null); }
/// <summary> /// Search a path with custom AStar algorithm /// (PathLink is use to explore the grid. this way, there's no duplicate of tile array when we extend open list) /// </summary> /// <param name="_Start">Tile to start from</param> /// <param name="_End">Tile to reach</param> /// <param name="_ChronoInfos">Struct with times value to evaluate performance</param> /// <param name="_MaxSeconds">Max time allowed to search a solution. If value is negative, no time limit applied</param> /// <returns>the shortest path from start tile to end tile if it exists, null otherwise</returns> public static Path AStar_LinkOpti(Tile _Start, Tile _End, out ChronoInfos _ChronoInfos, float _MaxSeconds) { StartChrono(); if (_Start == null || !_Start.IsAccessible || _End == null || !_End.IsAccessible) { _ChronoInfos = ChronoInfos.InfosNone; return(null); } List <PathLinkHeuristic> openList = new List <PathLinkHeuristic>(100) { new PathLinkHeuristic(_Start, Tile.GetManhattanDistance(_Start, _End)) }; HashSet <Tile> closeHashSet = new HashSet <Tile>(); CustomComparer <PathLinkHeuristic> customComparer = new CustomComparer <PathLinkHeuristic>(true); while (openList.Count > 0) { if (_MaxSeconds > 0 && chrono.Elapsed.TotalSeconds > _MaxSeconds) { _ChronoInfos = StopChrono(_Start, _End, false); return(null); } PathLinkHeuristic linkToExtend = openList.First(); if (linkToExtend.Tile == _End) { _ChronoInfos = StopChrono(_Start, _End, true); createSolutionChrono -= chrono.ElapsedMilliseconds; Path solution = Path.CreatePath(linkToExtend); createSolutionChrono += chrono.ElapsedMilliseconds; return(solution); } removeFromOpenChrono -= chrono.ElapsedMilliseconds; openList.RemoveAt(0); removeFromOpenChrono += chrono.ElapsedMilliseconds; if (closeHashSet.Contains(linkToExtend.Tile)) { continue; } closeHashSet.Add(linkToExtend.Tile); Tile tileToExtend = linkToExtend.Tile; foreachNeighborsChrono -= chrono.ElapsedMilliseconds; for (int i = 0; i < tileToExtend.Neighbors.Count; i++) { Tile neighbor = tileToExtend.Neighbors[i]; searchInCloseListChrono -= chrono.ElapsedMilliseconds; bool existInCloseList = closeHashSet.Contains(neighbor); searchInCloseListChrono += chrono.ElapsedMilliseconds; if (!neighbor.IsAccessible || existInCloseList) { continue; } extendPathChrono -= chrono.ElapsedMilliseconds; //PathLinkHeuristic extendedLink = new PathLinkHeuristic(linkToExtend, neighbor, Tile.GetManhattanDistance(neighbor, _End)); PathLinkHeuristic extendedLink = linkToExtend.MakeExtensionWith(neighbor, Tile.GetManhattanDistance(neighbor, _End)); extendPathChrono += chrono.ElapsedMilliseconds; searchInsertionChrono -= chrono.ElapsedMilliseconds; int indexInsertion = openList.BinarySearch(extendedLink, customComparer); if (indexInsertion < 0) { indexInsertion = ~indexInsertion; } searchInsertionChrono += chrono.ElapsedMilliseconds; insertToOpenListChrono -= chrono.ElapsedMilliseconds; openList.Insert(indexInsertion, extendedLink); insertToOpenListChrono += chrono.ElapsedMilliseconds; } foreachNeighborsChrono += chrono.ElapsedMilliseconds; } _ChronoInfos = StopChrono(_Start, _End, false); return(null); }