Jogue um movimento de xadrez válido, dado um tabuleiro em stdin

11

O programa toca em branco.

Exemplo stdin:

8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… … … … ♟ … … …
4 ║… … … … … … … …
3 ║… … ♘ … … … … …
2 ║♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h

Exemplo stdout:

8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… … … … ♟ … … …
4 ║… … … … ♙ … … …
3 ║… … ♘ … … … … …
2 ║♙ ♙ ♙ ♙ … ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h

Qualquer movimento válido está ok. "En passant" e castling são ignorados. Não há problema em mostrar mensagens de erro ou imprimir nada se não houver movimento válido.

A resposta com mais votos vence.

Hristo Hristov
fonte
Quero dizer uma mensagem de erro padrão causada por falha de alguma função interna do idioma. Então está tudo bem? - É obrigatório que o programa faça alguma mudança legal? Talvez jogadas especiais de castelos e peões devam ser opcionais com algum bônus?
deixou de girar no sentido anti-
2
@leftaroundabout: Sempre que você puder fazer um castelo, basta mover a torre, para que você possa pular a lógica disso pelo menos.
21712 hammar
2
... e pensando um pouco mais, o movimento "en passant" requer informações sobre quais movimentos anteriores foram feitos, o que não pode ser inferido apenas das posições das peças, então acho que pode ser seguro abandoná-lo. No entanto, se o primeiro movimento duplo está disponível pode ser inferido a partir da classificação do peão, então você pode incluir isso.
21712 hammar
@hammar: você está certo, eu não tinha pensado nisso. O movimento duplo também não é importante, exceto em um caso: quando você pode dar dois passos, você também pode dar um, por isso só se torna importante quando você está em jogo e o movimento duplo é o único movimento que cobre o rei. Além disso, mesmo quando você não precisa usar todos os movimentos, ainda precisa considerar que o preto pode responder com qualquer possibilidade.
deixou de girar no sentido anti-horáriowis
9
A demissão é contada como uma jogada legal? :)
gnibbler

Respostas:

16

Não estou reclamando de votos positivos, mas para ser justo ... minha solução aqui não é realmente tão boa assim. O Ugoren's é melhor, além da falta de suporte unicode. Certifique-se de examinar todas as respostas antes de votar, se você se deparar com essa pergunta apenas agora!
De qualquer forma.

Haskell, 893 888 904 952 (sem rosca)

862 (sem peões de movimentos duplos)

(Você não especificou se isso deveria ser código de golfe, mas parece-me que deveria)

χ=w⋈b;w="♙♢♤♔♕♖♗♘";b="♟♦♠♚♛♜♝♞"
μ=t⤀ζ++((\(x,y)->(x,-y))⤀)⤀μ;q c|((_,m):_)<-((==c).fst)☂(χ⋎μ)=m
t(x:y:l)=(d x,d y):t l;t _=[];d c=fromEnum c-78
ζ=["NM","NL","MMOM","MMMNMONMNOOMONOO",σ⋈δ,σ,δ,"MLOLPMPOOPMPLOLM"]
σ=l>>=(\c->'N':c:c:"N");δ=[l⋎l,reverse l⋎l]>>=(>>=(\(l,r)->[l,r]))
l="GHIJKLMOPQRSTU"
α c|c∊"♢♤"='♙'|c∊"♦♠"='♟'|c∊χ=c;π('♙':_)=6;π _=1
(⋎)=zip;(⤀)=map;(∊)=elem;(✄)=splitAt;(☂)=filter;(⋈)=(++)
φ r@(x,y)p a
 |x>7=φ(0,y+1)p a
 |y>7=[]
 |c<-a✠r=(c⌥r)p a y⋈φ(x+1,y)p a
(c⌥r)p a y
 |c==p!!0=(a☈r)c χ++const(y==π p)☂(a☈r)(p!!1)χ++(a☈r)(p!!2)('…':w)
 |c∊p=(a☈r)c χ
 |True=[]
a✠(x,y)=a!!y!!(x*2);o(x,y)=x>=0&&x<8&&y>=0&&y<8
(n➴a)(x,y)|(u,m:d)<-y✄a,(l,_:r)<-(x*2)✄m=u⋈(l⋈(n:r):d)
(a☈r@(x,y))c b=(α c➴('…'➴a)r)⤀((\r->o r&&not((a✠r)∊b))☂((\(ξ,υ)->(x+ξ,y+υ))⤀q c))
main=interact$unlines.uncurry((⋈).zipWith((⋈).(:" ║"))['8','7'..]
 .head.((all(any('♔'∊)).φ(0,0)b)☂).φ(0,0)w.(drop 3⤀)).(8✄).lines

Quando você tem o GHC instalado (por exemplo, como parte da plataforma Haskell ), você pode fazer apenas

