# Background

Puzzlang is a derivative of Brainfuck, where the symbol X executes a BF command based on three characters on top of it, and anything else does nothing.

The following is the translation table for Puzzlang, where X is the literal X and . stands for anything else:

 >      <      +      -      .      ,      [      ]

..X    X..    XXX    ...    .X.    X.X    XX.    .XX
X      X      X      X      X      X      X      X


Also, the entire source code wraps around both horizontally and vertically at the translation step. For example, the following code is an infinite loop:

XX X


since you can view the code like this (the dots are where the wrapped X's would go)

... ..
.XX X.


and matching with the translation table gives +[] for the three X's in order.

Nightmare Puzzlang is an evil twin of the regular Puzzlang. In Nightmare Puzzlang, each X translates into a byte based on its eight neighbors. Any non-X characters translate into nothing. The wrapping rule is the same.

Since there is no "official" specification, let's assume that the following pattern (where X denotes the one to translate)

abc
dXe
fgh


translates to abcdefgh in binary (X is one, non-X is zero). Then the following code

XX...
X..X.
X..XX
X..XX
X.XX.


translates to 4a b4 66 03 56 4b bf d2 6e fd c3 2c 70 in hex, or J´fVK¿ÒnýÃ,p as a string. Note that the resulting string will very likely have ASCII unprintables.

Translate the given Nightmare Puzzlang code into a string.

# Input & output

For input, you can take 2D array of chars, list of strings, or a single string whose lines are delimited by newlines. You can assume that the input is rectangular in shape, i.e. row lengths are equal.

For output, you can give a single string, a list of chars, or a list of charcodes.

# Test Cases

Note that the result must remain the same when any of the dots are replaced with anything else other than the capital X.

X (1 row, 1 column)
String: ÿ
Charcode: [255]

X. (1 row, 2 columns)
String: B
Charcode: [66]

X
. (2 rows, 1 column)
String: 
Charcode: [24]

X.
.X
String: ¥¥
Charcode: [165, 165]

X.X
.X.
String: 1Œ¥
Charcode: [49, 140, 165]

X.X
XX.
X.X
String: ÓmÎµv«
Charcode: [211, 109, 206, 181, 118, 171]

X.XX.XXX..XXXX.
String: BkÖkÿÖkÿÿÖ
Charcode: [66, 107, 214, 107, 255, 214, 107, 255, 255, 214]

X.XX.XXX.XXXXX.
XX.X..XX....X..
String: c­R){Ö9Z”JµÆïÖç
Charcode: [99, 173, 82, 41, 123, 214, 8, 24, 57, 90, 148, 74, 181, 198, 239, 214, 231]

X
X
X
.
.
X
.
X
X
.
X
String: ÿÿøø
Charcode: [255, 255, 248, 24, 31, 248, 31]

XX
X.
XX
.X
.X
XX
..
XX
XX
..
.X
String: º]ç]ºâG¸Xøø
Charcode: [186, 93, 231, 93, 186, 226, 71, 184, 88, 31, 31, 248, 248, 7]

XX XXX XX  XX
X  X X X X X
X  X X X X XX
X  X X X X X
XX XXX XX  XX

XXX XXX X  XX
X   X X X  X
X X X X X  XX
X X X X X  X
XXX XXX XX X
(11 rows, 13 columns, no extra padding, result has two newlines)
zôª}òªuJ½æbÂb‚cRBBBBJ½ÇCFCDcXH¸PH°H¸

æbÂBcRBBBJ½ÃFCFCbO¾UO¾UN”C
Charcode: [122, 244, 170, 125, 242, 170, 117, 74, 189, 230, 98, 194, 98, 130, 99, 82, 66, 66, 66, 66, 74, 189, 199, 67, 70, 67, 68, 99, 88, 144, 72, 184, 80, 72, 176, 72, 184, 26, 28, 16, 10, 29, 18, 2, 10, 29, 230, 98, 194, 66, 99, 82, 2, 66, 66, 66, 74, 189, 195, 70, 67, 70, 67, 98, 79, 190, 85, 79, 190, 85, 78, 148, 67]


# Rules

Standard rules apply. The shortest submission in bytes wins.

# Python 3, 166162 161 bytes

lambda p,r=range:[chr(int(''.join(str(+([n*2for n in p+p][y+i//3-1][x+i%3-1]=='X'))for i in r(9)if i-4),2))for y in r(len(p))for x in r(len(p[0]))if'X'==p[y][x]]


Takes as input a list of strings and returns a character array.

Try It Online!

Ungolfed (sorta):

def f(p):
chars = []
for y in range(len(p)):
for x in range(len(p[0])):
if p[y][x] != 'X':
continue
bits = []
for i in range(9):
if i == 4:
continue
bit_x = x + i%3 - 1
bit_y = y + i//3 - 1
char_at_cell = [n*2for n in p+p][bit_y][bit_x]
bit = str(+(char_at_cell=='X'))
bits.append(bit)
char_code = int(''.join(bits), 2)
chars.append(chr(char_code))
return chars


Edit: made shorter by 5 bytes thanks to Jo King and Jonathan Frech

• Since the function ins't recursive, you don't need to assign the lambda. 162 bytes – Jo King Sep 21 '18 at 6:46
• oh nice, didn't know that you could remove that, cheers. Just writing up the ungolfed version and will add in your changes – Cameron Aavik Sep 21 '18 at 6:49
• Note that the slash's orientation matters. You used / -- a slash -- to continue a line in C-style, use a backslash: \ . – Jonathan Frech Sep 23 '18 at 5:59
• You can golf your one != to a -. – Jonathan Frech Sep 23 '18 at 6:01

# JavaScript (ES6), 159 bytes

Takes input as a 2D array of characters. Returns an array of character codes.

f=M=>M.map((r,y)=>r.map((v,x)=>v>f&&o.push([...'22211000'].map((k,j)=>s|=(M[(y+h+~-k)%h][(x+w+~-'21020'[j%5])%w]>f)<<j,h=M.length,w=M[s=0].length)|s)),o=[])&&o


Try it online!

### Commented

f = M =>                        // f = main function taking the input matrix
//     it is named because we are later using '>f'
M.map((r, y) =>               // for each row r[] at position y in M[]:
r.map((v, x) =>             //   for each value v at position x in r[]:
v > f &&                  //     ignore this cell if v is not equal to 'X'
o.push(                   //     otherwise, push a new value in o[]:
[...'22211000']         //       iterate over dy values (+1)
.map((k, j) =>          //       for each value k at position j in this array:
s |= (                //         update s:
M[(y + h +          //           compute the row
~-k)              //           by adding dy = k - 1
% h]              //           and applying a modulo h
[(x + w +           //           compute the column
~-'21020'[j % 5]) //           by adding dx = [2,1,0,2,0,2,1,0][j] - 1
% w]              //           and applying a modulo w
> f                 //           test whether this cell is a 'X'
) << j,               //         and set the corresponding bit in s if it is
h = M.length,         //         initialize h = matrix height
w = M[s = 0].length   //         initialize w = matrix width and s = bitmask
) | s                   //       end of map() over dy; yield s
)                         //     end of push()
),                          //   end of map over r[]
o = []                      //   initialize o = output array
) && o                        // end of map over M[]; return o