Add non pawn movement generators
This commit is contained in:
@@ -76,7 +76,7 @@ static int pop_lsb_index(uint64_t *bb) {
|
|||||||
return idx;
|
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;
|
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;
|
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
|
return ray_attacks(square, +1, 0, occupied) // east
|
||||||
| ray_attacks(square, -1, 0, occupied) // west
|
| ray_attacks(square, -1, 0, occupied) // west
|
||||||
| ray_attacks(square, 0, +1, occupied) // north
|
| ray_attacks(square, 0, +1, occupied) // north
|
||||||
| ray_attacks(square, 0, -1, occupied); // south
|
| 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
|
return ray_attacks(square, +1, +1, occupied) // NE
|
||||||
| ray_attacks(square, -1, +1, occupied) // NW
|
| ray_attacks(square, -1, +1, occupied) // NW
|
||||||
| ray_attacks(square, +1, -1, occupied) // SE
|
| ray_attacks(square, +1, -1, occupied) // SE
|
||||||
| ray_attacks(square, -1, -1, occupied); // SW
|
| 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
|
// Simply combine both types of attacks
|
||||||
return rook_attacks(square, occupied) | bishop_attacks(square, occupied);
|
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) {
|
void print_board(const struct Board *b) {
|
||||||
static const char PIECE_CH[12] = {
|
static const char PIECE_CH[12] = {
|
||||||
'P','N','B','R','Q','K',
|
'P','N','B','R','Q','K',
|
||||||
|
|||||||
Reference in New Issue
Block a user