$ runhaskell def0.hs < examplechessboard.txt
8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… ♘ … … ♟ … … …
4 ║… … … … … … … …
3 ║… … … … … … … …
2 ║♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h
deixou de girar contra-relógio
fonte
Agora isso é loucura :) Vou verificá-la :)
Hristo Hristov
Alguma idéia de como testar essa grandiosidade? Ideone.com não pode lidar com isso ...
Hristo Hristov
@HristoHristov: estranho, não funciona no Ideone. Provavelmente tem a ver com caracteres não ASCII.
deixou de girar no sentido anti-horáriowis
sim, este é o problema com ideone
Hristo Hristov
14
Parabéns, você conseguiu fazer o Haskell parecer APL. :-)
Ilmari Karonen
11

C, 734 672 640 caracteres

Caracteres contados sem espaço em branco removível.
O formato do arquivo que usei não é o solicitado, mas sim o ASCII simplificado.
Preciso adicionar suporte a caracteres Unicode, isso custaria alguns caracteres.

char*r=" kpnbrq  KPNBRQ $ ,&)$wxy()879()8(6:GI(",B[256],*b=B,i;
e(x,d,m,V,c,r,n,p){
    for(r=0,p=b[x];m/++r;){
        n=x+d*r;
        if(p==2+8*(d<0)||n&136||!(b[n]?r=8,8^p^b[n]^8&&c&65^64:c&65^65)
            ? r=m,0
            : V?v(n,x):b[n]==1)
            return b[x]=0,b[n]=p%8-2||n/16%7?p:p+4;
    }
    return d>0&&e(x,-d,m,V,c);
}
d(x,v,m,i)char*m;{
    return(i=*m-40)?e(x,i%64,b[x]%8-2?b[x]&4?7:1:(x/16-1)%5|i%2?1:2,v,i)||d(x,v,m+1):0;
}
v(t,f){
    bcopy(B,b+=128,128);
    b[t]=b[f];b[f]=0;
    i=a(1,63);
    b=B;
    return!i;
}
a(c,n){
    return b[i=n*2-n%8]&&b[i]/8==c&&d(i,!c,r+r[b[i]%8+15]-10)||n--&&a(c,n);
}
main(){
    for(;gets(b);b+=8)for(;*b;b++)*b=strchr(r,*b)-r;b=B;
    for(i=64*!a(0,63);i<64;i++%8-7||puts(""))putchar(r[b[i*2-i%8]]);
}

Formato de arquivo de entrada / saída:
deve ter exatamente 8 linhas de exatamente 8 caracteres. pnbrqksão usados ​​para peças brancas, PNBRQKpeças pretas, espaços para espaços:

RNBQKBNR
PPPP PPP

 n  P


pppppppp
r bqkbnr

A lógica é bastante simples:
para cada movimento possível de cada peça branca, tente cada movimento possível de cada peça preta.
Se nenhum movimento preto capturar o rei branco, o movimento branco é válido.

A placa é mantida como char[256], tratada como uma matriz 16x16, onde apenas o 8x8 superior esquerdo é usado. Posições e vetores de movimento são mantidos em números inteiros de 8 bits ( x:4,y:4). O bit extra permite o uso de aritmética simples ( new_pos = old_pos + steps*direction), com fácil detecção da borda da placa ( &0x88faz a mágica). r[]codifica três coisas:

  1. Os primeiros 15 bytes mapeiam códigos de peça internos (K = 1, P = 2, N = 3, B = 4, R = 5, Q = 6) em letras.
  2. Os próximos 6 bytes mapeiam os códigos internos das peças para compensar a última parte (K e Q são os mesmos, B é a sua cauda).
  3. Os últimos 16 bytes codificam o movimento de todas as peças, como '('+vector.

Funções:

  1. mainlê o quadro, converte letras em código interno, liga apara encontrar movimentos em branco, imprime o quadro.
  2. acircula recursivamente sobre os 64 quadrados. Para cada peça da cor certa (parâmetro c), ele encontra a regra de movimento da peça e chama d.
  3. dcircula recursivamente sobre a regra de movimento codificado, que é uma lista de vetores, chamando ecada um. Ele fornece ea posição original, o vetor e o limite do alcance (7 para peças acima de B, 2 para peões de segundo escalão, 1 caso contrário).
  4. etesta todos os movimentos ao longo de um vetor. Se o movimento for possível (por exemplo, os peões avançam, dentro do tabuleiro, não bloqueados, a captura de peões na diagonal), verifica uma das duas coisas. Para movimentos em branco, corre vpara validar o movimento. Para movimentos em preto, verifica se o rei branco foi capturado. Se verdadeiro, a jogada é jogada no tabuleiro.
  5. vvalida um movimento branco. Ele copia o quadro de lado, executa o movimento para testar e chama anovamente, para procurar movimentos em preto.
