The smallest Chess arbiter

8

2

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).

vsz

Posted 2012-11-07T13:32:52.223

Reputation: 7 963

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. – dmckee --- ex-moderator kitten – 2012-11-07T14:26:55.857

@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. – vsz – 2012-11-07T14:35:02.457

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. – Peter Taylor – 2012-11-07T16:42:58.940

1@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. – vsz – 2012-11-07T17:12:55.350

On second thought, the checkmate condition will not be much easier to handle as the stalemate: you know, if the piece giving the check can be captured or blocked, it's not a checkmate. So if you have to handle those situations, I don't know why not go for the bonus -20% as well. – vsz – 2012-11-07T17:15:43.380

3What if the check was made by a pawn eligible for en passant capture? Is it safe to assume this does not occur? – Steven Rumbalski – 2012-11-07T20:24:12.433

@StevenRumbalski : yes, it's safe to assume. I didn't want to complicate things by needing to read and evaluate the last moves, so you can disregard en-passante completely. (If we knew the last move, it would be trivial to handle it, but we don't know it, so I don't expect you to handle it) – vsz – 2012-11-07T20:33:29.373

Answers

5

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

ugoren

Posted 2012-11-07T13:32:52.223

Reputation: 16 527