Add Pseudo Move Generator #12

Merged
Josh merged 17 commits from 7-add-pseudo-move-generator into main 2025-08-18 00:28:00 +00:00
Showing only changes of commit 55666004a0 - Show all commits

View File

@@ -146,11 +146,11 @@ void push_move(struct Move *out, int *count, int from, int to, uint8_t piece, ui
most complicated movement patterns and behaviors in the game. Separating out the logic should
hopefully make debugging easier.
*/
void gen_white_pawn_quiet_pushes(const struct Board *b, struct Move *out, int *count) {
const uint64_t occ = b->occ[BOTH];
void gen_white_pawn_quiet_pushes(const struct Board *board, struct Move *out, int *count) {
const uint64_t occ = board->occ[BOTH];
const uint64_t empty = ~occ;
const uint64_t pawns = b->pieces[P];
const uint64_t pawns = board->pieces[P];
// One-step pushes: shift pawns up by 8 onto empty squares
uint64_t one_step = (pawns << 8) & empty;
@@ -177,11 +177,11 @@ void gen_white_pawn_quiet_pushes(const struct Board *b, struct Move *out, int *c
}
}
void gen_black_pawn_quiet_pushes(const struct Board *b, struct Move *out, int *count) {
const uint64_t occ = b->occ[BOTH];
void gen_black_pawn_quiet_pushes(const struct Board *board, struct Move *out, int *count) {
const uint64_t occ = board->occ[BOTH];
const uint64_t empty = ~occ;
const uint64_t pawns = b->pieces[p];
const uint64_t pawns = board->pieces[p];
// One-step pushes: shift pawns down by 8 onto empty squares
uint64_t one_step = (pawns >> 8) & empty;
@@ -208,10 +208,10 @@ void gen_black_pawn_quiet_pushes(const struct Board *b, struct Move *out, int *c
// We will only allow pawns to promote to queen. Technically, they should be allowed
// to promote to any of the following: Rook, Bishop, Knight, Queen.
void gen_white_pawn_push_promotions(const struct Board *b, struct Move *out, int *count) {
const uint64_t occ = b->occ[BOTH];
void gen_white_pawn_push_promotions(const struct Board *board, struct Move *out, int *count) {
const uint64_t occ = board->occ[BOTH];
const uint64_t empty = ~occ;
const uint64_t pawns = b->pieces[P];
const uint64_t pawns = board->pieces[P];
// destinations on rank 8 reachable by a single push
uint64_t promos = ((pawns << 8) & empty) & RANK_8;
@@ -223,10 +223,10 @@ void gen_white_pawn_push_promotions(const struct Board *b, struct Move *out, int
}
}
void gen_black_pawn_push_promotions(const struct Board *b, struct Move *out, int *count) {
const uint64_t occ = b->occ[BOTH];
void gen_black_pawn_push_promotions(const struct Board *board, struct Move *out, int *count) {
const uint64_t occ = board->occ[BOTH];
const uint64_t empty = ~occ;
const uint64_t pawns = b->pieces[p];
const uint64_t pawns = board->pieces[p];
// destinations on rank 1 reachable by a single push
uint64_t promos = ((pawns >> 8) & empty) & RANK_1;
@@ -238,17 +238,17 @@ void gen_black_pawn_push_promotions(const struct Board *b, struct Move *out, int
}
}
void gen_white_pawn_capture_promotions(const struct Board *b, struct Move *out, int *count) {
const uint64_t opp = b->occ[BLACK];
void gen_white_pawn_capture_promotions(const struct Board *board, struct Move *out, int *count) {
const uint64_t opp = board->occ[BLACK];
// left capture (from white view): +7, mask off file A
uint64_t left = ((b->pieces[P] & ~FILE_A) << 7) & opp & RANK_8;
uint64_t left = ((board->pieces[P] & ~FILE_A) << 7) & opp & RANK_8;
while (left) {
int to = pop_lsb_index(&left);
int from = to - 7;
push_move(out, count,from, to, P, Q, MF_CAPTURE | MF_PROMO);
}
// right capture: +9, mask off file H
uint64_t right = ((b->pieces[P] & ~FILE_H) << 9) & opp & RANK_8;
uint64_t right = ((board->pieces[P] & ~FILE_H) << 9) & opp & RANK_8;
while (right) {
int to = pop_lsb_index(&right);
int from = to - 9;
@@ -256,17 +256,17 @@ void gen_white_pawn_capture_promotions(const struct Board *b, struct Move *out,
}
}
void gen_black_pawn_capture_promotions(const struct Board *b, struct Move *out, int *count) {
const uint64_t opp = b->occ[WHITE];
void gen_black_pawn_capture_promotions(const struct Board *board, struct Move *out, int *count) {
const uint64_t opp = board->occ[WHITE];
// from black view, “left” is -7 (mask off file H before shifting)
uint64_t left = ((b->pieces[p] & ~FILE_H) >> 7) & opp & RANK_1;
uint64_t left = ((board->pieces[p] & ~FILE_H) >> 7) & opp & RANK_1;
while (left) {
int to = pop_lsb_index(&left);
int from = to + 7;
push_move(out, count,from, to, p, q, MF_CAPTURE | MF_PROMO);
}
// “right” is -9 (mask off file A)
uint64_t right = ((b->pieces[p] & ~FILE_A) >> 9) & opp & RANK_1;
uint64_t right = ((board->pieces[p] & ~FILE_A) >> 9) & opp & RANK_1;
while (right) {
int to = pop_lsb_index(&right);
int from = to + 9;
@@ -274,9 +274,9 @@ void gen_black_pawn_capture_promotions(const struct Board *b, struct Move *out,
}
}
void gen_white_pawn_captures(const struct Board *b, struct Move *out, int *count) {
const uint64_t pawns = b->pieces[P];
const uint64_t opp = b->occ[BLACK];
void gen_white_pawn_captures(const struct Board *board, struct Move *out, int *count) {
const uint64_t pawns = board->pieces[P];
const uint64_t opp = board->occ[BLACK];
// Normal captures (exclude promotion rank)
uint64_t left_caps = ((pawns & ~FILE_A) << 7) & opp & ~RANK_8;
@@ -295,24 +295,24 @@ void gen_white_pawn_captures(const struct Board *b, struct Move *out, int *count
}
// En passant (destination is ep_square)
if (b->ep_square >= 0) {
uint64_t ep = 1ULL << b->ep_square;
if (board->ep_square >= 0) {
uint64_t ep = 1ULL << board->ep_square;
// From-squares that can capture onto ep (reverse of +7/+9)
uint64_t ep_from = (((ep & ~FILE_H) >> 7) | ((ep & ~FILE_A) >> 9)) & pawns;
while (ep_from) {
int from = pop_lsb_index(&ep_from);
int to = b->ep_square;
int to = board->ep_square;
// EP never promotes, so no promo piece; still a capture
push_move(out, count,from, to, P, 0, MF_CAPTURE | MF_ENPASSANT);
}
}
}
void gen_black_pawn_captures(const struct Board *b, struct Move *out, int *count) {
const uint64_t pawns = b->pieces[p];
const uint64_t opp = b->occ[WHITE];
void gen_black_pawn_captures(const struct Board *board, struct Move *out, int *count) {
const uint64_t pawns = board->pieces[p];
const uint64_t opp = board->occ[WHITE];
// Normal captures (exclude promotion rank)
uint64_t left_caps = ((pawns & ~FILE_H) >> 7) & opp & ~RANK_1; // from black POV, "left" is -7
@@ -330,15 +330,15 @@ void gen_black_pawn_captures(const struct Board *b, struct Move *out, int *count
}
// En passant
if (b->ep_square >= 0) {
uint64_t ep = 1ULL << b->ep_square;
if (board->ep_square >= 0) {
uint64_t ep = 1ULL << board->ep_square;
// From-squares that can capture onto ep (reverse of -7/-9)
uint64_t ep_from = (((ep & ~FILE_A) << 7) | ((ep & ~FILE_H) << 9)) & pawns;
while (ep_from) {
int from = pop_lsb_index(&ep_from);
int to = b->ep_square;
int to = board->ep_square;
push_move(out, count,from, to, p, 0, MF_CAPTURE | MF_ENPASSANT);
}
}
@@ -351,12 +351,12 @@ void gen_black_pawn_captures(const struct Board *b, struct Move *out, int *count
*/
void gen_knight_moves(const struct Board *b, struct Move *out, int *count, bool captures_only) {
enum Color side = b->side_to_move;
uint64_t own = b->occ[side];
uint64_t opp = b->occ[side ^ 1];
void gen_knight_moves(const struct Board *board, struct Move *out, int *count, bool captures_only) {
enum Color side = board->side_to_move;
uint64_t own = board->occ[side];
uint64_t opp = board->occ[side ^ 1];
uint8_t pid = (side == WHITE) ? N : n;
uint64_t bb = (side == WHITE) ? b->pieces[N] : b->pieces[n];
uint64_t bb = (side == WHITE) ? board->pieces[N] : board->pieces[n];
while (bb) {
int from = pop_lsb_index(&bb);
@@ -404,13 +404,13 @@ void gen_bishop_moves(const struct Board *board, struct Move *out, int *count, b
}
}
void gen_rook_moves(const struct Board *b, struct Move *out, int *count, 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];
void gen_rook_moves(const struct Board *board, struct Move *out, int *count, bool captures_only) {
enum Color side = board->side_to_move;
uint64_t own = board->occ[side];
uint64_t opp = board->occ[side ^ 1];
uint64_t occ = board->occ[BOTH];
uint8_t pid = (side == WHITE) ? R : r;
uint64_t bb = (side == WHITE) ? b->pieces[R] : b->pieces[r];
uint64_t bb = (side == WHITE) ? board->pieces[R] : board->pieces[r];
while (bb) {
int from = pop_lsb_index(&bb);
@@ -431,13 +431,13 @@ void gen_rook_moves(const struct Board *b, struct Move *out, int *count, bool ca
}
}
void gen_queen_moves(const struct Board *b, struct Move *out, int *count, 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];
void gen_queen_moves(const struct Board *board, struct Move *out, int *count, bool captures_only) {
enum Color side = board->side_to_move;
uint64_t own = board->occ[side];
uint64_t opp = board->occ[side ^ 1];
uint64_t occ = board->occ[BOTH];
uint8_t pid = (side == WHITE) ? Q : q;
uint64_t bb = (side == WHITE) ? b->pieces[Q] : b->pieces[q];
uint64_t bb = (side == WHITE) ? board->pieces[Q] : board->pieces[q];
while (bb) {
int from = pop_lsb_index(&bb);
@@ -458,12 +458,12 @@ void gen_queen_moves(const struct Board *b, struct Move *out, int *count, bool c
}
}
void gen_king_moves(struct Board *b, struct Move *out, int *count, bool captures_only) {
enum Color side = b->side_to_move;
uint64_t own = b->occ[side];
uint64_t opp = b->occ[side ^ 1];
void gen_king_moves(struct Board *board, struct Move *out, int *count, bool captures_only) {
enum Color side = board->side_to_move;
uint64_t own = board->occ[side];
uint64_t opp = board->occ[side ^ 1];
uint8_t pid = (side == WHITE) ? K : k;
uint64_t kk = (side == WHITE) ? b->pieces[K] : b->pieces[k];
uint64_t kk = (side == WHITE) ? board->pieces[K] : board->pieces[k];
if (!kk) return;
int from = first_set_index(kk);
@@ -483,26 +483,26 @@ void gen_king_moves(struct Board *b, struct Move *out, int *count, bool captures
}
if (!captures_only) {
uint64_t occ = b->occ[BOTH];
uint64_t occ = board->occ[BOTH];
if (side == WHITE) {
if ((b->castling_rights & CASTLE_WK) && !(occ & WK_EMPTY_MASK)) {
if ((board->castling_rights & CASTLE_WK) && !(occ & WK_EMPTY_MASK)) {
push_move(out, count,E1, WK_TO, K, 0, MF_CASTLE);
}
if ((b->castling_rights & CASTLE_WQ) && !(occ & WQ_EMPTY_MASK)) {
if ((board->castling_rights & CASTLE_WQ) && !(occ & WQ_EMPTY_MASK)) {
push_move(out, count,E1, WQ_TO, K, 0, MF_CASTLE);
}
} else {
if ((b->castling_rights & CASTLE_BK) && !(occ & BK_EMPTY_MASK)) {
if ((board->castling_rights & CASTLE_BK) && !(occ & BK_EMPTY_MASK)) {
push_move(out, count,E8, BK_TO, k, 0, MF_CASTLE);
}
if ((b->castling_rights & CASTLE_BQ) && !(occ & BQ_EMPTY_MASK)) {
if ((board->castling_rights & CASTLE_BQ) && !(occ & BQ_EMPTY_MASK)) {
push_move(out, count,E8, BQ_TO, k, 0, MF_CASTLE);
}
}
}
}
void print_board(const struct Board *b) {
void print_board(const struct Board *board) {
const char PIECE_CH[12] = {
'P','N','B','R','Q','K',
'p','n','b','r','q','k'
@@ -512,7 +512,7 @@ void print_board(const struct Board *b) {
for (int i = 0; i < 64; ++i) grid[i] = '.';
for (int p = 0; p < 12; ++p) {
uint64_t bb = b->pieces[p];
uint64_t bb = board->pieces[p];
while (bb) {
int sq = pop_lsb_index(&bb);
grid[sq] = PIECE_CH[p];