Apakah ini skakmat?

13

Sepenuhnya terkejut ini belum diposting, mengingat sejumlah besar teka-teki catur di situs. Sementara saya memikirkan hal ini sendiri, kredit untuk Anush karena mempostingnya ke kotak pasir kembali pada bulan Maret . Tapi saya pikir sudah cukup lama sehingga saya bisa melanjutkan dan melakukannya sendiri.

Sebuah skakmat dalam catur adalah posisi di mana raja diserang dan tidak ada langkah yang dapat mempertahankannya. Jika Anda tidak terbiasa dengan bagaimana bidak catur bergerak, Anda dapat membiasakan diri di Wikipedia .

Tantangan

Untuk tantangan ini, masukan Anda akan menjadi posisi papan catur dalam notasi apa pun yang Anda suka. Untuk memperjelas, input Anda akan menjelaskan potongan-potongan di papan catur, dengan warna dan posisinya, bersama dengan kotak tangkap en passant yang mungkin , jika ada. (Kemampuan untuk kastil tidak relevan karena Anda tidak dapat kastil tidak terkendali.) Anda mungkin menemukan notasi FEN berguna , tetapi format yang mudah digunakan baik-baik saja. Untuk kesederhanaan, Anda dapat menganggap itu Hitam untuk dimainkan - ini berarti Hitam akan selalu menjadi pemain skakmat. Posisi di mana White berada di check, skakmat, atau jalan buntu akan dianggap tidak valid untuk tantangan ini.

Anda harus menampilkan nilai yang benar jika posisi itu sekakmat, dan nilai yang salah jika tidak. Perhatikan bahwa jalan buntu bukanlah skakmat - raja harus diserang!

Kasus uji kebenaran

1k5R / 6R1 / 8/8/8/8/8 / 6K1 b - -

rn2r1k1 / pp1p1pQp / 3p4 / 1b1n4 / 1P2P3 / 2B5 / P5PP / R3K2R b - -

kr5R / rB6 / 8/8/8 / 5Q2 / 6K1 / R7 b - -

2K5 / 1B6 / 8/8/8 / 7N / R7 / R3r2k b - - 0 1

8 / 4Q1R1 / R7 / 5k2 / 3pP3 / 5K2 / 8/8 b - -

2K5 / 1B6 / 8/8/8 / 4b2N / R7 / 4r2k b - -

Kasus uji Falsey

rnbqkbnr / pppppppp / 8/8 / 4P3 / 8 / PPPP1PPP / RNBQKBNR b KQkq -

8/8/8/8/8 / 1KQ5 / 4N3 / 1k6 b - -

2K5 / 1B6 / 8/8/8 / 7N / R7 / 4r2k b - -

8/8 / 2Q5 / 3k4 / 3Q5 / 8/8 / 7K b - -

8 / 4Q1R1 / R7 / 5k2 / 3pP3 / 5K2 / 8/8 b - e3 (Awasi saat itu lewat!)

Golf kode - kode terpendek dalam byte menang. Semoga berhasil!

menyebarkan
sumber
2
Ini sepertinya pertanyaan yang bagus :)
Anush
1
Untuk kepentingan mandiri - yang seharusnya menjadi tantangan di sini - ini perlu disempurnakan lebih baik daripada mengandalkan tautan eksternal dan / atau mengasumsikan pengetahuan yang ada tentang aturan dan notasi catur. Saya sarankan membawanya kembali ke Sandbox saat sedang dikerjakan.
Shaggy
3
@Shaggy Tautan eksternal dalam tantangan ini hanya untuk kenyamanan. Saya tidak akan mencantumkan semua aturan catur di sini, karena sebagian besar tantangan catur lainnya mengandaikan pengetahuan mereka sebelumnya. Dan tautan lichess hanya berfungsi sebagai representasi visual yang berguna dari kasus uji; notasi didefinisikan dengan baik di luar lichess. Saya dapat menambahkan gambar tapi saya memutuskan untuk tidak merasa seperti banyak kekacauan.
bubar
1
Bisakah kita berasumsi bahwa papan telah diterima melalui permainan yang valid?
Post Rock Garf Hunter
1
Saya telah membuka kembali ini karena walaupun tugas utamanya sama, tantangan ini memiliki skema IO yang jauh lebih longgar (dan sejujurnya lebih baik) dan kriteria penilaian yang sedikit berbeda (dan jujur ​​lebih baik). Saya pikir mungkin yang lama harus ditutup sebagai tiruan dari yang baru tapi saya tidak akan memalu.
Post Rock Garf Hunter

Jawaban:

10

JavaScript (Node.js) ,  499 ... 374  370 byte

(b)(X)bX-1

Di bawah ini adalah nilai yang diharapkan untuk setiap kotak:

 0: empty square

 5: white pawn      6: black pawn
 9: white king     10: black king
17: white bishop   18: black bishop
33: white rook     34: black rook
49: white queen    50: black queen
65: white knight   66: black knight

640

b=>e=>(g=(c,k)=>b.map((v,p,h,s=p+(p&~7),M=t=>v&-~c?c?(B=[...b],K&=g(b[t?b[T]=b[p]:b[b[e-8]=0,e]=6,p]=0),b=B):k|=V&8:0,m=([a],[x,t,...d]=Buffer(a))=>d.map(c=>(h=n=>(V=(a+=c-66)&136?3:b[T=a+a%8>>1])&v&3||t>>!V&v>>x&n>31&&h(n-4/!V,M``))(t,a=s)))=>(v=b[p],m`##123ACQRS`,m`$?13QS`,m`%?2ACR`,m`&#!#04PTac`,c?(p-e+8.5&~1||M(),m`"!QS`,p<16?m`"&R`:m`""R`):m`"!13`))|k)(1,K=g())*K

Cobalah online!

Bagaimana?

Representasi dewan

Kami menggunakan representasi papan 0x88 klasik , sehingga kuadrat target di luar batas dapat dengan mudah dideteksi.

   |  a    b    c    d    e    f    g    h
---+----------------------------------------
 8 | 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 
 7 | 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 
 6 | 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 
 5 | 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 
 4 | 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 
 3 | 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 
 2 | 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 
 1 | 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77

Pindahkan pengodean

Setiap rangkaian gerakan dikodekan dengan 5 parameter:

  • jenis potongan
  • jumlah kotak maksimum yang dapat dikunjungi di setiap arah
  • sebuah bendera yang memberitahukan apakah penangkapan diizinkan
  • sebuah bendera yang memberi tahu jika non-tangkapan diperbolehkan
  • daftar arah

Semua parameter ini dikemas menjadi satu string. Misalnya, gerakan ksatria dikodekan sebagai berikut:

`&#!#04PTac`
 ||\______/
 ||    |                            +------> 0 + 1 = 1 square in each direction
 ||    |                            | +----> standard moves allowed
 ||    +---> 8 directions           | |+---> captures allowed
 ||                                / \||
 |+--------> ASCII code = 35 = 0b0100011
 |
 +---------> 1 << (ASCII code MOD 32) = 1 << 6 = 64

66

 char. | ASCII code | -66
-------+------------+-----
  '!'  |     33     | -33
  '#'  |     35     | -31
  '0'  |     48     | -18
  '4'  |     52     | -14
  'P'  |     80     | +14
  'T'  |     84     | +18
  'a'  |     97     | +31
  'c'  |     99     | +33

pemberian yang mana:

 [ - ] [-33] [ - ] [-31] [ - ]
 [-18] [ - ] [ - ] [ - ] [-14]
 [ - ] [ - ] [ N ] [ - ] [ - ]
 [+14] [ - ] [ - ] [ - ] [+18]
 [ - ] [+31] [ - ] [+33] [ - ]

Semua set gerakan dirangkum dalam tabel berikut, kecuali tangkapan en-passant yang diproses secara terpisah.

  string    | description             | N | S | C | directions
------------+-------------------------+---+---+---+----------------------------------------
 &#!#04PTac | knight                  | 1 | Y | Y | -33, -31, -18, -14, +14, +18, +31, +33
 ##123ACQRS | king                    | 1 | Y | Y | -17, -16, -15, -1, +1, +15, +16, +17
 "!13       | white pawn / captures   | 1 | N | Y | -17, -15
 "!QS       | black pawn / captures   | 1 | N | Y | +15, +17
 "&R        | black pawn / advance x2 | 2 | Y | N | +16
 ""R        | black pawn / advance x1 | 1 | Y | N | +16
 $?13QS     | bishop or queen         | 8 | Y | Y | -17, -15, +15, +17
 %?2ACR     | rook or queen           | 8 | Y | Y | -16, -1, +1, +16

Berkomentar

