291 lines
9.5 KiB
C
291 lines
9.5 KiB
C
/* bitboard.h - bitboard definitions.
|
|
*
|
|
* Copyright (C) 2021-2024 Bruno Raoult ("br")
|
|
* Licensed under the GNU General Public License v3.0 or later.
|
|
* Some rights reserved. See COPYING.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with this
|
|
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
|
*
|
|
*/
|
|
|
|
#ifndef _BITBOARD_H
|
|
#define _BITBOARD_H
|
|
|
|
#include <brlib.h>
|
|
#include <bitops.h>
|
|
|
|
#include "chessdefs.h"
|
|
#include "board.h"
|
|
#include "piece.h"
|
|
|
|
/* mapping square -> bitboard */
|
|
extern bitboard_t bb_sq[64];
|
|
/* squares between sq1 and sq2, exclusing both */
|
|
extern bitboard_t bb_between_excl[64][64];
|
|
/* squares between sq1 and sq2, including sq2 */
|
|
extern bitboard_t bb_between[64][64];
|
|
|
|
/**
|
|
* bb_sqrank[64]: square to rank
|
|
* bb_sqfile[64]: square to file
|
|
* bb_sqdiag[64]: square to diagonal
|
|
* bb_sqanti[64]: square to antidiagonal
|
|
*/
|
|
extern bitboard_t bb_sqrank[64], bb_sqfile[64], bb_sqdiag[64], bb_sqanti[64];
|
|
|
|
/* line (rank, file, diagonal or anti-diagonal) between two squares */
|
|
extern bitboard_t bb_line[64][64];
|
|
|
|
/* pawn, knight and king attacks */
|
|
extern bitboard_t bb_knight[64], bb_king[64], bb_pawn_attacks[2][64];
|
|
|
|
/* TODO (maybe C23?) when we can ensure an enum can be u64
|
|
*
|
|
* enum {
|
|
* A1bb = mask(A1), A2bb = mask(A2), A3bb = mask(A3), A4bb = mask(A4),
|
|
* A5bb = mask(A5), A6bb = mask(A6), A7bb = mask(A7), A8bb = mask(A8),
|
|
* B1bb = mask(B1), B2bb = mask(B2), B3bb = mask(B3), B4bb = mask(B4),
|
|
* B5bb = mask(B5), B6bb = mask(B6), B7bb = mask(B7), B8bb = mask(B8),
|
|
* C1bb = mask(C1), C2bb = mask(C2), C3bb = mask(C3), C4bb = mask(C4),
|
|
* C5bb = mask(C5), C6bb = mask(C6), C7bb = mask(C7), C8bb = mask(C8),
|
|
* D1bb = mask(D1), D2bb = mask(D2), D3bb = mask(D3), D4bb = mask(D4),
|
|
* D5bb = mask(D5), D6bb = mask(D6), D7bb = mask(D7), D8bb = mask(D8),
|
|
* E1bb = mask(E1), E2bb = mask(E2), E3bb = mask(E3), E4bb = mask(E4),
|
|
* E5bb = mask(E5), E6bb = mask(E6), E7bb = mask(E7), E8bb = mask(E8),
|
|
* F1bb = mask(F1), F2bb = mask(F2), F3bb = mask(F3), F4bb = mask(F4),
|
|
* F5bb = mask(F5), F6bb = mask(F6), F7bb = mask(F7), F8bb = mask(F8),
|
|
* G1bb = mask(G1), G2bb = mask(G2), G3bb = mask(G3), G4bb = mask(G4),
|
|
* G5bb = mask(G5), G6bb = mask(G6), G7bb = mask(G7), G8bb = mask(G8),
|
|
* H1bb = mask(H1), H2bb = mask(H2), H3bb = mask(H3), H4bb = mask(H4),
|
|
* H5bb = mask(H5), H6bb = mask(H6), H7bb = mask(H7), H8bb = mask(H8),
|
|
* };
|
|
*
|
|
* enum {
|
|
* FILE_Abb = 0x0101010101010101ull, FILE_Bbb = 0x0202020202020202ull,
|
|
* FILE_Cbb = 0x0404040404040404ull, FILE_Dbb = 0x0808080808080808ull,
|
|
* FILE_Ebb = 0x1010101010101010ull, FILE_Fbb = 0x2020202020202020ull,
|
|
* FILE_Gbb = 0x4040404040404040ull, FILE_Hbb = 0x8080808080808080ull,
|
|
*
|
|
* RANK_1bb = 0x00000000000000ffull, RANK_2bb = 0x000000000000ff00ull,
|
|
* RANK_3bb = 0x0000000000ff0000ull, RANK_4bb = 0x00000000ff000000ull,
|
|
* RANK_5bb = 0x000000ff00000000ull, RANK_6bb = 0x0000ff0000000000ull,
|
|
* RANK_7bb = 0x00ff000000000000ull, RANK_8bb = 0xff00000000000000ull
|
|
* };
|
|
*/
|
|
|
|
/* generated with bash:
|
|
* R="ABCDEFGH"
|
|
* F="12345678"
|
|
* for i in {0..63}; do
|
|
* printf "#define %c%cbb %#018llxull\n" ${R:i/8:1} ${F:i%8:1} $((1 << i))
|
|
* done
|
|
*/
|
|
#define A1bb 0x0000000000000001ull
|
|
#define A2bb 0x0000000000000002ull
|
|
#define A3bb 0x0000000000000004ull
|
|
#define A4bb 0x0000000000000008ull
|
|
#define A5bb 0x0000000000000010ull
|
|
#define A6bb 0x0000000000000020ull
|
|
#define A7bb 0x0000000000000040ull
|
|
#define A8bb 0x0000000000000080ull
|
|
#define B1bb 0x0000000000000100ull
|
|
#define B2bb 0x0000000000000200ull
|
|
#define B3bb 0x0000000000000400ull
|
|
#define B4bb 0x0000000000000800ull
|
|
#define B5bb 0x0000000000001000ull
|
|
#define B6bb 0x0000000000002000ull
|
|
#define B7bb 0x0000000000004000ull
|
|
#define B8bb 0x0000000000008000ull
|
|
#define C1bb 0x0000000000010000ull
|
|
#define C2bb 0x0000000000020000ull
|
|
#define C3bb 0x0000000000040000ull
|
|
#define C4bb 0x0000000000080000ull
|
|
#define C5bb 0x0000000000100000ull
|
|
#define C6bb 0x0000000000200000ull
|
|
#define C7bb 0x0000000000400000ull
|
|
#define C8bb 0x0000000000800000ull
|
|
#define D1bb 0x0000000001000000ull
|
|
#define D2bb 0x0000000002000000ull
|
|
#define D3bb 0x0000000004000000ull
|
|
#define D4bb 0x0000000008000000ull
|
|
#define D5bb 0x0000000010000000ull
|
|
#define D6bb 0x0000000020000000ull
|
|
#define D7bb 0x0000000040000000ull
|
|
#define D8bb 0x0000000080000000ull
|
|
#define E1bb 0x0000000100000000ull
|
|
#define E2bb 0x0000000200000000ull
|
|
#define E3bb 0x0000000400000000ull
|
|
#define E4bb 0x0000000800000000ull
|
|
#define E5bb 0x0000001000000000ull
|
|
#define E6bb 0x0000002000000000ull
|
|
#define E7bb 0x0000004000000000ull
|
|
#define E8bb 0x0000008000000000ull
|
|
#define F1bb 0x0000010000000000ull
|
|
#define F2bb 0x0000020000000000ull
|
|
#define F3bb 0x0000040000000000ull
|
|
#define F4bb 0x0000080000000000ull
|
|
#define F5bb 0x0000100000000000ull
|
|
#define F6bb 0x0000200000000000ull
|
|
#define F7bb 0x0000400000000000ull
|
|
#define F8bb 0x0000800000000000ull
|
|
#define G1bb 0x0001000000000000ull
|
|
#define G2bb 0x0002000000000000ull
|
|
#define G3bb 0x0004000000000000ull
|
|
#define G4bb 0x0008000000000000ull
|
|
#define G5bb 0x0010000000000000ull
|
|
#define G6bb 0x0020000000000000ull
|
|
#define G7bb 0x0040000000000000ull
|
|
#define G8bb 0x0080000000000000ull
|
|
#define H1bb 0x0100000000000000ull
|
|
#define H2bb 0x0200000000000000ull
|
|
#define H3bb 0x0400000000000000ull
|
|
#define H4bb 0x0800000000000000ull
|
|
#define H5bb 0x1000000000000000ull
|
|
#define H6bb 0x2000000000000000ull
|
|
#define H7bb 0x4000000000000000ull
|
|
#define H8bb 0x8000000000000000ull
|
|
|
|
#define FILE_Abb 0x0101010101010101ull
|
|
#define FILE_Bbb 0x0202020202020202ull
|
|
#define FILE_Cbb 0x0404040404040404ull
|
|
#define FILE_Dbb 0x0808080808080808ull
|
|
#define FILE_Ebb 0x1010101010101010ull
|
|
#define FILE_Fbb 0x2020202020202020ull
|
|
#define FILE_Gbb 0x4040404040404040ull
|
|
#define FILE_Hbb 0x8080808080808080ull
|
|
|
|
#define RANK_1bb 0x00000000000000ffull
|
|
#define RANK_2bb 0x000000000000ff00ull
|
|
#define RANK_3bb 0x0000000000ff0000ull
|
|
#define RANK_4bb 0x00000000ff000000ull
|
|
#define RANK_5bb 0x000000ff00000000ull
|
|
#define RANK_6bb 0x0000ff0000000000ull
|
|
#define RANK_7bb 0x00ff000000000000ull
|
|
#define RANK_8bb 0xff00000000000000ull
|
|
|
|
|
|
/*
|
|
static __always_inline bitboard_t bb_rank(int rank)
|
|
{
|
|
return RANK_1bb << (rank * 8);
|
|
}
|
|
static __always_inline bitboard_t bb_rel_rank(int rank, color)
|
|
{
|
|
return RANK_1bb << (rank * 8);
|
|
}
|
|
static __always_inline bitboard_t bb_file(int file)
|
|
{
|
|
return FILE_Abb << file;
|
|
}
|
|
*/
|
|
|
|
/**
|
|
* bb_next() - clear and return next (lsb) square of a bitboard.
|
|
* @bb: &bitboard
|
|
*
|
|
* The bitboard addressed by @bb must be non-zero.
|
|
*
|
|
* @return: first bit (lsb) of @bb.
|
|
*/
|
|
static __always_inline square_t bb_next(bitboard_t *bb)
|
|
{
|
|
square_t sq = lsb64(*bb);
|
|
*bb &= *bb - 1;
|
|
return sq;
|
|
}
|
|
|
|
/**
|
|
* bb_multiple() - test if a bitboard has multiple bits.
|
|
* @bb: bitboard
|
|
*
|
|
* @return: true if @bb has more than 1 bit, false otherwise.
|
|
*/
|
|
static __always_inline bool bb_multiple(bitboard_t bb)
|
|
{
|
|
return !!(bb & (bb - 1));
|
|
}
|
|
|
|
/**
|
|
* bb_shift() - shift bitboard
|
|
* @bb: bitboard
|
|
*
|
|
* No control is done on off-board shifting (i.e. shifting -1 from A2 gives H3).
|
|
*
|
|
* @return: true if @bb has more than 1 bit, false otherwise.
|
|
*/
|
|
static __always_inline bitboard_t bb_shift(bitboard_t bb, int shift)
|
|
{
|
|
return shift >= 0 ? bb << shift : bb >> -shift;
|
|
}
|
|
|
|
/**
|
|
* bb_pawns_attacks() - shift up pawns on both diagonals (attacks)
|
|
* @bb: pawns bitboard
|
|
* @push: shift value for pawn up
|
|
*
|
|
* Get the possible attacks for all @bb pawns.
|
|
*
|
|
* @return: squares attacked by @bbpawns
|
|
*/
|
|
static __always_inline bitboard_t bb_pawns_attacks(const bitboard_t bb, int push)
|
|
{
|
|
return bb_shift(bb & ~FILE_Abb, push - 1) | bb_shift(bb & ~FILE_Hbb, push + 1);
|
|
}
|
|
|
|
#define bb_rank(r) ((u64) RANK_1bb << ((r) * 8))
|
|
#define bb_file(f) ((u64) FILE_Abb << (f))
|
|
|
|
#define bb_rel_rank(r, c) bb_rank(sq_rel_rank(r, c))
|
|
#define bb_rel_file(f, c) bb_file(sq_rel_rank(f, c)) /* likely useless */
|
|
|
|
/**
|
|
* bb_sq_aligned() - check if two squares are aligned (same file or rank).
|
|
* @sq1, @sq2: the two squares.
|
|
*
|
|
* @return: true if @sq1 and @sq2 are on same line, false otherwise.
|
|
*/
|
|
static __always_inline bool bb_sq_aligned(square_t sq1, square_t sq2)
|
|
{
|
|
return bb_line[sq1][sq2];
|
|
}
|
|
|
|
/**
|
|
* bb_sq_aligned3() - check if 3 squares are aligned (same file or rank).
|
|
* @sq1, @sq2, @sq3: the three squares.
|
|
*
|
|
* @return: true if @sq1, @sq2, and @sq3 are aligned, false otherwise.
|
|
*/
|
|
static __always_inline bool bb_sq_aligned3(square_t sq1, square_t sq2, square_t sq3)
|
|
{
|
|
return bb_line[sq1][sq2] & BIT(sq3);
|
|
}
|
|
|
|
/**
|
|
* bb_sq_between() - check if a square is between two squares
|
|
* @sq: the possibly "in-between" square
|
|
* @sq1: square 1
|
|
* @sq2: square 2
|
|
*
|
|
* @return: bitboard of @sq if between @sq1 and @sq2.
|
|
*/
|
|
static __always_inline bitboard_t bb_sq_between(square_t sq, square_t sq1, square_t sq2)
|
|
{
|
|
return bb_between_excl[sq1][sq2] & BIT(sq);
|
|
}
|
|
|
|
bitboard_t bitboard_between_excl(square_t sq1, square_t sq2);
|
|
void bitboard_init(void);
|
|
|
|
bitboard_t bb_knight_moves(bitboard_t notmine, square_t sq);
|
|
bitboard_t bb_king_moves(bitboard_t notmine, square_t sq);
|
|
|
|
void bb_print(const char *title, const bitboard_t bitboard);
|
|
void bb_print_multi(const char *title, const int n, ...);
|
|
char *bb_rank_sprint(char *str, const uchar bb8);
|
|
char *bb_sq2str(const bitboard_t bb, char *str, int len);
|
|
|
|
#endif /* _BITBOARD_H */
|