/// <summary>
    /// 上升地形
    /// </summary>
    /// <param name="chunkSize">要上升的块</param>
    /// <param name="budget">水的块数</param>
    /// <returns>还剩下多少水的块</returns>
    private 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; //已经上升的块

        //上升的块<要上升的块&&寻路队列里还有cell
        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;

            //如果改变的这块高度出水了,则陆地的块-1
            //如果陆地的块为0,则跳出上升块的while
            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);
    }
예제 #2
0
    public void LandChunkGen(int chunkSize, bool firstChunk)
    {
        searchFrontierPhase += 1;
        TileCell firstCell = firstChunk ? FindRandom(.75f) : GetWaterCellWithinChunk();

        firstCell.SearchPhase     = searchFrontierPhase;
        firstCell.Distance        = 0;
        firstCell.SearchHeuristic = 0;
        searchFrontier.Enqueue(firstCell);
        TileCoordinates center = firstCell.coordinates;
        int             size   = 0;

        while (size < chunkSize && searchFrontier.Count > 0)
        {
            TileCell current = searchFrontier.Dequeue();
            if (current.type == TerrainType.Ocean)
            {
                landCells.Add(current);
                current.type = TerrainType.Grassland;
                size        += 1;
                foreach (TileCell neighbor in current.neighbors)
                {
                    if (neighbor.SearchPhase < searchFrontierPhase)
                    {
                        neighbor.SearchPhase     = searchFrontierPhase;
                        neighbor.Distance        = (int)neighbor.coordinates.DistanceTo(center);
                        neighbor.SearchHeuristic =
                            Random.value < jitterProbability ? 1 : 0;
                        searchFrontier.Enqueue(neighbor);
                    }
                }
            }
        }
        searchFrontier.Clear();
    }
예제 #3
0
    int RaiseTerrain(int chunkSize, int budget, MapRegion region)
    {
        searchFrontierPhase += 1;
        HexCell firstCell = GetRandomCell(region);

        //todo 测试使用生成默认的英雄
        if (HexGameUI.Instrance.selectedUnit == null)
        {
            HexGameUI.Instrance.selectedUnit = CreateHero(firstCell);
        }

        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);
    }
    /// <summary>
    /// Поднять уровень поверхности в регионе
    /// </summary>
    /// <param name="chunkSize"></param>
    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;
    }
예제 #5
0
    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)               // Avoid already too high areas
            {
                continue;
            }

            current.Elevation = newElevation;

            // If this cell just became land
            if (originalElevation < WaterLevel && newElevation >= WaterLevel && --budget == 0)
            {
                break;                 // If land budget over then bail
            }

            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);
                    // Randomly increase the cost estimation to jitter the terrain chunk
                    neighbor.SearchHeuristic = Random.value < JitterProbability ? 1: 0;
                    searchFrontier.Enqueue(neighbor);
                }
            }
        }
        searchFrontier.Clear();

        return(budget);
    }
예제 #6
0
    public int RaiseTerrain(int chunkSize, int budget, MapRegion mapRegion)
    {
        HexGrid.ResetSearchPhase();
        int     searchPhase = 1;
        HexCell firstCell   = GetRandomCell(mapRegion);

        firstCell.SearchPhase     = searchPhase;
        firstCell.Distance        = 0;
        firstCell.SearchHeuristic = 0;

        m_hexCellPriorityQueue.Clear();
        m_hexCellPriorityQueue.Enqueue(firstCell);

        HexCoordinates center = firstCell.Coordinates;

        int rise = Random.value < HighRiseProbability ? 2 : 1;

        int size = 0;

        while (size < chunkSize && m_hexCellPriorityQueue.Count > 0)
        {
            HexCell current           = m_hexCellPriorityQueue.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++;

            for (HexDirection dir = HexDirection.NE; dir <= HexDirection.NW; dir++)
            {
                HexCell neighbour = current.GetNeighbour(dir);
                if (neighbour != null && neighbour.SearchPhase < searchPhase)
                {
                    neighbour.SearchPhase     = searchPhase;
                    neighbour.Distance        = neighbour.Coordinates.DistanceTo(center);
                    neighbour.SearchHeuristic = Random.value < JitterProbability ? 1 : 0;
                    m_hexCellPriorityQueue.Enqueue(neighbour);
                }
            }
        }
        return(budget);
    }
예제 #7
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);
    }
예제 #8
0
 public void ClearPath()
 {
     m_searchQueue.Clear();
     foreach (HexCell hexCell in m_finalPath)
     {
         hexCell.SetLabel(null);
         hexCell.DisableHighlight();
     }
     m_finalPath.Clear();
     m_finalPathDictionary.Clear();
 }
예제 #9
0
    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);
    }
예제 #10
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());
    }
예제 #11
0
    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);
    }
예제 #12
0
파일: HexGrid.cs 프로젝트: JackeyZ/HexMap
    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);
    }
예제 #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));
            }
        }
    }
예제 #14
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);
    }
예제 #15
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);
    }
예제 #16
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);
    }
예제 #17
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);
    }
예제 #18
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);
    }
예제 #19
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);
    }
예제 #20
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);
    }
예제 #21
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);
    }
예제 #22
0
파일: HexGrid.cs 프로젝트: Mgel/RacingRogue
    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);
    }
예제 #23
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);
    }
예제 #24
0
    public void CreateHole()
    {
        Stack <HexCell> nextFrontier = new Stack <HexCell>();
        Stack <HexCell> holeFrontier = new Stack <HexCell>();

        for (int i = 0; i < cellCount; i++)
        {
            HexCell initCurrent = grid.GetCell(i);
            initCurrent.Elevation   = 0;
            initCurrent.SearchPhase = 0;
        }
        int     holeCellSize = Mathf.RoundToInt(grid.cellCountX * grid.cellCountZ * 0.5f);
        HexCell centerCell;

        if (grid.cellCountZ % 2 == 0)
        {
            centerCell = grid.GetCell(Mathf.RoundToInt((grid.cellCountX * grid.cellCountZ * 0.5f) + (grid.cellCountX * 0.5f)));
        }
        else
        {
            centerCell = grid.GetCell(Mathf.RoundToInt((grid.cellCountX * grid.cellCountZ * 0.5f)));
        }

        holeFrontier.Push(centerCell);
        while (holeFrontier.Count < holeCellSize && holeFrontier.Count < maxHoleCellSize && holeFrontier.Count > 0)
        {
            while (holeFrontier.Count > 0)
            {
                HexCell current = holeFrontier.Pop();
                if (current)
                {
                    bool setNewElevation;
                    int  newElevation = 0;
                    newElevation    = current.Elevation - 3;
                    setNewElevation = (newElevation >= elevationHole);
                    if (setNewElevation)
                    {
                        current.Elevation = newElevation;
                        for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
                        {
                            HexCell neighbor = current.GetNeighbor(d);
                            if (neighbor && neighbor.SearchPhase == 0)
                            {
                                neighbor.SearchPhase = 1;
                                nextFrontier.Push(neighbor);
                            }
                        }
                    }
                }
                else
                {
                    Debug.Log("current not found");
                }
            }
            while (nextFrontier.Count > 0)
            {
                HexCell current = nextFrontier.Pop();
                current.SearchPhase = 0;
                holeFrontier.Push(current);
            }
        }
        nextFrontier.Clear();
        searchFrontier.Clear();
    }
예제 #25
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);
    }
예제 #26
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);
                }
            }
        }
    }
예제 #27
0
파일: HexGrid.cs 프로젝트: guccang/HexMap
    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);
    }
예제 #28
0
    //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, 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);
    }