public override void Apply(T map)
        {
            int blobs      = this.Blobs.Pick(map.Rand);
            int startScale = Math.Max(this.MinScale, this.StartScale.Pick(map.Rand));

            for (int ii = 0; ii < blobs; ii++)
            {
                Loc  size   = new Loc(map.Width * startScale / 100, map.Height * startScale / 100);
                int  area   = size.X * size.Y;
                bool placed = false;
                while (area > 0 && area >= this.MinScale * map.Width / 100 * this.MinScale * map.Height / 100)
                {
                    bool[][] noise = new bool[size.X][];
                    for (int xx = 0; xx < size.X; xx++)
                    {
                        noise[xx] = new bool[size.Y];
                        for (int yy = 0; yy < size.Y; yy++)
                        {
                            noise[xx][yy] = map.Rand.Next(100) < AUTOMATA_CHANCE;
                        }
                    }

                    noise = NoiseGen.IterateAutomata(noise, CellRule.Gte5, CellRule.Gte4, AUTOMATA_ROUNDS);

                    bool IsWaterValid(Loc loc) => noise[loc.X][loc.Y];

                    BlobMap blobMap = Detection.DetectBlobs(new Rect(0, 0, noise.Length, noise[0].Length), IsWaterValid);

                    if (blobMap.Blobs.Count > 0)
                    {
                        int blobIdx = 0;
                        for (int bb = 1; bb < blobMap.Blobs.Count; bb++)
                        {
                            if (blobMap.Blobs[bb].Area > blobMap.Blobs[blobIdx].Area)
                            {
                                blobIdx = bb;
                            }
                        }

                        placed = this.AttemptBlob(map, blobMap, blobIdx);
                    }

                    if (placed)
                    {
                        break;
                    }

                    size = size * 7 / 10;
                    area = size.X * size.Y;
                }
            }
        }
        protected override bool AttemptBlob(T map, BlobMap blobMap, int blobIdx)
        {
            bool IsMapValid(Loc loc) => map.GetTile(loc).TileEquivalent(map.RoomTerrain);

            // the XY to add to translate from point on the map to point on the blob map
            Loc offset = Loc.Zero;

            bool IsBlobValid(Loc loc)
            {
                Loc srcLoc = loc + blobMap.Blobs[blobIdx].Bounds.Start;

                if (!Collision.InBounds(blobMap.Blobs[blobIdx].Bounds, srcLoc))
                {
                    return(false);
                }
                Loc destLoc = loc + offset;

                if (!map.CanSetTile(destLoc, this.Terrain))
                {
                    return(false);
                }
                return(blobMap.Map[srcLoc.X][srcLoc.Y] == blobIdx);
            }

            // attempt to place in 20 locations
            for (int jj = 0; jj < 20; jj++)
            {
                Rect blobRect = blobMap.Blobs[blobIdx].Bounds;
                offset = new Loc(map.Rand.Next(0, map.Width - blobRect.Width), map.Rand.Next(0, map.Height - blobRect.Height));
                Loc blobMod = blobMap.Blobs[blobIdx].Bounds.Start - offset;

                // pass this into the walkable detection function
                bool disconnects = Detection.DetectDisconnect(new Rect(0, 0, map.Width, map.Height), IsMapValid, offset, blobRect.Size, IsBlobValid, true);

                // if it's a pass, draw on tile if it's a wall terrain or a room terrain
                if (disconnects)
                {
                    continue;
                }

                this.DrawBlob(map, blobMap, blobIdx, offset, true);
                return(true);
            }

            return(false);
        }
Exemple #3
0
        public override void Apply(T map)
        {
            int waterPercent = this.WaterPercent.Pick(map.Rand);

            if (waterPercent == 0)
            {
                return;
            }

            int depthRange = 0x1 << (this.OrderComplexity + this.OrderSoftness); // aka, 2 ^ degree
            int minWater   = waterPercent * map.Width * map.Height / 100;

            int[][] noise      = NoiseGen.PerlinNoise(map.Rand, map.Width, map.Height, this.OrderComplexity, this.OrderSoftness);
            int[]   depthCount = new int[depthRange];
            for (int xx = 0; xx < map.Width; xx++)
            {
                for (int yy = 0; yy < map.Height; yy++)
                {
                    depthCount[noise[xx][yy]]++;
                }
            }

            int waterMark   = 0;
            int totalDepths = 0;

            for (int ii = 0; ii < depthCount.Length; ii++)
            {
                if (totalDepths + depthCount[ii] >= minWater)
                {
                    if (totalDepths + depthCount[ii] - minWater < minWater - totalDepths)
                    {
                        waterMark++;
                    }
                    break;
                }

                totalDepths += depthCount[ii];
                waterMark++;
            }

            if (this.RespectFloor)
            {
                this.DrawWhole(map, noise, depthRange, waterMark);
                return;
            }

            while (waterMark > 0)
            {
                bool IsWaterValid(Loc loc)
                {
                    int heightPercent = Math.Min(100, Math.Min(Math.Min(loc.X * 100 / BUFFER_SIZE, loc.Y * 100 / BUFFER_SIZE), Math.Min((map.Width - 1 - loc.X) * 100 / BUFFER_SIZE, (map.Height - 1 - loc.Y) * 100 / BUFFER_SIZE)));
                    int noiseVal      = (noise[loc.X][loc.Y] * heightPercent / 100) + (depthRange * (100 - heightPercent) / 100);

                    return(noiseVal < waterMark);
                }

                BlobMap blobMap = Detection.DetectBlobs(new Rect(0, 0, map.Width, map.Height), IsWaterValid);

                bool IsMapValid(Loc loc) => map.GetTile(loc).TileEquivalent(map.RoomTerrain);

                int blobIdx = 0;
                bool IsBlobValid(Loc loc)
                {
                    Loc srcLoc = loc + blobMap.Blobs[blobIdx].Bounds.Start;

                    if (!map.CanSetTile(srcLoc, this.Terrain))
                    {
                        return(false);
                    }
                    return(blobMap.Map[srcLoc.X][srcLoc.Y] == blobIdx);
                }

                for (; blobIdx < blobMap.Blobs.Count; blobIdx++)
                {
                    Rect blobRect = blobMap.Blobs[blobIdx].Bounds;

                    // pass this into the walkable detection function
                    bool disconnects = Detection.DetectDisconnect(new Rect(0, 0, map.Width, map.Height), IsMapValid, blobRect.Start, blobRect.Size, IsBlobValid, true);

                    // if it's a pass, draw on tile if it's a wall terrain or a room terrain
                    if (!disconnects)
                    {
                        this.DrawBlob(map, blobMap, blobIdx, blobRect.Start, true);
                    }
                    else
                    {
                        // if it's a fail, draw on the tile only if wall terrain
                        this.DrawBlob(map, blobMap, blobIdx, blobRect.Start, false);
                    }
                }

                waterMark -= Math.Max(1, depthRange / 8);
            }
        }