b => e => (
  // generate all moves for a given side
  g = (c, k) =>
    b.map((
      v, p, h,
      // s = square index in 0x88 format
      s = p + (p & ~7),
      // process a move
      M = t =>
        // make sure that the current piece is of the expected color
        v & -~c ?
          c ?
            // Black's turn: play the move
            ( // board backup
              B = [...b],
              // generate all White moves ...
              K &= g(
                // ... after the board has been updated
                b[
                  t ?
                    // standard move
                    b[T] = b[p]
                  :
                    // en-passant capture
                    b[b[e - 8] = 0, e] = 6,
                  p
                ] = 0
              ),
              // restore the board
              b = B
            )
          :
            // White's turn: just update the king's capture flag
            k |= V & 8
        :
          0,
      // generate all moves of a given type for a given piece
      m = ([a], [x, t, ...d] = Buffer(a)) =>
        d.map(c =>
          ( h = n =>
            ( // advance to the next target square
              V = (a += c - 66) & 136 ? 3 : b[T = a + a % 8 >> 1]
            )
            // abort if it's a border or a friendly piece
            & v & 3 ||
            // otherwise: if this kind of move is allowed
            t >> !V &
            // and the current piece is of the expected type
            v >> x &
            // and we haven't reached the maximum number of squares,
            n > 31 &&
            // process this move (if it's a capture, force n to
            // -Infinity so that the recursion stops)
            h(n - 4 / !V, M``)
          )(t, a = s)
        )
    ) =>
      (
        v = b[p],
        // king
        m`##123ACQRS`,
        // bishop or queen
        m`$?13QS`,
        // rook or queen
        m`%?2ACR`,
        // knight
        m`&#!#04PTac`,
        c ?
          // black pawn
          ( // en-passant capture
            p - e + 8.5 & ~1 || M(),
            // standard captures
            m`"!QS`,
            // standard moves
            p < 16 ? m`"&R` : m`""R`
          )
        :
          // white pawn (standard captures only)
          m`"!13`
      )
    ) | k
// is the black king in check if the Black don't move?
// is it still in check after each possible move?
)(1, K = g()) * K
Arnauld
sumber
8/1ppp4/1pkp4/8/2Q5/8/8/7K b - -
tsh
@ tsh Bug yang jauh lebih serius. Diperbaiki dengan biaya 6 byte untuk saat ini.
Arnauld
Bagaimana cara kerja tanpa representasi yang memberi tahu Anda jika lewat mungkin?
Anush
X
Aha. Terima kasih banyak.
Anush
6

Haskell , 1165 1065 1053 byte

Bytes disimpan berkat Leo Tenenbaum

