Jouez un coup d'échecs valide, avec un plateau sur stdin

11

Le programme est blanc.

Exemple stdin:

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

Exemple de sortie standard:

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

Tout mouvement valide est correct. "En passant" et le roque sont ignorés. Il est correct d'afficher des messages d'erreur ou de ne rien imprimer s'il n'y a pas de déplacement valide.

La réponse avec le plus de votes l'emporte.

Hristo Hristov
la source
Je veux dire un message d'erreur standard causé par l'échec d'une fonction intégrée de la langue. Alors ça va? - Est-il obligatoire que le programme puisse effectuer une démarche légale? Peut-être que les coups spéciaux de roque et de pion devraient être rendus optionnels avec un bonus?
cessé de tourner dans le sens inverse des aiguilles d'une montre le
2
@leftaroundabout: Chaque fois que vous pouvez roquer, vous pouvez simplement déplacer la tour à la place, vous pouvez donc ignorer la logique pour cela au moins.
hammar
2
... et en y réfléchissant un peu plus, le mouvement "en passant" nécessite des informations sur les mouvements précédents qui n'ont pas été déduits de la seule position des pièces, donc je suppose qu'il pourrait être sûr de laisser tomber cela. Cependant, si le double premier coup est disponible peut être déduit du rang du pion, vous voudrez peut-être l'inclure.
hammar
@hammar: vous avez raison, je n'y avais pas pensé. Le double coup n'est pas important non plus, sauf pour un cas: lorsque vous pouvez faire deux pas, vous pouvez aussi en faire un, donc cela ne devient important que lorsque vous êtes en échec et le double coup est le seul coup qui couvre le roi. De plus, même lorsque vous n'avez pas besoin de pouvoir utiliser chaque mouvement, vous devez toujours considérer que le noir peut répondre avec n'importe quelle possibilité.
cessé de tourner dans le sens inverse des aiguilles d'une montre le
9
La démission est-elle considérée comme une décision légale? :)
gnibbler

Réponses:

16

Je ne me plains pas des votes positifs, mais pour être juste ... ma solution ici n'est pas vraiment géniale. Ugoren est meilleur, à part le manque de support Unicode. Assurez-vous de regarder toutes les réponses avant de voter, si vous n'êtes tombé sur cette question que maintenant!
En tous cas.

Haskell, 893 888 904 952 (sans roque)

862 (sans double coup de pion)

(Vous n'avez pas précisé si c'était censé être du code golf, mais il me semble que ça devrait l'être)

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

Lorsque vous avez installé GHC (par exemple dans le cadre de la plate-forme Haskell ), vous pouvez simplement

$ runhaskell def0.hs < examplechessboard.txt
8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… ♘ … … ♟ … … …
4 ║… … … … … … … …
3 ║… … … … … … … …
2 ║♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h
a cessé de tourner dans le sens antihoraire
la source
Maintenant, c'est fou :) Je vais le vérifier :)
Hristo Hristov
Une idée de comment tester cette impression? Ideone.com ne peut pas le gérer ...
Hristo Hristov
@HristoHristov: étrange, cela ne fonctionne pas sur Ideone. Cela a probablement à voir avec les caractères non ASCII.
cessé de tourner dans le sens inverse des aiguilles d'une montre le
oui, c'est le problème avec ideone
Hristo Hristov
14
Félicitations, vous avez réussi à faire ressembler Haskell à APL. :-)
Ilmari Karonen
11

C, 734 672 640 caractères

Caractères comptés sans espace amovible.
Le format de fichier que j'ai utilisé n'est pas tel que demandé, mais ASCII simplifié.
J'ai besoin d'ajouter la prise en charge des caractères Unicode, cela coûterait quelques caractères.

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]]);
}

Format de fichier d'entrée / sortie:
Doit être exactement 8 lignes d'exactement 8 caractères. pnbrqksont utilisés pour les pièces blanches, PNBRQKpour les pièces noires, les espaces pour les espaces:

RNBQKBNR
PPPP PPP

 n  P


pppppppp
r bqkbnr

La logique est assez simple:
pour chaque mouvement possible de chaque pièce blanche, essayez chaque mouvement possible de chaque pièce noire.
Si aucun coup noir ne capture le roi blanc, le coup blanc est valide.

La carte est conservée comme char[256], traitée comme une matrice 16x16, où seul le 8x8 en haut à gauche est utilisé. Les positions et les vecteurs de mouvement sont conservés dans des entiers 8 bits ( x:4,y:4). Le bit supplémentaire permet d'utiliser une arithmétique simple ( new_pos = old_pos + steps*direction), avec une détection facile du bord de la carte ( &0x88fait la magie). r[]code trois choses:

  1. Les 15 premiers octets mappent les codes internes des pièces (K = 1, P = 2, N = 3, B = 4, R = 5, Q = 6) en lettres.
  2. Les 6 octets suivants mappent les codes de pièce internes aux décalages dans la dernière partie (K et Q sont les mêmes, B est leur queue).
  3. Les 16 derniers octets codent le mouvement de toutes les pièces, comme '('+vector.

