チェックメイトですか?


13

このサイトには多数のチェスのパズルがあるため、これがまだ投稿されていないことに完全に驚きました。私は自分でこれを考えていましたが、3月にサンドボックスに投稿したことについてAnushに感謝しますます。しかし、私は自分で先に進むことができるほど長いと思った。

チェスのチェックメイトは、キングが攻撃され、それを防御できる動きがない状況です。チェスの駒の動きに慣れていない場合は、ウィキペディアで詳しく知ることができます

チャレンジ

この挑戦のために、あなたのインプットはあなたが好きな表記法でチェス盤の位置になります。明確にするために、あなたの入力はチェス盤上の駒を色と位置とともに説明し、もしあれば可能性のある一時的な捕獲広場も示します。(キャッスルをチェックアウトすることはできないため、キャッスルする能力は無関係です。)FEN表記は便利ですが、便利なフォーマットであれば問題ありません。簡単にするために、あなたはそれがプレイする黒だと仮定することができます -これは、黒が常にチェックメイトされたプレイヤーであることを意味します。ホワイトがチェック、チェックメイト、またはステイルメイトにあるポジションは、このチャレンジでは無効と見なされます。

位置がチェックメイトの場合は真実の値を出力し、そうでない場合は偽の値を出力する必要があります。膠着状態はチェックメイトではないことに注意してください -キングを攻撃する必要があります!

真実のテストケース

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--

偽のテストケース

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(通行人を見てください!)

コードゴルフ-バイト単位の最短コードが勝ちます。幸運を!


2
これは素晴らしい質問のように見えます:)
アヌーシュ

1
自己完結型であるために-ここでのすべての課題はそうであるべき-これは、外部リンクに依存したり、チェスのルールと表記法に関する既存の知識を仮定するよりも、かなり肉付けする必要があります。作業中にSandboxに戻すことをお勧めします。
シャギー

3
@Shaggyこのチャレンジの外部リンクは、利便性のみを目的としています。他のほとんどのチェスの挑戦はそれらの予備知識を前提としているため、ここではチェスのすべてのルールをリストするつもりはありません。また、リンクスリンクは、テストケースの便利な視覚的表現としてのみ機能します。表記は、リッチの外側で明確に定義されています。画像を追加することはできましたが、多くの混乱のように感じたので、私はしないことにしました。
スキャター

1
ボードが有効なゲーム経由で到着したと仮定できますか?
ポストロックガーフハンター

1
コアタスクは同じですが、この課題にははるかに緩い(そして正直に良い)IOスキームとわずかに異なる(そして正直に良い)スコアリング基準があるため、これを再開しました。おそらく古いものは新しいもののduとして閉じられるべきだと思うが、私はそれを打つつもりはない。
ポストロックガーフハンター

回答:


10

JavaScript(Node.js) 499 ... 374  370バイト

(b)(X)bバツ1

以下は、各正方形の期待値です。

 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

オンラインでお試しください!

どうやって?

ボード代表

範囲外のターゲットスクエアを簡単に検出できるように、クラシック0x88ボード表現を使用します。

   |  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

エンコードを移動

動きの各セットは、5つのパラメーターでエンコードされます。

  • ピースの種類
  • 各方向に訪れることができる正方形の最大数
  • キャプチャが許可されているかどうかを示すフラグ
  • 非キャプチャが許可されているかどうかを示すフラグ
  • 道順のリスト

これらのパラメーターはすべて、単一のストリングにパックされています。たとえば、ナイトの動きは次のようにエンコードされます。

`&#!#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

与えるもの:

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

個別に処理されるen-passantキャプチャを除き、すべてのムーブセットを次の表にまとめます。

  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

コメント済み

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

8/1ppp4/1pkp4/8/2Q5/8/8/7K b - -
tsh

@tshより深刻なバグ。現時点では6バイトのコストで修正されています。
アーナルド

パッサンが可能かどうかを伝える表現なしでどのように機能しますか?
アヌーシュ

バツ

あぁ。どうもありがとう。
アヌーシュ

6

Haskell1165 1065 1053バイト

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)

オンラインでお試しください!

これは今のところ正確にゴルフされていませんが、スタートです。 途中でいくつかの助けを借りて、私はこれをかなり積極的にゴルフダウンしました(そして途中でエラーを修正しました)。

これがおそらく疑わしいことの1つは、王やポーンの通行人以外では、自分の駒の1つをキャプチャすることでチェックから逃れることはできないと想定していることです。チェスでは、この移動を行うことは許可されていませんが、私のプログラムでは、これらの移動を考慮してバイトを節約することを考慮しています。

そのような動きがあるため、この仮定は有効です

  1. 王が攻撃しているピースはキャプチャできないため、彼らがキャプチャするピースは黒です。

  2. 捕獲された黒の駒はすでにそれを行っていたため、王を攻撃している駒の経路をブロックすることはできません。

また、キングがいない場合はチェックインするという追加の規定を追加します。

また、このプログラムは、一時的に捕獲できるポーンが存在する場合、ポーンが最後に移動するピースであり、その移動は正当な移動であると仮定しています。これは、プログラムが黒のポーンを移動する正方形が空であるかどうかをチェックしないため、ピースがある場合、物事が少し厄介になる可能性があるためです。ただし、最後の動きが合法的な動きであり、さらにFENで表すことができない場合、これは取得できません。したがって、この仮定はかなり堅実に思えます。

参照用の「ゴルフ」バージョンは次のとおりです。

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)

オンラインでお試しください!


ゴルフのビットで1252バイト(TIOリンクが長すぎてこのコメントに収まりません...)
レオテネンバウム

@LeoTenenbaumありがとうございます。残念ながら、これを組み込む予定です。ゴルフをしているバージョンで、今修正した2つの偶発的なエラーがありました。確かに、この長いプログラムで多くの点で改善する余地があります。
ポストロックガーフハンター

@tshうん、私はそれが行く場所に王の場所を追加するのを忘れました。現在修正済み
ポストロックガーフハンター

リストの場合guard x = [0|x]、およびを使用x?y=Just(x,y)して、さらにいくつかのバイトを保存することもできます。1129バイト
レオテネンバウム

1

Python 3(PyPy)、729バイト

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'))

オンラインでお試しください!


現在、これは8/2p5/Q7/Q2k4/Q7/8/8/7K b - -(チェックメイトではなく)失敗します。
アーナルド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.