Haskell , 1165 1065 1053 bajtów
Bajty uratowane dzięki Leo Tenenbaumowi
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)
Wypróbuj online!
Na razie nie jest to do tej pory gra w golfa, ale to dopiero początek. Z pewną pomocą po drodze teraz grałem w golfa dość agresywnie (i naprawiłem błąd po drodze).
Jedną być może wątpliwą rzeczą jest to, że zakłada, że inaczej niż przez króla lub pionka en passant, nigdy nie można wymknąć się spod kontroli, zdobywając jeden ze swoich pionków. W szachach nie możesz wykonać tego ruchu, ale mój program rozważa te ruchy, aby zaoszczędzić bajty przy założeniu, że jeśli jesteś w szachu, nigdy cię to nie wydostanie.
To założenie jest ważne, ponieważ takie ruchy
Nie można schwytać elementu atakującego króla, ponieważ element, który schwytali, jest czarny.
Nie można zablokować ścieżki elementu atakującego króla, ponieważ złapany czarny element już by to zrobił.
Dodajemy również dodatkowy warunek, że jeśli nie masz króla, jesteś pod kontrolą.
Program ten zakłada również, że jeśli istnieje pionek, który można schwytać en passant, wówczas pionek był ostatnim elementem do poruszenia, a ruch ten był legalnym ruchem. Wynika to z faktu, że program nie sprawdza, czy kwadrat, na który przesuwa czarny pionek, jest pusty, więc jeśli jest jakiś element, rzeczy mogą się trochę krzywić. Nie można tego jednak uzyskać, jeżeli ostatni ruch był legalny, a ponadto nie może być reprezentowany w FEN . To założenie wydaje się więc dość solidne.
Oto moja wersja „bez golfa” w celach informacyjnych:
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)
Wypróbuj online!