// Try to flood fill the map. Each seperate contigious spot gets a different scratch number. protected int FloodFillWithContigiousNumbers(Map map) { ResetScratch(map); byte currentScratchNumber = 1; // First we walk the entire map, flood filling each for (int i = 0; i < map.Width; ++i) { for (int j = 0; j < map.Height; ++j) { if (map.GetTerrainAt(i, j) == TerrainType.Floor && map.GetScratchAt(i, j) == 0) { FloodFill(map, i, j, currentScratchNumber); currentScratchNumber++; } } } // If we didn't scratch any tiles, the map must be all walls, bail if (currentScratchNumber == 1) throw new MapGenerationFailureException("FillAllSmallerUnconnectedRooms came to a level with all walls?"); return currentScratchNumber; }
// Make sure map has one connected area protected bool CheckConnectivity(Map map) { const int CheckConnectivityScratchValue = 42; // Find a clear point Point clearPoint = GetFirstClearPoint(map); // Flood fill all connected tiles FloodFill(map, clearPoint.X, clearPoint.Y, CheckConnectivityScratchValue); // See if any floor tiles don't have our scratch, if so they are not connected for (int i = 0; i < map.Width; ++i) { for (int j = 0; j < map.Height; ++j) { if (map.GetTerrainAt(i, j) == TerrainType.Floor && map.GetScratchAt(i, j) != CheckConnectivityScratchValue) return false; } } return true; }
protected void FillAllSmallerUnconnectedRooms(Map map) { int currentScratchNumber = FloodFillWithContigiousNumbers(map); // Walk each tile, and count up the different groups. int[] numberOfTilesWithThatScratch = new int[currentScratchNumber]; numberOfTilesWithThatScratch.Initialize(); for (int i = 0; i < map.Width; ++i) { for (int j = 0; j < map.Height; ++j) { if (map.GetTerrainAt(i, j) == TerrainType.Floor) numberOfTilesWithThatScratch[map.GetScratchAt(i, j)]++; } } if (numberOfTilesWithThatScratch[0] != 0) throw new MapGenerationFailureException("Some valid tiles didn't get a scratch during FillAllSmallerRooms."); // Find the largest collection int biggestNumber = 1; for (int i = 2; i < currentScratchNumber; ++i) { if (numberOfTilesWithThatScratch[i] > numberOfTilesWithThatScratch[biggestNumber]) biggestNumber = i; } // Now walk level, and turn every floor tile without that scratch into a wall for (int i = 0; i < map.Width; ++i) { for (int j = 0; j < map.Height; ++j) { if (map.GetTerrainAt(i, j) == TerrainType.Floor && map.GetScratchAt(i, j) != biggestNumber) map.SetTerrainAt(i, j, TerrainType.Wall); // And reset the scratch while we're here map.SetScratchAt(i, j, 0); } } if (!CheckConnectivity(map)) throw new MapGenerationFailureException("FillAllSmallerUnconnectedRooms produced a non-connected map."); }
protected void FloodFill(Map map, int x, int y, byte scratchValue) { if (!map.IsPointOnMap(x, y)) return; if (map.GetTerrainAt(x, y) == TerrainType.Floor && map.GetScratchAt(x, y) == 0) { map.SetScratchAt(x, y, scratchValue); FloodFill(map, x + 1, y, scratchValue); FloodFill(map, x - 1, y, scratchValue); FloodFill(map, x, y + 1, scratchValue); FloodFill(map, x, y - 1, scratchValue); } }