//生成大陆 int RaiseTerrain(int chunkSize, int budget, MapRegion region) { searchFrontierPhase += 1; HexCell firstCell = GetRandomCell(region); firstCell.SearchPhase = searchFrontierPhase; firstCell.Distance = 0; firstCell.SearchHeuristic = 0; searchFrontier.Enqueue(firstCell); HexCoordinates center = firstCell.coordinates; int rise = Random.value < highRiseProbability ? 2 : 1; int size = 0; while (size < chunkSize && searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); int originalElevation = current.Elevation; int newElevation = originalElevation + rise; if (newElevation > elevationMaximum) { continue; } current.Elevation = newElevation; if ( originalElevation < waterLevel && newElevation >= waterLevel && --budget == 0 ) { break; } size += 1; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor && neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = neighbor.coordinates.DistanceTo(center); neighbor.SearchHeuristic = Random.value < jitterProbability ? 1 : 0;//随机化土地形状 searchFrontier.Enqueue(neighbor); } } } searchFrontier.Clear(); return(budget); }
public HashSet <HexCell> GetAvailableAttacks(HexCell fromCell, Int32 range) { var res = new HashSet <HexCell>(); var frontier = new HexCellPriorityQueue(); fromCell.Distance = 0; frontier.Enqueue(fromCell); while (frontier.Count > 0) { var current = frontier.Dequeue(); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor == fromCell) { continue; } if (neighbor.HasEnemyUnit(fromCell.Unit.Team) && fromCell.Coordinates.DistanceTo(neighbor.Coordinates) <= range && !res.Contains(neighbor)) { res.Add(neighbor); frontier.Enqueue(neighbor); } } } return(res); }
bool Search(HexCell fromCell, HexCell toCell, int speed) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } int currentTurn = current.Distance / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (neighbor.IsUnderwater) { continue; } int distance = current.Distance; neighbor.Distance = current.Distance + 1; if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
int RaiseTerrain(int chunkSize, int budget) { searchFrontierPhase += 1; HexCell firstCell = GetRandomCell(); firstCell.SearchPhase = searchFrontierPhase; firstCell.Distance = 0; firstCell.SearchHeuristic = 0; searchFrontier.Enqueue(firstCell); HexCoordinates center = firstCell.coordinates; int size = 0; while (size < chunkSize && searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.Elevation += 1; if (current.TerrainTypeIndex == 0) { current.TerrainTypeIndex = 1; if (--budget == 0) { break; } } size += 1; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; ++d) { HexCell neighbor = current.GetNeighbor(d); if (neighbor && neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = neighbor.coordinates.DistanceTo(center); neighbor.SearchHeuristic = Random.value < jitterProbability ? 1 : 0; searchFrontier.Enqueue(neighbor); } } } searchFrontier.Clear(); return(budget); }
void EvolveTerrainElevation(int chunkSize, MapRegion region, bool sinkTerrain) { searchFrontierPhase += 1; HexCell firstCell = GetRandomCell(region); firstCell.SearchPhase = searchFrontierPhase; firstCell.Distance = 0; firstCell.SearchHeuristic = 0; searchFrontier.Enqueue(firstCell); HexCoordinates center = firstCell.coordinates; int rise = Random.value < highRiseProbability ? highRiseElevation : 1; int sink = Random.value < highRiseProbability ? highSinkElevation : 1; int size = 0; while (size < chunkSize && searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); bool setNewElevation; int newElevation = 0; if (sinkTerrain) { int originalElevation = current.Elevation; newElevation = current.Elevation - sink; setNewElevation = (newElevation >= elevationMinimum); } else { int originalElevation = current.Elevation; newElevation = current.Elevation + rise; setNewElevation = (newElevation <= elevationMaximum); } if (setNewElevation) { current.Elevation = newElevation; size += 1; addFrontierNeighbors(current, center); } } searchFrontier.Clear(); }
private PathSearchResult Search(HexCell fromCell, HexCell toCell, Int32 speed, Int32 attackRange = 0) { if (!fromCell || !toCell) { return(new PathSearchResult()); } _searchFrontierPhase += 2; if (_searchFrontier == null) { _searchFrontier = new HexCellPriorityQueue(); } else { _searchFrontier.Clear(); } fromCell.SearchPhase = _searchFrontierPhase; fromCell.Distance = 0; _searchFrontier.Enqueue(fromCell); var canReach = true; var canAttack = false; while (_searchFrontier.Count > 0) { var current = _searchFrontier.Dequeue(); current.SearchPhase += 1; Int32 currentTurn = (current.Distance - 1) / speed; var absoluteTurn = current.AbsoluteDistance - 1; if (currentTurn > 0) { canReach = false; canAttack = current.AttackDistance <= attackRange && current.Unit && current.Unit.Team != fromCell.Unit.Team; } if (current == toCell) { return(new PathSearchResult(canReach, canAttack)); } for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > _searchFrontierPhase) { continue; } if (neighbor.TerrainType == HexTerrainTypes.Lake || (neighbor.Unit && neighbor.Unit.Team == fromCell.Unit.Team)) { continue; } Int32 moveCost = 0; if (current.HasRoad(d)) { moveCost = 1; } else { switch (neighbor.TerrainType) { case HexTerrainTypes.Flat: moveCost += 5; break; case HexTerrainTypes.Hill: moveCost += 10; break; case HexTerrainTypes.Forest: moveCost += 7; break; case HexTerrainTypes.Road: moveCost += 5; break; default: moveCost += 10; break; } } Int32 distance = (current.Distance - 1) + moveCost; Int32 absoluteDistance = (current.AbsoluteDistance - 1) + 1; Int32 attackDistance = 1; Int32 turn = distance / speed; var absoluteStep = absoluteDistance; if (absoluteStep > absoluteTurn) { absoluteDistance = absoluteStep + 1; if (!canReach) { attackDistance = current.AttackDistance + 1; } } if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < _searchFrontierPhase) { neighbor.SearchPhase = _searchFrontierPhase; neighbor.Distance = distance; neighbor.AbsoluteDistance = absoluteDistance; neighbor.AttackDistance = attackDistance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.Coordinates.DistanceTo(toCell.Coordinates); _searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { var oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.AttackDistance = attackDistance; neighbor.AbsoluteDistance = absoluteDistance; neighbor.PathFrom = current; _searchFrontier.Change(neighbor, oldPriority); } } } return(new PathSearchResult()); }
bool Search(HexCell_Script fromCell, HexCell_Script toCell, int speed) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } //WaitForSeconds delay = new WaitForSeconds(1 / 60f); fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { //yield return delay; HexCell_Script current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current.SearchPhase == 10000) { Debug.LogError("Could not find Path after 10000 searches!"); return(false); } if (current == toCell) { return(true); } int currentTurn = (current.Distance - 1) / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell_Script neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (neighbor.IsUnderwater || neighbor.Unit) { continue; } HexEdgeType edgeType = current.GetEdgeType(neighbor); if (edgeType == HexEdgeType.Cliff) { continue; } int moveCost; if (current.HasRoadThroughEdge(d)) { moveCost = 1; } else if (current.Walled != neighbor.Walled) { continue; } else { moveCost = edgeType == HexEdgeType.Flat ? 5 : 10; moveCost += neighbor.UrbanLevel + neighbor.FarmLevel + neighbor.PlantLevel; } int distance = current.Distance + moveCost; int turn = distance / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; //neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; //neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } //searchFrontier.Sort((x, y) => x.SearchPriority.CompareTo(y.SearchPriority)); } } return(false); }
bool Search(HexCell fromCell, HexCell toCell, int speed) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } int currentTurn = current.Distance / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (neighbor.IsUnderwater) { continue; } HexEdgeType edgeType = current.GetEdgeType(neighbor); if (edgeType == HexEdgeType.Cliff) { continue; } int moveCost; if (current.HasRoadThroughEdge(d)) { moveCost = 1; } else if (current.Walled != neighbor.Walled) { continue; } else { moveCost = edgeType == HexEdgeType.Flat ? 5 : 10; moveCost += neighbor.UrbanLevel + neighbor.FarmLevel + neighbor.PlantLevel; } int distance = current.Distance + moveCost; int turn = distance / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; //neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; //neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } int currentTurn = (current.Distance - 1) / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase ) { continue; } //if ( neighbor.IsUnderwater || neighbor.Unit ) { // continue; //} //HexEdgeType edgeType = current.GetEdgeType(neighbor); //if ( edgeType == HexEdgeType.Cliff ) { // continue; //} //int moveCost; //if ( current.HasRoadThroughEdge(d) ) { // moveCost = 1; //} //else if(current.Walled != neighbor.Walled ) { // continue; //} //else { // moveCost = ( edgeType == HexEdgeType.Flat ? 5 : 10 ); // moveCost += neighbor.UrbanLevel + neighbor.FarmLevel + neighbor.PlantLevel; //} if (!unit.IsValidDestination(neighbor)) { continue; } int moveCost = unit.GetMoveCost(current, neighbor, d); if (moveCost < 0) { continue; } int distance = current.Distance + moveCost; int turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
//Pathfinding search static bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.MovementCost = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } int currentTurn = (current.MovementCost - 1) / unit.defaultMovementPoints; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } //Hexes forbidden to move to if (!unit.CanEnter(neighbor)) { continue; } if (!neighbor.Traversable) { continue; } // int hexEnterCost = 0; //Special condition costs here hexEnterCost += neighbor.GetHexEnterMovementModifier(d, unit); //Default cost hexEnterCost += neighbor.IsOcean ? unit.oceanMovementCost : unit.landMovementCost; int combinedCost = current.MovementCost + hexEnterCost; int turn = (combinedCost - 1) / unit.defaultMovementPoints; if (turn > currentTurn) { combinedCost = turn * unit.defaultMovementPoints + hexEnterCost; } if (neighbor.SearchPhase < searchFrontierPhase) //Has not been set before { neighbor.SearchPhase = searchFrontierPhase; neighbor.MovementCost = combinedCost; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (combinedCost < neighbor.MovementCost) //Update cost { int oldPriority = neighbor.SearchPriority; neighbor.MovementCost = combinedCost; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
// Distance /*IEnumerator*/ bool Search(HexCell fromCell, HexCell toCell, int speed) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } //for (int count = 0; count < hexCells.Length; count++) //{ // hexCells[count].SetLabel(null); // hexCells[count].DisableOutline(); //} //fromCell.EnableOutline(Color.blue); // ----------------------------------- //toCell.EnableOutline(Color.red); // WaitForSeconds delay = new WaitForSeconds(1 / 360f); // List<HexCell> frontier = new List<HexCell>(); // ListPool<HexCell>.Add(frontier); // frontier.Add(fromCell); // frontier.RemoveAt(0); Cl fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { // yield return delay; HexCell current = searchFrontier.Dequeue(); if (current == toCell) { // current = current.PathFrom; //while(current != fromCell) //{ // int turn = current.Distance / speed; // current.SetLabel(turn.ToString()); // current.EnableOutline(Color.white); // current = current.PathFrom; //} //toCell.EnableOutline(Color.red); //break; return(true); } int currentTurn = (current.Distance - 1) / speed; for (HexDirection dir = HexDirection.TopRight; dir <= HexDirection.TopLeft; dir++) { HexCell neighbor = current.GetNeighbor(dir); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (neighbor.IsUnderwater || neighbor.Unit) { continue; } HexEdgeType edgeType = current.GetEdgeType(neighbor); if (edgeType == HexEdgeType.Cliff) { continue; } // int distance = current.Distance; int moveCost; if (current.HasRoadThroughEdge(dir)) { moveCost = 1; } else if (current.HasWallThroughEdge(dir)) { continue; } else { moveCost = (edgeType == HexEdgeType.Flat ? 2 : 4); // Non-Road // moveCost += // Objective } int distance = current.Distance + moveCost; int turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; // neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.hexCoordinates.DistanceTo(toCell.hexCoordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int pastPriority = neighbor.SearchPriority; neighbor.Distance = distance; // neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; searchFrontier.Change(neighbor, pastPriority); } } } return(false); }
public List <HexCell> SearchInRange(HexCell fromCell, int range, bool includeStart) { List <HexCell> retCells = ListPool <HexCell> .Get(); if (fromCell == null) { return(retCells); } if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } ClearSearch(); fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase = 1; retCells.Add(current); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > 0) { continue; } if (neighbor.IsUnderwater) { continue; } if (current.GetEdgeType(neighbor) == HexEdgeType.Cliff) { continue; } int distance = current.Distance + 1; if (distance > range) { continue; } if (neighbor.SearchPhase == 0) { neighbor.SearchPhase = 1; neighbor.Distance = distance; neighbor.SearchHeuristic = 0; searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; searchFrontier.Change(neighbor, oldPriority); } } } if (!includeStart) { retCells.Remove(fromCell); } return(retCells); }
/// <summary> /// Поиск пути /// </summary> /// <param name="fromCell"></param> /// <param name="toCell"></param> /// <returns></returns> bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; //выход из подпрограммы, если достигнута клетка, путь до которой нужно найти и подсветка пути if (current == toCell) { return(true); } //Сколько ходов требуется для достижения клетки(не той, которая выделена) int currentTurn = (current.Distance - 1) / speed; // Поиск в ширину 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; } int moveCost = unit.GetMoveCost(current, neighbor, d); if (moveCost < 0) { continue; } //расстояние до клетки назначения int distance = current.Distance + moveCost; //кол-во ходов до клетки назначения int turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
IEnumerator Search(HexCell fromCell, HexCell toCell) { if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } for (int i = 0; i < cells.Length; i++) { cells[i].Distance = int.MaxValue; cells[i].DisableHighlight(); } fromCell.EnableHighlight(Color.blue); toCell.EnableHighlight(Color.red); WaitForSeconds delay = new WaitForSeconds(1 / 60f); //List<HexCell> frontier = new List<HexCell>(); fromCell.Distance = 0; //frontier.Add(fromCell); searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { yield return(delay); HexCell current = searchFrontier.Dequeue(); //frontier.RemoveAt(0); if (current == toCell) { current = current.PathFrom; while (current != fromCell) { current.EnableHighlight(Color.white); current = current.PathFrom; } break; } for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor == null) // ANY TERRAIN MOVEMENT PENALTIES CAN BE ADDED HERE { continue; } int distance = current.Distance; distance += 1; if (neighbor.Distance == int.MaxValue) { neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); //frontier.Add(neighbor); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } //frontier.Sort((x, y) => x.SearchPriority.CompareTo(y.SearchPriority)); } } }
void Search(HexCell fromCell, HexCell toCell, HexUnit hexUnit, List <HexCell> results) { m_currentPathFrom = fromCell; m_currentPathTo = toCell; int speed = hexUnit.Speed; m_searchFrontierPhase = 2; ClearPath(); ResetSearchPhase(); for (int i = 0; i < m_cells.Count; i++) { m_cells[i].SetLabel(null); m_cells[i].DisableHighlight(); } WaitForSeconds delay = new WaitForSeconds(1 / 60f); fromCell.Distance = 0; fromCell.SearchPhase = m_searchFrontierPhase; m_searchQueue.Enqueue(fromCell); while (m_searchQueue.Count > 0) { //yield return delay;s HexCell current = m_searchQueue.Dequeue(); current.SearchPhase += 1; if (current == toCell) { BuildFinalPath(fromCell, toCell); if (results != null && m_finalPath.Count > 0) { results.AddRange(m_finalPath); } break; } int currentTurn = (current.Distance - 1) / speed; for (HexDirection dir = HexDirection.NE; dir <= HexDirection.NW; dir++) { HexCell neighbour = current.GetNeighbour(dir); if (neighbour == null || neighbour.SearchPhase > m_searchFrontierPhase) { continue; } if (!hexUnit.IsValidDestination(neighbour)) { continue; } int moveCost = hexUnit.GetMoveCost(current, neighbour, dir); if (moveCost < 0) { continue; } int distance = current.Distance; int newDistance = distance + moveCost; int turn = (newDistance - 1) / speed; if (turn > currentTurn) { newDistance = (turn * speed) + moveCost; } if (neighbour.SearchPhase < m_searchFrontierPhase) { neighbour.SearchPhase = m_searchFrontierPhase; neighbour.Distance = newDistance; SetPathCurrentNext(current, neighbour); neighbour.SearchHeuristic = neighbour.Coordinates.DistanceTo(toCell.Coordinates); m_searchQueue.Enqueue(neighbour); } else if (newDistance < neighbour.Distance) { neighbour.Distance = newDistance; SetPathCurrentNext(current, neighbour); m_searchQueue.Change(neighbour); } } } //for (int i = 0; i < m_cells.Count; i++) //{ // yield return delay; // m_cells[i].Distance = cell.Coordinates.DistanceTo(m_cells[i].Coordinates); //} }
bool Search(HexCell fromCell, HexCell toCell, int speed) { // Debug.Log(specificUIOption.WaterMoving + " In grid"); searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } int currentTurn = (current.Distance - 1) / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); // gameUI.gameObject.AddComponent<HexGameUI>(); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (!gameManager.WaterMoving) { if (neighbor.IsUnderwater || neighbor.Unit) { continue; } } HexEdgeType edgeType = current.GetEdgeType(neighbor); if (edgeType == HexEdgeType.Cliff) { continue; } int moveCost; if (current.HasRoadThroughEdge(d)) { moveCost = 1; } else if (current.Walled != neighbor.Walled) { continue; } else { moveCost = edgeType == HexEdgeType.Flat ? 1 : 2; moveCost += neighbor.UrbanLevel + neighbor.FarmLevel + neighbor.PlantLevel; } int distance = current.Distance + moveCost; int turn = (distance - 1) / speed; if (turn == 0) { // current.EnableValidation(Color.green); } if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
public List <ICell> FindPathOnMap(ICell fromCell, ICell toCell, IMap map) { if (_hexMapSettings == null) { _hexMapSettings = GameInstances.Instance.MapSettings; } List <ICell> path = new List <ICell>(); _searchFrontier.Clear(); for (int i = 0; i < map.Cells.Count; i++) { map.Cells[i].Distance = int.MaxValue; map.Cells[i].DisableHighlight(); map.Cells[i].UpdateLabel(string.Empty); } fromCell.EnableHighlight(_hexMapSettings.ColorSelectionFrom); toCell.EnableHighlight(_hexMapSettings.ColorSelectionTo); fromCell.Distance = 0; _searchFrontier.Enqueue(fromCell); while (_searchFrontier.Count > 0) { ICell current = _searchFrontier.Dequeue(); if (current == toCell) { current = current.PathFrom; path.Add(toCell); path.Add(toCell.PathFrom); while (current != fromCell) { current.EnableHighlight(_hexMapSettings.ColorPath); current = current.PathFrom; path.Add(current); } ; int i = 0; path.Reverse(); foreach (var item in path) { item.UpdateLabel(i++ + ""); } break; } for (HexDirection direction = HexDirection.NE; direction <= HexDirection.NW; direction++) { ICell neighbor = current.GetNeighbor(direction); if (neighbor == null) { continue; } if (!neighbor.IsWalkable) { continue; } int distance = current.Distance; if (current.HasRoadThroughEdge(direction)) { distance += 1; } else { distance += 10; } if (neighbor.Distance == int.MaxValue) { neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.Coordinates.DistanceTo(toCell.Coordinates); _searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; _searchFrontier.Change(neighbor, oldPriority); } } } return(map.Cells); }
bool Search(HexCell startCell, HexCell endCell) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } startCell.SearchPhase = searchFrontierPhase; startCell.Distance = 0; searchFrontier.Enqueue(startCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == endCell) { return(true); } //Add current cell's neighbors to queue for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (neighbor.elevation != ElevationLevel.Flat) { continue; } if (neighbor.IsSpecialFeature) { continue; } int distance = current.Distance; if (neighbor.TerrainTypeIndex >= 2) { distance += 6; } else if (neighbor.FeatureDensity >= 2) { distance += 6; } else { distance += 2; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(endCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
/// <summary> /// 搜索 /// </summary> /// <param name="fromCell">来的cell</param> /// <param name="toCell">要去的cell</param> /// <param name="unit">要移动的单位</param> /// <returns>是否可以寻路</returns> private /*IEnumerator*/ bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } /*foreach (var nowCell in cells) * { * if (nowCell != fromCell && nowCell != toCell) * { * nowCell.DisableHighlight(); * } * * nowCell.SetLabel(null); * }*/ fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { //yield return delay; var current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } var currentTurn = (current.Distance - 1) / speed; for (var d = HexDirection.NE; d <= HexDirection.NW; d++) { var neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (!unit.IsValidDestination(neighbor)) { continue; } int moveCost = unit.GetMoveCost(current, neighbor, d); if (moveCost < 0) { continue; } var distance = current.Distance + moveCost; var turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates .DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (neighbor.Distance > distance) { var oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } //coroutine = null; return(false); }
IEnumerator Search(HexCell fromCell, HexCell toCell) { if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } for (int i = 0; i < cells.Length; i++) { cells[i].Distance = int.MaxValue; cells[i].DisableHighlight(); } fromCell.EnableHighlight(Color.blue); toCell.EnableHighlight(Color.red); WaitForSeconds delay = new WaitForSeconds(1 / 60f); fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { yield return(delay); HexCell current = searchFrontier.Dequeue(); if (current == toCell) { current = current.PathFrom; while (current != fromCell) { current.EnableHighlight(Color.white); current = current.PathFrom; } break; } for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor == null) { continue; } if (neighbor.IsUnderwater) { continue; } HexEdgeType edgeType = current.GetEdgeType(neighbor); if (edgeType == HexEdgeType.Cliff) { continue; } int distance = current.Distance; if (current.HasRoadThroughEdge(d)) { distance += 1; } else if (current.Walled != neighbor.Walled) { continue; } else { distance += edgeType == HexEdgeType.Flat ? 5 : 10; distance += neighbor.UrbanLevel + neighbor.FarmLevel + neighbor.PlantLevel; } if (neighbor.Distance == int.MaxValue) { neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } }
List <HexCell> GetVisibleCells(HexCell fromCell, int range) { List <HexCell> visibleCells = ListPool <HexCell> .Get(); searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; visibleCells.Add(current); // if (current == toCell) { // return true; // } // int currentTurn = (current.Distance - 1) / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase ) { continue; } // … // int moveCost; // … int distance = current.Distance + 1; if (distance > range) { continue; } // int turn = (distance - 1) / speed; // if (turn > currentTurn) { // distance = turn * speed + moveCost; // } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; // neighbor.PathFrom = current; neighbor.SearchHeuristic = 0; searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; // neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(visibleCells); }
//A* search method private int FindDistanceTo(Coordinates sourceCell, Coordinates targetCell, List <Coordinates> path, Action <Coordinates> toDo, int maxDistance = Int32.MaxValue, bool wantToMove = true) { path?.Clear(); //_searchFrontierPhase += 2; foreach (var coord in _coords) { coord.distance = -1; coord.PathFrom = -1; //coord.QueueStatus = HexCellPriorityQueue.QueueStatus.PreQueue; coord.nextWithSamePriority = null; } if (_searchFrontier == null) { _searchFrontier = new HexCellPriorityQueue(); } else { _searchFrontier.Clear(); } if (sourceCell == null) { toDo?.Invoke(null); return(-1); //yield break; } //sourceCell.SearchPhase = _searchFrontierPhase; sourceCell.distance = 0; _searchFrontier.Enqueue(sourceCell); var foundTarget = false; var count = 0; while (_searchFrontier.Count > 0) { var current = _searchFrontier.Dequeue(); //current.SearchPhase += 1; for (var d = 0; d <= current.Neighbors; d++) { var neighbor = current.GetNeighbor(d); if (neighbor.index < 0 || neighbor.index >= _coords.Count) { continue; } var neighborCoord = _coords[neighbor.index]; if (neighborCoord == null || !neighborCoord.walkable || (wantToMove && neighborCoord.occupied) || neighborCoord.distance > -1) { continue; } neighborCoord.PathFrom = current.index; var distance = current.distance; var neighborDistance = neighborCoord.distance; if (neighborDistance == -1) { neighborCoord.distance = distance + 1; //neighborCoord.SearchPhase = _searchFrontierPhase; neighborCoord.SearchHeuristic = neighborCoord.FindDistanceTo(targetCell.coords); _searchFrontier.Enqueue(neighborCoord); } /*else if (distance < neighborDistance) * { * var oldPriority = neighborCoord.SearchPriority; * neighborCoord.distance = distance + 1; * _searchFrontier.Change(neighborCoord, oldPriority); * }*/ if (distance >= maxDistance) { _searchFrontier.Clear(); toDo?.Invoke(null); return(-1); //yield break; } if (neighborCoord == targetCell) { foundTarget = true; if (path != null) { path.Add(neighborCoord); current = neighborCoord; var count1 = 0; while (current.PathFrom > -1 && current.PathFrom != sourceCell.index) { if (count1 > 10000) { Debug.LogError("What the f**k"); break; } if (current.PathFrom > -1 && current.PathFrom < _coords.Count) { current = _coords[current.PathFrom]; path.Add(current); count1++; } } path.Reverse(); } break; } } if (foundTarget) { break; } /*if (count % 200 == 0) * { * yield return null; * }*/ count++; } if (targetCell.index < 0 || targetCell.index >= _coords.Count) { toDo?.Invoke(null); return(-1); //yield break; } toDo?.Invoke(targetCell); //yield return null; _searchFrontier.Clear(); return(targetCell.distance); }
bool Search(HexCell fromCell, HexCell toCell, int speed) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } int currentTurn = (current.Distance - 1) / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase ) { continue; } if (neighbor.IsUnderwater || neighbor.Unit) { continue; } if (neighbor.HasRiver && !neighbor.HasRoads) { continue; } HexEdgeType edgeType = current.GetEdgeType(neighbor); // modify by ztj // 移动力足够大的情况下悬崖也可以上去 //if (edgeType == HexEdgeType.Cliff) { // continue; //} float moveCost; if (current.HasRoadThroughEdge(d)) { moveCost = 1; } else if (current.Walled != neighbor.Walled) { continue; } else { //moveCost = edgeType == HexEdgeType.Flat ? 5 : 10; moveCost = MoveCost_Elevation[(int)edgeType]; moveCost += MoveCost_Terrain[current.TerrainTypeIndex]; //moveCost += neighbor.UrbanLevel + neighbor.FarmLevel + neighbor.PlantLevel; moveCost += MoveCost_Building[neighbor.UrbanLevel] + MoveCost_Building[neighbor.FarmLevel] + MoveCost_Building[neighbor.PlantLevel]; } int distance = current.Distance + (int)moveCost; int turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + (int)moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); // 遍历未访问的边界格子 while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; // +1,由待访问阶段,进入到已访问阶段 // 判断是否找到目标格子 if (current == toCell) { return(true); } int currentTurn = (current.Distance - 1) / speed; // 到达当前格子所需的回合数 // 把当前格子未访问的可达邻居全部加到待访问格子里 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; } int moveCost = unit.GetMoveCost(current, neighbor, d); // 当前格子到邻居的移动成本 if (moveCost < 0) { continue; } int distance = current.Distance + moveCost; int turn = (distance - 1) / speed; // 用刚得到的邻居距离,算出起点出到达邻居所需的回合数, -1是为了避免distance与speed相同时,得到turn为1,但其实本回合就能到达 // 判断该邻居是否在下一个回合才能到达 if (turn > currentTurn) { distance = turn * speed + moveCost; // 不直接使用上面distance的原因是,当前回合剩余行动点在下一回合会清零,所以到达该邻居实际上的移动成本更高 } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.Coordinates.DistanceTo(toCell.Coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } int currentTurn = (current.Distance - 1) / speed; 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; } int moveCost = unit.GetMoveCost(current, neighbor, d); if (moveCost < 0) { continue; } int distance = current.Distance + moveCost; int turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
List <HexCell> GetVisibleCells(HexCell fromCell, int range) { List <HexCell> visibleCells = ListPool <HexCell> .GLGet(); searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } // Units view range (Line of Sight) increase by altitude of cell they are in range += fromCell.ViewElevation; fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 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 ) { continue; } int distance = current.Distance + 1; if (distance + neighbor.ViewElevation > range || distance > fromCoordinates.DistanceTo(neighbor.Coordinates) || !neighbor.Explorable) { // Take neighbor view elevation into acount when comparing with range // Tall cells should block vision this way // Also ignore cells farther away than the shortest path to them // If we didnt do this then when high cells blocked vision we would sometimes // Be able to see around them, as if our vision could bend corners, because although // Higher cells blocked vision the searching algorithm still found a path to them // Also cells that cannot be explored should block vision continue; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.SearchHeuristic = 0; searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; searchFrontier.Change(neighbor, oldPriority); } } } return(visibleCells); }