mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 09:13:08 +00:00
Speedup and simplify pinners and blockers
To compute dicovered check or pinned pieces we use some bitwise operators that are not really needed because already accounted for at the caller site. For instance in evaluation we compute: pos.pinned_pieces(Us) & s Where pinned_pieces() is: st->blockersForKing[c] & pieces(c) So in this case the & operator with pieces(c) is useless, given the outer '& s'. There are many places where we can use the naked blockersForKing[] instead of the full pinned_pieces() or discovered_check_candidates(). This path is simpler than original and gives around 1% speed up for me. Also tested for speed by mstembera and snicolet (neutral in both cases). No functional change.
This commit is contained in:
parent
d438720a1c
commit
ad2a0e356e
5 changed files with 30 additions and 31 deletions
|
@ -306,7 +306,7 @@ namespace {
|
||||||
: Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK))
|
: Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK))
|
||||||
: pos.attacks_from<Pt>(s);
|
: pos.attacks_from<Pt>(s);
|
||||||
|
|
||||||
if (pos.pinned_pieces(Us) & s)
|
if (pos.blockers_for_king(Us) & s)
|
||||||
b &= LineBB[pos.square<KING>(Us)][s];
|
b &= LineBB[pos.square<KING>(Us)][s];
|
||||||
|
|
||||||
attackedBy2[Us] |= attackedBy[Us][ALL_PIECES] & b;
|
attackedBy2[Us] |= attackedBy[Us][ALL_PIECES] & b;
|
||||||
|
@ -392,8 +392,8 @@ namespace {
|
||||||
if (Pt == QUEEN)
|
if (Pt == QUEEN)
|
||||||
{
|
{
|
||||||
// Penalty if any relative pin or discovered attack against the queen
|
// Penalty if any relative pin or discovered attack against the queen
|
||||||
Bitboard pinners;
|
Bitboard queenPinners;
|
||||||
if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, pinners))
|
if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, queenPinners))
|
||||||
score -= WeakQueen;
|
score -= WeakQueen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,7 +413,7 @@ namespace {
|
||||||
: AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
|
: AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
|
||||||
|
|
||||||
const Square ksq = pos.square<KING>(Us);
|
const Square ksq = pos.square<KING>(Us);
|
||||||
Bitboard weak, b, b1, b2, safe, unsafeChecks;
|
Bitboard weak, b, b1, b2, safe, unsafeChecks, pinned;
|
||||||
|
|
||||||
// King shelter and enemy pawns storm
|
// King shelter and enemy pawns storm
|
||||||
Score score = pe->king_safety<Us>(pos, ksq);
|
Score score = pe->king_safety<Us>(pos, ksq);
|
||||||
|
@ -464,11 +464,12 @@ namespace {
|
||||||
// Unsafe or occupied checking squares will also be considered, as long as
|
// Unsafe or occupied checking squares will also be considered, as long as
|
||||||
// the square is in the attacker's mobility area.
|
// the square is in the attacker's mobility area.
|
||||||
unsafeChecks &= mobilityArea[Them];
|
unsafeChecks &= mobilityArea[Them];
|
||||||
|
pinned = pos.blockers_for_king(Us) & pos.pieces(Us);
|
||||||
|
|
||||||
kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
|
kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
|
||||||
+ 102 * kingAdjacentZoneAttacksCount[Them]
|
+ 102 * kingAdjacentZoneAttacksCount[Them]
|
||||||
+ 191 * popcount(kingRing[Us] & weak)
|
+ 191 * popcount(kingRing[Us] & weak)
|
||||||
+ 143 * popcount(pos.pinned_pieces(Us) | unsafeChecks)
|
+ 143 * popcount(pinned | unsafeChecks)
|
||||||
- 848 * !pos.count<QUEEN>(Them)
|
- 848 * !pos.count<QUEEN>(Them)
|
||||||
- 9 * mg_value(score) / 8
|
- 9 * mg_value(score) / 8
|
||||||
+ 40;
|
+ 40;
|
||||||
|
|
|
@ -135,7 +135,7 @@ namespace {
|
||||||
// if the pawn is not on the same file as the enemy king, because we
|
// if the pawn is not on the same file as the enemy king, because we
|
||||||
// don't generate captures. Note that a possible discovery check
|
// don't generate captures. Note that a possible discovery check
|
||||||
// promotion has been already generated amongst the captures.
|
// promotion has been already generated amongst the captures.
|
||||||
Bitboard dcCandidates = pos.discovered_check_candidates();
|
Bitboard dcCandidates = pos.blockers_for_king(Them);
|
||||||
if (pawnsNotOn7 & dcCandidates)
|
if (pawnsNotOn7 & dcCandidates)
|
||||||
{
|
{
|
||||||
Bitboard dc1 = shift<Up>(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq);
|
Bitboard dc1 = shift<Up>(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq);
|
||||||
|
@ -241,7 +241,7 @@ namespace {
|
||||||
&& !(PseudoAttacks[Pt][from] & target & pos.check_squares(Pt)))
|
&& !(PseudoAttacks[Pt][from] & target & pos.check_squares(Pt)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pos.discovered_check_candidates() & from)
|
if (pos.blockers_for_king(~us) & from)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
|
||||||
assert(!pos.checkers());
|
assert(!pos.checkers());
|
||||||
|
|
||||||
Color us = pos.side_to_move();
|
Color us = pos.side_to_move();
|
||||||
Bitboard dc = pos.discovered_check_candidates();
|
Bitboard dc = pos.blockers_for_king(~us) & pos.pieces(us);
|
||||||
|
|
||||||
while (dc)
|
while (dc)
|
||||||
{
|
{
|
||||||
|
@ -403,8 +403,9 @@ ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) {
|
||||||
template<>
|
template<>
|
||||||
ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {
|
ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {
|
||||||
|
|
||||||
Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
|
Color us = pos.side_to_move();
|
||||||
Square ksq = pos.square<KING>(pos.side_to_move());
|
Bitboard pinned = pos.blockers_for_king(us) & pos.pieces(us);
|
||||||
|
Square ksq = pos.square<KING>(us);
|
||||||
ExtMove* cur = moveList;
|
ExtMove* cur = moveList;
|
||||||
|
|
||||||
moveList = pos.checkers() ? generate<EVASIONS >(pos, moveList)
|
moveList = pos.checkers() ? generate<EVASIONS >(pos, moveList)
|
||||||
|
|
|
@ -464,7 +464,7 @@ const string Position::fen() const {
|
||||||
|
|
||||||
Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const {
|
Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const {
|
||||||
|
|
||||||
Bitboard result = 0;
|
Bitboard blockers = 0;
|
||||||
pinners = 0;
|
pinners = 0;
|
||||||
|
|
||||||
// Snipers are sliders that attack 's' when a piece is removed
|
// Snipers are sliders that attack 's' when a piece is removed
|
||||||
|
@ -476,14 +476,14 @@ Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners
|
||||||
Square sniperSq = pop_lsb(&snipers);
|
Square sniperSq = pop_lsb(&snipers);
|
||||||
Bitboard b = between_bb(s, sniperSq) & pieces();
|
Bitboard b = between_bb(s, sniperSq) & pieces();
|
||||||
|
|
||||||
if (!more_than_one(b))
|
if (b && !more_than_one(b))
|
||||||
{
|
{
|
||||||
result |= b;
|
blockers |= b;
|
||||||
if (b & pieces(color_of(piece_on(s))))
|
if (b & pieces(color_of(piece_on(s))))
|
||||||
pinners |= sniperSq;
|
pinners |= sniperSq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return blockers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -540,7 +540,7 @@ bool Position::legal(Move m) const {
|
||||||
|
|
||||||
// A non-king move is legal if and only if it is not pinned or it
|
// A non-king move is legal if and only if it is not pinned or it
|
||||||
// is moving along the ray towards or away from the king.
|
// is moving along the ray towards or away from the king.
|
||||||
return !(pinned_pieces(us) & from)
|
return !(blockers_for_king(us) & from)
|
||||||
|| aligned(from, to_sq(m), square<KING>(us));
|
|| aligned(from, to_sq(m), square<KING>(us));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,7 +632,7 @@ bool Position::gives_check(Move m) const {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Is there a discovered check?
|
// Is there a discovered check?
|
||||||
if ( (discovered_check_candidates() & from)
|
if ( (st->blockersForKing[~sideToMove] & from)
|
||||||
&& !aligned(from, to, square<KING>(~sideToMove)))
|
&& !aligned(from, to, square<KING>(~sideToMove)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -105,8 +105,7 @@ public:
|
||||||
|
|
||||||
// Checking
|
// Checking
|
||||||
Bitboard checkers() const;
|
Bitboard checkers() const;
|
||||||
Bitboard discovered_check_candidates() const;
|
Bitboard blockers_for_king(Color c) const;
|
||||||
Bitboard pinned_pieces(Color c) const;
|
|
||||||
Bitboard check_squares(PieceType pt) const;
|
Bitboard check_squares(PieceType pt) const;
|
||||||
|
|
||||||
// Attacks to/from a given square
|
// Attacks to/from a given square
|
||||||
|
@ -296,12 +295,8 @@ inline Bitboard Position::checkers() const {
|
||||||
return st->checkersBB;
|
return st->checkersBB;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard Position::discovered_check_candidates() const {
|
inline Bitboard Position::blockers_for_king(Color c) const {
|
||||||
return st->blockersForKing[~sideToMove] & pieces(sideToMove);
|
return st->blockersForKing[c];
|
||||||
}
|
|
||||||
|
|
||||||
inline Bitboard Position::pinned_pieces(Color c) const {
|
|
||||||
return st->blockersForKing[c] & pieces(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard Position::check_squares(PieceType pt) const {
|
inline Bitboard Position::check_squares(PieceType pt) const {
|
||||||
|
|
|
@ -108,6 +108,13 @@ namespace {
|
||||||
void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
|
void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
|
||||||
void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCnt, int bonus);
|
void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCnt, int bonus);
|
||||||
|
|
||||||
|
inline bool gives_check(const Position& pos, Move move) {
|
||||||
|
Color us = pos.side_to_move();
|
||||||
|
return type_of(move) == NORMAL && !(pos.blockers_for_king(~us) & pos.pieces(us))
|
||||||
|
? pos.check_squares(type_of(pos.moved_piece(move))) & to_sq(move)
|
||||||
|
: pos.gives_check(move);
|
||||||
|
}
|
||||||
|
|
||||||
// perft() is our utility to verify move generation. All the leaf nodes up
|
// perft() is our utility to verify move generation. All the leaf nodes up
|
||||||
// to the given depth are generated and counted, and the sum is returned.
|
// to the given depth are generated and counted, and the sum is returned.
|
||||||
template<bool Root>
|
template<bool Root>
|
||||||
|
@ -823,10 +830,7 @@ moves_loop: // When in check, search starts from here
|
||||||
extension = DEPTH_ZERO;
|
extension = DEPTH_ZERO;
|
||||||
captureOrPromotion = pos.capture_or_promotion(move);
|
captureOrPromotion = pos.capture_or_promotion(move);
|
||||||
movedPiece = pos.moved_piece(move);
|
movedPiece = pos.moved_piece(move);
|
||||||
|
givesCheck = gives_check(pos, move);
|
||||||
givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates()
|
|
||||||
? pos.check_squares(type_of(movedPiece)) & to_sq(move)
|
|
||||||
: pos.gives_check(move);
|
|
||||||
|
|
||||||
moveCountPruning = depth < 16 * ONE_PLY
|
moveCountPruning = depth < 16 * ONE_PLY
|
||||||
&& moveCount >= FutilityMoveCounts[improving][depth / ONE_PLY];
|
&& moveCount >= FutilityMoveCounts[improving][depth / ONE_PLY];
|
||||||
|
@ -1238,9 +1242,7 @@ moves_loop: // When in check, search starts from here
|
||||||
{
|
{
|
||||||
assert(is_ok(move));
|
assert(is_ok(move));
|
||||||
|
|
||||||
givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates()
|
givesCheck = gives_check(pos, move);
|
||||||
? pos.check_squares(type_of(pos.moved_piece(move))) & to_sq(move)
|
|
||||||
: pos.gives_check(move);
|
|
||||||
|
|
||||||
moveCount++;
|
moveCount++;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue