6
\$\begingroup\$

Task

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.

    First example


  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.

    second example


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

    third example


  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:

    fourth example

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!
\$\endgroup\$
6
  • \$\begingroup\$ Can't search guard chess on google, all is some variant with a piece named guard \$\endgroup\$
    – l4m2
    Commented Dec 22, 2022 at 18:23
  • \$\begingroup\$ @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.) \$\endgroup\$
    – Arnauld
    Commented Dec 22, 2022 at 18:29
  • 1
    \$\begingroup\$ Maybe add cases where tile is guarded but not attacked? \$\endgroup\$
    – l4m2
    Commented Dec 22, 2022 at 18:37
  • \$\begingroup\$ and case where king is double attacked. Likely one would just check the 3x3 range get attacked exactly once \$\endgroup\$
    – l4m2
    Commented Dec 22, 2022 at 18:39
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Dec 22, 2022 at 19:57

2 Answers 2

6
\$\begingroup\$

Python + chess, 175 166 161 bytes

def f(e):b=chess.Board(e);s=b.attacks(k:=b.king(0));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
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Why add king to generator? \$\endgroup\$
    – l4m2
    Commented Dec 23, 2022 at 19:10
  • \$\begingroup\$ @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 \$\endgroup\$
    – jezza_99
    Commented Dec 23, 2022 at 20:45
4
\$\begingroup\$

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
\$\endgroup\$
3
  • \$\begingroup\$ ?!(g[++k,[K,L]]^=1):0 can be &&!(g[++k,[K,L]]^=1) for -1 \$\endgroup\$ Commented Dec 29, 2022 at 13:09
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Dec 29, 2022 at 13:26
  • \$\begingroup\$ -5 by extracting the y*y \$\endgroup\$
    – emanresu A
    Commented Mar 11, 2023 at 8:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.