Example #1
0
        /// <summary>
        /// Creates a finished map (placing cliffs, smoothing them, turning/mirroring the map, etc.)
        /// </summary>
        /// <param name="half"> The half to work on. </param>
        /// <param name="function"> The way to create the complete map. </param>
        /// <returns> The finished map. </returns>
        public MapPhenotype CreateFinishedMap(Half half, Enums.MapFunction function)
        {
            var tempMap = this.CreateCompleteMap(half, function);

            tempMap.PlaceCliffs();
            tempMap.SmoothCliffs();
            tempMap = tempMap.CreateCompleteMap(half, function);
            return(tempMap);
        }
Example #2
0
        /// <summary>
        /// Creates a map where one part has been turned onto the other part of the map.
        /// </summary>
        /// <param name="half"> The half to work on. </param>
        /// <param name="function"> The way to create the complete map. </param>
        /// <returns> The complete map. </returns>
        public MapPhenotype CreateCompleteMap(Half half, Enums.MapFunction function)
        {
            this.mapHalf = half;

            var newHeightLevels = (HeightLevel[, ]) this.HeightLevels.Clone();
            var newMapItems     = (Item[, ]) this.MapItems.Clone();
            var rocks           = (bool[, ]) this.DestructibleRocks.Clone();

            // Figures out which part of the map that should be looked at.
            var xStart = (half == Half.Right) ? this.XSize / 2 : 0;
            var xEnd   = (half == Half.Left) ? this.XSize / 2 : this.XSize;
            var yStart = (half == Half.Top) ? this.YSize / 2 : 0;
            var yEnd   = (half == Half.Bottom) ? this.YSize / 2 : this.YSize;

            for (var y = yStart; y < yEnd; y++)
            {
                var otherY = y;

                // If we mirror top or bottom or turn the map, find the height to copy to.
                if ((function == Enums.MapFunction.Mirror && (half == Half.Top || half == Half.Bottom)) ||
                    function == Enums.MapFunction.Turn)
                {
                    otherY = this.YSize - y - 1;
                }

                for (var x = xStart; x < xEnd; x++)
                {
                    var otherX = x;

                    // If we mirror left or right or turn the map, find the width to copy to.
                    if ((function == Enums.MapFunction.Mirror && (half == Half.Left || half == Half.Right)) ||
                        function == Enums.MapFunction.Turn)
                    {
                        otherX = this.XSize - x - 1;
                    }

                    newHeightLevels[otherX, otherY] = this.HeightLevels[x, y];
                    newMapItems[otherX, otherY]     = this.MapItems[x, y];
                    rocks[otherX, otherY]           = this.DestructibleRocks[x, y];
                }
            }

            var newMap = new MapPhenotype(newHeightLevels, newMapItems, rocks);

            return(newMap);
        }
Example #3
0
        /// <summary>
        /// Updates the list of cliff positions.
        /// </summary>
        /// <param name="half">
        /// The half to look for cliffs on.
        /// </param>
        public void UpdateCliffPositions(Half half)
        {
            var xStart = (half == Half.Right) ? this.XSize / 2 : 0;
            var xEnd   = (half == Half.Left) ? this.XSize / 2 : this.XSize;
            var yStart = (half == Half.Top) ? this.YSize / 2 : 0;
            var yEnd   = (half == Half.Bottom) ? this.YSize / 2 : this.YSize;

            this.CliffPositions.Clear();

            for (var x = xStart; x < xEnd; x++)
            {
                for (var y = yStart; y < yEnd; y++)
                {
                    if (this.HeightLevels[x, y] == HeightLevel.Cliff)
                    {
                        this.CliffPositions.Add(new Tuple <int, int>(x, y));
                    }
                }
            }
        }
