The smallest Chess arbiter 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).
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 $ ,&amp;)$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&lt;0)&amp;&amp;!(n&amp;136)&amp;&amp;(b[n]?r=8,p&amp;8^b[n]&amp;8&amp;&amp;c&amp;65^64:c&amp;65^65)&amp;&amp;
        ((V?v(n,x):b[n]%8==1&amp;&amp;(s&amp;=~((b[n]&gt;7?8:2)))),e(x,d,m,V,c,r+1))
    :0)||d&gt;0&amp;&amp;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]&amp;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&amp;(b[f]&gt;7?8:2))==0?
            bcopy(B,b+=128,128),
            s|=(b[f]&gt;7?8:2),
            b[f]^=b[t]=b[f],
            a(b[t]&lt;8,63),
            b=B
        :0
    :
        (s|=b[f]&gt;7?1:4);
}
a(c,n){
    b[i=n*2-n%8]&amp;&amp;b[i]/8==c?d(i,!Q++,r+r[b[i]%8+15]-10),Q--:0;n--&amp;&amp;a(c,n);
}
p(c,t){
    return(t=c?s%4:s/4)!=2&amp;&amp;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");
}