Ugoren
fonte
Por fim, uma solução com a codificação compactada adequada dos movimentos possíveis! E é bem rápido. Você não acha que poderia adicionar um invólucro Unicode e ainda ser menor que o meu código?
deixou de girar contra-
@leftaroundabout, acho que posso. O principal problema é que estou trabalhando em uma linha de comando do Linux, onde você não pode ver o Unicode, portanto, a depuração seria irritante. Eu também tenho uma versão que economiza cerca de 40 bytes (eu atualizarei em breve), por isso tenho muitos caracteres para trabalhar.
22412 ugoren
@ugoren: Certamente, qualquer distribuição Linux moderna a meio caminho suporta UTF-8 imediatamente?
han
@han, eu estou trabalhando no Windows e conectar ao Linux por SSH, e Unicode não funciona. Posso escrever em um arquivo e abrir no Windows, mas isso não é mais interessante.
23412 ugoren
Isso será compilado com o gcc? Estou usando o Geany for Windows com MinGW e ele será compilado com vários erros e avisos, mas não será compilado / executado.eg: C: \ Usuários \ xxx \ AppData \ Local \ Temp \ ccpBG9zy.o: codegolfchess.c :(. text + 0x2d8): referência indefinida para `bcopy 'collect2: ld retornou 1 status de saída
rpd
5

Python 2.6, 886 - 1425 caracteres

Minha versão inicial (nas revisões) tinha 886 caracteres, mas não satisfazia completamente as especificações (não checava se evitava o xeque-mate; nem considerava os possíveis movimentos das peças pretas).

Agora sim (e eu corrigi vários erros no original). Infelizmente, isso tem um custo em caracteres: 1425 por enquanto, mas ainda deve haver pouco espaço para melhorias. Esta versão deve ser muito mais sólida no tratamento de casos extremos do que a anterior.

#-*-coding:utf8-*-
import sys;e=enumerate
B,W=["♟","♜","♞","♝","♛","♚"],["♙","♖","♘","♗","♕","♔"]
R={"♙":[11,42],"♖":[28],"♘":[31],"♗":[8],"♕":[8,28],"♔":[1,21]}
def F(w):return sum([[(i,j)for j,p in e(o)if p==w]for i,o in e(Z)],[])
def G(x,y):
 P=Z[x][y];D=P in W;L=[]
 for o in R[P]if D else R[unichr(ord(P.decode('utf8'))-6).encode('utf8')]:
  r,k="%02d"%o        
  for g,h in[[(-1,-1),(1,1),(-1,1),(1,-1)],[[(1,-1),(1,1)],[(-1,-1),(-1,1)]][D],[(-1,0),(1,0),(0,-1),(0,1)],[(-2,-1),(-2,1),(-1,-2),(-1,2),(1,-2),(1,2),(2,-1),(2,1)],[(-1,0)]][int(r)]:
   J=0
   for i in range(int(k)):
    T=x+(i+1)*g;U=y+(i+1)*h
    if T<0 or T>7 or U<0 or U>7:break
    M=Z[T][U]
    if not J:L.append((T,U,P,M))
    else:break
    if r in"02"and(M in W+B):
     J=1
     if not((D and M in B)or(not D and M in W)):L.pop()
    elif(r=="1"and not((D and M in B)or(not D and M in W)))or(r=="4"and((i==1 and x!=6)or M!="…")):L.pop()
 return L  
Z=[[y for y in l[5:].split()]for l in sys.stdin.readlines()[:-2]]
Q=[]
for p in R:
 for i,j in F(p):
  for M,L,c,_ in G(i,j):
   O=Z[M][L];Z[i][j]="…";Z[M][L]=c;E=[];map(E.extend,map(F,B))
   if not any(any(1 for _,_,_,I in G(v,h)if I==["♔","♚"][c in B])for v,h in E):Q.append((i,j,M,L,c))
   Z[i][j]=c;Z[M][L]=O
(x,y,X,Y,p)=Q[0];Z[x][y]="…";Z[X][Y]=p
for i,h in e(Z):print`8-i`+' ║'+' '.join(h)
print"——╚"+"═"*16+"\n—— a b c d e f g h"

Exemplo de entrada e saída:

# ENTRADA

8 ♝ ♞ ♝… ♚ ♝ ♞ ♜
7 ♟ ♟ ♟ ♟… ♟ ♟ ♟
6………………………
5……………………
4…………………
3……………………
2 ♙ ♙ ♙ ♙ ♙…
1 ║♖ ♘ ♗ ♕ ♔ ♘ ♖
——╚═══════════════
- abcdefgh
# RESULTADO

8 ♝ ♞ ♝… ♚ ♝ ♞ ♜
7 ♟ ♟ ♟ ♟… ♟ ♟ ♟
6………………………
5……………………
4…………………
3…………………
2 ♙ ♙ ♙ ♙ ♙……
1 ║♖ ♘ ♗ ♕ ♔ ♘ ♖
——╚════════════════
- abcdefgh
ChristopheD
fonte
São 886 bytes, mas apenas 854 caracteres. (Meu programa tem mais de 1kB, graças aos muitos operadores não ASCII!) - Você ainda adicionará uma verificação para levar o rei?
deixou de girar contra-relógiowis
@leftaroundabout: Eu adicionei o cheque rei (o que me obriga a também considerar possíveis jogadas de preto e adiciona muitos caracteres ...). Bem, esta versão deve ser mais sólida em casos extremos (tanto quanto eu testei).
21712 ChristopheD