# Is the king in check?

Challenge:
Given a 2D array (8x8) of characters, is the enemy king in check?
The program should return true if and only if the king is currently in check.
Standard chess rules apply.

Specifications:
The game is provided using a 2D array,
where blank space means there is not a piece on that square.
You may assume that the only characters that will appear
in the array are one of: [SPACE]kpnbrqKPNBRQ

The 2D array is given as a y-major array
that starts from the bottom left (a1 square),
which means accessing the array would be: board[row][column].
For example: board[0][0] is a1, and board[3][5] is f4

Character set:
King - K
Pawn - P
Knight - N
Bishop - B
Rook - R
Queen - Q

Your own pieces are in uppercase, and the enemy pieces are in lowercase.
Also, enemy pieces only serve the purpose of blocking a check, so they are essentially the same as pawns.

Test case:

In this game, the given array would be:

r bqk  r
p pp Bpp
pn  n
p  Q
b PP
P
PP   PPP
RNB K NR


and should return true. Note that even if the bishop on f7 wasn't protected, it should still return true.

Happy golfing!

• Related: Is it checkmate?. Commented Feb 24 at 15:08
• Why this input instead of FEN?
– qwr
Commented Feb 24 at 22:45
• @qwr I think this input needs a lot less explanation (and possibly less code) than Forsyth Edwards Notation, which is generally known only by chess fans. Commented Feb 25 at 1:45
• Because the board orientation matters for pawn moves, I think you should clarify how the black and white pieces are arranged, rather than just mentioning your own pieces and enemy pieces. Commented Feb 28 at 11:45
• @Arnauld It is specified that the a1 square is the first entry of the array. I thought it would've implied the orientation of the board. Commented Feb 28 at 13:04

# Charcoal, 95 bytes

≔⪫ＥθＳ¶η¿⊙⌕ＡηN⁼⁵ΣＸ⟦⁻÷ι⁹÷⌕ηk⁹⁻﹪ι⁹﹪⌕ηk⁹⟧²-«Ｐη…η⌕ηk≔Ｅ⁸ＫＤ⁹✳ιζ⎚∨⊙✂ζ⁵χ²⁼§ι¹P⊙ζ№⊞Ｏ⟦Q⟧§RBκ§Φι⊙…ι⊕μ∧π⁻ ν¹


Try it online! Link is to verbose version of code. Outputs a Charcoal boolean, i.e. - for in check, nothing if not. Explanation:

≔⪫ＥθＳ¶η


Input the board and join it on newlines.

¿⊙⌕ＡηN⁼⁵ΣＸ⟦⁻÷ι⁹÷⌕ηk⁹⁻﹪ι⁹﹪⌕ηk⁹⟧²-«


If there is a knight a knight's move away from the king, then output a -, otherwise:

Ｐη…η⌕ηk≔Ｅ⁸ＫＤ⁹✳ιζ⎚


Temporarily write the board to the canvas so that all of the ranks, files and diagonals to the king can be extracted.

∨⊙✂ζ⁵χ²⁼§ι¹P⊙ζ№⊞Ｏ⟦Q⟧§RBκ§Φι⊙…ι⊕μ∧π⁻ ν¹


Check for pawns that are checking the king and check the first piece in every direction for a piece that can check the king from that direction.

# JavaScript (ES6), 188 bytes

Expects a matrix of characters and returns a Boolean value.

f=(m,P,X,Y)=>m.some((r,y)=>r.some((p,x)=>P?{N:(H=x-X,H*=H)+(v=y-Y)*v-5,B:B=H-v*v|(g=A=>u=(c=m[A+=-(A>Y)|A<Y][x+=-(x>X)|x<X])!=P&&c>g|g(A))(y),R:u|=H*=v,Q:B*u,P:H-1}[p]+P=='0k':f(m,p,x,y)))


Try it online!

## Position editor

