public List <Tile> FindReachableTiles(Unit unit, Tile center, int ap) { List <Tile> tiles = new List <Tile>(); Dictionary <Tile, FibonacciHeapNode <TileMeta> > tileMap = new Dictionary <Tile, FibonacciHeapNode <TileMeta> >(); FibonacciHeap <TileMeta> heap = new FibonacciHeap <TileMeta>(); tileMap.Add(center, heap.Push(new TileMeta(center, 0))); while (!heap.IsEmpty()) { TileMeta tileMeta = heap.Pop().Value; Tile tile = tileMeta.tile; tiles.Add(tile); int previousCost = tileMeta.value; foreach (Vector2Int gridPosition in GetAdjacentGridPositions(tile.x, tile.y)) { tile = GetTile(gridPosition); if (IsAccessible(unit, tile)) { int cost = previousCost + unit.Statistics.CalculateEffectiveFatigue(tile.Cost, FatigueType.Movement); if (tileMap.ContainsKey(tile)) { FibonacciHeapNode <TileMeta> node = tileMap[tile]; if (cost < node.Value.value) { heap.Decrement(node, new TileMeta(tile, cost)); } } else if (cost <= ap) { tileMap.Add(tile, heap.Push(new TileMeta(tile, cost))); } } } } return(tiles); }
public static Path <T> FindPath <T>(INavGrid <T> navGrid, T start, T destination, AccessibilityPredicate IsAccessible) where T : IEquatable <T> { Vector2Int startIndices = navGrid.GetGridPosition(start); Vector2Int destinationIndices = navGrid.GetGridPosition(destination); if (!IsAccessible(startIndices.x, startIndices.y) || !IsAccessible(destinationIndices.x, destinationIndices.y)) { return(null); } if (start.Equals(destination)) { return(new Path <T>(start)); } int length = navGrid.Length; int width = navGrid.Width; bool[,] closedList = new bool[length, width]; AStarTile <T>[,] tiles = new AStarTile <T> [length, width]; for (int x = 0; x < length; x++) { for (int y = 0; y < width; y++) { tiles[x, y].indices = new Vector2Int(x, y); tiles[x, y].previous = new Vector2Int(-1, -1); tiles[x, y].f = float.MaxValue; tiles[x, y].g = float.MaxValue; tiles[x, y].h = float.MaxValue; } } FibonacciHeap <AStarTile <T> > openList = new FibonacciHeap <AStarTile <T> >(); Dictionary <Vector2Int, FibonacciHeapNode <AStarTile <T> > > openListMap = new Dictionary <Vector2Int, FibonacciHeapNode <AStarTile <T> > >(); tiles[startIndices.x, startIndices.y].indices = startIndices; tiles[startIndices.x, startIndices.y].previous = startIndices; tiles[startIndices.x, startIndices.y].f = 0; tiles[startIndices.x, startIndices.y].g = 0; tiles[startIndices.x, startIndices.y].h = 0; openListMap.Add(startIndices, openList.Push(tiles[startIndices.x, startIndices.y])); while (!openList.IsEmpty()) { AStarTile <T> current = openList.Pop().Value; Vector2Int currentIndices = current.indices; int x = currentIndices.x; int y = currentIndices.y; closedList[x, y] = true; List <Vector2Int> adjacentGridPositions = navGrid.GetAdjacentGridPositions(x, y); for (int i = 0; i < adjacentGridPositions.Count; i++) { Vector2Int neighborIndices = adjacentGridPositions[i]; int xi = neighborIndices.x; int yi = neighborIndices.y; if (neighborIndices == destinationIndices) { tiles[xi, yi].previous = currentIndices; LinkedList <T> wayPoints = new LinkedList <T>(); while (neighborIndices != startIndices) { wayPoints.AddFirst(navGrid.GetTile(neighborIndices)); neighborIndices = tiles[neighborIndices.x, neighborIndices.y].previous; } return(new Path <T>(start, wayPoints)); } if (closedList[xi, yi] || !IsAccessible(xi, yi)) { continue; } float gNew = current.g + MathUtility.ManhattanDistance(xi, yi, x, y); float hNew = MathUtility.ManhattanDistance(xi, yi, destinationIndices.x, destinationIndices.y); float fNew = gNew + hNew; if (tiles[xi, yi].f < fNew) { continue; } tiles[xi, yi].previous = currentIndices; tiles[xi, yi].g = gNew; tiles[xi, yi].h = hNew; tiles[xi, yi].f = fNew; if (!openListMap.ContainsKey(neighborIndices)) { openListMap.Add(neighborIndices, openList.Push(tiles[xi, yi])); } else { openList.Decrement(openListMap[neighborIndices], tiles[xi, yi]); } } } return(null); }