1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-30 16:53: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:
Marco Costalba 2017-04-28 20:33:30 -07:00 committed by Joona Kiiski
parent b1b19343cd
commit e06a117d5e
8 changed files with 37 additions and 32 deletions

View file

@ -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)]

View file

@ -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,18 +191,22 @@ 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 };
@ -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]);
} }
} }
} }

View file

@ -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];
} }
} }

View file

@ -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)];

View file

@ -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);

View file

@ -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

View file

@ -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 {

View file

@ -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)