predicate which returns true if a tile should be considered a 'wall'
grid of tiles to find enclosed area in
tile that may be part of an enclosed region
if yes, an area is not considered enclosed if there is a diagonal opening.
a range of tiles in the enclosure (empty if origin is not part of an enclosed region)
1 import std.array; 2 import std.algorithm : equal; 3 4 // let the 'X's represent 'walls', and the other letters 'open' areas we'd link to identify 5 auto tiles = rectGrid([ 6 // 0 1 2 3 4 5 <-col| row 7 [ 'X', 'X', 'X', 'X', 'X', 'X' ], // 0 8 [ 'X', 'a', 'a', 'X', 'b', 'X' ], // 1 9 [ 'X', 'a', 'a', 'X', 'b', 'X' ], // 2 10 [ 'X', 'X', 'X', 'X', 'X', 'X' ], // 3 11 [ 'd', 'd', 'd', 'X', 'c', 'X' ], // 4 12 [ 'd', 'd', 'd', 'X', 'X', 'c' ], // 5 13 ]); 14 15 static bool isWall(char c) { return c == 'X'; } 16 17 // starting on a wall should return an empty result 18 assert(tiles.enclosedTiles!isWall(RowCol(0, 0)).empty); 19 20 // all tiles in the [1,1] -> [2,2] area should find the 'a' room 21 assert(tiles.enclosedTiles!isWall(RowCol(1, 1)).equal(['a', 'a', 'a', 'a'])); 22 assert(tiles.enclosedTiles!isWall(RowCol(1, 2)).equal(['a', 'a', 'a', 'a'])); 23 assert(tiles.enclosedTiles!isWall(RowCol(2, 1)).equal(['a', 'a', 'a', 'a'])); 24 assert(tiles.enclosedTiles!isWall(RowCol(2, 2)).equal(['a', 'a', 'a', 'a'])); 25 26 // get the two-tile 'b' room at [1,4] -> [2,4] 27 assert(tiles.enclosedTiles!isWall(RowCol(1, 4)).equal(['b', 'b'])); 28 assert(tiles.enclosedTiles!isWall(RowCol(2, 4)).equal(['b', 'b'])); 29 30 // get the single tile 'c' room at 4,4 31 assert(tiles.enclosedTiles!isWall(RowCol(4, 4)).equal(['c'])); 32 // if we require that diagonals be blocked too, 'c' is not an enclosure 33 assert(tiles.enclosedTiles!isWall(RowCol(4, 4), Diagonals.yes).empty); 34 35 // the 'd' region is not an enclosure (touches map edge) 36 assert(tiles.enclosedTiles!isWall(RowCol(4, 1)).empty); 37 assert(tiles.enclosedTiles!isWall(RowCol(5, 0)).empty);
Find an area of tiles enclosed by 'walls'.