f=(m,P,X,Y)=>m.some((r,y)=>r.some((p,x)=>P?{N:(H=x-X,H*=H)+(v=y-Y)*v-5,B:B=H-v*v|(g=A=>u=(c=m[A+=-(A>Y)|A<Y][x+=-(x>X)|x<X])!=P&&c>g|g(A))(y),R:u|=H*=v,Q:B*u,P:H-1}[p]+P=='0k':f(m,p,x,y)))
let board = document.getElementById("board"), pce = document.getElementById("pce"), b = [...Array(8)].map(_ => Array(8).fill(-1)), sel = 5; b[1][2] = 6; b[2][4] = 4; setClick(board, (x, y) => { b[y][x] = b[y][x] == sel ? -1 : sel; draw(); }); setClick(pce, (x, y) => { sel = x * 6 + 5 - y; draw(); }); draw(); function setClick(el, callback) { el.addEventListener("click", e => { let o = el.getBoundingClientRect(); callback(e.clientX - o.left >> 5, e.clientY - o.top >> 5); }) } function draw() { let html = "", m = []; for(let y = 0; y < 8; y++) for(let x = 0; x < 8; x++) { html += <div class="sq ${x + y & 1 ? "dark" : "light"}">${~b[y][x] ? &#${9812 + b[y][x]}; : ""}</div>; (m[y] = m[y] || [])[x] = " KQRBNPkqrbnp"[b[y][x] + 1]; } document.getElementById("res").innerHTML = f(m) ? "YES" : "NO"; board.innerHTML = html; html = ""; for(let y = 0; y < 6; y++) for(let x = 0; x < 2; x++) html += <div class="sq${x * 6 + 5 - y == sel ? "sel" : x + y & 1 ? "dark" : "light"}">&#{9817 + x * 6 - y};</div>; pce.innerHTML = html; } body { font-family:Arial; } #board { float:left; width:256px; height:256px; } #pce { float:left; margin-left:32px; width:64px; height:192px; } .sq { float:left; width:32px; height:32px; line-height:32px; text-align:center; font-size:30px; cursor:pointer; } .dark { background-color:#7ab; } .light { background-color:#9cd; } .sel { background-color:#fd4; } <p>Black king in check: <span id="res"></span></p><div id="board"></div><div id="pce"></div> ## Commented ### Main function f = ( // f is a recursive function taking: m, // m[] = input matrix P, // P = piece on the target square X, Y // (X, Y) = position of the target square ) => // m.some((r, y) => // for each row r[] at index y in m[]: r.some((p, x) => // for each piece p at index x in r[]: P ? // if P is defined (2nd pass): { // N: ..., // \ test whether the target square is B: ..., // | attacked by the source square (x, y) R: ..., // |-- according to the piece p Q: ..., // | these tests (which are detailed below) P: ... // / return 0 for truthy }[p] // + P // append P to the result == '0k' // if we get '0k', the enemy king is attacked : // else (1st pass): f(m, p, x, y) // do a recursive call, using the current // square as the target square ) // end of inner some() ) // end of outer some()  ### Knight test ( // define: H = x - X, // H = (x - X)² H *= H // ) + ( // and: v = y - Y // v = y - Y ) * v // - 5 // test whether H + v² = 5, which may only happen // if we have H = 4, v² = 1 or H = 1, v² = 4  ### Bishop test B = // save the result in B H - v * v | // we must have H = v² ( g = A => // g is a recursive function u = // which sets a flag u if the path from the source ( // square to the target square is blocked: c = // c is the value of the square that is reached m[ // when we move towards the target square A += -(A > Y) // by adding the sign of Y - A to A | A < Y // ][ // x += -(x > X) // and adding the sign of X - x to x | x < X // ] // ) != P && // stop when c = P c > g | // set u if c is greater than or equal to 'B' // (i.e. the square is not empty) g(A) // recursive call )(y) // initial call to g with A = y  ### Rook test u |= H *= v // we must have u = 0 and either H = 0 or v = 0  ### Queen test B * u // queen = bishop * rook  ### Pawn test H - 1 // we must have (x - X)² = 1 and y - Y = 1 // and H is now (x - X)² * (y - Y)  ### King test Assuming that the position is valid, a king may not be attacked by the other king. Therefore, there is no test at all for king attacks. # Ruby, 192 170 167 166 bytes ->s{z=!k=/k/=~s+=/*9
72.times{|i|i%8<1?(C=D=i/8%3+i/24*9-10;J=k):" "!=W&&D=0
z||="RQBP"[~C%2,C/8>i%16?3:2]=~/#{W=s[J+=D]}/||s[i]*((i%9-k%9)*(i/9-k/9))**2==?N*4}
!!z}


Try it online!

Function taking a newline separated string as an argument. See meta for discussion of equivalence of strings and arrays, and use of sentinel values as separators/terminators. A final newline is required (It would cost 1 byte $/*9->$/*10 to remove this requirement.) The two !! at the end ensure a clean true/false value is returned. Deleting them would save 2 bytes but return only a truthy/falsy output.

Explanation

Take a 72-character argument consisting of 8 lines each of 9 characters including the final newline. Add 9 newlines $/to the end. The newlines will act as non-space characters and prevent scanning from circling round to the other side of the board. Assign k to the index of the king by regex /k/. Assign false=!k to z. Iterate 72 times (scan up to 8 squares from the king in 9 possible directions. Simultaneously scan all 72 characters for knights.) ->s{z=!k=/k/=~s+=$/*9
72.times{|i|


If i%8==0 set J to the location of the king and select a new direction C=D to scan in. Offsets for horizontal scanning are i/8%3-1=[-1,0,1] Offsets for vertical scanning are i/8/3*9-9=[-9,0,9]. Combining these gives diagonal scanning +/-10 and +/-8. 0+0=0 is also generated as a ninth possible offset but makes no difference to the result. If i%8>0 check if the last character scanned W was a space, and if not set D=0 to prevent further scanning in that direction.

i%8<1?(C=D=i/8%3+i/24*9-10;J=k):" "!=W&&D=0


Check the character at s[J+=D] advancing J in direction D. Depending on the value of C select the values of character that would threaten the king. Where C is odd +/-1,+/-9 they start at index 0: RQ. Where C is even +/-8,+/-10 they start at index 1: QBP. Pawns should only be checked for on the first step in a diagonal direction i%16=0 and where the y direction is positive C/8>0.

z||="RQBP"[~C%2,C/8>i%16?3:2]=~/#{W=s[J+=D]}/


Check also for knights, which threaten the king on squares s[i] where (i%9-k%9)*(i/9-k/9) is +/-2. Squaring this gives 4. We take the character at s[i] and multiply by the numerical value giving a string of identical characters, then check if equal to the string ?N*4="NNNN". This is fewer bytes than separate string and numerical checks.

||s[i]*((i%9-k%9)*(i/9-k/9))**2==?N*4


Close the iteration loop and clean up the final value z from truthy/falsy to true/false by inverting twice.

}
!!z}


# Python 3, 258 bytes

I thought I'd try my own challenge cuz why not. It's not terrible but it could be better. I'll try to post an explanation when I have time.

Takes a 2D array (just like the challenge description).

f=lambda b:any(['PN'[(p:=z-60)>0]in(g:=f"{(' '*16).join(map(''.join,b)):^576}")[(k:=g.find('k'))-p]+(p>0)*g[k+p]for z in b'%#mkVR']+[((t:=g[k-8*n:k+8*n:n])[9+(i<0)*i:8+(i>0)*i].split()==[])*(t[i+8]in'RBQQ'[n<0::2])for n in[1,24,-23,-25]for i in range(-8,8)])


# Perl 5-MList::Util=pairmap, 316 286 bytes

sub{map{map{($r,$c)=($t,$_)if($l=$_[$t][$_])eq'k';push@n,$t,$_ if'N'eq$l}0..7;++$t}@_;map{$v.=$_[$u=$r+$_][$c];$x.=$c+$_>=0&&$_[$u][$c+$_];$y.=$c-$_>=0&&$_[$u][$c-$_];}-$r..7-$r;(pairgrep{abs(($r-$a)*($c-$b))==2}@n)|(grep/[QR] *k|k *[QR]/,$v,"@{$_[$r]}")|grep/kP|[QB] *k|k *[QB]/,$x,\$y}


Try it online!