replace pawn_shift_xxx with bb_pawns_attacks

This commit is contained in:
2024-05-28 09:40:20 +02:00
parent 972046351b
commit ec64e2e44d
9 changed files with 85 additions and 151 deletions

View File

@@ -115,13 +115,16 @@ bitboard_t sq_attackers(const pos_t *pos, const bitboard_t occ, const square_t s
/* pawn */
to = pos->bb[c][PAWN];
tmp = pawn_shift_upleft(sqbb, opp) & to;
tmp = bb_pawns_attacks(sqbb, sq_up(opp)) & to;
attackers |= tmp;
//to = pos->bb[c][PAWN];
//tmp = pawn_shift_upleft(sqbb, opp) & to;
//attackers |= tmp;
# ifdef DEBUG_ATTACK_ATTACKERS
bb_print("att pawn upleft", tmp);
# endif
tmp = pawn_shift_upright(sqbb, opp) & to;
attackers |= tmp;
//tmp = pawn_shift_upright(sqbb, opp) & to;
//attackers |= tmp;
# ifdef DEBUG_ATTACK_ATTACKERS
bb_print("att pawn upright", tmp);
# endif

View File

@@ -160,10 +160,10 @@ void bitboard_init(void)
/* 3) pawn, knight and king attacks
*/
for (square_t sq = A1; sq <= H8; ++sq) {
if (sq >= A2)
bb_pawn_attacks[BLACK][sq] = pawn_attacks_bb(BIT(sq), BLACK);
if (sq <= H7)
bb_pawn_attacks[WHITE][sq] = pawn_attacks_bb(BIT(sq), WHITE);
if (sq <= H7)
bb_pawn_attacks[WHITE][sq] = bb_pawns_attacks(BIT(sq), sq_up(WHITE));
if (sq >= A2)
bb_pawn_attacks[BLACK][sq] = bb_pawns_attacks(BIT(sq), sq_up(BLACK));
for (int vec = 0; vec < 8; ++vec) {
int dst = sq + knight_vector[vec];

View File

@@ -234,12 +234,25 @@ 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))
#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).
@@ -276,55 +289,6 @@ static __always_inline bitboard_t bb_sq_between(square_t sq, square_t sq1, squar
return bb_between_excl[sq1][sq2] & BIT(sq);
}
/* TODO: when OK, replace with macros */
static __always_inline bitboard_t shift_n(const bitboard_t bb)
{
return bb << NORTH;
}
static __always_inline bitboard_t shift_ne(const bitboard_t bb)
{
return (bb & ~FILE_Hbb) << NORTH_EAST;
}
static __always_inline bitboard_t shift_e(const bitboard_t bb)
{
return (bb & ~FILE_Hbb) << EAST;
}
static __always_inline bitboard_t shift_se(const bitboard_t bb)
{
return (bb & ~FILE_Hbb) >> -SOUTH_EAST;
}
static __always_inline bitboard_t shift_s(const bitboard_t bb)
{
return bb >> -SOUTH;
}
static __always_inline bitboard_t shift_sw(const bitboard_t bb)
{
return (bb & ~FILE_Abb) >> -SOUTH_WEST;
}
static __always_inline bitboard_t shift_w(const bitboard_t bb)
{
return (bb & ~FILE_Abb) >> -WEST;
}
static __always_inline bitboard_t shift_nw(const bitboard_t bb)
{
return (bb & ~FILE_Abb) << NORTH_WEST;
}
/* pawn moves/attacks (for bitboards) */
#define pawn_shift_up(bb, c) ((c) == WHITE ? shift_n(bb): shift_s(bb))
#define pawn_shift_upleft(bb, c) ((c) == WHITE ? shift_nw(bb): shift_se(bb))
#define pawn_shift_upright(bb, c) ((c) == WHITE ? shift_ne(bb): shift_sw(bb))
#define pawn_attacks_bb(bb, c) (pawn_shift_upleft(bb, c) | \
pawn_shift_upright(bb, c))
/* pawn move (for single pawn) - NO SQUARE CONTROL HERE !
* Need to make functions with control instead.
*/
#define pawn_push_up(sq, c) ((sq) + ((c) == WHITE ? NORTH: SOUTH))
//#define pawn_push_upleft(sq, c) ((sq) + ((c) == WHITE ? NORTH_WEST: SOUTH_EAST))
//#define pawn_push_upright(sq, c) ((sq) + ((c) == WHITE ? NORTH_EAST: SOUTH_WEST))
bitboard_t bitboard_between_excl(square_t sq1, square_t sq2);
void bitboard_init(void);

View File

