Сыграйте правильный шахматный ход, получив доску на stdin

11

Программа играет белым.

Пример stdin:

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

Пример stdout:

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

Любой действительный ход в порядке. «En passant» и рокировка игнорируются. Можно нормально показывать сообщения об ошибках или ничего не печатать, если нет действительного перемещения.

Ответ с наибольшим количеством голосов побеждает.

Христо Христов
источник
Я имею в виду стандартное сообщение об ошибке, вызванное сбоем какой-либо встроенной функции языка. Так что все в порядке? - Обязательно ли, чтобы программа могла сделать любой законный ход? Возможно, специальные ходы рокировки и пешки следует сделать необязательными с некоторым бонусом?
перестал поворачиваться против часовой стрелки с
2
@leftaroundabout: Всякий раз, когда вы можете делать замок, вы можете просто вместо этого перемещать ладью, так что вы можете пропустить логику для этого, по крайней мере.
Хаммар
2
... и, подумав еще немного, ход "en passant" требует информации о том, что были сделаны предыдущие ходы, что не может быть выведено только из позиций фигур, поэтому я думаю, что было бы безопасно отбросить это. Однако то, доступен ли двойной первый ход, может быть выведено из ранга пешки, так что вы можете включить это.
Хаммар
@hammar: ты прав, я не думал об этом. Двойной ход также не важен, за исключением одного случая: когда вы можете сделать два шага, вы также можете сделать один шаг, поэтому он становится важным только тогда, когда вы находитесь под контролем, и двойной ход - единственный ход, который охватывает короля. Кроме того, даже если вам не нужно использовать каждый ход, вам все равно нужно учитывать, что черные могут ответить с любой возможностью.
перестал поворачиваться против часовой стрелки с
9
Отставка считается легальным ходом? :)
gnibbler

Ответы:

16

Я не жалуюсь на голосование против, но, честно говоря, мое решение здесь не так уж и хорошо. Угорен лучше, кроме отсутствия поддержки юникода. Обязательно посмотрите все ответы перед голосованием, если вы сталкивались с этим вопросом только сейчас!
Так или иначе.

Haskell, 893 888 904 952 (без рокировки)

862 (без пешечных удвоений)

(Вы не указали, должен ли это быть код гольф, но мне кажется, что так и должно быть)

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

Когда у вас установлен GHC (например, как часть платформы Haskell ), вы можете просто

$ runhaskell def0.hs < examplechessboard.txt
8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… ♘ … … ♟ … … …
4 ║… … … … … … … …
3 ║… … … … … … … …
2 ║♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h
перестал поворачиваться против часовой стрелки
источник
Теперь это безумие :) Я проверю это :)
Христо Христов
Любая идея, как проверить эту удивительность? Ideone.com не может справиться с этим ...
Христо Христов
@ ХристоХристов: странно, это не работает на Ideone. Вероятно, имеет отношение к не-ASCII символам.
перестал поворачиваться против часовой стрелки с
да, это проблема с идеоном
Христо Христов
14
Поздравляю, вам удалось заставить Haskell выглядеть как APL. :-)
Илмари Каронен
11

C 734 672 640 знаков

Символы учитываются без съемных пробелов.
Формат файла, который я использовал, не соответствует требованиям, но упрощен ASCII.
Мне нужно добавить поддержку символов Unicode, это будет стоить несколько символов.

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

Формат файла ввода / вывода:
должно быть ровно 8 строк ровно по 8 символов. pnbrqkиспользуются для белых фигур, PNBRQKдля черных фигур, пространства для пробелов:

RNBQKBNR
PPPP PPP

 n  P


pppppppp
r bqkbnr

Логика довольно проста:
для каждого возможного хода каждой белой фигуры, попробуйте каждый возможный ход каждой черной фигуры.
Если ни один черный ход не захватывает белого короля, белый ход действителен.

Плата поддерживается в char[256]виде матрицы 16x16, где используется только верхний левый 8x8. Позиции и векторы движения хранятся в 8-битных целых числах ( x:4,y:4). Дополнительный бит позволяет использовать простую арифметику ( new_pos = old_pos + steps*direction), с легким обнаружением края доски ( &0x88делает волшебство). r[]кодирует три вещи:

  1. Первые 15 байтов отображают внутренние коды частей (K = 1, P = 2, N = 3, B = 4, R = 5, Q = 6) в буквы.
  2. Следующие 6 байтов отображают внутренние коды частей на смещения в последней части (K и Q одинаковы, B - их хвост).
  3. Последние 16 байтов кодируют движение всех фигур, как '('+vector.

