[Question]
  [
Your challenge is given an input of a prison layout to work out whether any of the prisoners can escape.
**Input**
Input may be in any reasonable format such as a string, array, array of arrays etc. The input will consist of three characters, in this case `#`, `P` and space. The input will not necessarily contain all three characters.
* `#`: A wall
* `P`: A prisoner
* space: An empty space
An example input will look like:
```
#####
#   #
# P #
#   #
#####
```
**Output**
A truthy/falsey value of whether or not the prison is secure. The prison is only secure if it can hold **all** of the prisoners. If **any** prisoner can escape it is not secure.
A prisoner can escape if they are not fully enclosed by a wall. A diagonal joining is fully enclosed.
**Test cases**
```
############# Truthy
# P #  P#   #
#   #   # P #
#############
############# Truthy
# P    P    #
#   #   # P #
#############
############# Falsey
# P #  P#   #
#   #   # P #
########## ##
####          Truthy
#   #
 #   #
  # P ####
  ####
P             Falsey
###           Falsey
# #
# #
### P
```
  
[Answer]
## [Snails](https://github.com/feresum/PMA), 13 bytes
```
!(t\P(o\ ),o~
```
[Try it online!](https://tio.run/##K85LzMwp/v9fUaMkJkAjP0ZBUye/7v9/ZWTApawQoKCsoBAAxAognoICBAeAeDCgoKwMAA "Snails – Try It Online")
Prints `0` for insecure prisons and the size of the input's bounding box for secure prisons.
The idea is to ensure that we can't find a path from a `P` to an out of bounds cell (`~`) moving only orthogonally (`o`) through spaces. The `t` is a teleport so that regardless where we attempt the match it tries all possible starting positions to find a `P`.
[Answer]
# [C# (.NET Core)](https://www.microsoft.com/net/core/platform), 485 480 474 470 421 408 bytes
The absolutely wrong tool and approach, but nonetheless...
* 7 bytes (and more) saved with the useful tips from TheLethalCoder.
* 4 bytes saved by returning an integer.
* 4 more bytes saved thanks (once again) to TheLethalCoder by replacing `' '` with `32` in the comparisons.
* LOTS of bytes saved by refactoring the code.
* 13 more bytes thanks to (guess who?) TheLethalCoder. :) I keep forgetting his tips and he keeps reminding me them.
```
m=>{var p='P';int a=m.Length,b=m[0].Length,i=0,j,x,y;var c=new System.Collections.Stack();for(;i<a;i++)for(j=0;j<b;j++)if(m[i][j]==p)c.Push(new[]{i,j});while(c.Count>0){var t=(int[])c.Pop();x=t[0];y=t[1];if(x<1|x>a-2|y<1|y>b-2)return 0;foreach(var v in new[]{-1,1}){var z=x>0&x<a-1&y>0&y<b-1;if(z&m[x+v][y]==32){m[x][y]=p;c.Push(new[]{x+v,y});}if(z&m[x][y+v]==32){m[x][y]=p;c.Push(new[]{x,y+v});}}}return 1;}
```
[Try it online!](https://tio.run/##5VJRa9swEH7vrzgaSC1iGzt7lBUYgT11YMhgD8YPiqok8mI5yEpqN/Vvz07JvC5QiunLVnYg605836fPpxN1ICojT4AhtryuITWqrvRCir2RN@74eP66qC23SsChUg/wlSvt1dYovc5y4GZdk9@4F4aLRVtbWYZf9lokYsNNlme5r7SdwQoYnEo2Ox64gR27S@8ongNnZXgv9dpu/CUrsyjvK8Uiv/Abv6WOIJiWj736vNpupbCq0nW4sFz88AhdVcajKuFUTSbEFQWLaJEsaYG1WnllpvKsyBnbERGm@3rjoWCWH5VfdIQ@btRWegKV9@g1ImeTlnnoMMsdodrhHQ2zaJC2uMU5RdEmiZ@bGQ@mzy1m7WwZTImRdm80RM6R5GLjOakDKA2XC4PYj7vLBU@smUXjJuFBPG4xa5NlEDvdp3GZNZNDnrVo@NOUHLE8Fzt6ZR4xfov2u56DIKS9zfER4jhd98tqTLsTvXntGefY4Worw@9GWXmvtPRWTgX6l73iXA@Ci9vRn3EbfqvmSPxsDG894r8ChxRGACkuGAQHuKx0EPwNM1fojhD6P3UD/lo3@nzwzw0Cwwt6APjSMGdmELh3/XEG6BwDBwj6IfogA/SOboz@oW5056w7/QQ "C# (.NET Core) – Try It Online")
Basically I expand the positions of the P's whenever a white space is around until it reaches (or not) the border of the layout.
Some licenses:
* I use a `char[][]` as the input for the layout.
* Returns `0` as insecure and `1` as secure.
[Answer]
# [Perl 5](https://www.perl.org/), 69 bytes
*-10 bytes thanks to [@Grimy](https://codegolf.stackexchange.com/users/6484/grimy).*
*-2 bytes thanks to [@Neil](https://codegolf.stackexchange.com/users/17602/neil).*
77 byte of code + `-p0` flags.
```
/
/;$_=s/(P| )(.{@{-}})?(?!\1)(?1)/P$2P/s?redo:!/\A.*P|P.*\Z|^P|P$/m
```
[Try it online!](https://tio.run/##fU7BCoJAEL3vV4zoQQPdCroYYUF1rDl0CmmxWlAwk3U9SPbttm4lBtWDffNmeG92ci7SSWMauarg5sOGEjq12KygNtbg2N5tfnPvdyewAyMcOXYwcihaY6RFIPj56hs0XHgDrNEbhPv6oIRFLw1jq82SMbKVMReQZHkpC5BxJOEUZXDkIEXCzz4hO1HKuPKJ2QcxAUFBU9sp1g/b7sNJ1lFa8OpLXiXQ/JuHNv88QE9Bo7MrCZ0mr3i7HeDt7r7H/iF6R4/VBJsf8wc)
Some *short* explanations:  
The idea is to put a `P` everywhere the prisoners can go. If any `P` is on the first/last line, or the first/last column, then the prisoners can go there and therefor escape, which means the prison isn't secure.  
`s/(P| )(.{@{-}})?(?!\1)(?1)/P$2P/s` replaces a space on the right of or bellow a `P` with a `P`, or a space on the left or on top of a `P`.  
Finally, `/\A.*P|P.*\Z|^P|P$/m` checks if a line starts or ends with a `P`, or if there is a `P` on the first or the last line.
[Answer]
## JavaScript (ES6), ~~134~~ 133 bytes
Takes input as an array of arrays of characters. Returns `0` (insecure) or `1` (secure).
```
f=a=>a.map((r,y)=>r.map((c,x)=>c>'O'&&[-1,1,0,0].map((X,i)=>(R=a[y+1-'1102'[i]])&&R[X+=x]?R[X]<'!'?R[o=2,X]=c:0:o=0)),o=1)|o&2?f(a):o
```
### Test cases
```
f=a=>a.map((r,y)=>r.map((c,x)=>c>'O'&&[-1,1,0,0].map((X,i)=>(R=a[y+1-'1102'[i]])&&R[X+=x]?R[X]<'!'?R[o=2,X]=c:0:o=0)),o=1)|o&2?f(a):o
console.log(f([
  [...'#############'],
  [...'# P #  P#   #'],
  [...'#   #   # P #'],
  [...'#############']
]))
console.log(f([
  [...'#############'],
  [...'# P    P    #'],
  [...'#   #   # P #'],
  [...'#############']
]))
console.log(f([
  [...'#############'],
  [...'# P #  P#   #'],
  [...'#   #   # P #'],
  [...'########## ##']
]))
console.log(f([
  [...'####'],
  [...'#   #'],
  [...' #   #'],
  [...'  # P ####'],
  [...'  ####']
]))
console.log(f([
  [...'P']
]))
console.log(f([
  [...'###'],
  [...'# #'],
  [...'# #'],
  [...'### P']
]))
```
[Answer]
## JavaScript (ES6), 121 bytes
```
f=s=>s==(s=s.replace(eval('/( |P)([^]{'+s.search`
`+'})?(?!\\1)[ P]/'),'P$2P'))?!/^.*P|P.*$/.test(s)&!/^P|P$/m.test(s):f(s)
```
Takes input as a newline-delimited rectangular string. Returns 0 for insecure and 1 for secure. Based on my answer to [Detect Failing Castles](https://codegolf.stackexchange.com/questions/109015), although it would be more efficient to test for an escaped prisoner at each step, rather than once they'd finished exploring the prison.
[Answer]
# [APL (Dyalog Classic)](https://www.dyalog.com/), 40 bytes
```
{⊃2≠(××{1⊃⌈/⍵,⍉⍵}⌺3 3)⍣≡(⌽1,⍉)⍣4⊢'# '⍳⍵}
```
[Try it online!](https://tio.run/##nU3LasJQEN3frxjI4ipUNNWVX3F/4aKkhAZSGjcibmxRk@aKLiS7onbrrrgRXOVPzo@kcxOpdiEFB@ZxzpyZo1@CRn@og/Cp0Qt0FPm9Aou1H2K6bBUe1xGSt0fEm1qe5dnIZYR03oQ5PMDE3MZIj21q12G@EG9rSE@u3VjcQbKTDkmYbyssikH5zxwQ71559HivLZVnzEQ8wXx2MZ@V35NJhI93TFelidl3paf9QGomZfgsx0IMyBXOdQiHFDlEipMsIqpSWfRHeeOYoyz/HrfucqZr50ol6NwqseWJLi7q14zl5@Q/SvwA "APL (Dyalog Classic) – Try It Online")
`'# '⍳⍵` encode `'#'`, `' '`, `'P'` as 0 1 2
`(⌽1,⍉)⍣4` surround with 1s
`(××{1⊃⌈/⍵,⍉⍵}⌺3 3)⍣≡` max-of-neighbours flood fill of non-zero cells
`⊃2≠` do we not have a 2 at the top left?
[Answer]
# Octave, ~~64~~ 55 bytes
```
@(a,z=padarray(a,[1 1]))~nnz(bwfill(z==35,1,1,4)&z>35);
```
[Try it online!](https://tio.run/##y08uSSxL/f/fQSNRp8q2IDElsagosRLIiTZUMIzV1KzLy6vSSCpPy8zJ0aiytTU21TEEQhNNtSo7Y1NN6/@JecUa0Xp6elzqyshAHchXCFBQVlAIAGIFCF9BAYIDIHw4UACqj9Xk@g8A "Octave – Try It Online")
or
[Verify all test cases!](https://tio.run/##pY5BCsIwFET3OcVAwCTQTaldScQjZF@6@NYWhFClVMWIXj1GU2qLG8EJP2Qg8@Yfqp7Otfee9I0Vgk8lwASHAQdMGHDx8kAcE/0sULIvRkQEva8/EL9tgSlCYNSQCX8xPmI8NgCfdiNKTDXgBOa4uMhQjxBi9xVjVW1tc2rlRlLi9JF21HV0DaZIkZZKPdrWye2l2VsrndZZnqThLNXCrbNcJaT8Ew "Octave – Try It Online")
Explanation:
```
z=padarray(a,[1 1])       %add a boundary(of 0s) around the scene
F = bwfill(z==35,1,1,4)   %flood fill the prison starting from the boundary
~nnz(F&z>35);             %if position of at least a prisoner  is filled then the prison is not secure 
```
[Answer]
# [Stax](https://github.com/tomtheisen/stax), 35 [bytes](https://github.com/tomtheisen/stax/blob/master/docs/packed.md#packed-stax)CP437
```
ä¬my■╡╤▲l@┤êr*⌠\¶ƒläå─▄¶√¿ [Uy⌠Só4↔
```
[Try it online!](https://staxlang.xyz/#c=%C3%A4%C2%ACmy%E2%96%A0%E2%95%A1%E2%95%A4%E2%96%B2l%40%E2%94%A4%C3%AAr*%E2%8C%A0%5C%C2%B6%C6%92l%C3%A4%C3%A5%E2%94%80%E2%96%84%C2%B6%E2%88%9A%C2%BF+%5BUy%E2%8C%A0S%C3%B34%E2%86%94&i=%23%23%23%23%23%23%23%23%23%23%23%23%23%0A%23+P+%23++P%23+++%23%0A%23+++%23+++%23+P+%23%0A%23%23%23%23%23%23%23%23%23%23%23%23%23%0A%0A%23%23%23%23%23%23%23%23%23%23%23%23%23%0A%23+P++++P++++%23%0A%23+++%23+++%23+P+%23%0A%23%23%23%23%23%23%23%23%23%23%23%23%23%0A%0A%23%23%23%23%23%23%23%23%23%23%23%23%23%0A%23+P+%23++P%23+++%23%0A%23+++%23+++%23+P+%23%0A%23%23%23%23%23%23%23%23%23%23+%23%23%0A%0A%23%23%23%23++++++++++%0A%23+++%23%0A+%23+++%23%0A++%23+P+%23%23%23%23%0A++%23%23%23%23%0A%0AP+++++++++++++%0A%0A%23%23%23+++++++++++%0A%23+%23%0A%23+%23%0A%23%23%23+P&a=1&m=1)
Surely golfing language without an internal to handle path-finding can do this as well!
## Explanation
Uses the unpacked format to explain.
```
zLz]Y+Mys+y+{{{" P|P ""PP"Rm}Y!My!Mgphh' =
zLz]Y+Mys+y+                                  Surround the original matrix with four borders of whitespaces
            {                      gp         Iterate until a fixed point is found, return the single fixed point
             {              }Y!               Store the block in register Y and execute it
              {" P|P ""PP"Rm                  For each row, flood every space adjacent to a P with P.
                               My!            Transpose the matrix and do the flooding again
                                     hh' =    The final matrix has a space on the upper left corner that has not been flooded by P 
```
[Answer]
# SmileBASIC, ~~154~~ 146 bytes
I was hoping an answer using flood fill would be shorter than this.
```
DEF S P
FOR J=0TO 1X=1Y=1FOR I=0TO LEN(P)-1GPSET X,Y,-(P[I]=="#")GPAINT X,Y,-1,-J*(P[I]>@A)X=X*(P[I]>"31")+1INC Y,X<2NEXT
NEXT?!GSPOIT(0,0)GCLS
END
```
Replace `31` with the corresponding ASCII character.
]