Les fonctions:

  1. mainlit le tableau, convertit les lettres en code interne, appelle apour trouver des mouvements blancs, imprime le tableau.
  2. aboucle récursivement sur les 64 carrés. Pour chaque pièce de la bonne couleur (paramètre c), elle trouve la règle de déplacement de la pièce et appelle d.
  3. dboucle récursivement sur la règle de mouvement codée, qui est une liste de vecteurs, appelant epour chacun d'eux. Il donne ela position d'origine, le vecteur et la limite de portée (7 pour les pièces au-dessus de B, 2 pour les pions de deuxième rang, 1 sinon).
  4. eteste tous les mouvements le long d'un vecteur. Si le mouvement est possible (c'est-à-dire que les pions avancent, à l'intérieur du plateau, non bloqués, la capture du pion en diagonale), vérifie l'une des deux choses. Pour les coups blancs, exécute vpour valider le coup. Pour les coups noirs, vérifie si le roi blanc est capturé. Si c'est vrai, le coup est joué sur le plateau.
  5. vvalide un coup blanc. Il copie le tableau de côté, exécute le mouvement pour tester et appelle à anouveau pour rechercher les mouvements noirs.
ugoren
la source
Enfin une solution avec un bon encodage compressé des mouvements possibles! Et c'est bien rapide. Ne pensez-vous pas que vous pourriez ajouter un wrapper Unicode tout en étant plus court que mon code?
cessé de tourner dans le sens inverse des aiguilles d'une montre le
@leftaroundabout, je suppose que je peux. Le problème principal est que je travaille sur une ligne de commande Linux, où vous ne pouvez pas voir Unicode, donc le débogage serait ennuyeux. J'ai également une version qui enregistre environ 40 octets de plus (je mettrai à jour bientôt), j'ai donc beaucoup de caractères avec lesquels travailler.
ugoren
@ugoren: Sûrement n'importe quelle distribution Linux moderne à mi-chemin prend en charge UTF-8 hors de la boîte?
han
@han, je travaille sur Windows et je me connecte à Linux par SSH, et Unicode ne fonctionne pas. Je peux écrire dans un fichier et ouvrir dans Windows, mais ce n'est plus intéressant.
ugoren
Est-ce que cela se compilera avec gcc? J'utilise Geany pour Windows avec MinGW et il se compilera avec un tas d'erreurs et d'avertissements mais il ne sera pas généré / exécuté.eg: C: \ Users \ xxx \ AppData \ Local \ Temp \ ccpBG9zy.o: codegolfchess.c :(. text + 0x2d8): référence indéfinie à `bcopy 'collect2: ld a renvoyé 1 état de sortie
rpd
5

Python 2.6, 886 - 1425 caractères

Ma version initiale (dans les révisions) était de 886 caractères mais ne satisfaisait pas complètement la spécification (elle ne vérifiait pas pour éviter l'échec et échec; elle ne considérait même pas les mouvements possibles des pièces noires).

Maintenant c'est le cas (et j'ai corrigé plusieurs bugs dans l'original). Hélas, cela a un coût en caractères: 1425 pour l'instant, mais il devrait encore y avoir peu de place pour l'amélioration. Cette version devrait être beaucoup plus solide dans la gestion des cas de bord que la précédente.

#-*-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"

Exemple d'entrée et de sortie:

# CONTRIBUTION

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

8 ║♜ ♞ ♝… ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟… ♟ ♟ ♟
6 ║………………………
5 ║………… ♟………
4 ║………………… ♙ ♛
3 ║…………… ♙ ♙…
2 ║♙ ♙ ♙ ♙ ♙………
1 ║♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖
——╚════════════════
—— abcdefgh
ChristopheD
la source
C'est 886 octets, mais seulement 854 caractères. (Mon programme a plus de 1 Ko, grâce aux nombreux opérateurs non ASCII!) - Allez-vous ajouter une vérification pour prendre le roi?
cessé de tourner dans le sens inverse des aiguilles d'une montre le
@leftaroundabout: J'ai ajouté les chèques roi (ce qui m'oblige également à tenir compte des éventuels mouvements de noir, et ajoute beaucoup de personnages ...). Eh bien, cette version devrait être plus solide autour des cas de bord (pour autant que je l'ai testé).
ChristopheD