n=Nothing
x?y=Just(x,y)
o(x,y)=x<0||y<0||x>7||y>7
m#k@(x,y)|o k=n|1>0=m!!x!!y
z(x,y)m p(a,b)|o(x+a,y+b)=1<0|Just g<-m#(x+a,y+b)=elem g[(p,0),(5,0)]|1>0=z(x+a,y+b)m p(a,b)
t(x,y)p(a,b)m|o(x+a,y+b)=[]|g<-(x+a,y+b)=(g%p)m++do[0|m#g==n];t g p(a,b)m
c m|(x,y):_<-[(a,b)|a<-u,b<-u,m#(a,b)==6?1],k<-z(x,y)m=or$[m#(x+a,y+b)==6?0|a<-0:s,b<-0:s]++do a<-s;[k 3(a,b)|b<-s]++(k 2<$>[(a,0),(0,a)])++[m#l==4?0|b<-[2,-2],l<-[(x+a,y+b),(x+b,y+a)]]++[m#(x-1,y+a)==p?0|p<-[0,1]]
c m=1>0
(k%p)m=[[[([p|a==k]++[m#a])!!0|a<-(,)b<$>u]|b<-u]|not$o k]
w(Just(_,1))=1<0
w x=1>0
m!u@(x,y)|g<-m#u,Just(q,1)<-g,v<-((u%n)m>>=),r<-v.t u g,k<-(do[0|n==m#(x+1,y)];(u%n)m>>=(x+1,y)%g)++(do a<-s;[0|n<m#(x+1,y+a)];v$(x+1,y+a)%g)++(do[0|(x,n,n)==(1,m#(x+1,y),m#(x+2,y))];v$(x+2,y)%g)++(do a<-s;[0|1?0==m#(x,y+a)];v((x,y+a)%n)>>=(x+1,y+a)%g)=[k,k,do a<-s;[(a,0),(0,a)]>>=r,do a<-s;b<-s;r(a,b),do a<-s;b<-[2,-2];l<-[(x+a,y+b),(x+b,y+a)];v$l%g,do a<-0:s;b<-[0|a/=0]++s;r(a,b),do a<-[x-1..x+1];b<-[y-1..y+1];[0|w$m#(a,b)];v$(a,b)%g]!!q
m!u=[]
u=[0..7]
s=[1,-1]
q m=all c$m:do a<-u;b<-u;m!(a,b)

Cobalah online!

Ini bukan golf yang tepat seperti sekarang, tapi ini awal. Dengan beberapa bantuan di sepanjang jalan, saya sekarang telah menurunkan ini dengan cukup agresif (dan memperbaiki kesalahan di sepanjang jalan).

Satu hal yang mungkin dipertanyakan adalah apakah ini mengasumsikan bahwa, selain oleh seorang raja atau pion dalam perjalanan, Anda tidak akan pernah bisa keluar dari cek dengan mengambil salah satu karya Anda sendiri. Dalam catur, Anda tidak diizinkan untuk melakukan langkah ini, tetapi program saya menganggap langkah-langkah ini untuk menghemat byte dengan asumsi bahwa jika Anda berada dalam kendali, ini tidak akan pernah bisa mengeluarkan Anda dari itu.

Asumsi ini berlaku karena bergerak seperti itu

  1. Tidak dapat menangkap bidak yang menyerang raja, karena bidak yang mereka ambil berwarna hitam.

  2. Tidak dapat memblokir jalan potongan yang menyerang raja, karena potongan hitam yang ditangkap sudah melakukan itu.

Kami juga menambahkan ketentuan tambahan bahwa jika Anda tidak memiliki raja, Anda berada dalam kendali.

Program ini juga membuat asumsi bahwa jika ada pion yang dapat ditangkap secara diam-diam, maka pion itu adalah bagian terakhir untuk dipindahkan dan langkah itu adalah langkah legal. Ini karena program tidak memeriksa apakah kuadrat itu memindahkan pion hitam menjadi kosong sehingga jika ada bagian di sana hal-hal bisa sedikit kacau. Namun ini tidak dapat diperoleh jika langkah terakhir adalah langkah hukum dan selanjutnya tidak dapat diwakili dalam FEN . Jadi anggapan ini agaknya solid.

Ini adalah versi "ungolfed" saya untuk referensi:

import Control.Monad
out(x,y)=x<0||y<0||x>7||y>7
at b (x,y)
  |out(x,y)=Nothing
  |otherwise=(b!!x)!!y
inLine (x,y) ps m (a,b) 
  | out (x+a,y+b) = False
  | elem (m `at` (x+a,y+b)) $ Just <$> ps = True
  | m `at` (x+a,y+b) == Nothing = inLine (x+a,y+b) ps m (a,b) 
  | otherwise = False
goLine (x,y) p (a,b)m
  | out (x+a,y+b) = []
  | otherwise = case m `at` (x+a,y+b) of
--    Just (n,1) -> []
    Just (n,_) -> set(x+a,y+b)p m
    Nothing    -> set(x+a,y+b)p m ++ goLine(x+a,y+b)p(a,b)m
checkBishop (x,y) m=or[inLine(x,y)[(3,0),(5,0)]m(a,b)|a<-[1,-1],b<-[1,-1]]
checkRook   (x,y) m=or$do
  a<-[1,-1]
  inLine(x,y)[(2,0),(5,0)]m<$>[(a,0),(0,a)]
checkKnight (x,y) m=any((==Just(4,0)).(at m))$do
  a<-[1,-1]
  b<-[2,-2]
  [(x+a,y+b),(x+b,y+a)]
checkPawn (x,y) m=or[at m a==Just(p,0)|a<-[(x-1,y+1),(x-1,y-1)],p<-[0,1]]
checkKing (x,y) m=or[at m(a,b)==Just(6,0)|a<-[x-1..x+1],b<-[y-1..y+1]]
check m
  | u:_<-[(a,b)|a<-[0..7],b<-[0..7],(m!!a)!!b==Just(6,1)] =
    checkBishop u m ||
    checkRook   u m ||
    checkKnight u m ||
    checkPawn   u m ||
    checkKing   u m
  | otherwise = True
set (x,y) p m=[[[head$[p|(a,b)==(y,x)]++[(m!!b)!!a]|a<-[0..7]]|b<-[0..7]]|not$out(x,y)]
white(Just(n,0))=True
white x=False
moves m (x,y)
 |g<-m `at` (x,y)=case g of
  Just(2,1) -> do
    a<-[1,-1]
    b<-[(a,0),(0,a)]
    set(x,y)Nothing m>>=goLine (x,y) g b
  Just(3,1) -> do
    a<-[1,-1]
    b<-[1,-1]
    set(x,y)Nothing m>>=goLine (x,y) g(a,b)
  Just(4,1) -> do
    n<-set(x,y)Nothing m
    a<-[1,-1]
    b<-[2,-2]
    l<-[(x+a,y+b),(x+b,y+a)]
    -- guard$white$n `at` l
    set l g n
  Just(5,1) -> do
    a<-[1,-1]
    c<-[(a,0),(0,a),(a,1),(a,-1)]
    set(x,y)Nothing m>>=goLine (x,y) g c
  Just(6,1) -> do
    a<-[x-1..y+1]
    b<-[x-1..y+1]
    guard$white(m `at`(a,b))||Nothing==m`at`(a,b)
    set(x,y)Nothing m>>=set(a,b)g
  Just(n,1) -> (do
    guard$Nothing==m `at` (x+1,y)
    set(x,y)Nothing m>>=set(x+1,y)g) ++ (do
      a<-[1,-1]
      guard$white$m`at`(x+1,y+a)
      set(x,y)Nothing m>>=set(x+1,y+a)g) ++ (do
        guard$(x,Nothing,Nothing)==(1,m`at`(x+1,y),m`at`(x+1,y))
        set(x,y)Nothing m>>=set(x+2,y)g) ++ (do
          a<-[1,-1]
          guard$Just(1,0)==m`at`(x,y+a)
          set(x,y)Nothing m>>=set(x,y+a)Nothing>>=set(x+1,y+a)g)
  _ -> []
checkmate m=all check$m:do
  a<-[0..7]
  b<-[0..7]
  moves m(a,b)

Cobalah online!

Posting Rock Garf Hunter
sumber
1252 byte dengan sedikit bermain golf (tautan TIO terlalu panjang untuk ditampung dalam komentar ini ...)
Leo Tenenbaum
@ LeoTenenbaum Terima kasih banyak saya akan memasukkan ini segera sayangnya ada dua kesalahan tidak disengaja dalam versi yang Anda bermain golf dari yang sekarang saya sudah perbaiki. Pasti ada ruang untuk meningkatkan dalam banyak hal dengan program selama ini.
Posting Rock Garf Hunter
@tsh ya, saya lupa menambahkan lokasi raja ke tempat tujuan. diperbaiki sekarang
Post Rock Garf Hunter
Untuk daftar,, guard x = [0|x]dan Anda juga dapat menggunakan x?y=Just(x,y)untuk menyimpan beberapa byte lagi: 1129 byte
Leo Tenenbaum
1

Python 3 (PyPy) , 729 byte

F=lambda a,b:a<'^'<=b or a>'^'>=b
def m(b,P,A=0):
 yield b
 for(r,f),p in b.items(): 
  if F(P,p):continue
  *d,n,k={'R':[(0,1),8,4],'N':[(1,2),(2,1),2,4],'B':[(1,1),8,4],'Q':[(0,1),(1,1),8,4],'K':[(0,1),(1,1),2,4],'P':[(2,0),(1,0),(1,1),(1,-1),2,1],'p':[(-2,0),(-1,0),(-1,1),(-1,-1),2,1]}[p if p=='p'else p.upper()]
  if p in'pP':d=d[d!=[2,7][p=='p']+A:]
  for u,v in d:
   for j in range(k):
    for i in range(1,n):
     U=r+u*i;V=f+v*i;t=b.get((U,V),'^')
     if U<1or U>8or V<1 or V>8:break
     if F(p,t):
      B=dict(b);B[(U,V)]=B.pop((r,f))
      if t in'eE':B.pop(([U+1,U-1][t=='e'],V))
      yield B
     if t not in'^eE':break
    u,v=v,-u
M=lambda b:all(any('k'not in C.values()for C in m(B,'W',1))for B in m(b,'b'))

Cobalah online!

RootTwo
sumber
Saat ini gagal untuk 8/2p5/Q7/Q2k4/Q7/8/8/7K b - -(bukan skakmat).
Arnauld