1 /***************************************************************************
2 check.cpp - description
4 begin : Wed Mar 13 2002
5 copyright : (C) 2002-2005 by Maurizio Monge
6 email : monge@linuz.sns.it
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
20 /*******************************************************************************
21 Find the pins for color to move and set a flag to mark whick is the
22 pinning direction. The under_check var is also set to a value that is
23 0/1/2 if the color to move is under no check, check or double check.
24 *******************************************************************************/
26 Board::find_check_and_pins()
28 ASSERT(data
[king_pos
[1]] == WK
);
29 ASSERT(data
[king_pos
[0]] == BK
);
30 ASSERT(DISTANCE(king_pos
[0], king_pos
[1]) >= 2);
38 uint8_t pos
= king_pos
[IS_WHITE(color_to_move
)];
39 uint8_t attacker
= other_color
;
40 uint8_t defender
= color_to_move
;
41 uint8_t killer
= BISHOP
|attacker
;
48 /* check bishop (or queen) attacks */
59 if(OUT_OF_BOARD(check
))
62 if(COLOR_OF(d
[check
]) == defender
)
64 if(maybe_ink
==0xff) //first piece on the line?
70 break; //two non-offending pieces in the line
73 if( (d
[check
] & ((uint8_t)~ROOK
)) == killer
)
76 { //under a true check, sign all
77 register uint8_t p
= pos
;
88 cg
[maybe_ink
] = NFREE
|i
|DIAG
;
96 /* check rook (or queen) attacks */
97 killer
= ROOK
|attacker
;
109 if(OUT_OF_BOARD(check
))
112 if(COLOR_OF(d
[check
]) == defender
)
114 if(maybe_ink
==0xff) //first piece on the line?
120 break; //two non-offending pieces in the line
123 if( (d
[check
] & ((uint8_t)~BISHOP
)) == killer
)
126 { //under a true check, sign all
127 register uint8_t p
= pos
;
138 cg
[maybe_ink
] = NFREE
|i
|COLM
;
146 /* check knight attacks */
147 killer
= KNIGHT
|attacker
;
149 KnightMove
* hm
= &knightmoves
[pos
];
150 for(int i
=hm
->numm
;i
>=0;i
--)
153 if(d
[check
] == killer
)
161 /* check pawn attacks */
163 killer
= PAWN
|attacker
;
164 check
= pos
- up_dir
[IS_WHITE(attacker
)] + RIGHT
;
165 if(!OUT_OF_BOARD(check
) && (d
[check
] == killer
))
172 if(!OUT_OF_BOARD(check
) && (d
[check
] == killer
))
181 /*******************************************************************************
182 Find the pins for the other color.
183 *******************************************************************************/
185 Board::find_other_pins()
187 ASSERT(data
[king_pos
[1]] == WK
);
188 ASSERT(data
[king_pos
[0]] == BK
);
189 ASSERT(DISTANCE(king_pos
[0], king_pos
[1]) >= 2);
197 uint8_t pos
= king_pos
[IS_WHITE(other_color
)];
198 uint8_t attacker
= color_to_move
;
199 uint8_t killer
= BISHOP
|attacker
;
204 /* check bishop (or queen) attacks */
205 for(int i
=3;i
>=0;i
--)
215 if(OUT_OF_BOARD(check
))
218 if( (d
[check
] & ((uint8_t)~ROOK
)) == killer
)
220 ASSERT(maybe_ink
!=0xff); //else, under a true check!
221 cg
[maybe_ink
] = NFREE
|i
|DIAG
;
233 /* check rook (or queen) attacks */
234 killer
= ROOK
|attacker
;
236 for(int i
=3;i
>=0;i
--)
246 if(OUT_OF_BOARD(check
))
249 if( (d
[check
] & ((uint8_t)~BISHOP
)) == killer
)
251 ASSERT(maybe_ink
!=0xff); //else, under a true check!
252 cg
[maybe_ink
] = NFREE
|i
|COLM
;
266 /*******************************************************************************
267 Almost exact, does not handle en-passant and castle
268 *******************************************************************************/
270 Board::move_is_check(const Move
& m
)
272 /* discover check? */
273 /* if a pawn is marked on an attack line and moves, it is almost
274 always a check (unless very rare en-passant on the attack line) */
278 uint8_t enking
= king_pos
[IS_WHITE(other_color
)];
279 uint8_t delta
= enking
- m
.to
;
280 uint8_t piece
= PIECE_OF(data
[m
.from
]);
282 /* not 100% exact, promotion to queen/rook may give check backward
283 and it would not be detected because of the pawn itself "interposed" */
284 if(m
.flags
>= PROMOTE_FIRST
)
285 piece
= m
.flags
-PROMOTE0
;
291 if(delta
== RIGHT_OF(up_dir
[IS_WHITE(color_to_move
)]) ||
292 delta
== LEFT_OF(up_dir
[IS_WHITE(color_to_move
)]))
294 /* TODO:handle promote */
300 int deltax
= X(enking
) - X(m
.to
);
301 int deltay
= Y(enking
) - Y(m
.to
);
303 /* to see if it is reachable test if the distance is sqrt(5) */
304 if(deltax
*deltax
+ deltay
*deltay
== 5)
312 int deltax
= X(enking
) - X(m
.to
);
313 int deltay
= Y(enking
) - Y(m
.to
);
314 if(ABS(deltax
) == ABS(deltay
))
316 uint8_t inc
= (deltax
>0?RIGHT
:LEFT
) + (deltay
>0?UP
:DOWN
);
317 for(uint8_t currpos
= m
.to
+inc
; currpos
!= enking
; currpos
+=inc
)
322 if(piece
!= QUEEN
) /* for the queen fall through to the rook */
328 int deltax
= X(enking
) - X(m
.to
);
329 int deltay
= Y(enking
) - Y(m
.to
);
330 if(ABS(deltax
)==0 || ABS(deltay
)==0)
332 uint8_t inc
= deltax
>0 ? RIGHT
: (deltax
<0 ? LEFT
: (deltay
>0?UP
:DOWN
));
333 for(uint8_t currpos
= m
.to
+inc
; currpos
!= enking
; currpos
+=inc
)