Example #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CellularAutomata"/> class that takes an existing height map instead of creating and seeding a new one.
        /// </summary>
        /// <param name="xSize"> The x size of the map. </param>
        /// <param name="ySize"> The y size of the map. </param>
        /// <param name="half"> The half of the map to work on. </param>
        /// <param name="map"> The existing height map. </param>
        /// <param name="r"> The random object. </param>
        public CellularAutomata(int xSize, int ySize, Enums.Half half, Enums.HeightLevel[,] map, Random r = null)
        {
            this.Map = (Enums.HeightLevel[, ])map.Clone();

            this.random = r ?? MapHelper.Random;

            this.XSize = xSize;
            this.YSize = ySize;

            // Figure out which part of the map that should be looked at.
            // Make sure we work on a bit more than half the map, in order to avoid that the edge along the middle does not have
            // "empty" neighbours from the beginning.
            this.caXStart = (half == Enums.Half.Right) ? (this.XSize / 2) - (int)(this.XSize * 0.1) : 0;
            this.caXEnd   = (half == Enums.Half.Left) ? (this.XSize / 2) + (int)(this.XSize * 0.1) : this.XSize;
            this.caYStart = (half == Enums.Half.Top) ? (this.YSize / 2) - (int)(this.YSize * 0.1) : 0;
            this.caYEnd   = (half == Enums.Half.Bottom) ? (this.YSize / 2) + (int)(this.YSize * 0.1) : this.YSize;

            this.ruleSet = new Ruleset();
            this.LoadBasicRuleset();
        }
Example #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CellularAutomata"/> class.
        /// </summary>
        /// <param name="xSize"> The x size of the map. </param>
        /// <param name="ySize"> The y size of the map. </param>
        /// <param name="half"> The half of the map to work on. </param>
        /// <param name="oddsOfHeight1"> The odds of a tile being changed to height 1. </param>
        /// <param name="oddsOfHeight2"> The odds of a tile being changed to height 2. </param>
        /// <param name="maxRangeToGroupPoint"> The max range to the group points. </param>
        /// <param name="groupPoints"> The number of points where terrain should be grouped during the initial seeding. </param>
        /// <param name="generateHeight2"> Determines if the cellular automata should generate height2 or not. </param>
        /// <param name="r"> The random to use. If null, will use the MapHelper Random. </param>
        public CellularAutomata(
            int xSize,
            int ySize,
            Enums.Half half,
            double oddsOfHeight1     = 0.4,
            double oddsOfHeight2     = 0.2,
            int maxRangeToGroupPoint = 15,
            int groupPoints          = 3,
            bool generateHeight2     = true,
            Random r = null)
        {
            this.Map = new Enums.HeightLevel[xSize, ySize];

            this.random = r ?? MapHelper.Random;

            this.XSize = xSize;
            this.YSize = ySize;

            // Figure out which part of the map that should be looked at.
            // Make sure we work on a bit more than half the map, in order to avoid that the edge along the middle does not have
            // "empty" neighbours from the beginning.
            this.caXStart = (half == Enums.Half.Right) ? (this.XSize / 2) - (int)(this.XSize * 0.1) : 0;
            this.caXEnd   = (half == Enums.Half.Left) ? (this.XSize / 2) + (int)(this.XSize * 0.1) : this.XSize;
            this.caYStart = (half == Enums.Half.Top) ? (this.YSize / 2) - (int)(this.YSize * 0.1) : 0;
            this.caYEnd   = (half == Enums.Half.Bottom) ? (this.YSize / 2) + (int)(this.YSize * 0.1) : this.YSize;

            // Create points around which the terrain should be grouped
            var groupList = new List <Position>();

            for (var i = 0; i < groupPoints; i++)
            {
                var x = this.random.Next(this.caXStart, this.caXEnd);
                var y = this.random.Next(this.caYStart, this.caYEnd);
                groupList.Add(new Position(x, y));
            }

            for (var y = this.caYStart; y < this.caYEnd; y++)
            {
                for (var x = this.caXStart; x < this.caXEnd; x++)
                {
                    var odds = this.random.NextDouble();

                    if (groupList.Count > 0)
                    {
                        var closest = (double)MapHelper.ClosestTo(new Position(x, y), groupList, maxRangeToGroupPoint);
                        if (closest <= maxRangeToGroupPoint)
                        {
                            odds = odds - ((maxRangeToGroupPoint - closest) / (maxRangeToGroupPoint * 3));
                        }
                        // ReSharper disable once RedundantCast
                        if (closest < (int)(maxRangeToGroupPoint / 2))
                        {
                            odds = odds / 2;
                        }
                    }

                    if (generateHeight2 && odds < oddsOfHeight2)
                    {
                        this.Map[x, y] = Enums.HeightLevel.Height2;
                    }
                    else if (odds < oddsOfHeight1)
                    {
                        this.Map[x, y] = Enums.HeightLevel.Height1;
                    }
                }
            }

            this.ruleSet = new Ruleset();
            this.LoadRuleset();
        }