replace pawn_shift_xxx with bb_pawns_attacks
This commit is contained in:
@@ -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
|
||||
|
@@ -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];
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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>
|
||||
|
||||
|
71
src/fen.c
71
src/fen.c
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user