diff --git a/src/bitboard.h b/src/bitboard.h index 7d36b0a62..50eb11864 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -155,6 +155,9 @@ constexpr Bitboard pawn_attacks_bb(Bitboard b) { : shift(b) | shift(b); } +constexpr Bitboard pawn_single_push_bb(Color c, Bitboard b) { + return c == WHITE ? shift(b) : shift(b); +} // Returns a bitboard representing an entire line (from board edge // to board edge) that intersects the two given squares. If the given squares @@ -397,6 +400,18 @@ inline constexpr auto PseudoAttacks = []() constexpr { return attacks; }(); +inline constexpr auto PawnPushOrAttacks = []() constexpr { + std::array, COLOR_NB> attacks{}; + + for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) + { + attacks[WHITE][s1] = pawn_single_push_bb(WHITE, square_bb(s1)) | PseudoAttacks[WHITE][s1]; + attacks[BLACK][s1] = pawn_single_push_bb(BLACK, square_bb(s1)) | PseudoAttacks[BLACK][s1]; + } + + return attacks; +}(); + // Returns the pseudo attacks of the given piece type // assuming an empty board. diff --git a/src/evaluate.h b/src/evaluate.h index 4af7093e0..a4a56d9f2 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -33,7 +33,7 @@ namespace Eval { // for the build process (profile-build and fishtest) to work. Do not change the // name of the macro or the location where this macro is defined, as it is used // in the Makefile/Fishtest. -#define EvalFileDefaultNameBig "nn-9a0cc2a62c52.nnue" +#define EvalFileDefaultNameBig "nn-7bf13f9655c8.nnue" #define EvalFileDefaultNameSmall "nn-47fc8b7fff06.nnue" namespace NNUE { diff --git a/src/nnue/features/full_threats.cpp b/src/nnue/features/full_threats.cpp index 03ad158e6..6cae5d0ed 100644 --- a/src/nnue/features/full_threats.cpp +++ b/src/nnue/features/full_threats.cpp @@ -21,6 +21,7 @@ #include "full_threats.h" #include +#include #include #include #include @@ -72,7 +73,7 @@ constexpr auto make_piece_indices_piece() { for (Square from = SQ_A1; from <= SQ_H8; ++from) { - Bitboard attacks = PseudoAttacks[C][from]; + Bitboard attacks = PawnPushOrAttacks[C][from]; for (Square to = SQ_A1; to <= SQ_H8; ++to) { @@ -135,8 +136,8 @@ constexpr auto init_threat_offsets() { else if (from >= SQ_A2 && from <= SQ_H7) { - Bitboard attacks = (pieceIdx < 8) ? pawn_attacks_bb(square_bb(from)) - : pawn_attacks_bb(square_bb(from)); + Bitboard attacks = + (pieceIdx < 8) ? PawnPushOrAttacks[WHITE][from] : PawnPushOrAttacks[BLACK][from]; cumulativePieceOffset += constexpr_popcount(attacks); } } @@ -209,6 +210,7 @@ inline sf_always_inline IndexType FullThreats::make_index( void FullThreats::append_active_indices(Color perspective, const Position& pos, IndexList& active) { Square ksq = pos.square(perspective); Bitboard occupied = pos.pieces(); + Bitboard pawns = pos.pieces(PAWN); for (Color color : {WHITE, BLACK}) { @@ -248,6 +250,20 @@ void FullThreats::append_active_indices(Color perspective, const Position& pos, if (index < Dimensions) active.push_back(index); } + + // Set of pawns which are prevented from movement by a pawn in front of them + Bitboard pushers = pawn_single_push_bb(~c, pawns) & pos.pieces(c, PAWN); + while (pushers) + { + Square from = pop_lsb(pushers); + Square to = from + pawn_push(c); + Piece attacked = pos.piece_on(to); + assert(type_of(attacked) == PAWN); + + IndexType index = make_index(perspective, attacker, from, to, attacked, ksq); + if (index < Dimensions) + active.push_back(index); + } } else { diff --git a/src/nnue/features/full_threats.h b/src/nnue/features/full_threats.h index 76f5b74c6..4a39c6648 100644 --- a/src/nnue/features/full_threats.h +++ b/src/nnue/features/full_threats.h @@ -42,7 +42,7 @@ class FullThreats { static constexpr std::uint32_t HashValue = 0x8f234cb8u; // Number of feature dimensions - static constexpr IndexType Dimensions = 60144; + static constexpr IndexType Dimensions = 60720; // clang-format off // Orient a square according to perspective (rotates by 180 for black) diff --git a/src/position.cpp b/src/position.cpp index d7918e453..78ebac35c 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1265,8 +1265,25 @@ void Position::update_piece_threats(Piece pc, Bitboard threatened = attacks_bb(pc, s, occupied) & occupiedNoK; Bitboard incoming_threats = - (PseudoAttacks[KNIGHT][s] & knights) | (attacks_bb(s, WHITE) & blackPawns) - | (attacks_bb(s, BLACK) & whitePawns) | (PseudoAttacks[KING][s] & kings); + (PseudoAttacks[KNIGHT][s] & knights) | (PseudoAttacks[KING][s] & kings); + + // Compute both incoming and outgoing pawn threats. Incoming pawn pushers are only + // added if 'pc' is a pawn. + if (type_of(pc) == PAWN) + { + Bitboard whiteAttacks = PawnPushOrAttacks[WHITE][s]; + Bitboard blackAttacks = PawnPushOrAttacks[BLACK][s]; + + threatened |= (color_of(pc) == WHITE ? whiteAttacks : blackAttacks) & pieces(PAWN); + + incoming_threats |= whiteAttacks & blackPawns; + incoming_threats |= blackAttacks & whitePawns; + } + else + { + incoming_threats |= + (attacks_bb(s, WHITE) & blackPawns) | (attacks_bb(s, BLACK) & whitePawns); + } #ifdef USE_AVX512ICL if constexpr (PutPiece)