and to use this in move generation. Since I dont see it in Crafty,
I guess its not done by others yet. I get a pretty good speedup
when doing perft, based on this.
The basic idea is to look at the king from a queens view, plus
knights view when needed.
One nice thing is that when not in check, all queen, rook, bishop
and knight moves are legal by default, pinned or not.
Also, to help generate check evasions, the CheckDetect function generates
what I call CheckAtk, a bitmap of all squares to reach for to intersect
or capture the check giving piece, when not in double check.
Here's some sample code, hopefully self explanatory.
Cheers!, Lasse
Code: Select all
int CheckDetect(U32 ply)
// Determines if wtm is in check or double check.
// Sets KingVulnAtk[wtm]
// Sets CheckAtk = all sqrs that evades single check if reached by a piece
// Returns 0: Not in check 1: Single check 2: Double check
{
U32 M = Game_MoveList[Game_Ply+ply-1];
if (!M || SPECIAL(M)) return CheckDetectSlow(ply);
U64 Atk = 0, KVA;
int fr, to, ksqr;
ksqr = FirstOne(Pieces[wtm][King]);
fr = FROM(M); to = TO(M);
KVA = PosInfo[ply].KingVulnAtk[wtm] = RookAttacks(ksqr) | BishopAttacks(ksqr);
PosInfo[ply].InCheck = 0;
PosInfo[ply].CheckAtk = 0;
if ((SetBit(fr) | SetBit(to)) & (KVA | KnightAttacks[ksqr])) {
// Discovered check
if (SetBit(fr) & KVA & MaskRook[ksqr]) {
Atk = (SetBit(fr) | RookAttacks(fr)) & MaskRook[ksqr];
if (Atk & (Pieces[!wtm][Queen] | Pieces[!wtm][Rook])) {
PosInfo[ply].CheckAtk = Atk;
PosInfo[ply].InCheck++;
goto DirectCheck;
}
}
if (SetBit(fr) & KVA & MaskBishop[ksqr]) {
Atk = (SetBit(fr) | BishopAttacks(fr)) & MaskBishop[ksqr];
if (Atk & (Pieces[!wtm][Queen] | Pieces[!wtm][Bishop])) {
PosInfo[ply].CheckAtk = Atk;
PosInfo[ply].InCheck++;
}
}
DirectCheck:
if (SetBit(to) & KVA & MaskRook[ksqr]) {
Atk = (SetBit(to) | RookAttacks(to)) & KVA & MaskRook[ksqr];
if (Atk & (Pieces[!wtm][Queen] | Pieces[!wtm][Rook])) {
PosInfo[ply].CheckAtk |= Atk;
PosInfo[ply].InCheck++;
return PosInfo[ply].InCheck;
}
}
if (SetBit(to) & KVA & MaskBishop[ksqr]) {
Atk = (SetBit(to) | BishopAttacks(to)) & KVA & MaskBishop[ksqr];
if (Atk & (Pieces[!wtm][Queen] | Pieces[!wtm][Bishop])) {
PosInfo[ply].CheckAtk |= Atk;
PosInfo[ply].InCheck++;
return PosInfo[ply].InCheck;
}
}
Atk = SetBit(to) & KnightAttacks[ksqr] & Pieces[!wtm][Knight];
if (Atk) {
PosInfo[ply].CheckAtk |= Atk;
PosInfo[ply].InCheck++;
return PosInfo[ply].InCheck;
}
Atk = SetBit(to) & PawnAttacks[wtm][ksqr] & Pieces[!wtm][Pawn];
if (Atk) {
PosInfo[ply].CheckAtk |= Atk;
PosInfo[ply].InCheck++;
return PosInfo[ply].InCheck;
}
}
return PosInfo[ply].InCheck;
}
int Movgen(U32 ply, U64 Trg)
// Generates q-legal (QRBN legal) moves to MoveList when InCheck == 0
// returns (-1) if king is attacked, else the number of moves
{
U64 Atk, Pcs, B;
int fr, to;
U32 *M;
U32 ksqr = FirstOne(Pieces[wtm][King]);
if (ply>0) PosInfo[ply].FirstMove = PosInfo[ply-1].LastMove;
M = PosInfo[ply].LastMove = PosInfo[ply].FirstMove;
Pcs = Pieces[wtm][Queen];
while (Pcs) {
fr = wtm ? FirstOne(Pcs) : LastOne(Pcs);
Atk = RookAttacks(fr) | BishopAttacks(fr);
if (Atk & Pieces[!wtm][King]) return -1;
Atk ^= Atk & Pieces[wtm][ALL];
Pcs ^= SetBit(fr);
B = SetBit(fr) & MaskRook[ksqr] & PosInfo[ply].KingVulnAtk[wtm];
if (B) { // Possible rook pin
B = Atk & MaskRook[fr] & MaskRook[ksqr];
if (B & (Pieces[!wtm][Rook] | Pieces[!wtm][Queen])) {
Atk = B;
goto RollQueen;
}
}
B = SetBit(fr) & MaskBishop[ksqr] & PosInfo[ply].KingVulnAtk[wtm];
if (B) { // Possible bishop pin
B = Atk & MaskBishop[fr] & MaskBishop[ksqr];
if (B & (Pieces[!wtm][Bishop] | Pieces[!wtm][Queen])) {
Atk = B;
goto RollQueen;
}
}
RollQueen:
Atk &= Trg;
fr = (fr<<6)+(((wtm<<3)+Queen)<<12);
while (Atk) {
to = wtm ? FirstOne(Atk) : LastOne(Atk);
*M++=fr+to+(Board[to]<<16);
Atk ^= SetBit(to);
}
}
PosInfo[ply].LastMove = M;
return (M-PosInfo[ply].FirstMove);
}