예제 #1
0
    private void Traverse(ConnectedArea area,
                          int currentRow, int currentCol)
    {
        char currentCell = Matrix[currentRow][currentCol];

        BoolMatrix[currentRow][currentCol] = false;

        if (currentCell == '*')
        {
            return;
        }

        area.Size++;
        if (currentRow - 1 >= 0 && BoolMatrix[currentRow - 1][currentCol])
        {
            Traverse(area, currentRow - 1, currentCol);
        }
        if (currentRow + 1 < rows && BoolMatrix[currentRow + 1][currentCol])
        {
            Traverse(area, currentRow + 1, currentCol);
        }
        if (currentCol + 1 < cols && BoolMatrix[currentRow][currentCol + 1])
        {
            Traverse(area, currentRow, currentCol + 1);
        }
        if (currentCol - 1 >= 0 && BoolMatrix[currentRow][currentCol - 1])
        {
            Traverse(area, currentRow, currentCol - 1);
        }
    }
예제 #2
0
        private static void FindConnectedCells(int row, int col, ConnectedArea newArea)
        {
            if (
                row < 0 ||
                col < 0 ||
                row >= matrix.GetLength(0) ||
                col >= matrix.GetLength(1)
                )
            {
                return;
            }

            if (matrix[row, col] == '*' || matrix[row, col] == 'v')
            {
                return;
            }

            newArea.Size++;
            matrix[row, col] = 'v';

            FindConnectedCells(row, col + 1, newArea);
            FindConnectedCells(row, col - 1, newArea);
            FindConnectedCells(row + 1, col, newArea);
            FindConnectedCells(row - 1, col, newArea);
        }
예제 #3
0
    private int SortMethod(ConnectedArea a, ConnectedArea b)
    {
        if (a.Size < b.Size)
        {
            return(1);
        }
        if (a.Size > b.Size)
        {
            return(-1);
        }

        if (a.LocationY < b.LocationY)
        {
            return(-1);
        }
        if (a.LocationY > b.LocationY)
        {
            return(1);
        }

        if (a.LocationX < b.LocationX)
        {
            return(-1);
        }
        if (a.LocationX > b.LocationX)
        {
            return(1);
        }

        return(0);
    }
예제 #4
0
    public void Setup()
    {
        var random = new Random(3);
        var board  =
            new CellBoard(new Size(256, 256))
            .Fill(random, probabilityAlive: 0.5)
            .MakeBorderAlive(thickness: 1)
            .GenerateStandardCave()
            .ScaleAndSmooth(times: 3)
            .TrimToLargestDeadArea();

        _area = ConnectedAreaAnalyzer
                .FindForegroundAreas(board.Dimensions, p => board[p] == CellType.Dead)
                .MaxBy(a => a.Area);
    }
예제 #5
0
    private void GetAreas()
    {
        for (int row = 0; row < rows; row++)
        {
            for (int col = 0; col < cols; col++)
            {
                if (Matrix[row][col] != '*' && BoolMatrix[row][col])
                {
                    var area = new ConnectedArea(row, col);
                    Traverse(area, row, col);
                    areas.Add(area);
                }
            }
        }

        areas.Sort((a, b) => SortMethod(a, b));
    }
예제 #6
0
        private static void FindConnectedArea(int row, int col, ConnectedArea area)
        {
            if (row < 0 || col < 0 || row >= rows || col >= cols)
            {
                return;
            }

            if (isVisited[row, col] || matrix[row, col] == '*')
            {
                return;
            }

            area.Size++;
            isVisited[row, col] = true;
            FindConnectedArea(row, col + 1, area);
            FindConnectedArea(row + 1, col, area);
            FindConnectedArea(row, col - 1, area);
            FindConnectedArea(row - 1, col, area);
        }
