mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 08:43:09 +00:00
Retire the misdesigned StepAttacks[] array.
StepAttacks[] is misdesigned, the color dependance is specific to pawns, and trying to generalise to king and knights, proves neither useful nor convinient in practice. So this patch reformats the code with the following changes: - Use PieceType instead of Piece in attacks_() functions - Use PseudoAttacks for KING and KNIGHT - Rename StepAttacks[] into PawnAttacks[] Original patch and idea from Alain Savard. No functional change. Closes #1086
This commit is contained in:
parent
b1b19343cd
commit
e06a117d5e
8 changed files with 37 additions and 32 deletions
|
@ -117,7 +117,7 @@ namespace {
|
||||||
if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
|
if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
|
||||||
|| ksq[WHITE] == psq
|
|| ksq[WHITE] == psq
|
||||||
|| ksq[BLACK] == psq
|
|| ksq[BLACK] == psq
|
||||||
|| (us == WHITE && (StepAttacksBB[W_PAWN][psq] & ksq[BLACK])))
|
|| (us == WHITE && (PawnAttacks[WHITE][psq] & ksq[BLACK])))
|
||||||
result = INVALID;
|
result = INVALID;
|
||||||
|
|
||||||
// Immediate win if a pawn can be promoted without getting captured
|
// Immediate win if a pawn can be promoted without getting captured
|
||||||
|
@ -125,13 +125,13 @@ namespace {
|
||||||
&& rank_of(psq) == RANK_7
|
&& rank_of(psq) == RANK_7
|
||||||
&& ksq[us] != psq + NORTH
|
&& ksq[us] != psq + NORTH
|
||||||
&& ( distance(ksq[~us], psq + NORTH) > 1
|
&& ( distance(ksq[~us], psq + NORTH) > 1
|
||||||
|| (StepAttacksBB[KING][ksq[us]] & (psq + NORTH))))
|
|| (PseudoAttacks[KING][ksq[us]] & (psq + NORTH))))
|
||||||
result = WIN;
|
result = WIN;
|
||||||
|
|
||||||
// Immediate draw if it is a stalemate or a king captures undefended pawn
|
// Immediate draw if it is a stalemate or a king captures undefended pawn
|
||||||
else if ( us == BLACK
|
else if ( us == BLACK
|
||||||
&& ( !(StepAttacksBB[KING][ksq[us]] & ~(StepAttacksBB[KING][ksq[~us]] | StepAttacksBB[W_PAWN][psq]))
|
&& ( !(PseudoAttacks[KING][ksq[us]] & ~(PseudoAttacks[KING][ksq[~us]] | PawnAttacks[~us][psq]))
|
||||||
|| (StepAttacksBB[KING][ksq[us]] & psq & ~StepAttacksBB[KING][ksq[~us]])))
|
|| (PseudoAttacks[KING][ksq[us]] & psq & ~PseudoAttacks[KING][ksq[~us]])))
|
||||||
result = DRAW;
|
result = DRAW;
|
||||||
|
|
||||||
// Position will be classified later
|
// Position will be classified later
|
||||||
|
@ -157,7 +157,7 @@ namespace {
|
||||||
const Result Bad = (Us == WHITE ? DRAW : WIN);
|
const Result Bad = (Us == WHITE ? DRAW : WIN);
|
||||||
|
|
||||||
Result r = INVALID;
|
Result r = INVALID;
|
||||||
Bitboard b = StepAttacksBB[KING][ksq[Us]];
|
Bitboard b = PseudoAttacks[KING][ksq[Us]];
|
||||||
|
|
||||||
while (b)
|
while (b)
|
||||||
r |= Us == WHITE ? db[index(Them, ksq[Them] , pop_lsb(&b), psq)]
|
r |= Us == WHITE ? db[index(Them, ksq[Them] , pop_lsb(&b), psq)]
|
||||||
|
|
|
@ -41,7 +41,6 @@ Bitboard FileBB[FILE_NB];
|
||||||
Bitboard RankBB[RANK_NB];
|
Bitboard RankBB[RANK_NB];
|
||||||
Bitboard AdjacentFilesBB[FILE_NB];
|
Bitboard AdjacentFilesBB[FILE_NB];
|
||||||
Bitboard InFrontBB[COLOR_NB][RANK_NB];
|
Bitboard InFrontBB[COLOR_NB][RANK_NB];
|
||||||
Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB];
|
|
||||||
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
|
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
|
||||||
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
|
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
|
||||||
Bitboard DistanceRingBB[SQUARE_NB][8];
|
Bitboard DistanceRingBB[SQUARE_NB][8];
|
||||||
|
@ -49,6 +48,7 @@ Bitboard ForwardBB[COLOR_NB][SQUARE_NB];
|
||||||
Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
|
Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
|
||||||
Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
|
Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
|
||||||
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
|
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
|
||||||
|
Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -191,21 +191,25 @@ void Bitboards::init() {
|
||||||
DistanceRingBB[s1][SquareDistance[s1][s2] - 1] |= s2;
|
DistanceRingBB[s1][SquareDistance[s1][s2] - 1] |= s2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int steps[][9] = { {}, { 7, 9 }, { 17, 15, 10, 6, -6, -10, -15, -17 },
|
int steps[][5] = { {}, { 7, 9 }, { 6, 10, 15, 17 }, {}, {}, {}, { 1, 7, 8, 9 } };
|
||||||
{}, {}, {}, { 9, 7, -7, -9, 8, 1, -1, -8 } };
|
|
||||||
|
|
||||||
for (Color c = WHITE; c <= BLACK; ++c)
|
for (Color c = WHITE; c <= BLACK; ++c)
|
||||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
for (PieceType pt : { PAWN, KNIGHT, KING })
|
||||||
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
||||||
for (int i = 0; steps[pt][i]; ++i)
|
for (int i = 0; steps[pt][i]; ++i)
|
||||||
{
|
{
|
||||||
Square to = s + Square(c == WHITE ? steps[pt][i] : -steps[pt][i]);
|
Square to = s + Square(c == WHITE ? steps[pt][i] : -steps[pt][i]);
|
||||||
|
|
||||||
if (is_ok(to) && distance(s, to) < 3)
|
if (is_ok(to) && distance(s, to) < 3)
|
||||||
StepAttacksBB[make_piece(c, pt)][s] |= to;
|
{
|
||||||
|
if (pt == PAWN)
|
||||||
|
PawnAttacks[c][s] |= to;
|
||||||
|
else
|
||||||
|
PseudoAttacks[pt][s] |= to;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Square RookDeltas[] = { NORTH, EAST, SOUTH, WEST };
|
Square RookDeltas[] = { NORTH, EAST, SOUTH, WEST };
|
||||||
Square BishopDeltas[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
|
Square BishopDeltas[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
|
||||||
|
|
||||||
init_magics(RookTable, RookAttacks, RookMagics, RookMasks, RookShifts, RookDeltas, magic_index<ROOK>);
|
init_magics(RookTable, RookAttacks, RookMagics, RookMasks, RookShifts, RookDeltas, magic_index<ROOK>);
|
||||||
|
@ -216,14 +220,14 @@ void Bitboards::init() {
|
||||||
PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0);
|
PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0);
|
||||||
PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0);
|
PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0);
|
||||||
|
|
||||||
for (Piece pc = W_BISHOP; pc <= W_ROOK; ++pc)
|
for (PieceType pt : { BISHOP, ROOK })
|
||||||
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
|
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
|
||||||
{
|
{
|
||||||
if (!(PseudoAttacks[pc][s1] & s2))
|
if (!(PseudoAttacks[pt][s1] & s2))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LineBB[s1][s2] = (attacks_bb(pc, s1, 0) & attacks_bb(pc, s2, 0)) | s1 | s2;
|
LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
|
||||||
BetweenBB[s1][s2] = attacks_bb(pc, s1, SquareBB[s2]) & attacks_bb(pc, s2, SquareBB[s1]);
|
BetweenBB[s1][s2] = attacks_bb(pt, s1, SquareBB[s2]) & attacks_bb(pt, s2, SquareBB[s1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,6 @@ extern Bitboard FileBB[FILE_NB];
|
||||||
extern Bitboard RankBB[RANK_NB];
|
extern Bitboard RankBB[RANK_NB];
|
||||||
extern Bitboard AdjacentFilesBB[FILE_NB];
|
extern Bitboard AdjacentFilesBB[FILE_NB];
|
||||||
extern Bitboard InFrontBB[COLOR_NB][RANK_NB];
|
extern Bitboard InFrontBB[COLOR_NB][RANK_NB];
|
||||||
extern Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB];
|
|
||||||
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
|
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
|
||||||
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
|
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
|
||||||
extern Bitboard DistanceRingBB[SQUARE_NB][8];
|
extern Bitboard DistanceRingBB[SQUARE_NB][8];
|
||||||
|
@ -74,6 +73,7 @@ extern Bitboard ForwardBB[COLOR_NB][SQUARE_NB];
|
||||||
extern Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
|
extern Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
|
||||||
extern Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
|
extern Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
|
||||||
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
|
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
|
||||||
|
extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
|
||||||
|
|
||||||
|
|
||||||
/// Overloads of bitwise operators between a Bitboard and a Square for testing
|
/// Overloads of bitwise operators between a Bitboard and a Square for testing
|
||||||
|
@ -246,14 +246,16 @@ inline Bitboard attacks_bb(Square s, Bitboard occupied) {
|
||||||
return (Pt == ROOK ? RookAttacks : BishopAttacks)[s][magic_index<Pt>(s, occupied)];
|
return (Pt == ROOK ? RookAttacks : BishopAttacks)[s][magic_index<Pt>(s, occupied)];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard attacks_bb(Piece pc, Square s, Bitboard occupied) {
|
inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) {
|
||||||
|
|
||||||
switch (type_of(pc))
|
assert(pt != PAWN);
|
||||||
|
|
||||||
|
switch (pt)
|
||||||
{
|
{
|
||||||
case BISHOP: return attacks_bb<BISHOP>(s, occupied);
|
case BISHOP: return attacks_bb<BISHOP>(s, occupied);
|
||||||
case ROOK : return attacks_bb<ROOK>(s, occupied);
|
case ROOK : return attacks_bb<ROOK>(s, occupied);
|
||||||
case QUEEN : return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
|
case QUEEN : return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
|
||||||
default : return StepAttacksBB[pc][s];
|
default : return PseudoAttacks[pt][s];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace {
|
||||||
|
|
||||||
// Knight promotion is the only promotion that can give a direct check
|
// Knight promotion is the only promotion that can give a direct check
|
||||||
// that's not already included in the queen promotion.
|
// that's not already included in the queen promotion.
|
||||||
if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ksq))
|
if (Type == QUIET_CHECKS && (PseudoAttacks[KNIGHT][to] & ksq))
|
||||||
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
|
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
|
||||||
else
|
else
|
||||||
(void)ksq; // Silence a warning under MSVC
|
(void)ksq; // Silence a warning under MSVC
|
||||||
|
@ -346,7 +346,7 @@ ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
|
||||||
if (pt == PAWN)
|
if (pt == PAWN)
|
||||||
continue; // Will be generated together with direct checks
|
continue; // Will be generated together with direct checks
|
||||||
|
|
||||||
Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces();
|
Bitboard b = pos.attacks_from(pt, from) & ~pos.pieces();
|
||||||
|
|
||||||
if (pt == KING)
|
if (pt == KING)
|
||||||
b &= ~PseudoAttacks[QUEEN][pos.square<KING>(~us)];
|
b &= ~PseudoAttacks[QUEEN][pos.square<KING>(~us)];
|
||||||
|
|
|
@ -104,7 +104,6 @@ namespace {
|
||||||
bool opposed, backward;
|
bool opposed, backward;
|
||||||
Score score = SCORE_ZERO;
|
Score score = SCORE_ZERO;
|
||||||
const Square* pl = pos.squares<PAWN>(Us);
|
const Square* pl = pos.squares<PAWN>(Us);
|
||||||
const Bitboard* pawnAttacksBB = StepAttacksBB[make_piece(Us, PAWN)];
|
|
||||||
|
|
||||||
Bitboard ourPawns = pos.pieces(Us , PAWN);
|
Bitboard ourPawns = pos.pieces(Us , PAWN);
|
||||||
Bitboard theirPawns = pos.pieces(Them, PAWN);
|
Bitboard theirPawns = pos.pieces(Them, PAWN);
|
||||||
|
@ -129,8 +128,8 @@ namespace {
|
||||||
// Flag the pawn
|
// Flag the pawn
|
||||||
opposed = theirPawns & forward_bb(Us, s);
|
opposed = theirPawns & forward_bb(Us, s);
|
||||||
stoppers = theirPawns & passed_pawn_mask(Us, s);
|
stoppers = theirPawns & passed_pawn_mask(Us, s);
|
||||||
lever = theirPawns & pawnAttacksBB[s];
|
lever = theirPawns & PawnAttacks[Us][s];
|
||||||
leverPush = theirPawns & pawnAttacksBB[s + Up];
|
leverPush = theirPawns & PawnAttacks[Us][s + Up];
|
||||||
doubled = ourPawns & (s - Up);
|
doubled = ourPawns & (s - Up);
|
||||||
neighbours = ourPawns & adjacent_files_bb(f);
|
neighbours = ourPawns & adjacent_files_bb(f);
|
||||||
phalanx = neighbours & rank_bb(s);
|
phalanx = neighbours & rank_bb(s);
|
||||||
|
|
|
@ -595,7 +595,7 @@ bool Position::pseudo_legal(const Move m) const {
|
||||||
&& empty(to - pawn_push(us))))
|
&& empty(to - pawn_push(us))))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!(attacks_from(pc, from) & to))
|
else if (!(attacks_from(type_of(pc), from) & to))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Evasions generator already takes care to avoid some kind of illegal moves
|
// Evasions generator already takes care to avoid some kind of illegal moves
|
||||||
|
@ -648,7 +648,7 @@ bool Position::gives_check(Move m) const {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case PROMOTION:
|
case PROMOTION:
|
||||||
return attacks_bb(Piece(promotion_type(m)), to, pieces() ^ from) & square<KING>(~sideToMove);
|
return attacks_bb(promotion_type(m), to, pieces() ^ from) & square<KING>(~sideToMove);
|
||||||
|
|
||||||
// En passant capture with check? We have already handled the case
|
// En passant capture with check? We have already handled the case
|
||||||
// of direct checks and ordinary discovered check, so the only case we
|
// of direct checks and ordinary discovered check, so the only case we
|
||||||
|
|
|
@ -109,7 +109,7 @@ public:
|
||||||
// Attacks to/from a given square
|
// Attacks to/from a given square
|
||||||
Bitboard attackers_to(Square s) const;
|
Bitboard attackers_to(Square s) const;
|
||||||
Bitboard attackers_to(Square s, Bitboard occupied) const;
|
Bitboard attackers_to(Square s, Bitboard occupied) const;
|
||||||
Bitboard attacks_from(Piece pc, Square s) const;
|
Bitboard attacks_from(PieceType pt, Square s) const;
|
||||||
template<PieceType> Bitboard attacks_from(Square s) const;
|
template<PieceType> Bitboard attacks_from(Square s) const;
|
||||||
template<PieceType> Bitboard attacks_from(Square s, Color c) const;
|
template<PieceType> Bitboard attacks_from(Square s, Color c) const;
|
||||||
Bitboard slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const;
|
Bitboard slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const;
|
||||||
|
@ -276,16 +276,16 @@ inline Bitboard Position::attacks_from(Square s) const {
|
||||||
assert(Pt != PAWN);
|
assert(Pt != PAWN);
|
||||||
return Pt == BISHOP || Pt == ROOK ? attacks_bb<Pt>(s, byTypeBB[ALL_PIECES])
|
return Pt == BISHOP || Pt == ROOK ? attacks_bb<Pt>(s, byTypeBB[ALL_PIECES])
|
||||||
: Pt == QUEEN ? attacks_from<ROOK>(s) | attacks_from<BISHOP>(s)
|
: Pt == QUEEN ? attacks_from<ROOK>(s) | attacks_from<BISHOP>(s)
|
||||||
: StepAttacksBB[Pt][s];
|
: PseudoAttacks[Pt][s];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline Bitboard Position::attacks_from<PAWN>(Square s, Color c) const {
|
inline Bitboard Position::attacks_from<PAWN>(Square s, Color c) const {
|
||||||
return StepAttacksBB[make_piece(c, PAWN)][s];
|
return PawnAttacks[c][s];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard Position::attacks_from(Piece pc, Square s) const {
|
inline Bitboard Position::attacks_from(PieceType pt, Square s) const {
|
||||||
return attacks_bb(pc, s, byTypeBB[ALL_PIECES]);
|
return attacks_bb(pt, s, byTypeBB[ALL_PIECES]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard Position::attackers_to(Square s) const {
|
inline Bitboard Position::attackers_to(Square s) const {
|
||||||
|
|
|
@ -1292,7 +1292,7 @@ void Tablebases::init(const std::string& paths) {
|
||||||
if (MapA1D1D4[s1] == idx && (idx || s1 == SQ_B1)) // SQ_B1 is mapped to 0
|
if (MapA1D1D4[s1] == idx && (idx || s1 == SQ_B1)) // SQ_B1 is mapped to 0
|
||||||
{
|
{
|
||||||
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
|
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
|
||||||
if ((StepAttacksBB[KING][s1] | s1) & s2)
|
if ((PseudoAttacks[KING][s1] | s1) & s2)
|
||||||
continue; // Illegal position
|
continue; // Illegal position
|
||||||
|
|
||||||
else if (!off_A1H8(s1) && off_A1H8(s2) > 0)
|
else if (!off_A1H8(s1) && off_A1H8(s2) > 0)
|
||||||
|
|
Loading…
Add table
Reference in a new issue