Функции:

  1. mainчитает доску, конвертирует буквы во внутренний код, звонит, aчтобы найти белые ходы, печатает доску.
  2. aрекурсивно зацикливается на 64 квадратах. Для каждого куска правильного цвета (параметра c) он находит правило перемещения для куска и вызывает d.
  3. dрекурсивно зацикливается на закодированном правиле движения, которое представляет собой список векторов, вызывающих eкаждый из них. Он дает eисходную позицию, вектор и предел диапазона (7 для фигур выше B, 2 для пешек второго ранга, 1 в противном случае).
  4. eпроверяет все движения по вектору. Если ход возможен (т.е. пешки движутся вперед, внутри доски, не заблокированы, пешка захватывается по диагонали), проверяется одна из двух вещей. Для белых ходов, пробеги, vчтобы проверить ход. Для черных ходов проверяет, захвачен ли белый король. Если это правда, ход играется на доске.
  5. vпроверяет ход белых. Он копирует доску в сторону, выполняет ход, чтобы проверить, и aснова вызывает , чтобы найти ходы черных.
ugoren
источник
Наконец, решение с надлежащим сжатым кодированием возможных ходов! И это очень быстро. Не думаете ли вы, что можете добавить оболочку Unicode и при этом быть короче моего кода?
перестал поворачиваться против часовой стрелки с
@ leftaroundabout, наверное, смогу. Основная проблема в том, что я работаю в командной строке Linux, где вы не видите Unicode, поэтому отладка будет раздражать. У меня также есть версия, которая сохраняет около 40 байтов (я скоро обновлю), поэтому у меня есть много символов для работы.
Угорен
@ugoren: Конечно, любой современный дистрибутив Linux поддерживает UTF-8 из коробки?
хан
@ Хан, я работаю в Windows и подключаюсь к Linux по SSH, а Unicode не работает. Я могу написать в файл и открыть в Windows, но это уже не интересно.
Угорен
Будет ли это компилироваться с GCC? Я использую Geany для Windows с MinGW, и он будет компилироваться с кучей ошибок и предупреждений, но он не будет собирать / run.eg: C: \ Users \ xxx \ AppData \ Local \ Temp \ ccpBG9zy.o: codegolfchess.c :(. text + 0x2d8): неопределенная ссылка на `bcopy 'collect2: ld вернул 1 статус выхода
rpd
5

Python 2.6, 886 - 1425 символов

Моя первоначальная версия (в ревизиях) содержала 886 символов, но не полностью удовлетворяла спецификации (она не проверяла, чтобы не было матов; она даже не учитывала возможные ходы черных фигур).

Теперь это происходит (и я исправил несколько ошибок в оригинале). Увы, это связано с расходами на персонажей: на данный момент 1425, но все еще не должно быть места для улучшений. Эта версия должна быть намного более надежной в обработке крайних случаев, чем предыдущая.

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

Пример ввода и вывода:

# ВХОД

8 ║♜ ♞ ♝… ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟… ♟ ♟ ♟
6 ║………………………
5 ║………… ♟………
4 ║…………… ♙ ♛
3 ║…………… ♙……
2 ║♙ ♙ ♙ ♙ ♙… ♙…
1 ║♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖
--╚═══════════════
—— abcdefgh
# ВЫХОД

8 ║♜ ♞ ♝… ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟… ♟ ♟ ♟
6 ║………………………
5 ║………… ♟………
4 ║…………… ♙ ♛
3 ║………… ♙ ♙…
2 ║♙ ♙ ♙ ♙ ♙………
1 ║♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖
--╚════════════════
—— abcdefgh
ChristopheD
источник
Это 886 байт, но только 854 символа. (Моя программа имеет более 1 КБ, благодаря множеству не-ASCII операторов!) - Вы собираетесь добавить проверку на получение короля?
перестал поворачиваться против часовой стрелки с
@leftaroundabout: я добавил проверки короля (что заставляет меня также учитывать возможные ходы черных и добавляет много символов ...). Ну что ж, эта версия должна быть более надежной в крайних случаях (насколько я тестировал).
ChristopheD