I'm using a pandas dataframe to store a dynamic 2D game map for a rougelike style game map editor. The player can draw and erase rooms. I need to draw walls around these changing rooms.
I have this:
0 1 2 3 4 5 6
0 . . . x . .
1 . . x x . .
2 . x x x . .
3 . . . . . .
4 . . . . . .
And need this:
0 1 2 3 4 5 6
0 . # # x # .
1 # # x x # .
2 # x x x # .
3 # # # # # .
4 . . . . . .
What is the most efficient way to do this?
So far I followed the approach outlined here, but this leaves me with some nested if and for before and after the lambda. As I have to check first if a cell is currently dug out. Then check all eight neighbors if they are dug out or not before changing the matching cells. This really takes a tool on the frame rate. I can't be the first to struggle with something like this, but got stuck at finding a solution.
I was hoping to find a way by applying mask or a similar binary comparison. Still, I have no idea how to efficiently do the neighbor checks without falling back into nested loops.
What you want to do is called a binary dilation. You can do this on the underlying numpy array with
scipy.ndimage.morphology.binary_dilation:output:
Now to get a different symbol, you can use a more complex mask (
binary_dilation(a)^a) with a XOR operation (^):output:
all neighbors
Use a different structuring element (here a 3x3 matrix of 1s):
output:
other kernels
You can easily adapt the code to have any combination of neighbors
example: top left