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); } }
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); }
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); }
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); }
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)); }
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); }
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}"); } }
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(); } } } }
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); }
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))); }
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()); }
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);