示例#1
0
    public IEnumerable <HexEdge> GetPath(
        Hex fromHex,
        Hex toHex,
        HexUnit hexUnit,
        HexAdjacencyGraph graph
        )
    {
        return(AStarSearch(fromHex, toHex, hexUnit, graph));

// Presentation concerns should not be in this method.
//        SetPathDistanceLabelAndEnableHighlights(toHex, unit.Speed);
    }
    public HexMapRivers(
        HexMap hexMap,
        List <ClimateData> climate,
        int waterLevel,
        int elevationMax
        )
    {
        _hexMap                = hexMap;
        _riverLists            = new List <RiverList>();
        _riverOriginCandidates = new List <Hex>();
        _riverDigraph          = new RiverDigraph();
        _adjacencyGraph        = hexMap.AdjacencyGraph;

        for (int i = 0; i < _hexMap.SizeSquared; i++)
        {
            Hex hex = _hexMap.GetHex(i);

            if (hex.IsUnderwater)
            {
                continue;
            }

            ClimateData data = climate[i];

            float weight =
                data.moisture * (hex.elevation - waterLevel) /
                (elevationMax - waterLevel);

            if (weight > 0.75)
            {
                _riverOriginCandidates.Add(hex);
                _riverOriginCandidates.Add(hex);
            }

            if (weight > 0.5f)
            {
                _riverOriginCandidates.Add(hex);
            }

            if (weight > 0.25f)
            {
                _riverOriginCandidates.Add(hex);
            }
        }
    }
示例#3
0
    public void Step(
        ClimateParameters parameters
        )
    {
        HexAdjacencyGraph adjacencyGraph =
            _hexMap.AdjacencyGraph;

        // Initialize the next climate step.
        ClimateData[] nextClimates = new ClimateData[ClimateArray.Length];

        // Populate the next climate step.
        for (int i = 0; i < ClimateArray.Length; i++)
        {
            nextClimates[i] = new ClimateData();
        }

        // For each hex cell...
        for (int i = 0; i < _hexMap.SizeSquared; i++)
        {
            Hex            source        = _hexMap.GetHex(i);
            List <HexEdge> adjacentEdges =
                adjacencyGraph.GetOutEdgesList(source);

            // Get the next climate step for that cell.
            StepClimate(
                ClimateArray,
                ref nextClimates,
                source,
                adjacentEdges,
                parameters
                );

            source.clouds      = nextClimates[source.Index].clouds;
            source.moisture    = nextClimates[source.Index].moisture;
            source.temperature = nextClimates[source.Index].clouds;
        }

        ClimateArray = nextClimates;
    }
示例#4
0
    public static HexAdjacencyGraph FromHexGrid(
        HexGrid <Hex> hexGrid
        )
    {
        List <HexEdge> edges = new List <HexEdge>();

        for (
            int i = 0;
            i < hexGrid.Rows * hexGrid.Columns;
            i++
            )
        {
            Hex current = hexGrid[i];

            foreach (
                Hex neighbor in hexGrid.GetNeighbors(i)
                )
            {
                HexEdge newEdge = new HexEdge(
                    current,
                    neighbor,
                    CubeVector.HexDirectionWrapping(
                        current.CubeCoordinates,
                        neighbor.CubeCoordinates,
                        hexGrid.WrapSize
                        )
                    );

                edges.Add(newEdge);
            }
        }

        HexAdjacencyGraph result = new HexAdjacencyGraph();

        result.AddVerticesAndEdgeRange(edges);
        return(result);
    }
示例#5
0
    public void Triangulate(
        HexMap hexMap,
        float hexOuterRadius,
        HexAdjacencyGraph adjacencyGraph,
        RiverDigraph riverGraph,
        RoadUndirectedGraph roadGraph,
        ElevationDigraph elevationGraph
        )
    {
        _terrainLayer.Clear();
        _riversLayer.Clear();
        _roadsLayer.Clear();
        _openWaterLayer.Clear();
        _waterShoreLayer.Clear();
        _estuariesLayer.Clear();
        _features.Clear();

        for (int i = 0; i < Hexes.Length; i++)
        {
            Hex current = Hexes[i];

            if (current)
            {
                Dictionary <HexDirections, Hex> neighbors =
                    adjacencyGraph.GetNeighborByDirection(current);

                Dictionary <HexDirections, ElevationEdgeTypes> edgeTypes =
                    elevationGraph.GetNeighborEdgeTypes(current);

                Dictionary <HexDirections, bool> roadEdges =
                    roadGraph.GetNeighborRoads(current);

                List <HexDirections> borderDirections =
                    adjacencyGraph.GetBorderDirectionsList(current);

                HexRiverData riverData = riverGraph.GetRiverData(current);

                TriangulateHex(
                    current,
                    neighbors,
                    borderDirections,
                    hexOuterRadius,
                    riverData,
                    roadEdges,
                    edgeTypes,
                    hexMap.WrapSize,
                    _terrainLayer,
                    _riversLayer,
                    _roadsLayer,
                    _openWaterLayer,
                    _waterShoreLayer,
                    _estuariesLayer,
                    _features
                    );
            }
        }

        _terrainLayer.Draw();
        _riversLayer.Draw();
        _roadsLayer.Draw();
        _openWaterLayer.Draw();
        _waterShoreLayer.Draw();
        _estuariesLayer.Draw();
        _features.Apply();
    }
        public Hex Step(
            HexAdjacencyGraph adjacencyGraph,
            ref RiverDigraph riverDigraph,
            float extraLakeProbability,
            float hexOuterRadius,
            int waterLevel
            )
        {
            if (RiverHead.IsUnderwater)
            {
                return(null);
            }

            int minNeighborElevation  = int.MaxValue;
            int minNeighborWaterLevel = int.MaxValue;

            List <HexDirections> flowDirections = new List <HexDirections>();
            HexDirections        direction      = HexDirections.Northeast;

            for (
                HexDirections directionCandidate = HexDirections.Northeast;
                directionCandidate <= HexDirections.Northwest;
                directionCandidate++
                )
            {
                Hex neighborInDirection =
                    adjacencyGraph.TryGetNeighborInDirection(
                        RiverHead,
                        directionCandidate
                        );

                if (!neighborInDirection || River.Contains(neighborInDirection))
                {
                    continue;
                }

                if (neighborInDirection.elevation < minNeighborElevation)
                {
                    minNeighborElevation  = neighborInDirection.elevation;
                    minNeighborWaterLevel = neighborInDirection.WaterLevel;
                }

                // If the direction points to the river origin, or to a
                // neighbor which already has an incoming river, continue.
                if (
                    neighborInDirection == RiverHead ||
                    riverDigraph.HasIncomingRiver(neighborInDirection)
                    )
                {
                    continue;
                }

                int delta =
                    neighborInDirection.elevation - RiverHead.elevation;

                // If the elevation in the given direction is positive,
                // continue.
                if (delta > 0)
                {
                    continue;
                }

                // If the direction points away from the river origin and
                // any neighbors which already have an incoming river, and
                // the elevation in the given direction is negative or
                // zero, and the neighbor has an outgoing river, branch
                // river in this direction.
                if (
                    riverDigraph.HasOutgoingRiver(neighborInDirection)
                    )
                {
                    SetOutgoingRiver(
                        RiverHead,
                        neighborInDirection,
                        directionCandidate,
                        ref riverDigraph
                        );

                    River.Add(neighborInDirection);
                    return(neighborInDirection);
                }

                // If the direction points away from the river origin and
                // any neighbors which already have an incoming river, and
                // the elevation in the given direction is not positive,
                // and the neighbor does not have an outgoing river in the
                // given direction...

                // If the direction is a decline, make the probability for
                // the branch 4 / 5.
                if (delta < 0)
                {
                    flowDirections.Add(directionCandidate);
                    flowDirections.Add(directionCandidate);
                    flowDirections.Add(directionCandidate);
                }

                // If the rivers local length is 1, and the direction does
                // not result in a slight river bend, but rather a straight
                // river or a corner river, make the probability of the
                // branch 2 / 5
                if (
                    River.Count == 1 ||
                    (directionCandidate != direction.NextClockwise2() &&
                     directionCandidate != direction.PreviousClockwise2())
                    )
                {
                    flowDirections.Add(directionCandidate);
                }

                flowDirections.Add(directionCandidate);
            }

            // If there are no candidates for branching the river...
            if (flowDirections.Count == 0)
            {
                // If the river contains only the river origin...
                if (River.Count == 1)
                {
                    // Do nothing and return null
                    return(null);
                }

                // If the hex is surrounded by hexes at a higher elevation,
                // set the water level of the hex to the minium elevation
                // of all neighbors.
                if (minNeighborElevation >= RiverHead.elevation)
                {
                    RiverHead.WaterLevel = RiverHead.elevation;

                    // If the hex is of equal elevation to a neighbor with
                    // a minimum elevation, lower the current hexes
                    // elevation to one below the minimum elevation of all
                    // of its neighbors so that it becomes a small lake
                    // that the river feeds into, and then break out of the
                    // while statement terminating the river in a lake
                    // rather than into the ocean.
                    if (minNeighborElevation == RiverHead.elevation)
                    {
                        RiverHead.SetElevation(
                            minNeighborElevation - 1,
                            hexOuterRadius,
                            _hexMap.WrapSize
                            );
                    }
                }

                return(null);
            }

            direction = flowDirections[
                Random.Range(0, flowDirections.Count)
                        ];

            Hex neighborInRandomDirection =
                adjacencyGraph.TryGetNeighborInDirection(
                    RiverHead,
                    direction
                    );

            SetOutgoingRiver(
                RiverHead,
                neighborInRandomDirection,
                direction,
                ref riverDigraph
                );

            // If the hex is lower than the minimum elevation of its
            // neighbors assign a lake based on a specified probability.
            if (
                minNeighborElevation >= RiverHead.elevation &&
                Random.value < extraLakeProbability
                )
            {
                RiverHead.WaterLevel = RiverHead.elevation;

                RiverHead.SetElevation(
                    minNeighborElevation - 1,
                    hexOuterRadius,
                    _hexMap.WrapSize
                    );
            }

            River.Add(neighborInRandomDirection);
            return(neighborInRandomDirection);
        }
示例#7
0
    /// <summary>
    /// Search this HexGrid.
    /// </summary>
    /// <param name="start"></param>
    /// <param name="end"></param>
    /// <param name="unit"></param>
    /// <returns></returns>
    private IEnumerable <HexEdge> AStarSearch(
        Hex start,
        Hex end,
        HexUnit unit,
        HexAdjacencyGraph graph
        )
    {
        IEnumerable <HexEdge> result;

//        AlgorithmExtensions.ShortestPathsAStar<Hex, HexEdge>(
//            graph,
//            GetPathfindingEdgeWeight,
//            GetPathfindingHeursitic,
//            start
//        ).Invoke(end, out result);

        return(null);

/*        int speed = unit.Speed;
 *
 *      _searchFrontierPhase += 2;
 *
 *      if (_searchFrontier == null)
 *      {
 *          _searchFrontier = new HexPriorityQueue();
 *      }
 *      else
 *      {
 *          _searchFrontier.Clear();
 *      }
 *
 * // Temporarily using a list instead of a priority queue.
 * // Should optimize this later.
 * //
 *      start.SearchPhase = _searchFrontierPhase;
 *      start.Distance = 0;
 *      _searchFrontier.Enqueue(start);
 *
 *      while (_searchFrontier.Count > 0)
 *      {
 *          Hex current = _searchFrontier.Dequeue();
 *          current.SearchPhase += 1;
 *
 *          if (current == end)
 *          {
 *              return true;
 *          }
 *
 *          int currentTurn = (current.Distance - 1) / speed;
 *
 *          for (HexDirection direction = HexDirection.Northeast; direction <= HexDirection.Northwest; direction++)
 *          {
 *              Hex neighbor = current.GetNeighbor(direction);
 *
 *              if
 *              (
 *                  neighbor == null ||
 *                  neighbor.SearchPhase > _searchFrontierPhase
 *              )
 *              {
 *                  continue;
 *              }
 *
 *              if (!unit.IsValidDestination(neighbor))
 *              {
 *                  continue;
 *              }
 *
 *              int moveCost = unit.GetMoveCost(current, neighbor, direction);
 *
 *              if (moveCost < 0)
 *              {
 *                  continue;
 *              }
 *
 * // Wasted movement points are factored into the cost of hexes outside
 * // the boundary of the first turn by adding the turn number multiplied
 * // by the speed plus the cost to move into the hex outside the boundary
 * // of the first turn. This method ensures that the the distances with
 * // which the algorithm is using to calculate the best path take into
 * // account wasted movement points.
 * //
 *              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(end.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;
 */
    }