예제 #7
0
        public static void Main()
        {
            //matrix = new[,]{
            //    { ' ', ' ', ' ', '*', ' ', ' ', ' ', '*', ' '},
            //    { ' ', ' ', ' ', '*', ' ', ' ', ' ', '*', ' '},
            //    { ' ', ' ', ' ', '*', ' ', ' ', ' ', '*', ' '},
            //    { ' ', ' ', ' ', ' ', '*', ' ', '*', ' ', ' '}
            //};

            matrix = new[,]{
                { '*', ' ', ' ', '*', ' ', ' ', ' ', '*', ' ', ' '},
                { '*', ' ', ' ', '*', ' ', ' ', ' ', '*', ' ', ' '},
                { '*', ' ', ' ', '*', '*', '*', '*', '*', ' ', ' '},
                { '*', ' ', ' ', '*', ' ', ' ', ' ', '*', ' ', ' '},
                { '*', ' ', ' ', '*', ' ', ' ', ' ', '*', ' ', ' '}
            };

            rows = matrix.GetLength(0);
            cols = matrix.GetLength(1);

            isVisited = new bool[rows, cols];
            var connectedAreas = new SortedSet<ConnectedArea>();

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    if (!isVisited[i, j] && matrix[i, j] != '*')
                    {
                        var area = new ConnectedArea(i,j,0);
                        FindConnectedArea(i, j, area);
                        connectedAreas.Add(area);
                    }
                }
            }

            int counter = 1;
            Console.WriteLine("Total areas found: " + connectedAreas.Count);
            foreach (var arr in connectedAreas)
            {
                Console.WriteLine($"Area #{counter} at ({arr.X}, {arr.Y}), size: {arr.Size}");
            }
        }
예제 #8
0
 private static void FindAreas()
 {
     for (int row = 0; row < matrix.Length; row++)
     {
         for (int col = 0; col < matrix[row].Length; col++)
         {
             char currentElement = matrix[row][col];
             if (currentElement != '*' && currentElement != 'v')
             {
                 ConnectedArea area = new ConnectedArea();
                 area.X    = row;
                 area.Y    = col;
                 area.Size = TraverseArea(row, col);
                 areas.Add(area);
                 Console.WriteLine();
             }
         }
     }
 }
예제 #9
0
        public static void Main()
        {
            int[] startPoint = FindStartPoint();

            while (startPoint != null)
            {
                ConnectedArea newArea = new ConnectedArea()
                {
                    Row = startPoint[0],
                    Col = startPoint[1],
                    Size = 0
                };

                FindConnectedCells(startPoint[0], startPoint[1], newArea);

                areas.Add(newArea);
                startPoint = FindStartPoint();
            }

            PrintAreas(areas);
        }
예제 #10
0
    public static IEnumerable <(Position Location, TreasureType Type)> RandomlyPlaceTreasure(
        ConnectedArea area,
        IEnumerable <Position> edge,
        LightMap floorLighting,
        LightRange lightRange,
        Random random)
    {
        var maxScore = 3 * lightRange.DarkLevels;
        var cutOff   = (int)(0.5 * maxScore);

        var scoredLocations = edge
                              .Select(p => new { Location = p, Score = area.CountAdjacentWalls(p) * -floorLighting[p] })
                              .OrderBy(scoredLocation => scoredLocation.Score)
                              .Where(scoredLocation => scoredLocation.Score >= cutOff)
                              .OrderBy(sl => random.Next())
                              .ToArray();

        var numberToTake = scoredLocations.Length / 2;

        return(scoredLocations.Take(numberToTake).Select(sl => (sl.Location, TreasureType.Medium)));
    }
