Chain reaction of bombs Introduction:

Before the task, here is what every element does on the map:

Plain land (X): This does nothing.

Destroyed land (-): This is the same as plain land, but destroyed by a bomb.

The active bomb (!): On a map, this will destroy everything in a 3x3 square:

XXXXX                         XXXXX
XXXXX                         X---X
XX!XX     &gt; will become &gt;     X---X
XXXXX                         X---X
XXXXX                         XXXXX


The passive bomb (@): It does nothing, until it is detonated by another bomb. This also has a 3x3 square explosion radius:

XXXXX                         XXXXX
XXXXX                         XXXXX
XX@XX     &gt; will become &gt;     XX@XX (nothing happened)
XXXXX                         XXXXX
XXXXX                         XXXXX


But:

XXXXX                         XXXXX
XXXXX                         X---X
XX@XX     &gt; will become &gt;     ----X (both bombs have exploded)
X!XXX                         ----X
XXXXX                         ---XX


The nuke (~): It does nothing, until it is detonated by another bomb. The difference is that this bomb has a 5x5 square explosion radius:

XXXXX                         XXXXX
XXXXX                         XXXXX
XX~XX     &gt; will become &gt;     XX~XX (nothing happened)
XXXXX                         XXXXX
XXXXX                         XXXXX


But:

XXXXX                         -----
XXXXX                         -----
XX~XX     &gt; will become &gt;     ----- (both bombs have exploded)
X!XXX                         -----
XXXXX                         -----


The task


Given a 9x9 map, output the map after the chain reaction.
You may provide a function or a program.
This is code-golf, so the submission with the least amount of bytes wins!


Test cases

Test case 1 (3 steps):

XXXXXXXXX           XXXXXXXXX
----XXXXX           ----XXXXX
XXXX@XXXX           XXXX@XXXX
XXXXXXXX-           XXX---XX-
XXXX@XXXX     &gt;     ------XXX
XXXXXXXX-           ------XX-
XX~XXXXXX           -----XXXX
X!XXXXXX-           -----XXX-
XXXXXXXXX           -----XXXX


Test case 2 (2 steps):

XXXXXXXXX           XXXXXXXXX
XXXXXXXXX           XXXXXXXXX
XX~XXXXXX           XX~XXXXXX
---------           ---------
XXXX!XXXX     &gt;     XXX---XXX
XXXXXXXXX           XXX------
XXX@@X@!X           XXX@@----
XXXXXXXXX           XXXXX----
XXXXXXXXX           XXXXXXXXX


Test case 3 (2 steps):

XXXXXXXXX           XXXXXXXXX
XXXXXXXXX           XXXXXXXXX
XX~XXXXXX           XX~XXXXXX
XXXXXXXXX           XXX---XXX
XXXX!XXXX     &gt;     XXX---XXX
XXXXXXXXX           XXX------
XXX@@X@!X           XXX@@----
XXXXXXXXX           XXXXX----
XXXXXXXXX           XXXXXXXXX


Test case 4 (1 step):

XXXXXXXXX           XXXXXXXXX
XXXX-XXXX           XXXX-XXXX
XXXXXXXXX           XXX---XXX
XX-X!X-XX           XX-----XX
XXXXXXXXX     &gt;     XXX---XXX
XX-----XX           XX-----XX
XXXX-XXXX           XXXX-XXXX
XXXXXXXXX           XXXXXXXXX
XXXXXXXXX           XXXXXXXXX


Test case 5 (9 steps):

!XXXXXXXX           ---XXXXXX
X@XXXXXXX           ----XXXXX
XX@XXXXXX           -----XXXX
XXX@XXXXX           X-----XXX
XXXX@XXXX     &gt;     XX-----XX
XXXXX@XXX           XXX-----X
XXXXXX@XX           XXXX-----
XXXXXXX@X           XXXXX----
XXXXXXXX@           XXXXXX---


Test case 6 (9 steps):

XX@@@XXXX           ------XXX
XXXXXXXXX           ------XXX
~XXXXXXXX           ---XXXXXX
XXXXXXXXX           ---XXXXXX
~XXXXXXXX     &gt;     ---XXXXXX
XXXXXXXXX           ---XXXXXX
~XXXXXXXX           ---XXXXXX
@XXXXXXXX           ---XXXXXX
!XXXXXXXX           ---XXXXXX


Test case 7 (3 steps):

!XXXXXXXX           ---XXXXXX
X@XXXXXXX           ----XXXXX
XX@XXXXXX           ----XXXXX
XXXXXXXXX           X---X----
XXXXXX@@!     &gt;     XXXXX----
XXXXXXXXX           X---X----
XX@XXXXXX           ----XXXXX
X@XXXXXXX           ----XXXXX
!XXXXXXXX           ---XXXXXX
Matlab, 120 111 bytes
function f=c(f);c=@(x,i)conv2(x+0,ones(i),'s');a=c(f&lt;34,3);for k=f;a=c(a&amp;f&lt;65,3)|a;a=c(a&amp;f&gt;99,5)|a;end;f(a)='-'


Convolution is the key to success.

The idea is following: Find the active bomb. Enlarge this area to a 3x3 square. Find new affected bombs, enlarge the correspoding areas to the corresponding size and add those to the previously destroyed area. Repeat this enough times (in my case as many times as we have input characters, just because that is the shortest variant) to be sure that we reached a stationary point (=no more exploding bombs). Then set all the destroyed area to - and display the result.
The input is assumed to be a matrix of characters, e.g.
['!XXXXXXXX';
'X@XXXXXXX';
'XX@XXXXXX';
'XXX@XXXXX';
'XXXX@XXXX';
'XXXXX@XXX';
'XXXXXX@XX';
'XXXXXXX@X';
'XXXXXXXX@'];