From 9c9dedc7bfc955e9a3cda424b108bca8e3eabced Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 16 Aug 2025 15:07:13 -0400 Subject: [PATCH] Add non pawn movement generators --- engine/src/bitboard.c | 179 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 175 insertions(+), 4 deletions(-) diff --git a/engine/src/bitboard.c b/engine/src/bitboard.c index c8cad1c..8959818 100644 --- a/engine/src/bitboard.c +++ b/engine/src/bitboard.c @@ -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',