diff --git a/src/bitboard.c b/src/bitboard.c index 2d518e4..4003729 100644 --- a/src/bitboard.c +++ b/src/bitboard.c @@ -12,6 +12,7 @@ */ #include +#include #include "brlib.h" @@ -30,9 +31,18 @@ static int king_vector[8] = { NORTH, NORTH_EAST, EAST, SOUTH_EAST, SOUTH, SOUTH_WEST, WEST, NORTH_WEST }; +static int bishop_vector[4] = { + NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST +}; +static int rook_vector[4] = { + NORTH, EAST, SOUTH, WEST +}; bitboard_t sq_bb[SQUARE_MAX]; +bitboard_t sq_bbrank[64], sq_bbfile[64], sq_bbdiag[64], sq_bbanti[64]; + bitboard_t knight_attacks[64], king_attacks[64]; +bitboard_t pawn_attacks[2]; /* we will create only dest squares for A1-D4 square, then flip */ @@ -44,11 +54,55 @@ bitboard_t knight_attacks[64], king_attacks[64]; */ void bitboard_init(void) { - square_t sq, dst; + struct { + union { + struct { + bitboard_t diag; + bitboard_t anti; + bitboard_t vert; + bitboard_t hori; + }; + bitboard_t all[4]; + }; + } tmpmasks[64] = {0}; + struct { + int df, dr; + } dirs[4] = { + { 0, 1 }, /* vertical/file */ + { 1, 0 }, /* horizontal/rank */ + { 1, 1 }, /* diagonal */ + { 1, -1 }, /* antidiagonal */ + } ; + square_t sq; + int dst, dst_f, dst_r; + + /* square to bitboard */ for (sq = A1; sq <= H8; ++sq) sq_bb[sq] = mask(sq); + /* square to rank/file/diagonal/antidiagonal */ + for (sq = 0; sq < 64; ++sq) { + int r = sq_rank(sq), f = sq_file(sq); + for (int mult = -7; mult < 8; ++mult) { + for (int dir = 0; dir < 4; ++dir) { + dst_f = f + mult * dirs[dir].df; + dst_r = r + mult * dirs[dir].dr; + if (sq_coord_ok(dst_f) && sq_coord_ok(dst_r)) { + dst = sq_make(dst_f, dst_r); + tmpmasks[sq].all[dir] |= mask(dst); + } + } + } + } + for (sq = 0; sq < 64; ++sq) { + sq_bbfile[sq] = tmpmasks[sq].all[0]; + sq_bbrank[sq] = tmpmasks[sq].all[1]; + sq_bbdiag[sq] = tmpmasks[sq].all[2]; + sq_bbanti[sq] = tmpmasks[sq].all[3]; + } + + /* knight and king attacks */ for (sq = A1; sq <= H8; ++sq) { for (int vec = 0; vec < 8; ++vec) { dst = sq + knight_vector[vec]; @@ -69,21 +123,62 @@ void bitboard_init(void) /** * bitboard_print() - print simple bitboard representation - * @bb: the bitboard - * @tit: a string or NULL + * @title: a string or NULL + * @bitboard: the bitboard */ -void bitboard_print(const bitboard_t bb, const char *tit) +void bitboard_print(const char *title, const bitboard_t bitboard) { //char c = p? p: 'X'; - if (tit) - printf("%s\n", tit); + if (title) + printf("%s\n", title); for (rank_t r = RANK_8; r >= RANK_1; --r) { - printf("%d ", r); + printf("%d ", r + 1); for (file_t f = FILE_A; f <= FILE_H; ++f) { - printf(" %c", bb & sq_bb[sq_make(f, r)] ? 'X': '.'); + printf(" %c", bitboard & sq_bb[sq_make(f, r)] ? 'X': '.'); } printf("\n"); } - printf("\n A B C D E F G H\n"); + printf(" a b c d e f g h\n"); + return; +} + +/** + * bitboard_print_multi() - print multiple bitboards horizontally + * @title: a string or NULL + * @n: number of bitboards + * @bb_ptr...: pointers to bitboards + * + * @n is the number of bitboards to print. If @n -s > 8, it is reduced to 8; + */ +void bitboard_print_multi(const char *title, const int n, ...) +{ + bitboard_t bb[16]; + int i; + va_list ap; + + va_start(ap, n); + for (i = 0; i < n; ++i) { + bb[i] = va_arg(ap, bitboard_t); + } + va_end(ap); + //char c = p? p: 'X'; + if (title) + printf("%s\n", title); + + for (rank_t r = RANK_8; r >= RANK_1; --r) { + for (i = 0; i < n; ++i) { + printf("%d ", r + 1); + for (file_t f = FILE_A; f <= FILE_H; ++f) { + printf(" %c", bb[i] & sq_bb[sq_make(f, r)] ? 'X': '.'); + } + printf(" "); + } + printf("\n"); + } + for (i = 0; i < n; ++i) { + printf(" a b c d e f g h"); + printf(" "); + } + printf("\n"); return; } diff --git a/src/bitboard.h b/src/bitboard.h index 187f9d6..346129d 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -22,7 +22,13 @@ typedef u64 bitboard_t; -extern bitboard_t sq_bb[64], knight_attacks[64], king_attacks[64]; +/* mapping square -> bitboard */ +extern bitboard_t sq_bb[64]; + +/* mapping square -> rank/file/diagonal/antidiagonal */ +extern bitboard_t sq_bbrank[64], sq_bbfile[64], sq_bbdiag[64], sq_bbanti[64]; + +extern bitboard_t knight_attacks[64], king_attacks[64]; #define mask(i) ( 1ULL << (i) ) @@ -56,6 +62,7 @@ static __always_inline bitboard_t bb_rotate_90(bitboard_t b) } extern void bitboard_init(void); -extern void bitboard_print(const bitboard_t bitboard, const char *title); +extern void bitboard_print(const char *title, const bitboard_t bitboard); +extern void bitboard_print_multi(const char *title, const int n, ...); #endif /* _BITBOARD_H */ diff --git a/src/board.h b/src/board.h index b7a6376..745ef5d 100644 --- a/src/board.h +++ b/src/board.h @@ -80,6 +80,7 @@ static __always_inline rank_t sq_rank(square_t square) #define sq_ok(sq) ((sq) >= A1 && (sq) <= H8) +#define sq_coord_ok(c) ((c) >= 0 && (c) < 8) /* Chebyshev distance: https://www.chessprogramming.org/Distance */ #define sq_dist(sq1, sq2) (max(abs(sq_file(sq2) - sq_file(sq1)), \ diff --git a/src/move.c b/src/move.c index 7f1d23e..08ef54e 100644 --- a/src/move.c +++ b/src/move.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include diff --git a/test/bitboard-test.c b/test/bitboard-test.c index 980050c..a3ce8e1 100644 --- a/test/bitboard-test.c +++ b/test/bitboard-test.c @@ -13,11 +13,19 @@ int main(int __unused ac, __unused char**av) { char str[128]; bitboard_init(); + for (int i = 0; i < 64; ++i) { + char str[128]; + sprintf(str, "\ndiag/antidiag/vert %d", i); + bitboard_print_multi(str, 5, + sq_bbfile[i] | sq_bbrank[i] | sq_bbdiag[i] | sq_bbanti[i], + sq_bbfile[i], sq_bbrank[i], + sq_bbdiag[i], sq_bbanti[i]); + } for (square_t sq = 0; sq < 64; ++sq) { sprintf(str, "%2d %#lx %#lx knight", sq, sq_bb[sq], knight_attacks[sq]); - bitboard_print(knight_attacks[sq], str); + bitboard_print(str, knight_attacks[sq]); sprintf(str, "%2d %#lx %#lx knight", sq, sq_bb[sq], king_attacks[sq]); - bitboard_print(king_attacks[sq], str); + bitboard_print(str, king_attacks[sq]); } return 0; }