9
\$\begingroup\$

Alternatively: Now you're checking with portals!

Inspired this challenge

I am somewhat of a self-declared Chess Anarchist. That means that when I play chess, en passant is forced (else the brick gets used), double check is mate (and pasta), and all sorts of new pieces and squares are added to the game.

One such piece is the Knook (also called an "Empress" or "Chancellor" in fairy chess). It moves like a horsey and a rook combined. Another common addition are portals, like the kinds you see in the Portal series. They behave as you would expect.

Therefore, in this challenge, I'll be give you the position of a white knook, two black kings and an orange and blue portal. You'll give me the square I should move my knook to in order to check both the kings at once and win the game.

Detailed Explanation of Knooks and Portals

The Knook

Here is how a knight moves in chess:

enter image description here

Here is how a rook moves in chess:

enter image description here

Therefore, this is how a knook (knight + rook) moves in chess:

enter image description here

In BCPS notation, it's move is EM. In Parlett notation, it's move is n+, ~ 1/2. In Betza notation, it's move is RN.

Portals

From the Portal Wiki:

Portals in a pair act as a direct link between one another. Anything that goes into one portal comes instantly out the other.

Therefore, when a piece moves into a portal, it comes out the other portal. Portals occupy a single square. There are only ever two portals on a board - one orange and one blue. Pieces cannot land on a portal, as they'd just infinitely teleport between the orange and blue portals. Pieces can also attack through portals (so a piece in a position where another piece could exit a portal would be able to be taken.)

Here's are some examples of how a rook would move through a portal. Note that it always exits the other portal in the direction it entered the first portal. Note that the rook also cannot "jump" over the portal - it has to go through if there is a portal in its way.

Here's how a knight would move through portals. Note that it can either move two squares into a portal and exit one square in a perpendicular direction, or one square into a portal and exit two squares in a perpendicular direction.

Therefore, this is how a knook would move through a portal, obeying laws of both the rook and knight portal movement rules:

An Example

On the following board, the knook is on square b2, the black kings are on d7 and f6 and the portals are on squares b5 and d2. The winning move is to move the knook through the blue portal to d5, which checks the king on d7 via rook moves and the king on f6 via knight moves.

On the following board, the knook is on square c5, the black kings are on g3 and h4 and the portals are on squares f7 and g4. The winning move is to move the knook to d7, as the knook threatens to take the king on h4 with rook moves after portal travel and threatens to take the king on g3 with knight moves after portal travel.

On the following board, the knook is on square f4. The black kings are on b8 and d3. The portals are on squares f6 and a4. The winning move is to move the knook through the portal on d6 and exit the portal on a4 via a knight move (up 2, right 1). This checks both kings.

Rules

  • The positions will be given in algebraic chess notation (letter then number of the square).
  • The winning move will be returned in algebraic chess notation.
  • Positions can be given and returned in any reasonable and convienient format, including:
    • A list of strings (e.g. ["f4", "b8", "d3", "f6", "a4"])
    • A list of list of strings (e.g. [["f", "4"], ["b", "8"], ["d", "3"], ["f", "6"], ["a", "4"]])
    • A list of list of numbers that represent the character codes of each string item (e.g. [[102, 52], [98, 56], [100, 51], [102, 54], [97, 52]])
    • A list of string, number pairs (e.g. [["f", 4], ["b", 8], ["d", 3], ["f", 6], ["a", 4]])
  • Input formats and output formats don't have to match, so long as they are consistent.
  • Piece positions can be taken in any order (e.g. [portal 1, portal 2, knook, king 1, king 2] or [knook, king 1, king 2, portal 1, portal 2])
  • This doesn't change much, but you can assume that the black kings will never be on the c2 square.
  • You may assume that there will always be at least one solution to each input.
  • The board layout may start with 0 or 1 king(s) already in check. Your goal is to double check.
  • Double check is strictly defined as checking both kings for this challenge. A knook checking a king through a portal and starting in check is counted as a single check only for simplicity.
  • It doesn't matter if a king can capture the knook if double check is achieved. All that matters is that both kings are in check at the same time.
  • If there is more than one solution, you can output one, or all of the solutions.
  • Portal travel might not be required for a winning move. Double check via normal knook movement is just as valid as portal usage.
  • This is , so the shortest answer in bytes in each language wins.

Testcases

Input order is [knook, king 1, king 2, portal 1, portal 2]

