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)
import std.array; import std.algorithm : equal; // let the 'X's represent 'walls', and the other letters 'open' areas we'd link to identify auto tiles = rectGrid([ // 0 1 2 3 4 5 <-col| row [ 'X', 'X', 'X', 'X', 'X', 'X' ], // 0 [ 'X', 'a', 'a', 'X', 'b', 'X' ], // 1 [ 'X', 'a', 'a', 'X', 'b', 'X' ], // 2 [ 'X', 'X', 'X', 'X', 'X', 'X' ], // 3 [ 'd', 'd', 'd', 'X', 'c', 'X' ], // 4 [ 'd', 'd', 'd', 'X', 'X', 'c' ], // 5 ]); static bool isWall(char c) { return c == 'X'; } // starting on a wall should return an empty result assert(tiles.enclosedTiles!isWall(RowCol(0, 0)).empty); // all tiles in the [1,1] -> [2,2] area should find the 'a' room assert(tiles.enclosedTiles!isWall(RowCol(1, 1)).equal(['a', 'a', 'a', 'a'])); assert(tiles.enclosedTiles!isWall(RowCol(1, 2)).equal(['a', 'a', 'a', 'a'])); assert(tiles.enclosedTiles!isWall(RowCol(2, 1)).equal(['a', 'a', 'a', 'a'])); assert(tiles.enclosedTiles!isWall(RowCol(2, 2)).equal(['a', 'a', 'a', 'a'])); // get the two-tile 'b' room at [1,4] -> [2,4] assert(tiles.enclosedTiles!isWall(RowCol(1, 4)).equal(['b', 'b'])); assert(tiles.enclosedTiles!isWall(RowCol(2, 4)).equal(['b', 'b'])); // get the single tile 'c' room at 4,4 assert(tiles.enclosedTiles!isWall(RowCol(4, 4)).equal(['c'])); // if we require that diagonals be blocked too, 'c' is not an enclosure assert(tiles.enclosedTiles!isWall(RowCol(4, 4), Diagonals.yes).empty); // the 'd' region is not an enclosure (touches map edge) assert(tiles.enclosedTiles!isWall(RowCol(4, 1)).empty); assert(tiles.enclosedTiles!isWall(RowCol(5, 0)).empty);
Find an area of tiles enclosed by 'walls'.