/* * Get a path from start to end using A* algorithm */ public static Hex[] GetPath(Hex start, Hex end) { //discovered nodes HexPriorityQueue openSet = new HexPriorityQueue(); openSet.Add(start, Heuristic(start, end)); //cameFrom[h] is the hex preceding h in the final path Dictionary <Hex, Hex> cameFrom = new Dictionary <Hex, Hex>(); //g[h] = cost of best path from start to h so far -- default values should be infinity Dictionary <Hex, float> g = new Dictionary <Hex, float>(); g[start] = 0; Dictionary <Hex, float> f = new Dictionary <Hex, float>(); f[start] = Heuristic(start, end); HashSet <Hex> done = new HashSet <Hex>(); while (openSet.Count() > 0) { Hex currHex = openSet.Dequeue(); if (f[currHex] >= Mathf.Infinity) // no route is possible { return(ReconstructPath(null, null, Mathf.Infinity)); } else if (currHex == end) // found the best route { return(ReconstructPath(cameFrom, currHex, g[currHex])); } Hex[] neighbors = currHex.GetNeighbors(); foreach (Hex n in neighbors) { float tentative_gScore = g[currHex] + n.GetMovementCost(); if (!g.ContainsKey(n) || tentative_gScore < g[n]) { cameFrom[n] = currHex; g[n] = tentative_gScore; f[n] = g[n] + Heuristic(n, end); openSet.Add(n, f[n]); //may create copies of hexes with different f values } } } //didnt find a way to reach end return(null); }
public void GenerateMap(int x, int z, bool wrapping) { Random.State originalRandomState = Random.state; if (!useFixedSeed) { seed = Random.Range(0, int.MaxValue); seed ^= (int)System.DateTime.Now.Ticks; seed ^= (int)Time.unscaledTime; seed &= int.MaxValue; } Random.InitState(seed); cellCount = x * z; grid.CreateMap(x, z, wrapping); if (searchFrontier == null) { searchFrontier = new HexPriorityQueue(); } for (int i = 0; i < cellCount; i++) { grid.GetCell(i).WaterLevel = waterLevel; } CreateRegions(); CreateLand(); ErodeLand(); CreateClimate(); CreateRivers(); SetTerrainType(); CreateBorders(x, z); for (int i = 0; i < cellCount; i++) { grid.GetCell(i).SearchPhase = 0; } Random.state = originalRandomState; }
List <HexCell> GetVisibleCells(HexCell fromCell, int range) { List <HexCell> visibleCells = ListPool <HexCell> .Get(); searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexPriorityQueue(); } else { searchFrontier.Clear(); } range += fromCell.ViewElevation; fromCell.SearchPhase = searchFrontierPhase; fromCell.MovementCost = 0; searchFrontier.Enqueue(fromCell); HexCoordinates fromCoordinates = fromCell.coordinates; while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; visibleCells.Add(current); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase || !neighbor.Explorable ) { continue; } int distance = current.MovementCost + 1; if (distance + neighbor.ViewElevation > range || distance > fromCoordinates.DistanceTo(neighbor.coordinates) ) { continue; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.MovementCost = distance; neighbor.SearchHeuristic = 0; searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.MovementCost) { int oldPriority = neighbor.SearchPriority; neighbor.MovementCost = distance; searchFrontier.Change(neighbor, oldPriority); } } } return(visibleCells); }
//the main search method. returns whether or not a path has been found. bool Search(HexCell fromCell, HexCell toCell, Unit unit) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.MovementCost = 0; //in turns, but unadjusted to speed searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } int currentCellMovementCost = current.MovementCost - 1; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (!unit.IsValidDestination(neighbor)) { continue; } float movementCost = unit.GetMoveCost(current, neighbor, d); if (movementCost < 0) { continue; } //DEBUG movementCost = 1; //DEBUG int newNeighborMC = (int)(current.MovementCost + movementCost); if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.MovementCost = newNeighborMC; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (newNeighborMC < neighbor.MovementCost) { int oldPriority = neighbor.SearchPriority; neighbor.MovementCost = newNeighborMC; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }