Пример #1
0
        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);
        }