/*
     * Get a path from start to end using A* algorithm
     */
    public static Hex[] GetPath(Hex start, Hex end)
    {
        //discovered nodes
        HexPriorityQueue openSet = new HexPriorityQueue();

        openSet.Add(start, Heuristic(start, end));

        //cameFrom[h] is the hex preceding h in the final path
        Dictionary <Hex, Hex> cameFrom = new Dictionary <Hex, Hex>();

        //g[h] = cost of best path from start to h so far -- default values should be infinity
        Dictionary <Hex, float> g = new Dictionary <Hex, float>();

        g[start] = 0;

        Dictionary <Hex, float> f = new Dictionary <Hex, float>();

        f[start] = Heuristic(start, end);

        HashSet <Hex> done = new HashSet <Hex>();

        while (openSet.Count() > 0)
        {
            Hex currHex = openSet.Dequeue();

            if (f[currHex] >= Mathf.Infinity)  // no route is possible
            {
                return(ReconstructPath(null, null, Mathf.Infinity));
            }
            else if (currHex == end)     // found the best route
            {
                return(ReconstructPath(cameFrom, currHex, g[currHex]));
            }

            Hex[] neighbors = currHex.GetNeighbors();
            foreach (Hex n in neighbors)
            {
                float tentative_gScore = g[currHex] + n.GetMovementCost();
                if (!g.ContainsKey(n) || tentative_gScore < g[n])
                {
                    cameFrom[n] = currHex;
                    g[n]        = tentative_gScore;
                    f[n]        = g[n] + Heuristic(n, end);
                    openSet.Add(n, f[n]); //may create copies of hexes with different f values
                }
            }
        }

        //didnt find a way to reach end
        return(null);
    }
예제 #2
0
    public void GenerateMap(int x, int z, bool wrapping)
    {
        Random.State originalRandomState = Random.state;
        if (!useFixedSeed)
        {
            seed  = Random.Range(0, int.MaxValue);
            seed ^= (int)System.DateTime.Now.Ticks;
            seed ^= (int)Time.unscaledTime;
            seed &= int.MaxValue;
        }
        Random.InitState(seed);

        cellCount = x * z;
        grid.CreateMap(x, z, wrapping);
        if (searchFrontier == null)
        {
            searchFrontier = new HexPriorityQueue();
        }
        for (int i = 0; i < cellCount; i++)
        {
            grid.GetCell(i).WaterLevel = waterLevel;
        }
        CreateRegions();
        CreateLand();
        ErodeLand();
        CreateClimate();
        CreateRivers();
        SetTerrainType();
        CreateBorders(x, z);

        for (int i = 0; i < cellCount; i++)
        {
            grid.GetCell(i).SearchPhase = 0;
        }

        Random.state = originalRandomState;
    }
예제 #3
0
    List <HexCell> GetVisibleCells(HexCell fromCell, int range)
    {
        List <HexCell> visibleCells = ListPool <HexCell> .Get();

        searchFrontierPhase += 2;
        if (searchFrontier == null)
        {
            searchFrontier = new HexPriorityQueue();
        }
        else
        {
            searchFrontier.Clear();
        }

        range += fromCell.ViewElevation;
        fromCell.SearchPhase  = searchFrontierPhase;
        fromCell.MovementCost = 0;
        searchFrontier.Enqueue(fromCell);
        HexCoordinates fromCoordinates = fromCell.coordinates;

        while (searchFrontier.Count > 0)
        {
            HexCell current = searchFrontier.Dequeue();
            current.SearchPhase += 1;
            visibleCells.Add(current);

            for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
            {
                HexCell neighbor = current.GetNeighbor(d);
                if (
                    neighbor == null ||
                    neighbor.SearchPhase > searchFrontierPhase ||
                    !neighbor.Explorable
                    )
                {
                    continue;
                }

                int distance = current.MovementCost + 1;
                if (distance + neighbor.ViewElevation > range ||
                    distance > fromCoordinates.DistanceTo(neighbor.coordinates)
                    )
                {
                    continue;
                }

                if (neighbor.SearchPhase < searchFrontierPhase)
                {
                    neighbor.SearchPhase     = searchFrontierPhase;
                    neighbor.MovementCost    = distance;
                    neighbor.SearchHeuristic = 0;
                    searchFrontier.Enqueue(neighbor);
                }
                else if (distance < neighbor.MovementCost)
                {
                    int oldPriority = neighbor.SearchPriority;
                    neighbor.MovementCost = distance;
                    searchFrontier.Change(neighbor, oldPriority);
                }
            }
        }
        return(visibleCells);
    }
예제 #4
0
    //the main search method. returns whether or not a path has been found.
    bool Search(HexCell fromCell, HexCell toCell, Unit unit)
    {
        searchFrontierPhase += 2;
        if (searchFrontier == null)
        {
            searchFrontier = new HexPriorityQueue();
        }
        else
        {
            searchFrontier.Clear();
        }

        fromCell.SearchPhase  = searchFrontierPhase;
        fromCell.MovementCost = 0; //in turns, but unadjusted to speed
        searchFrontier.Enqueue(fromCell);
        while (searchFrontier.Count > 0)
        {
            HexCell current = searchFrontier.Dequeue();
            current.SearchPhase += 1;

            if (current == toCell)
            {
                return(true);
            }

            int currentCellMovementCost = current.MovementCost - 1;

            for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
            {
                HexCell neighbor = current.GetNeighbor(d);
                if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase)
                {
                    continue;
                }
                if (!unit.IsValidDestination(neighbor))
                {
                    continue;
                }


                float movementCost = unit.GetMoveCost(current, neighbor, d);


                if (movementCost < 0)
                {
                    continue;
                }

                //DEBUG
                movementCost = 1;
                //DEBUG

                int newNeighborMC = (int)(current.MovementCost + movementCost);

                if (neighbor.SearchPhase < searchFrontierPhase)
                {
                    neighbor.SearchPhase     = searchFrontierPhase;
                    neighbor.MovementCost    = newNeighborMC;
                    neighbor.PathFrom        = current;
                    neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates);
                    searchFrontier.Enqueue(neighbor);
                }
                else if (newNeighborMC < neighbor.MovementCost)
                {
                    int oldPriority = neighbor.SearchPriority;
                    neighbor.MovementCost = newNeighborMC;
                    neighbor.PathFrom     = current;
                    searchFrontier.Change(neighbor, oldPriority);
                }
            }
        }
        return(false);
    }