# Is this position a pure mirror mate?

A pure mirror checkmate is a checkmate position, where the mated king is surrounded by 8 empty squares which are attacked or guarded by the winning side exactly once. You will be given a valid chess position where Black is in mate. Your task is to find if that mate is a pure mirror checkmate.

#### Examples (click for larger images)

1. This is a pure mirror mate. Squares f5, g5, are protected by the king only, h5, h6, h7 by the rook only and f6, f7, g7 by the two knights only.

1. This position does not match the criteria. It is a mirror mate, but it's not pure, as d7 is guarded by the bishop and attacked by the rook.

1. This position is not a pure mirror mate as well, since the king is not surrounded by 8 empty squares.

1. This is a pure mate, but not a mirror mate (not all 8 squares surrounding the king are empty), therefore it doesn't meet the criteria:

## Input

As mentioned above, your input will be a valid chess position, where black will be in mate. You may take the input as an FEN or as a grid/matrix/2D array. From the examples above:

1. first position:

4N2N/4q3/6k1/8/5K2/8/8/7R

. . . . N . . N
. . . . q . . .
. . . . . . k .
. . . . . . . .
. . . . . K . .
. . . . . . . .
. . . . . . . .
. . . . . . . R

2. second position

8/R7/4k3/2P3P1/3K4/7B/8/8

. . . . . . . .
R . . . . . . .
. . . . k . . .
. . P . . . P .
. . . K . . . .
. . . . . . . B
. . . . . . . .
. . . . . . . .

3. third position

7b/8/8/5N2/8/7k/5N2/7K

. . . . . . . b
. . . . . . . .
. . . . . . . .
. . . . . N . .
. . . . . . . .
. . . . . . . k
. . . . . N . .
. . . . . . . K

4. fourth position:

2NN4/4k3/1b2NNb1/8/6N1/8/6K1/q6n

. . N N . . . .
. . . . k . . .
. b . . N N b .
. . . . . . . .
. . . . . . N .
. . . . . . . .
. . . . . . K .
q . . . . . . n


## Rules

• The chess position will always be valid and black will always be in mate.
• There will be no double checks (the king won't be attacked twice).
• You can receive input through any of the standard IO methods.
• This is , so shortest code in bytes wins!
• Can't search guard chess on google, all is some variant with a piece named guard
– l4m2
Dec 22, 2022 at 18:23
• @l4m2 In this context, S guarded by X means that the square S is not currently attacked by the white piece X but it would be if the black king moves there. (Like the white bishop on d7 in the 2nd test case.) Dec 22, 2022 at 18:29
• Maybe add cases where tile is guarded but not attacked?
– l4m2
Dec 22, 2022 at 18:37
• and case where king is double attacked. Likely one would just check the 3x3 range get attacked exactly once
– l4m2
Dec 22, 2022 at 18:39
• @l4m2 the original definition says double check is allowed if the mate could be parried without it. For simplicity, in the positions given, there will be no double checks. Dec 22, 2022 at 19:57

# Python + chess, 175166 162 bytes

def f(e):b=chess.Board(e);k=b.king(0);s=b.attacks(k);b.remove_piece_at(k);return(any(len(b.attackers(1,q))>1or b.piece_at(q)for q in s)or len(s)<8)^1
import chess


Attempt This Online!

-9 bytes thanks to rule clarification by @l4m2
-4 bytes because I realised I could just use chess.Board instead of chess.BaseBoard

Takes the fen as input and outputs 1 for a pure mirror mate and 0 otherwise. Using the chess library certainly made this easier. Explanation:

def f(e):
b=chess.Board(e)                # Generates the board with the input fen
k=b.king(0)                     # Finds the square of the black king
s=b.attacks(k)                  # Get a generator of all squares surrounding the king by finding the squares he attacks
b.remove_piece_at(k)            # Remove the king from the square to allow us to find guarded squares
return(
any(                        # If any of the following return True
[len(b.attackers(1,q))>1# There is more than one attacker
or b.piece_at(q)    # Or there is a piece present
for q in s]         # In the squares surrounding the king
)or                     # or
len(s)<8                    # There are less than 8 squares surrounding the king
)^1                         # Flip boolean and return

• Why add king to generator?
– l4m2
Dec 23, 2022 at 19:10
• @l4m2 to check that there is only one piece putting the king in check. For some reason I thought that was a criteria, but reading the comments it doesn't need to check for that Dec 23, 2022 at 20:45

# JavaScript (Node.js), 381 334 330 bytes

B=>(Q=q=>B.some((b,i)=>b.some((R,j)=>q?+q?'*kk'[(K-i)**2+(L-j)**2]==R&&!(Q[++k,[K,L]]^=1):!eval(q,x=I-i,y=J-j)&R=='.'&&Q(1,K=i,L=j):(I=i,J=j,h=(m,n,r=4,p=i+m,q=j+n,x=B[K=p])=>x&&(x[L=q]in{k,'.':0})?Q(1)|h(m,n,r,p+m,q+n):r&&h(n,-m,r-1),z={N:x*x-5,P:-x,K:x*x>2}[R])?Q('y*y+'+z):R in{R,Q}&&h(1,0)||R in{B,Q}&&h(1,1))))(k=0)|k<8


Try it online!

-2 bytes from Kevin Cruijssen

-4 bytes from emanresu A

foo = a=>g1(k=0)|k<8;
g1 = q=>a.some((b,i)=>b.some((c,j)=>(
I=i,J=j,
c=='N'?g2((x,y)=>x*x+y*y-5): // Knight
c=='P'?g2((x,y)=>y*y-x):
c=='K'?g2((x,y)=>x*x+y*y>2):
c=='R'?h(1,0):
c=='B'?h(1,1):
c=='Q'?h(1,1)|h(1,0):
0
)));
g2 = q=>a.some((b,i)=>b.some((c,j)=>
!q(I-i,J-j)&  // Correct destination
c=='.'&&      // Empty
g3(1,K=i,L=j) // then go
));
g3 = q=>a.some((b,i)=>b.some((c,j)=>
[,1,1][(K-i)**2+(L-j)**2]&c=='k'? // Near king
!(g[M=[K,L]]=!g[++k,M]) // count as an attack
:0                      // and memory the pos
));
h = (m,n,r=4,p=i+m,q=j+n,x=a[K=p])=>
x&&(x[L=q]=='.'|x[q]=='k')? // Not blocked
g3(1)|h(m,n,r,p+m,q+n):      // Next step
r&&h(n,-m,r-1) // rotate 90 degree

• ?!(g[++k,[K,L]]^=1):0 can be &&!(g[++k,[K,L]]^=1) for -1 Dec 29, 2022 at 13:09
• Actually, same applies to the c=='Q'?h(1,1)|h(1,0):0 -> c=='Q'&&h(1,1)|h(1,0) for another -1 byte. Dec 29, 2022 at 13:26
• -5 by extracting the y*y Mar 11 at 8:34