@@ -139,8 +139,10 @@ typedef enum {
/* define diff for relative squares */
#define sq_up(c) ((c) == WHITE ? NORTH: SOUTH)
#define sq_upleft(c) ((c) == WHITE ? NORTH_WEST: SOUTH_EAST)
#define sq_upright(c) ((c) == WHITE ? NORTH_EAST: SOUTH_WEST)
/* Attention here: We mix "up" (color dependent) and W/E, color independant.
*/
#define sq_upwest(up) ((up) - 1)
#define sq_upeast(up) ((up) + 1)
#include <time.h>

View File

@@ -61,18 +61,20 @@ static const char *castle_str = "KQkq";
#define SKIP_BLANK(p) for(;isspace(*(p)); (p)++)
/**
* fen_check(pos_t *pos) - test (and try to fix) fen-generated position.
* @pos: position
* fen_ok() - test (and try to fix) fen-generated position.
* @pos: &position
* @fixit: action flag
*
* Test and fix the following:
* Test and possibly fix the following:
* - inconsistent castle flags (if K & R are not in correct position)
* - inconsistent en-passant square (turn, bad pawn position)
* - inconsistent en-passant square (turn, bad pawns positions)
*
* pos_ok() is also called, leading to fatal errors if something is wrong.
* if @fixit is true, any error above will be fixed, and pos_ok() will
is also called, leading to fatal errors if something is wrong.
*
* @return: 0 if OK, 1 if OK after fix, -1 if fatal issue.
*/
static int fen_check(pos_t *pos)
int fen_ok(pos_t *pos, bool fixit)
{
char *colstr[2] = { "white", "black"};
int warning = 0;
@@ -87,18 +89,17 @@ static int fen_check(pos_t *pos)
piece_t pawn = MAKE_PIECE(PAWN, them);
bitboard_t att = bb_pawn_attacks[them][ep] & pos->bb[us][PAWN];
if (warn(eprank != rank6 ||
pos->board[ep - up] != pawn ||
pos->board[ep] != EMPTY ||
pos->board[ep + up] != EMPTY ||
att == 0ull,
"fen warn: wrong en-passant settings. (fixed)\n")) {
# ifdef DEBUG_FEN
printf("ep5=%o ep6=%o ep7=%o\n", sq_make(epfile, rank5),
sq_make(epfile, rank6), sq_make(epfile, rank7));
# endif
if (eprank != rank6 ||
pos->board[ep - up] != pawn ||
pos->board[ep] != EMPTY ||
pos->board[ep + up] != EMPTY ||
att == 0ull) {
warning++;
pos->en_passant = SQUARE_NONE;
if (fixit) {
warn(true, "pos warn: wrong en-passant settings (fixed).\n");
pos->en_passant = SQUARE_NONE;
}
}
}
@@ -112,28 +113,28 @@ static int fen_check(pos_t *pos)
bitboard_t r_q = bb_sq[sq_make(FILE_A, rank1)];
/* where they are */
bitboard_t kings = pos->bb[color][KING];
bitboard_t rooks = pos->bb[color][ROOK];
bitboard_t kingbb = pos->bb[color][KING];
bitboard_t rookbb = pos->bb[color][ROOK];
castle_rights_t castle_k = color == WHITE? CASTLE_WK: CASTLE_BK;
castle_rights_t castle_q = color == WHITE? CASTLE_WQ: CASTLE_BQ;
if (pos->castle & castle_k) {
if (warn(!(k & kings && r_k & rooks),
"fen warn: wrong %s short castling K or R position (fixed)\n",
colstr[color])) {
warning++;
if (pos->castle & castle_k && !(k & kingbb && r_k & rookbb)) {
warning++;
if (fixit) {
warn(true, "fen warn: wrong %s short castling (fixed)\n",
colstr[color]);
pos->castle &= ~castle_k;
}
}
if (pos->castle & castle_q) {
if (warn(!(k & kings && r_q & rooks),
"fen warn: wrong %s long castling K or R position (fixed)\n",
colstr[color])) {
warning++;
if (pos->castle & castle_q && !(k & kingbb && r_q & rookbb)) {
warning++;
if (fixit) {
warn(true, "fen warn: wrong %s long castling (fixed)\n",
colstr[color]);
pos->castle &= ~castle_q;
}
}
}
return pos_ok(pos, 0) ? warning: -1;
return warning;
}
/**
@@ -253,15 +254,15 @@ end:
err_line, err_pos, err_char, err_char)) {
return NULL;
}
if (fen_check(&tmppos) < 0)
return NULL;
fen_ok(&tmppos, true); /* fix e.p & castling flags */
if (!pos_ok(&tmppos, false))
return NULL; /* invalid position: ignored */
tmppos.key = zobrist_calc(&tmppos);
if (!pos)
pos = pos_new();
pos_copy(&tmppos, pos);
//puts("prout 1");
//pos_print_raw(&tmppos, 1);
//puts("prout 2");
# ifdef DEBUG_FEN
pos_print_raw(&tmppos, 1);
# endif

View File

@@ -20,6 +20,7 @@
extern const char *startfen; /* startup position */
extern int fen_ok(pos_t *pos, bool fixit);
extern pos_t *startpos(pos_t *pos);
extern pos_t *fen2pos(pos_t *pos, const char *fen);
extern char *pos2fen(const pos_t *pos, char *fen);

View File

@@ -96,17 +96,14 @@ bool pseudo_is_legal(const pos_t *pos, const move_t move)
* would discover a R/Q horizontal check.
*/
if (is_enpassant(move)) {
bitboard_t rank5 = us == WHITE? RANK_5bb: RANK_4bb;
bitboard_t rank5 = bb_rel_rank(RANK_1, us);
if ((pos->bb[us][KING] & rank5)) {
bitboard_t exclude = BIT(pos->en_passant - sq_up(us)) | BIT(from);
bitboard_t rooks = (pos->bb[them][ROOK] | pos->bb[them][QUEEN]) & rank5;
while (rooks) {
square_t rook = bb_next(&rooks);
if (hyperbola_rank_moves(occ ^ exclude, rook) & kingbb)
return false;
}
if (hyperbola_rank_moves(occ ^ exclude, king) & rooks)
return false;
}
}
return true;
@@ -467,62 +464,25 @@ movelist_t *pos_gen_pseudo(pos_t *pos, movelist_t *movelist)
}
/* pawn: captures */
/*
* tmp_bb = pawn_attacks_bb(pos->bb[us][PAWN], us) & enemy_pieces;
* //bb_print("FAIL", tmp_bb);
* to_bb = tmp_bb & ~rel_rank8;
* while (to_bb) {
* to = bb_next(&to_bb);
* from_bb = bb_pawn_attacks[them][to] & pos->bb[us][PAWN];
* while (from_bb) {
* from = bb_next(&from_bb);
* *moves++ = move_make(from, to);
* }
* }
* to_bb = tmp_bb & rel_rank8;
* while (to_bb) {
* to = bb_next(&to_bb);
* from_bb = bb_pawn_attacks[them][to] & pos->bb[us][PAWN];
* while (from_bb) {
* from = bb_next(&from_bb);
* moves = move_make_promotions(moves, from, to);
* }
* }
*/
/* pawn: captures left */
bitboard_t filter = ~bb_rel_file(FILE_A, us);
shift = sq_upleft(us);
tmp_bb = bb_shift(pos->bb[us][PAWN] & filter, shift) & enemy_pieces;
tmp_bb = bb_pawns_attacks(pos->bb[us][PAWN], shift) & enemy_pieces;
//bb_print("FAIL", tmp_bb);
to_bb = tmp_bb & ~rel_rank8;
while (to_bb) {
to = bb_next(&to_bb);
from = to - shift;
*moves++ = move_make(from, to);
from_bb = bb_pawn_attacks[them][to] & pos->bb[us][PAWN];
while (from_bb) {
from = bb_next(&from_bb);
*moves++ = move_make(from, to);
}
}
to_bb = tmp_bb & rel_rank8;
while (to_bb) {
to = bb_next(&to_bb);
from = to - shift;
moves = move_gen_promotions(moves, from, to);
}
/* pawn: captures right */
filter = ~bb_rel_file(FILE_H, us);
shift = sq_upright(us);
tmp_bb = bb_shift(pos->bb[us][PAWN] & filter, shift) & enemy_pieces;
to_bb = tmp_bb & ~rel_rank8;
while (to_bb) {
to = bb_next(&to_bb);
from = to - shift;
*moves++ = move_make(from, to);
}
to_bb = tmp_bb & rel_rank8;
while (to_bb) {
to = bb_next(&to_bb);
from = to - shift;
moves = move_gen_promotions(moves, from, to);
from_bb = bb_pawn_attacks[them][to] & pos->bb[us][PAWN];
while (from_bb) {
from = bb_next(&from_bb);
moves = move_gen_promotions(moves, from, to);
}
}
/* pawn: en-passant

View File

@@ -346,7 +346,7 @@ bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboa
*
* @return: (if @strict is false) return true if check is ok, false otherwise.
*/
bool pos_ok(const pos_t *pos, const bool strict)
bool pos_ok(pos_t *pos, const bool strict)
{
int n, count = 0, bbcount = 0, error = 0;
color_t us = pos->turn, them = OPPONENT(us);
@@ -397,6 +397,9 @@ bool pos_ok(const pos_t *pos, const bool strict)
error += warn_on(popcount64(pos_checkers(pos, us)) > 2);
/* kings distance is less than 2 */
error += warn_on(sq_dist(pos->king[WHITE], pos->king[BLACK]) < 2);
/* e.p. and castling rights check */
error += fen_ok(pos, false);
if (strict) {
bug_on(error);
/* not reached */

View File

@@ -180,7 +180,7 @@ bitboard_t pos_checkers(const pos_t *pos, const color_t color);
bitboard_t pos_king_pinners(const pos_t *pos, const color_t color);
bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboard_t );
bool pos_ok(const pos_t *pos, const bool strict);
bool pos_ok(pos_t *pos, const bool strict);
void pos_print(const pos_t *pos);
void pos_print_mask(const pos_t *pos, const bitboard_t mask);