9
\$\begingroup\$

Write a program, which, upon gazing at a chess table, can say whether there is a check or a checkmate.

Input: a chess table in text form, the last line of the input being the first rank (the starting line of White)

The starting position in this input would look like this (space is an empty square, capital letters are White): why aren't the spaces displayed here?

rnbqkbnr
pppppppp




PPPPPPPP
RNBQKBNR

The program should print one or more of the following (without quotes, of course), depending on the situation:

  • "The White King is in check!" (if already in checkmate, don't display this!)
  • "The Black King is in check!" (if already in checkmate, don't display this!)
  • "The White King is in checkmate!"
  • "The Black King is in checkmate!"
  • "White is in stalemate!" (There would be a stalemate if White moved - optional)
  • "Black is in stalemate!" (There would be a stalemate if Black moved - optional)
  • "Both kings are safe for now." (if none of the above apply)

The input is guaranteed to be correct and be a legal chess position (no two kings of the same color, no two kings in check, etc.).

Score:

The score is the character count, lowest wins, not sooner than 10 days after the first valid answer. If the optional stalemate evaluation is implemented, the size will be decreased by 20% (for this situation, assume en-passant cannot be performed).

\$\endgroup\$
7
  • \$\begingroup\$ I believe that stalemate can depend on who is to move (i.e. I could move out of check into a position that would be stalemate except that it is now my opponent turn to move and he'll have to change something). I'll try to manufacture such a state. \$\endgroup\$ Commented Nov 7, 2012 at 14:26
  • \$\begingroup\$ @dmckee : This is why I separated white and black. You have to print "white is in stalemate" if there would be a stalemate if white moved. I'll edit it to make it more clear. \$\endgroup\$
    – vsz
    Commented Nov 7, 2012 at 14:35
  • \$\begingroup\$ What about unconditional stalemate (e.g. only kings left on the board)? Edit: ah, "one or more". Still, it would be good to include this in the test cases which I'm sure you're going to add. \$\endgroup\$ Commented Nov 7, 2012 at 16:42
  • 1
    \$\begingroup\$ @PeterTaylor: Well they are not technically a stalemate. One that occasion, we would have to include the King + one Knight or Bishop vs King, which is also a draw. And then the eternal check. And so on. Ok, If you want to implement it (and the unavoidable mate in x also?) you are free to do it, but I will not make them to a strict requirement. So in that case I'll accept the "Both kings are safe for now." output in case of only kings left on board. \$\endgroup\$
    – vsz
    Commented Nov 7, 2012 at 17:12
  • 3
    \$\begingroup\$ What if the check was made by a pawn eligible for en passant capture? Is it safe to assume this does not occur? \$\endgroup\$ Commented Nov 7, 2012 at 20:24

1 Answer 1

5
\$\begingroup\$

C, 837-20%=669.6 chars

Based on this answer. You can see some explanations about the implementation there.
The original is golfed quite well, the modifications not so much, so there's room for improvement.
I also wouldn't be surprised to find bugs, my QA wasn't very rigorous.

char*r=" KPNBRQ  kpnbrq $ ,&)$wxy()879()8(6:GI(",B[256],*b=B,i,Q,s,*X[]={"Stalemate","Checkmate","","Check"};
e(x,d,m,V,c,r,n,p){
    p=b[x];
    return(m/r?
        n=x+d*r,
        p-2-8*(d<0)&&!(n&136)&&(b[n]?r=8,p&8^b[n]&8&&c&65^64:c&65^65)&&
        ((V?v(n,x):b[n]%8==1&&(s&=~((b[n]>7?8:2)))),e(x,d,m,V,c,r+1))
    :0)||d>0&&e(x,-d,m,V,c,1);
}
d(x,v,m,i)char*m;{
    (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,1),d(x,v,m+1):0;
}
v(t,f){
    b[t]%8-1?
        (s&(b[f]>7?8:2))==0?
            bcopy(B,b+=128,128),
            s|=(b[f]>7?8:2),
            b[f]^=b[t]=b[f],
            a(b[t]<8,63),
            b=B
        :0
    :
        (s|=b[f]>7?1:4);
}
a(c,n){
    b[i=n*2-n%8]&&b[i]/8==c?d(i,!Q++,r+r[b[i]%8+15]-10),Q--:0;n--&&a(c,n);
}
p(c,t){
    return(t=c?s%4:s/4)!=2&&printf("%s%s%s is in %s\n",t?"The ":"",c?"White":"Black",t?" king":"",X[t]);
}
main(){
    for(;gets(b);b+=8)for(;*b;b++)*b=strchr(r,*b)-r;b=B;
    a(0,63);
    a(1,63);
    p(0)||p(8)||puts("Both kings are safe for now");
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.