Exemplo n.º 1
0
    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);
    }
Exemplo n.º 2
0
    //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);
    }
Exemplo n.º 3
0
    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);
    }
Exemplo n.º 4
0
    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);
    }
Exemplo n.º 6
0
    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);
    }
Exemplo n.º 7
0
    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);
    }
Exemplo n.º 8
0
    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);
    }
Exemplo n.º 9
0
    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);
    }
Exemplo n.º 10
0
    // 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);
    }
Exemplo n.º 11
0
    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);
    }
Exemplo n.º 12
0
    /// <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);
    }
Exemplo n.º 13
0
    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));
            }
        }
    }
Exemplo n.º 14
0
    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);
        //}
    }
Exemplo n.º 15
0
    /// <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);
    }
Exemplo n.º 16
0
    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);
    }
Exemplo n.º 17
0
    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);
                }
            }
        }
    }
Exemplo n.º 18
0
    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);
    }
Exemplo n.º 19
0
    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);
    }
Exemplo n.º 20
0
    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);
    }