ASCII-Art Zombie Invasion Simulation To simulate a zombie invasion, start with a grid of # and  representing the map:

##   ##
###   #
## ##  
  # ###
#  ####



# represents land.
 represents water.


The zombies start at a point on the map...

##   ##
###   #
## %#  
  # ###
#  ####


...and spread. % denotes land infected by zombies.

However, zombies cannot swim. They can move across land in the same way a king moves in chess - one square in any diagonal or orthogonal direction:

!!!
!%!
!!!


At the end of the simulation, some land will be infected with zombies:

%%   ##
%%%   #
%% %%  
  % %%%
#  %%%%


Your task is to simulate the zombie invasion. Write a program (or function) that takes as input a string representing the initial state of the grid, and two numbers representing the coordinates of the initial zombie. The program should output (or return) the final state of the invasion.

Specifications


Your program may print an optional trailing newline.
You can assume the input will be in the correct format (padded with spaces), with an optional trailing newline.
You can assume the initial zombie will start on land and will not die immediately.
This is code-golf, so the shortest answer (in bytes) wins.
-100% bonus if your code can also solve the Halting Problem for arbitrary Turing machines.
Your program should handle board widths of up to 50 chars.
Kotlin, 283 218 bytes

Unnamed lambda (with a nested function, heh).

Golfed

{i:String,x:Int,y:Int-&gt;val m=i.lines().map{it.toCharArray()};fun v(x:Int,y:Int){try{if(m[y][x]=='#'){m[y][x]='%';for(c in-1..1)for(d in-1..1)if(!(c==0&amp;&amp;d==0))v(x+c,y+d)}}catch(e:Exception){}};v(x, y);m.map(::println)}


Ungolfed

fun zombies(input: String, startX: Int, startY: Int) {
    val m = input.lines().map(String::toCharArray)      // build game map
    fun invade(x: Int, y: Int) {                        // nested functions, woo!
        try {
            if (m[y][x] == '#') {                       // if land
                m[y][x] = '%'                           // mark as invaded
                for (dx in -1..1) {                      // generate neighbour tiles
                    for (dy in -1..1) {
                        if (!(dx == 0 &amp;&amp; dy == 0)) {
                            invade(x + dx, y + dy)        // attempt to invade neighbours
                        }
                    }
                }
            }
        } catch(e: Exception) {}                        // catches ArrayIndexOutOfBounds
    }

    invade(startX, startY)                              // start the invasion
    m.map(::println)                                    // print final state
}


Saved quite a few bytes by switching to a recursive solution.