Skip to content

Commit b66ff7a

Browse files
BM123499MichaelB7
authored andcommitted
Change definition of between_bb()
We remark that in current master, most of our use cases for between_bb() can be optimized if the second parameter of the function is added to the segment. So we change the definition of between_bb(s1, s2) such that it excludes s1 but includes s2. We also use a precomputed array for between_bb() for another small speed gain (see https://tests.stockfishchess.org/tests/view/604d09f72433018de7a389fb). Passed STC: LLR: 2.96 (-2.94,2.94) {-0.25,1.25} Total: 18736 W: 1746 L: 1607 D: 15383 Ptnml(0-2): 61, 1226, 6644, 1387, 50 https://tests.stockfishchess.org/tests/view/60428c84ddcba5f0627bb6e4 Yellow LTC: LTC: LLR: -3.00 (-2.94,2.94) {0.25,1.25} Total: 39144 W: 1431 L: 1413 D: 36300 Ptnml(0-2): 13, 1176, 17184, 1178, 21 https://tests.stockfishchess.org/tests/view/605128702433018de7a38ca1 Closes official-stockfish#3397 --------- Verified for correctness by running perft on the following position: ./stockfish position fen 4rrk1/1p1nq3/p7/2p1P1pp/3P2bp/3Q1Bn1/PPPB4/1K2R1NR w - - 40 21 go perft 6 Nodes searched: 6136386434 -------- No functional change
1 parent 9ec9d6f commit b66ff7a

File tree

4 files changed

+27
-16
lines changed

4 files changed

+27
-16
lines changed

src/bitboard.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
2727

2828
Bitboard SquareBB[SQUARE_NB];
2929
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
30+
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
3031
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
3132
Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
3233

@@ -106,8 +107,14 @@ void Bitboards::init() {
106107

107108
for (PieceType pt : { BISHOP, ROOK })
108109
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
110+
{
109111
if (PseudoAttacks[pt][s1] & s2)
110-
LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
112+
{
113+
LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
114+
BetweenBB[s1][s2] = (attacks_bb(pt, s1, square_bb(s2)) & attacks_bb(pt, s2, square_bb(s1)));
115+
}
116+
BetweenBB[s1][s2] |= s2;
117+
}
111118
}
112119
}
113120

src/bitboard.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ extern uint8_t PopCnt16[1 << 16];
7373
extern uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
7474

7575
extern Bitboard SquareBB[SQUARE_NB];
76+
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
7677
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
7778
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
7879
extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
@@ -213,19 +214,22 @@ inline Bitboard line_bb(Square s1, Square s2) {
213214
}
214215

215216

216-
/// between_bb() returns a bitboard representing squares that are linearly
217-
/// between the two given squares (excluding the given squares). If the given
218-
/// squares are not on a same file/rank/diagonal, we return 0. For instance,
219-
/// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5 and E6.
217+
/// between_bb(s1, s2) returns a bitboard representing the squares in the semi-open
218+
/// segment between the squares s1 and s2 (excluding s1 but including s2). If the
219+
/// given squares are not on a same file/rank/diagonal, it returns s2. For instance,
220+
/// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5, E6 and F7, but
221+
/// between_bb(SQ_E6, SQ_F8) will return a bitboard with the square F8. This trick
222+
/// allows to generate non-king evasion moves faster: the defending piece must either
223+
/// interpose itself to cover the check or capture the checking piece.
220224

221225
inline Bitboard between_bb(Square s1, Square s2) {
222-
Bitboard b = line_bb(s1, s2) & ((AllSquares << s1) ^ (AllSquares << s2));
223-
return b & (b - 1); //exclude lsb
226+
assert(is_ok(s1) && is_ok(s2));
227+
return BetweenBB[s1][s2];
224228
}
225229

226230

227-
/// forward_ranks_bb() returns a bitboard representing the squares on the ranks
228-
/// in front of the given one, from the point of view of the given color. For instance,
231+
/// forward_ranks_bb() returns a bitboard representing the squares on the ranks in
232+
/// front of the given one, from the point of view of the given color. For instance,
229233
/// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2.
230234

231235
constexpr Bitboard forward_ranks_bb(Color c, Square s) {

src/movegen.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ namespace {
168168
{
169169
assert(rank_of(pos.ep_square()) == relative_rank(Us, RANK_6));
170170

171-
// An en passant capture cannot resolve a discovered check.
171+
// An en passant capture cannot resolve a discovered check
172172
if (Type == EVASIONS && (target & (pos.ep_square() + Up)))
173173
return moveList;
174174

@@ -229,7 +229,7 @@ namespace {
229229
target = ~pos.pieces();
230230
break;
231231
case EVASIONS:
232-
target = between_bb(pos.square<KING>(Us), lsb(pos.checkers())) | pos.checkers();
232+
target = between_bb(pos.square<KING>(Us), lsb(pos.checkers()));
233233
break;
234234
case NON_EVASIONS:
235235
target = ~pos.pieces(Us);
@@ -340,7 +340,7 @@ ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) {
340340
if (more_than_one(pos.checkers()))
341341
return moveList; // Double check, only a king move can save the day
342342

343-
// Generate blocking evasions or captures of the checking piece
343+
// Generate blocking interpositions or captures of the checking piece
344344
return us == WHITE ? generate_all<WHITE, EVASIONS>(pos, moveList)
345345
: generate_all<BLACK, EVASIONS>(pos, moveList);
346346
}

src/position.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ void Position::set_castling_right(Color c, Square rfrom) {
318318
Square kto = relative_square(c, cr & KING_SIDE ? SQ_G1 : SQ_C1);
319319
Square rto = relative_square(c, cr & KING_SIDE ? SQ_F1 : SQ_D1);
320320

321-
castlingPath[cr] = (between_bb(rfrom, rto) | between_bb(kfrom, kto) | rto | kto)
321+
castlingPath[cr] = (between_bb(rfrom, rto) | between_bb(kfrom, kto))
322322
& ~(kfrom | rfrom);
323323
}
324324

@@ -611,8 +611,8 @@ bool Position::pseudo_legal(const Move m) const {
611611
if (more_than_one(checkers()))
612612
return false;
613613

614-
// Our move must be a blocking evasion or a capture of the checking piece
615-
if (!((between_bb(lsb(checkers()), square<KING>(us)) | checkers()) & to))
614+
// Our move must be a blocking interposition or a capture of the checking piece
615+
if (!(between_bb(square<KING>(us), lsb(checkers())) & to))
616616
return false;
617617
}
618618
// In case of king moves under check we have to remove king so as to catch
@@ -1221,7 +1221,7 @@ bool Position::has_game_cycle(int ply) const {
12211221
Square s1 = from_sq(move);
12221222
Square s2 = to_sq(move);
12231223

1224-
if (!(between_bb(s1, s2) & pieces()))
1224+
if (!((between_bb(s1, s2) ^ s2) & pieces()))
12251225
{
12261226
if (ply > i)
12271227
return true;

0 commit comments

Comments
 (0)