Haskell , 1165 1065 1053 byte
Byte salvati grazie a 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)
Provalo online!
Questo non è esattamente ben golfato al momento, ma è un inizio. Con un po 'di aiuto lungo la strada, ora ho risolto il problema in modo piuttosto aggressivo (e ho corretto un errore lungo la strada).
L'unica cosa forse discutibile che fa è che si presume che, a parte un re o un pedone en passant, non si possa mai sfuggire al controllo catturando uno dei propri pezzi. Negli scacchi non ti è permesso fare questa mossa, ma il mio programma considera queste mosse per salvare byte supponendo che se sei sotto controllo questo non ti farà mai uscire.
Questa ipotesi è valida perché tali mosse
Non è possibile catturare il pezzo che sta attaccando il re, poiché il pezzo che catturano è nero.
Non è possibile bloccare il percorso del pezzo che sta attaccando il re, poiché il pezzo nero catturato lo avrebbe già fatto.
Aggiungiamo anche la clausola aggiuntiva che se non hai un re sei sotto controllo.
Questo programma presuppone anche che se c'è una pedina che può essere catturata in modo passivo, la pedina è stata l'ultima pedina da muovere e quella mossa è stata una mossa legale. Questo perché il programma non controlla se il quadrato in cui si sposta il pedone nero è vuoto, quindi se c'è un pezzo lì le cose possono diventare un po 'complicate. Tuttavia, ciò non può essere ottenuto se l'ultima mossa è stata una mossa legale e inoltre non può essere rappresentata nella FEN . Quindi questo assunto sembra piuttosto solido.
Ecco la mia versione "ungolfed" per riferimento:
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)
Provalo online!