예제 #11
0
    static (ImmutableArray <MapSquare>, ImmutableArray <Sector>, ImmutableArray <Tile>) CreateGeometry(
        Size size,
        ConnectedArea cave,
        CellBoard alternateFloor,
        CellBoard alternateCeiling,
        LightMap floorLight,
        LightMap ceilingLight,
        TextureQueue textureQueue,
        string texturePrefix)
    {
        var planeMap = new Canvas(size);

        double minLight  = 0.2;
        double darkStep  = (1 - minLight) / ceilingLight.Range.DarkLevels;
        double maxLight  = 1.1;
        double lightStep = (maxLight - 1) / ceilingLight.Range.LightLevels;


        double GetAlpha(int light) =>
        light switch
        {
            0 => 0,
            int pos when pos > 0 => pos * lightStep,
            int neg when neg < 0 => - neg * darkStep,
            _ => throw new InvalidOperationException("Impossible")
        };


        string GetTextureName(Corners corners, int light, bool isEastWest = false)
        {
            string name = $"t{(int)corners:D2}{light:+#;-#;#}{(isEastWest ? "dark" : "")}";

            var patches = ImmutableArray.CreateBuilder <Patch>();

            if (light > 0)
            {
                patches.Add(
                    new Patch(
                        $"{texturePrefix}{(int)corners:D2}",
                        0,
                        0,
                        Blend: new ColorBlend("FFFFFF", GetAlpha(light))));
            }
            else if (light < 0)
            {
                patches.Add(
                    new Patch(
                        $"{texturePrefix}{(int)corners:D2}",
                        0,
                        0,
                        Blend: new ColorBlend("000000", GetAlpha(light))));
            }
            else
            {
                patches.Add(
                    new Patch(
                        $"{texturePrefix}{(int)corners:D2}",
                        0,
                        0));
            }

            if (isEastWest)
            {
                patches.Add(
                    new Patch(
                        $"{texturePrefix}{(int)corners:D2}",
                        0,
                        0,
                        Blend: new ColorBlend("000000"),
                        Style: RenderStyle.Translucent,
                        Alpha: 0.075));
            }

            textureQueue.Add(new CompositeTexture(name, 256, 256, patches.ToImmutable(), XScale: 4, YScale: 4));
            return(name);
        }

        Corners GetCorners(CellBoard board, Position pos) => Corner.CreateFromUpperLeft(
            upperLeft: pos, on: p => board[p] == CellType.Dead);

        Corners GetSideCorners(Position left, Position right) => Corner.Create(
            topLeft: alternateCeiling[left] == CellType.Dead,
            topRight: alternateCeiling[right] == CellType.Dead,
            bottomLeft: alternateFloor[left] == CellType.Dead,
            bottomRight: alternateFloor[right] == CellType.Dead
            );

        int GetSideLight(Position p) => (ceilingLight[p] + floorLight[p]) / 2;

        var sectorSequence = new ModelSequence <SectorDescription, Sector>(description =>
                                                                           new Sector(
                                                                               TextureCeiling: GetTextureName(description.Ceiling, description.CeilingLight),
                                                                               TextureFloor: GetTextureName(description.Floor, description.FloorLight)));
        var tileSequence = new ModelSequence <TileDescription, Tile>(description =>
                                                                     new Tile(
                                                                         TextureEast: GetTextureName(description.EastCorners, description.EastLight, isEastWest: true),
                                                                         TextureNorth: GetTextureName(description.NorthCorners, description.NorthLight),
                                                                         TextureWest: GetTextureName(description.WestCorners, description.WestLight, isEastWest: true),
                                                                         TextureSouth: GetTextureName(description.SouthCorners, description.SouthLight),
                                                                         TextureOverhead: GetTextureName(description.FloorCorners, 0)));

        for (int y = 0; y < size.Height; y++)
        {
            for (int x = 0; x < size.Width; x++)
            {
                var pos = new Position(x, y);

                int tileId = -1;
                if (!cave.Contains(pos))
                {
                    tileId = tileSequence.GetIndex(new TileDescription(
                                                       NorthCorners: GetSideCorners(left: pos + Offset.Right, right: pos),
                                                       EastCorners: GetSideCorners(left: pos + Offset.DownAndRight, right: pos + Offset.Right),
                                                       SouthCorners: GetSideCorners(left: pos + Offset.Down, right: pos + Offset.DownAndRight),
                                                       WestCorners: GetSideCorners(left: pos, right: pos + Offset.Down),
                                                       FloorCorners: GetCorners(alternateFloor, pos),
                                                       NorthLight: GetSideLight(pos + Offset.Up),
                                                       EastLight: GetSideLight(pos + Offset.Right),
                                                       SouthLight: GetSideLight(pos + Offset.Down),
                                                       WestLight: GetSideLight(pos + Offset.Left)));
                }

                int sectorId = sectorSequence.GetIndex(new SectorDescription(
                                                           Floor: GetCorners(alternateFloor, pos),
                                                           Ceiling: GetCorners(alternateCeiling, pos),
                                                           FloorLight: floorLight[pos],
                                                           CeilingLight: ceilingLight[pos]));

                planeMap.Set(x, y,
                             tile: tileId,
                             sector: sectorId,
                             zone: 0);
            }
        }

        return(
            planeMap.ToPlaneMap(),
            sectorSequence.GetDefinitions().ToImmutableArray(),
            tileSequence.GetDefinitions().ToImmutableArray());
    }
예제 #12
0
        static bool FindTraversableCell()
        {
            for (int i = 0; i < matrix.GetLength(0); i++)
            {
                for (int j = 0; j < matrix.GetLength(1); j++)
                {
                    if (matrix[i, j] == ' ')
                    {
                        currentArea = new ConnectedArea()
                        {
                            X = i,
                            Y = j,
                        };

                        return true;
                    }
                }
            }

            return false;
        }
 public static int CountAdjacentWalls(this ConnectedArea area, Position p) =>
 (area.Contains(p + CoordinateSystem.TopLeft.Up) ? 0 : 1) +
 (area.Contains(p + CoordinateSystem.TopLeft.Down) ? 0 : 1) +
 (area.Contains(p + CoordinateSystem.TopLeft.Left) ? 0 : 1) +
 (area.Contains(p + CoordinateSystem.TopLeft.Right) ? 0 : 1);