From f1a081a7b6344e37c7a847bfea414c840739881e Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Mon, 26 Feb 2024 19:15:42 +0100 Subject: [PATCH] add pawn movegen (untested) --- src/move.h | 19 +++++--- src/movegen.c | 113 ++++++++++++++++++++++++++++++++++++------- test/bitboard-test.c | 27 ++++++++--- test/fen-test.c | 14 +++--- 4 files changed, 136 insertions(+), 37 deletions(-) diff --git a/src/move.h b/src/move.h index 70bedec..e0963ad 100644 --- a/src/move.h +++ b/src/move.h @@ -36,13 +36,13 @@ /* move flags */ #define M_FLAGS_BEG 18 -#define M_HAS_FLAGS mask(_M_FLAGS_BEG + 0) /* probably unused */ -#define M_CAPTURE mask(_M_FLAGS_BEG + 1) -#define M_ENPASSANT mask(_M_FLAGS_BEG + 2) -#define M_PROMOTION mask(_M_FLAGS_BEG + 3) -#define M_CASTLE_K mask(_M_FLAGS_BEG + 4) -#define M_CASTLE_Q mask(_M_FLAGS_BEG + 5) -#define M_CHECK mask(_M_FLAGS_BEG + 6) /* probably unknown/useless */ +#define M_HAS_FLAGS mask(M_FLAGS_BEG + 0) /* probably unused */ +#define M_CAPTURE mask(M_FLAGS_BEG + 1) +#define M_ENPASSANT mask(M_FLAGS_BEG + 2) +#define M_PROMOTION mask(M_FLAGS_BEG + 3) +#define M_CASTLE_K mask(M_FLAGS_BEG + 4) +#define M_CASTLE_Q mask(M_FLAGS_BEG + 5) +#define M_CHECK mask(M_FLAGS_BEG + 6) /* probably unknown/useless */ #define M_FLAGS (M_CAPTURE | M_ENPASSANT | M_PROMOTION | \ M_CASTLE_K | M_CASTLE_Q | M_CHECK) @@ -55,6 +55,11 @@ static inline move_t move_make(square_t from, square_t to) return (to << 3) | from; } +static inline move_t move_make_promote(square_t from, square_t to, piece_type_t piece) +{ + return move_make(from, to) | M_ENPASSANT | (piece << 15); +} + static inline move_t move_from(move_t move) { return move & 56; diff --git a/src/movegen.c b/src/movegen.c index fa81f89..fa0a034 100644 --- a/src/movegen.c +++ b/src/movegen.c @@ -18,9 +18,16 @@ #include "piece.h" #include "move.h" -//void add_pseudo_move(move_t *pmove, square_t from, square_t to) -//{ -// pmov +/** + * gen_pawn_push() - generate pawn push + * @pos: position + * + * Generate all pseudo pawn pushes. + */ +//int gen_pawn_push(pos_t *pos, bitboard_t occ) + //{ + + //} /** @@ -32,29 +39,32 @@ */ int gen_all_pseudomoves(pos_t *pos) { - int me = pos->turn, other = OPPONENT(me); - bitboard_t my_pieces = pos->bb[me][ALL_PIECES], notmine = ~my_pieces, - other_pieces = pos->bb[other][ALL_PIECES], - occ = my_pieces | other_pieces, movebits; + color_t me = pos->turn, enemy = OPPONENT(me); + bitboard_t my_pieces = pos->bb[me][ALL_PIECES], not_my_pieces = ~my_pieces, + enemy_pieces = pos->bb[enemy][ALL_PIECES]; + bitboard_t occ = my_pieces | enemy_pieces, empty = ~occ; + bitboard_t movebits, from_pawns; + int tmp1, tmp2, from, to; movelist_t moves = pos->moves; /* sliding pieces */ bit_for_each64(from, tmp1, pos->bb[me][BISHOP]) { - movebits = hyperbola_bishop_moves(occ, from) & notmine; + movebits = hyperbola_bishop_moves(occ, from) & not_my_pieces; bit_for_each64(to, tmp2, movebits) { moves.move[moves.nmoves++] = move_make(from, to); } } bit_for_each64(from, tmp1, pos->bb[me][ROOK]) { - movebits = hyperbola_rook_moves(occ, from) & notmine; + movebits = hyperbola_rook_moves(occ, from) & not_my_pieces; bit_for_each64(to, tmp2, movebits) { moves.move[moves.nmoves++] = move_make(from, to); } } + /* TODO: remove this one */ bit_for_each64(from, tmp1, pos->bb[me][QUEEN]) { - movebits = hyperbola_queen_moves(occ, from) & notmine; + movebits = hyperbola_queen_moves(occ, from) & not_my_pieces; bit_for_each64(to, tmp2, movebits) { moves.move[moves.nmoves++] = move_make(from, to); } @@ -62,24 +72,93 @@ int gen_all_pseudomoves(pos_t *pos) /* knight */ bit_for_each64(from, tmp1, pos->bb[me][KNIGHT]) { - movebits = bb_knight_moves(occ, from) & notmine; + movebits = bb_knight_moves(occ, from) & not_my_pieces; bit_for_each64(to, tmp2, movebits) { moves.move[moves.nmoves++] = move_make(from, to); } } /* king */ - movebits = bb_king_moves(occ, pos->king[me]) & notmine; + movebits = bb_king_moves(occ, pos->king[me]) & not_my_pieces; bit_for_each64(to, tmp2, movebits) { moves.move[moves.nmoves++] = move_make(from, to); } + /* pawn: relative rank and files */ + bitboard_t rel_rank7 = (me == WHITE ? RANK_7bb : RANK_2bb); + bitboard_t rel_rank3 = (me == WHITE ? RANK_3bb : RANK_6bb); + bitboard_t rel_filea = (me == WHITE ? FILE_Abb : FILE_Hbb); + bitboard_t rel_fileh = (me == WHITE ? FILE_Hbb : FILE_Abb); + int en_passant = pos->en_passant == SQUARE_NONE? 0: pos->en_passant; + bitboard_t enemy_avail = bb_sq[en_passant] | enemy_pieces; + + /* pawn: ranks 2-6 push 1 and 2 squares */ + movebits = pawn_push(pos->bb[me][PAWN] & ~rel_rank7, me) & empty; + bit_for_each64(to, tmp1, movebits) { + from = pawn_push(to, enemy); /* reverse push */ + moves.move[moves.nmoves++] = move_make(from, to); + } + movebits = pawn_push(movebits & rel_rank3, me) & empty; + bit_for_each64(to, tmp1, movebits) { + from = pawn_push(pawn_push(to, enemy), enemy); + moves.move[moves.nmoves++] = move_make(from, to); + } + /* pawn: rank 7 push */ + movebits = pawn_push(pos->bb[me][PAWN] & rel_rank7, me) & empty; + bit_for_each64(to, tmp1, movebits) { + from = pawn_push(to, enemy); /* reverse push */ + moves.move[moves.nmoves++] = move_make_promote(from, to, QUEEN); + moves.move[moves.nmoves++] = move_make_promote(from, to, ROOK); + moves.move[moves.nmoves++] = move_make_promote(from, to, BISHOP); + moves.move[moves.nmoves++] = move_make_promote(from, to, KNIGHT); + } + + /* pawn: ranks 2-6 captures left, including en-passant */ + from_pawns = pos->bb[me][PAWN] & ~rel_rank7 & ~rel_filea; + movebits = pawn_take_left(from_pawns, me) & enemy_avail; + bit_for_each64(to, tmp1, movebits) { + from = pawn_take_left(to, enemy); /* reverse capture */ + moves.move[moves.nmoves++] = move_make(from, to); + } + /* pawn: rank 7 captures left */ + from_pawns = pos->bb[me][PAWN] & rel_rank7 & ~rel_filea; + movebits = pawn_take_left(from_pawns, me) & enemy_avail; + bit_for_each64(to, tmp1, movebits) { + from = pawn_take_left(to, enemy); /* reverse capture */ + moves.move[moves.nmoves++] = move_make_promote(from, to, QUEEN); + moves.move[moves.nmoves++] = move_make_promote(from, to, ROOK); + moves.move[moves.nmoves++] = move_make_promote(from, to, BISHOP); + moves.move[moves.nmoves++] = move_make_promote(from, to, KNIGHT); + } + + /* pawn: ranks 2-6 captures right, including en-passant */ + from_pawns = pos->bb[me][PAWN] & ~rel_rank7 & ~rel_fileh; + movebits = pawn_take_right(from_pawns, me) & enemy_avail; + bit_for_each64(to, tmp1, movebits) { + from = pawn_take_right(to, enemy); + moves.move[moves.nmoves++] = move_make(from, to); + } + /* pawn: rank 7 captures right */ + from_pawns = pos->bb[me][PAWN] & rel_rank7 & ~rel_fileh; + movebits = pawn_take_right(from_pawns, me) & enemy_pieces; + bit_for_each64(to, tmp1, movebits) { + from = pawn_take_right(to, enemy); /* reverse capture */ + moves.move[moves.nmoves++] = move_make_promote(from, to, QUEEN); + moves.move[moves.nmoves++] = move_make_promote(from, to, ROOK); + moves.move[moves.nmoves++] = move_make_promote(from, to, BISHOP); + moves.move[moves.nmoves++] = move_make_promote(from, to, KNIGHT); + } + /* TODO - * pawn ranks 2-6 advance (1 push, + 2 squares for rank 2) - * pawns ranks 2-6 capture - * pawns rank 7 advance + promotion - * pawns rank 7 capture + promotion - * pawns en-passant + * DONE. pawn ranks 2-6 advance (1 push, + 2 squares for rank 2) + * DONE. pawns rank 7 advance + promotions + * DONE. pawns ranks 2-6 captures, left and right + * DONE. pawns en-passant (with capture) + * DONE. pawns rank 7 capture + promotion * castle + * + * add function per piece, and type, for easier debug + * */ + return moves.nmoves; } diff --git a/test/bitboard-test.c b/test/bitboard-test.c index 1bd0fc6..58aab17 100644 --- a/test/bitboard-test.c +++ b/test/bitboard-test.c @@ -4,10 +4,11 @@ #include #include -#include "../src/position.h" -#include "../src/piece.h" -#include "../src/bitboard.h" -#include "../src/hyperbola-quintessence.h" +#include "bug.h" +#include "position.h" +#include "piece.h" +#include "bitboard.h" +#include "hyperbola-quintessence.h" int main(int __unused ac, __unused char**av) { @@ -21,11 +22,25 @@ int main(int __unused ac, __unused char**av) ); bitboard_print_multi(str, 7, bb_file[i] | bb_rank[i] | - bb_diagonal[i] | bb_antidiagonal[i], - bb_diagonal[i], bb_antidiagonal[i], + bb_diag[i] | bb_anti[i], + bb_diag[i], bb_anti[i], bb_file[i], bb_rank[i], bb_knight[i], bb_king[i]); } + bitboard_print_multi("a1-a8 a1-h8 a1-h1 a2-a7 a2-g7 a2-g2", 6, + bb_between[A1][A8], bb_between[A1][H8], + bb_between[A1][H1], bb_between[A2][A7], + bb_between[A2][G7], bb_between[A2][G2]); + bitboard_print_multi("c3-c6 c3-f6 c3-f3 c3-e1 c3-c1 c3-a1 c3-a3 c3-a5", 8, + bb_between[C3][C6], bb_between[C3][F6], + bb_between[C3][F3], bb_between[C3][E1], + bb_between[C3][C1], bb_between[C3][A1], + bb_between[C3][A3], bb_between[C3][A5]); + bitboard_print_multi("c4-c6 c4-f6 c4-f3 c4-e1 c4-c1 c4-a1 c4-a3 c4-a5", 8, + bb_between[C4][C6], bb_between[C4][F6], + bb_between[C4][F3], bb_between[C4][E1], + bb_between[C4][C1], bb_between[C4][A1], + bb_between[C4][A3], bb_between[C4][A5]); /* * for (square_t sq = 0; sq < 64; ++sq) { * sprintf(str, "%2d %#lx %#lx knight", sq, bb_sq[sq], bb_knight[sq]); diff --git a/test/fen-test.c b/test/fen-test.c index d4b1660..5b4ce57 100644 --- a/test/fen-test.c +++ b/test/fen-test.c @@ -1,10 +1,11 @@ -#include "debug.h" -#include "pool.h" +//#include -#include "../src/chessdefs.h" -#include "../src/bitboard.h" -#include "../src/position.h" -#include "../src/fen.h" +#include "bug.h" + +#include "chessdefs.h" +#include "bitboard.h" +#include "position.h" +#include "fen.h" int main(int ac, char**av) { @@ -13,7 +14,6 @@ int main(int ac, char**av) const char *fen; char revfen[128]; int comp; - //debug_init(5, stderr, true); //pos_pool_init(); bitboard_init();