Positions -> Winning Square
["b2", "d7", "f6", "b5", "d2"] -> "d5"
["c5", "g3", "h4", "f7", "g4"] -> "d7"
["f4", "b8", "d3", "f6", "a4"] -> "a4"
["h1", "a1", "a3", "c1", "f1"] -> "b1"
["c2", "a8", "h8", "d2", "d6"] -> "d8"
["d2", "c6", "g2", "b2", "g7"] -> "g6"
["d3", "f6", "h6", "d4", "e4"] -> "g4"
["c4", "f7", "h5", "a2", "f5"] -> "b2" // Attacks through the portal
["h5", "a7", "e2", "a4", "g6"] -> "g3" // Attacks a7 through the portal and e2 normally.
["h6", "d4", "g3", "a1", "a8"] -> "f5" // No portal travel needed
\$\endgroup\$
23
  • 2
    \$\begingroup\$ @FryAmTheEggman as stated in the introduction: "double check is mate (and pasta)". This isn't your regular chess game. This is the anarchist's game! Therefore, it doesn't matter if a king can take the knook. Also, it's stated in the rules that there may be more than one solution. \$\endgroup\$
    – lyxal
    Commented Jan 31, 2023 at 1:53
  • 1
    \$\begingroup\$ you actually put all the anarchy chess memes into a codegolf challenge what has this world come to \$\endgroup\$
    – pacman256
    Commented Jan 31, 2023 at 2:10
  • 1
    \$\begingroup\$ Can the knook choose to not use a portal? For example if it's on f3 and there is a portal on d3 can it move to d2 or c3? \$\endgroup\$
    – loopy walt
    Commented Jan 31, 2023 at 3:30
  • 1
    \$\begingroup\$ @loopywalt as shown in the last test case, portal travel is not required \$\endgroup\$
    – lyxal
    Commented Jan 31, 2023 at 3:58
  • 2
    \$\begingroup\$ @loopywalt if it's a knight move, it can jump over the portal. Rooks however will go through the portal \$\endgroup\$
    – lyxal
    Commented Jan 31, 2023 at 4:21

3 Answers 3

7
\$\begingroup\$

Python3, 970 bytes:

M=[((1,0),1,3),((0,1),0,2),((-1,0),1,3),((0,-1),0,2)]
def A(c):
 q=[(c[0],i,1,[c[0]])for i,*_ in M]+[(c[0],[(i,2),(M[j][0],1)],0,[c[0]])for i,*J in M for j in J]+[(c[0],[(i,1),(M[j][0],2)],0,[c[0]])for i,*J in M for j in J]
 while q:
  (x,y),m,o,P=q.pop(0)
  if o:
   X,Y=m
   if 0<=x+X<8 and 0<=y+Y<8:
    if(T:=(x+X,y+Y))in P:continue
    if T in c[1:3]:yield(1,T)
    elif T in c[-2:]:q+=[([*{*c[-2:]}-{T}][0],m,o,P+[T])]
    else:yield(0,T);q+=[(T,m,o,P+[T])]
  else:
   [(X,Y),C],*I=m
   if 0<=x+X<8 and 0<=y+Y<8:
    if(T:=(x+X,y+Y))in P:continue
    if C-1==0 and[]==I:yield(T in c[1:3],T)
    else:
     if T in c[-2:]and C-1:continue
     q+=[([T,[*{*c[-2:]}-{T}][0]][T in c[-2:]],[[[(X,Y),C-1]]+I,I][C-1==0],0,P+[T])]
def f(d):
 S,*c=[(8-int(b),ord(a)-97)for a,b in d]
 q,s=[S],[S]
 while q:
  S=q.pop(0)
  for x,y in A([S]+c):
   q+=[y]
   if x==0:
    k=[[],[]]
    for X,Y in A([y]+c):k[X]+=[Y]
    if{*k[1]}=={*([1]+c)[1:3]}:return chr(97+y[1])+str(8-y[0])

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ I think replacing the continues with 0s and then replacing the next ifs with elifs will save a few bytes. (The TIO link is too long to put in this comment.) \$\endgroup\$
    – The Thonnu
    Commented Feb 1, 2023 at 9:51
  • \$\begingroup\$ i.e. if(T:=(x+X,y+Y))in P:continue; if T in c[1:3]:yield(1,T) becomes if(T:=(x+X,y+Y))in P:0; elif T in c[1:3]:yield(1,T) and you can do the same for the other one. \$\endgroup\$
    – The Thonnu
    Commented Feb 1, 2023 at 9:52
  • \$\begingroup\$ "d5", "d2", "d4", "e5", "e6" should be "e4" \$\endgroup\$
    – tsh
    Commented Feb 2, 2023 at 6:56
4
\$\begingroup\$

JavaScript (Node.js), 367 bytes

(R,J,K,$,_)=>(
  U=p=>parseInt(p,36),     // internal type
  P=U($),Q=U(_),           // Portal
  g=n=>(                   // p^P^Q switch P and Q
    M=(p,a,b)=>a?M((p+=a)-P&&p-Q?p:p^P^Q,b):p==n,
                           // Two movements for knight
    h=(p,x)=>
      [1,2,-1,-2].some((i,_,o)=>o.some(j=>
        i*i-j*j&&M(U(p),i*36,j)|M(U(p),j,i*36)
      ))|                  // X then Y; Y then X
      (e=(w,i=24,q=U(p))=>q-U(x)?
                           // Maximum 13 moves + w%36 range 8
        (q+=w)-P&&q-Q?
          w%36<i&&q==n|e(w,i-1,q)
        :
          e(w,i,q^P^Q)     // Not counting teleport don't hurt
      )(36)|e(-36)|e(1)|e(-1):0
  )(R)&h(J,K)&h(K,J)&~-n%36<8&
  !~[J,K,$,_].indexOf(N=n.toString(36))?N:g(-~n)
)(360)

