new pos/bb funcs, legal(), better castling gen, etc. [see commit details]

- new sq_pinners
- new pseudo_is_legal() (unfinished)
- improve castling pseudo move gen

- more position and lower level bitboard helper funcs:
  - pos_{_occ,between_occ,between_count,pinners}
  - bb_{rank,file,rel_rank,_sq_aligned,_sq_between)
- rename some bitboard globals
- replace bb ranks/files enums with defines (issue with clang)
  -> Need to find a way to use enum safely
- tests:
  - add common-test.h
  - new attack-test.c
This commit is contained in:
2024-03-07 10:50:19 +01:00
parent b351d198b8
commit 87e7695873
20 changed files with 913 additions and 373 deletions

View File

@@ -35,60 +35,110 @@
* T on @sq could attack a white T piece.
*
* @Return: a bitboard of attackers.
*
*/
// #define DEBUG_ATTACK_ATTACKERS1
bitboard_t sq_attackers(const pos_t *pos, const square_t sq, const color_t c)
{
bitboard_t attackers = 0;
bitboard_t attackers = 0, tmp;
bitboard_t sqbb = mask(sq);
bitboard_t c_pieces = pos->bb[c][ALL_PIECES];
bitboard_t occ = c_pieces | pos->bb[OPPONENT(c)][ALL_PIECES];
bitboard_t occ = pos_occ(pos);
bitboard_t to;
color_t opp = OPPONENT(c);
/* pawn */
to = pos->bb[c][PAWN];
attackers |= pawn_shift_upleft(sqbb, opp) & to;
# ifdef DEBUG_ATTACK
bitboard_print("sq_attackers after pawn upleft", attackers);
tmp = pawn_shift_upleft(sqbb, opp) & to;
attackers |= tmp;
# ifdef DEBUG_ATTACK_ATTACKERS1
bb_print("att pawn upleft", tmp);
# endif
attackers |= pawn_shift_upright(sqbb, opp) & to;
# ifdef DEBUG_ATTACK
bitboard_print("sq_attackers pawn upright", attackers);
tmp = pawn_shift_upright(sqbb, opp) & to;
attackers |= tmp;
# ifdef DEBUG_ATTACK_ATTACKERS1
bb_print("att pawn upright", tmp);
# endif
/* knight & king */
to = pos->bb[c][KNIGHT];
attackers |= bb_knight_moves(to, sq);
# ifdef DEBUG_ATTACK
bitboard_print("sq_attackers after knight", attackers);
tmp = bb_knight_moves(to, sq);
attackers |= tmp;
# ifdef DEBUG_ATTACK_ATTACKERS1
bb_print("att knight", tmp);
# endif
to = pos->bb[c][KING];
attackers |= bb_king_moves(to, sq);
# ifdef DEBUG_ATTACK
bitboard_print("sq_attackers after king", attackers);
tmp = bb_king_moves(to, sq);
attackers |= tmp;
# ifdef DEBUG_ATTACK_ATTACKERS1
bb_print("att king", tmp);
# endif
/* bishop / queen */
to = pos->bb[c][BISHOP] | pos->bb[c][QUEEN];
attackers |= hyperbola_bishop_moves(occ, sq) & to;
# ifdef DEBUG_ATTACK
bitboard_print("sq_attackers after bishop/queen", attackers);
tmp = hyperbola_bishop_moves(occ, sq) & to;
attackers |= tmp;
# ifdef DEBUG_ATTACK_ATTACKERS1
bb_print("att bishop/queen", tmp);
# endif
/* rook / queen */
to = pos->bb[c][ROOK] | pos->bb[c][QUEEN];
# ifdef DEBUG_ATTACK
bitboard_print("sq_attackers after queen", attackers);
# endif
attackers |= hyperbola_rook_moves(occ, sq) & to;
# ifdef DEBUG_ATTACK
bitboard_print("sq_attackers after rook/queen", attackers);
tmp = hyperbola_rook_moves(occ, sq) & to;
attackers |= tmp;
# ifdef DEBUG_ATTACK_ATTACKERS1
bb_print("att rook/queen", tmp);
bb_print("ATTACKERS", attackers);
printf("attackers=%lx\n", attackers);
# endif
return attackers;
}
/**
* sq_pinners() - find pinners on a square
* @pos: position
* @sq: square to test
* @c: attacker color
*
* Find all @c pieces which are separated from @sq by only one piece (of
* any color).
*
* @Return: a bitboard of attackers.
*/
bitboard_t sq_pinners(const pos_t *pos, const square_t sq, const color_t c)
{
bitboard_t attackers, pinners = 0;
bitboard_t occ = pos_occ(pos);
bitboard_t maybe_pinner, tmp, lines;
/* bishop type */
attackers = pos->bb[c][BISHOP] | pos->bb[c][QUEEN];
/* occupancy on sq diag and antidiag */
lines = (bb_sqdiag[sq] | bb_sqanti[sq]) & occ;
bit_for_each64(maybe_pinner, tmp, attackers) {
bitboard_t between = bb_between_excl[maybe_pinner][sq];
/* keep only squares between AND on sq diag/anti */
if (popcount64(between & lines) == 1)
pinners |= mask(maybe_pinner);
}
/* same for rook type */
attackers = pos->bb[c][ROOK] | pos->bb[c][QUEEN];
lines = (bb_sqrank[sq] | bb_sqfile[sq]) & occ;
bit_for_each64(maybe_pinner, tmp, attackers) {
bitboard_t between = bb_between_excl[maybe_pinner][sq];
if (popcount64(between & lines) == 1)
pinners |= mask(maybe_pinner);
}
# ifdef DEBUG_ATTACK_ATTACKERS1
char str[32];
printf("pinners : %s\n", pos_pinners2str(pos, str, sizeof(str)));
printf("pinners : %lx\n", pinners);
# endif
return pinners;
}
/**
* sq_attackers() - find all attackers on a square
* @pos: position