Edsel Apostol wrote:I have another crazy idea I wanted to try. I will include piece forks in my staged move generation. Has anyone done this before? I'm thinking of doing it like this:
For the rooks:
Code: Select all
u64 targetPieces= (enemy pieces to consider in the fork).
u64 targetMask = (fillWest(targetPieces, occupied) & fillEast(targetPieces, occupied)) | (fillNorth(targetPieces, occupied) & fillSouth(targetPieces, occupied));
u64 pieceMask = WhiteRooks;
while(pieceMask){
int from = popFirstBit(&pieceMask);
u64 moveMask = targetMask & RookMoves(from, occupied);
.....
}
It's basically the same with pawns, bishops and queens but I can't think of an easy way for knights. Any clever ideas?
Here goes my code for generating forks, pawns and knights for now:
Code: Select all
// shift the parameter b with i places to the left
uint64 shiftLeft(uint64 b, uint32 i) {return (b << i);}
// shift the parameter b with i places to the right
uint64 shiftRight(uint64 b, uint32 i) {return (b >> i);}
static uint64 (*ShiftPtr[])(uint64, uint32) = {&shiftLeft, &shiftRight};
/* this generates non tactical non checking knight and pawn forking moves only */
void genForks(const position_t *pos, sort_t *sort) {
static const int Shift[] = {9, 7};
uint64 pc_bits, mv_bits, pawns, xpawns, enemy_pawnattacks, mask, dcc;
int from, to, side, xside;
ASSERT(pos != NULL);
ASSERT(sort != NULL);
sort->size = 0;
side = pos->side;
xside = side^1;
pawns = pos->pawns & pos->color[side];
xpawns = pos->pawns & pos->color[xside];
dcc = discoveredCheckCandidates(pos, side);
mask = pos->color[xside] & ~pos->kings & ~pos->pawns;
mask = (((*ShiftPtr[xside])(mask, Shift[xside]) & ~FileABB) & ((*ShiftPtr[xside])(mask, Shift[side]) & ~FileHBB));
mv_bits = mask & (*ShiftPtr[pos->side])(pawns, 8) & ~pos->occupied;
while (mv_bits) {
to = popFirstBit(&mv_bits);
pc_bits = (PawnMoves[to][pos->side^1] & pawns) & ~dcc;
ASSERT(bitCnt(pc_bits) <= 1);
while (pc_bits) {
from = popFirstBit(&pc_bits);
sort->list[sort->size++].m = GenOneForward(from, to);
}
}
mv_bits = mask & Rank4ByColorBB[pos->side] & (*ShiftPtr[pos->side])(pawns, 16)
& (*ShiftPtr[pos->side])(~pos->occupied, 8) & ~pos->occupied;
while (mv_bits) {
to = popFirstBit(&mv_bits);
pc_bits = pawns & Rank2ByColorBB[pos->side] & FileMask[to] & ~dcc;
ASSERT(bitCnt(pc_bits) <= 1);
while (pc_bits) {
from = popFirstBit(&pc_bits);
sort->list[sort->size++].m = GenTwoForward(from, to);
}
}
enemy_pawnattacks = (((*ShiftPtr[xside])(xpawns, Shift[xside]) & ~FileABB) | ((*ShiftPtr[xside])(xpawns, Shift[side]) & ~FileHBB));
mask = knightForkTargetSquare(pos->color[xside] & (pos->queens | pos->rooks | pos->bishops)) & ~enemy_pawnattacks & ~pos->occupied;
pc_bits = pos->knights & pos->color[side] & ~dcc;
while (pc_bits) {
from = popFirstBit(&pc_bits);
mv_bits = KnightMoves[from] & mask;
while (mv_bits) {
to = popFirstBit(&mv_bits);
sort->list[sort->size++].m = GenKnightMove(from, to, getPiece(pos, to));
}
}
}
At first I thought that rooks, bishops and queens would be as easy as I've described above, I was wrong. One needs to consider the
intersection of all ray attacks. For the masks of rook and bishop, each of them would take 6
and and 5
or bit operations. For queens 28
and and 27
or bit operations. I don't think that or'ing the rook and bishop result is sufficient enough for the queen mask. Is there any better way?