Try it online!

Modified to list all possible outputs

[ 'b2', 'd7', 'f6', 'b5', 'd2' ] [ 'b6', 'd5', 'd6' ]
[ 'c5', 'g3', 'h4', 'f7', 'g4' ] [ 'd7', 'f5', 'h5' ]
[ 'f4', 'b8', 'd3', 'f6', 'a4' ] [ 'b4' ]
[ 'h1', 'a1', 'a3', 'c1', 'f1' ] [ 'b1', 'c2' ]
[ 'c2', 'a8', 'h8', 'd2', 'd6' ] [ 'c8', 'd8' ]
[ 'd2', 'c6', 'g2', 'b2', 'g7' ] [ 'a7', 'c2', 'c7', 'e7', 'g6' ]
[ 'd3', 'f6', 'h6', 'd4', 'e4' ] [ 'g4' ]
[ 'c4', 'f7', 'h5', 'a2', 'f5' ] []
[ 'h5', 'a7', 'e2', 'a4', 'g6' ] [ 'g3' ]
[ 'h6', 'd4', 'g3', 'a1', 'a8' ] [ 'f5', 'g4' ]
\$\endgroup\$
3
  • \$\begingroup\$ "d5", "d2", "d4", "e5", "e6" should be "e4" \$\endgroup\$
    – tsh
    Commented Feb 2, 2023 at 6:56
  • \$\begingroup\$ @tsh Fast fixed \$\endgroup\$
    – l4m2
    Commented Feb 2, 2023 at 9:11
  • \$\begingroup\$ seem new issue that die in \$\endgroup\$
    – l4m2
    Commented Feb 2, 2023 at 9:13
3
\$\begingroup\$

Charcoal, 194 163 bytes

UMθ⍘ι⁴⁰≔E²⊟θδF⁸FE⁸⁺κ⁺⁴⁰¹×⁴⁰ι¿¬№⁺θδκ«≔⟦⟧ηFθ«≔⊙⊞OΦ⟦δ⮌δ⟧⬤⟦κλ⟧№⟦¹¦²¦⁴⁰¦⁸⁰⟧↔⁻ξ§μπυ№⟦³⁸¦⁴²¦⁷⁹¦⁸¹⟧↔⁻⁻λκ↨μ±¹ζF⟦¹¦⁴⁰±¹±⁴⁰⟧«≔κεF¹⁵«≧⁺με≧⁺⁼λεζ¿№δε≦⁻Σδε¿‹⁰⌕θε≔⁰μ»»⊞ηζ»¿⌊η⟦⍘κ⁴⁰

Try it online! Link is to verbose version of code. Explanation:

UMθ⍘ι⁴⁰

Inspired by @l4m2's use of base conversion, convert the inputs from "base 40" (chosen to make it easier for me to calculate the various constants).

≔E²⊟θδ

Split off the portal squares.

F⁸FE⁸⁺κ⁺⁴⁰¹×⁴⁰ι¿¬№⁺θδκ«

Loop over each potential square, converted into a "base 40" value, but excluding the input squares.

≔⟦⟧η

Start counting the number of pieces this square attacks.

Fθ«

Loop over the knook and the two kings.

≔⊙⊞OΦ⟦δ⮌δ⟧⬤⟦κλ⟧№⟦¹¦²¦⁴⁰¦⁸⁰⟧↔⁻ξ§μπυ№⟦³⁸¦⁴²¦⁷⁹¦⁸¹⟧↔⁻⁻λκ↨μ±¹ζ

Check whether the portals are near to the two squares (trying both permutations of squares near to different portals), then also considering the case of a regular knight's move away, see whether the squares are a knight's move away, and if any of the three cases succeeds then mark this square as attackable.

F⟦¹¦⁴⁰±¹±⁴⁰⟧«

Loop over all possible rook movements.

≔κε

Start at one square.

F¹⁵«

Repeat 15 times.

≧⁺με

Move one square in the current direction.

≧⁺⁼λεζ

If this is the target square then mark it as attackable.

¿№δε≦⁻Σδε

If it's a portal then jump through it.

¿‹⁰⌕θε≔⁰μ

If it's a king then stop moving.

»»⊞ηζ

Keep count of the number of pieces that were attackable.

»¿⌊η⟦⍘κ⁴⁰

Output the square if all three were attackable, meaning that the knook can move to this square, and from this square can check both kings.

\$\endgroup\$

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.