Add non pawn movement generators
This commit is contained in:
@@ -76,7 +76,7 @@ static int pop_lsb_index(uint64_t *bb) {
|
||||
return idx;
|
||||
}
|
||||
|
||||
static inline uint64_t ray_attacks(int start_square, int delta_file, int delta_rank, uint64_t occupied)
|
||||
static uint64_t ray_attacks(int start_square, int delta_file, int delta_rank, uint64_t occupied)
|
||||
{
|
||||
uint64_t attacks = 0;
|
||||
|
||||
@@ -104,25 +104,196 @@ static inline uint64_t ray_attacks(int start_square, int delta_file, int delta_r
|
||||
return attacks;
|
||||
}
|
||||
|
||||
static inline uint64_t rook_attacks(int square, uint64_t occupied) {
|
||||
static uint64_t rook_attacks(int square, uint64_t occupied) {
|
||||
return ray_attacks(square, +1, 0, occupied) // east
|
||||
| ray_attacks(square, -1, 0, occupied) // west
|
||||
| ray_attacks(square, 0, +1, occupied) // north
|
||||
| ray_attacks(square, 0, -1, occupied); // south
|
||||
}
|
||||
|
||||
static inline uint64_t bishop_attacks(int square, uint64_t occupied) {
|
||||
static uint64_t bishop_attacks(int square, uint64_t occupied) {
|
||||
return ray_attacks(square, +1, +1, occupied) // NE
|
||||
| ray_attacks(square, -1, +1, occupied) // NW
|
||||
| ray_attacks(square, +1, -1, occupied) // SE
|
||||
| ray_attacks(square, -1, -1, occupied); // SW
|
||||
}
|
||||
|
||||
static inline uint64_t queen_attacks(int square, uint64_t occupied) {
|
||||
static uint64_t queen_attacks(int square, uint64_t occupied) {
|
||||
// Simply combine both types of attacks
|
||||
return rook_attacks(square, occupied) | bishop_attacks(square, occupied);
|
||||
}
|
||||
|
||||
static void push_move(struct Move *out, int *count, int from, int to, uint8_t piece, uint8_t promo, uint8_t flags)
|
||||
{
|
||||
out[*count] = (Move){
|
||||
.from = (uint16_t)from,
|
||||
.to = (uint16_t)to,
|
||||
.piece = piece,
|
||||
.promo = promo, // 0 for non-promo;
|
||||
.flags = flags
|
||||
};
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
|
||||
Pieces that are not PAWNs
|
||||
|
||||
|
||||
*/
|
||||
static void gen_knight_moves(const struct Board *b, struct Move *out, int *n, bool captures_only) {
|
||||
enum Color side = b->side_to_move;
|
||||
uint64_t own = b->occ[side];
|
||||
uint64_t opp = b->occ[side ^ 1];
|
||||
uint8_t pid = (side == WHITE) ? N : n;
|
||||
uint64_t bb = (side == WHITE) ? b->pieces[N] : b->pieces[n];
|
||||
|
||||
while (bb) {
|
||||
int from = pop_lsb_index(&bb);
|
||||
uint64_t mask = KNIGHT_ATTACKS[from] & ~own;
|
||||
uint64_t caps = mask & opp;
|
||||
|
||||
if (!captures_only) {
|
||||
uint64_t quiet = mask & ~opp;
|
||||
while (quiet) {
|
||||
int to = pop_lsb_index(&quiet);
|
||||
push_move(out, n, from, to, pid, 0, MF_NONE);
|
||||
}
|
||||
}
|
||||
while (caps) {
|
||||
int to = pop_lsb_index(&caps);
|
||||
push_move(out, n, from, to, pid, 0, MF_CAPTURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_bishop_moves(const struct Board *b, struct Move *out, int *n, bool captures_only) {
|
||||
enum Color side = b->side_to_move;
|
||||
uint64_t own = b->occ[side];
|
||||
uint64_t opp = b->occ[side ^ 1];
|
||||
uint64_t occ = b->occ[BOTH];
|
||||
uint8_t pid = (side == WHITE) ? B : b;
|
||||
uint64_t bb = (side == WHITE) ? b->pieces[B] : b->pieces[b];
|
||||
|
||||
while (bb) {
|
||||
int from = pop_lsb_index(&bb);
|
||||
uint64_t mask = bishop_attacks(from, occ) & ~own;
|
||||
uint64_t caps = mask & opp;
|
||||
|
||||
if (!captures_only) {
|
||||
uint64_t quiet = mask & ~opp;
|
||||
while (quiet) {
|
||||
int to = pop_lsb_index(&quiet);
|
||||
push_move(out, n, from, to, pid, 0, MF_NONE);
|
||||
}
|
||||
}
|
||||
while (caps) {
|
||||
int to = pop_lsb_index(&caps);
|
||||
push_move(out, n, from, to, pid, 0, MF_CAPTURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_rook_moves(const struct Board *b, struct Move *out, int *n, bool captures_only) {
|
||||
enum Color side = b->side_to_move;
|
||||
uint64_t own = b->occ[side];
|
||||
uint64_t opp = b->occ[side ^ 1];
|
||||
uint64_t occ = b->occ[BOTH];
|
||||
uint8_t pid = (side == WHITE) ? R : r;
|
||||
uint64_t bb = (side == WHITE) ? b->pieces[R] : b->pieces[r];
|
||||
|
||||
while (bb) {
|
||||
int from = pop_lsb_index(&bb);
|
||||
uint64_t mask = rook_attacks(from, occ) & ~own;
|
||||
uint64_t caps = mask & opp;
|
||||
|
||||
if (!captures_only) {
|
||||
uint64_t quiet = mask & ~opp;
|
||||
while (quiet) {
|
||||
int to = pop_lsb_index(&quiet);
|
||||
push_move(out, n, from, to, pid, 0, MF_NONE);
|
||||
}
|
||||
}
|
||||
while (caps) {
|
||||
int to = pop_lsb_index(&caps);
|
||||
push_move(out, n, from, to, pid, 0, MF_CAPTURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_queen_moves(const struct Board *b, struct Move *out, int *n, bool captures_only) {
|
||||
enum Color side = b->side_to_move;
|
||||
uint64_t own = b->occ[side];
|
||||
uint64_t opp = b->occ[side ^ 1];
|
||||
uint64_t occ = b->occ[BOTH];
|
||||
uint8_t pid = (side == WHITE) ? Q : q;
|
||||
uint64_t bb = (side == WHITE) ? b->pieces[Q] : b->pieces[q];
|
||||
|
||||
while (bb) {
|
||||
int from = pop_lsb_index(&bb);
|
||||
uint64_t mask = (rook_attacks(from, occ) | bishop_attacks(from, occ)) & ~own;
|
||||
uint64_t caps = mask & opp;
|
||||
|
||||
if (!captures_only) {
|
||||
uint64_t quiet = mask & ~opp;
|
||||
while (quiet) {
|
||||
int to = pop_lsb_index(&quiet);
|
||||
push_move(out, n, from, to, pid, 0, MF_NONE);
|
||||
}
|
||||
}
|
||||
while (caps) {
|
||||
int to = pop_lsb_index(&caps);
|
||||
push_move(out, n, from, to, pid, 0, MF_CAPTURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_king_moves(struct Board *b, struct Move *out, int *n, bool captures_only) {
|
||||
enum Color side = b->side_to_move;
|
||||
uint64_t own = b->occ[side];
|
||||
uint64_t opp = b->occ[side ^ 1];
|
||||
uint8_t pid = (side == WHITE) ? K : k;
|
||||
uint64_t kk = (side == WHITE) ? b->pieces[K] : b->pieces[k];
|
||||
|
||||
if (!kk) return;
|
||||
int from = first_set_index(kk);
|
||||
uint64_t mask = KING_ATTACKS[from] & ~own;
|
||||
uint64_t caps = mask & opp;
|
||||
|
||||
if (!captures_only) {
|
||||
uint64_t quiet = mask & ~opp;
|
||||
while (quiet) {
|
||||
int to = pop_lsb_index(&quiet);
|
||||
push_move(out, n, from, to, pid, 0, MF_NONE);
|
||||
}
|
||||
}
|
||||
while (caps) {
|
||||
int to = pop_lsb_index(&caps);
|
||||
push_move(out, n, from, to, pid, 0, MF_CAPTURE);
|
||||
}
|
||||
|
||||
if (!captures_only) {
|
||||
uint64_t occ = b->occ[BOTH];
|
||||
if (side == WHITE) {
|
||||
if ((b->castling_rights & CASTLE_WK) && !(occ & WK_EMPTY_MASK)) {
|
||||
push_move(out, n, E1, WK_TO, K, 0, MF_CASTLE);
|
||||
}
|
||||
if ((b->castling_rights & CASTLE_WQ) && !(occ & WQ_EMPTY_MASK)) {
|
||||
push_move(out, n, E1, WQ_TO, K, 0, MF_CASTLE);
|
||||
}
|
||||
} else {
|
||||
if ((b->castling_rights & CASTLE_BK) && !(occ & BK_EMPTY_MASK)) {
|
||||
push_move(out, n, E8, BK_TO, k, 0, MF_CASTLE);
|
||||
}
|
||||
if ((b->castling_rights & CASTLE_BQ) && !(occ & BQ_EMPTY_MASK)) {
|
||||
push_move(out, n, E8, BQ_TO, k, 0, MF_CASTLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_board(const struct Board *b) {
|
||||
static const char PIECE_CH[12] = {
|
||||
'P','N','B','R','Q','K',
|
||||
|
||||
Reference in New Issue
Block a user