mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
Init threat offsets at compile time
Init threat offsets at compile time. Avoid another global init function call. Passed STC Non-Regression: https://tests.stockfishchess.org/tests/view/694971a83c8768ca4507275c LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 43296 W: 11284 L: 11077 D: 20935 Ptnml(0-2): 152, 4611, 11924, 4800, 161 closes https://github.com/official-stockfish/Stockfish/pull/6487 No functional change
This commit is contained in:
+2
-46
@@ -32,7 +32,6 @@ uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
|
|||||||
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
|
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
|
||||||
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
|
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
|
||||||
Bitboard RayPassBB[SQUARE_NB][SQUARE_NB];
|
Bitboard RayPassBB[SQUARE_NB][SQUARE_NB];
|
||||||
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
|
|
||||||
|
|
||||||
alignas(64) Magic Magics[SQUARE_NB][2];
|
alignas(64) Magic Magics[SQUARE_NB][2];
|
||||||
|
|
||||||
@@ -42,13 +41,6 @@ Bitboard RookTable[0x19000]; // To store rook attacks
|
|||||||
Bitboard BishopTable[0x1480]; // To store bishop attacks
|
Bitboard BishopTable[0x1480]; // To store bishop attacks
|
||||||
|
|
||||||
void init_magics(PieceType pt, Bitboard table[], Magic magics[][2]);
|
void init_magics(PieceType pt, Bitboard table[], Magic magics[][2]);
|
||||||
|
|
||||||
// Returns the bitboard of target square for the given step
|
|
||||||
// from the given square. If the step is off the board, returns empty bitboard.
|
|
||||||
Bitboard safe_destination(Square s, int step) {
|
|
||||||
Square to = Square(s + step);
|
|
||||||
return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an ASCII representation of a bitboard suitable
|
// Returns an ASCII representation of a bitboard suitable
|
||||||
@@ -86,18 +78,6 @@ void Bitboards::init() {
|
|||||||
|
|
||||||
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
|
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
|
||||||
{
|
{
|
||||||
PseudoAttacks[WHITE][s1] = pawn_attacks_bb<WHITE>(square_bb(s1));
|
|
||||||
PseudoAttacks[BLACK][s1] = pawn_attacks_bb<BLACK>(square_bb(s1));
|
|
||||||
|
|
||||||
for (int step : {-9, -8, -7, -1, 1, 7, 8, 9})
|
|
||||||
PseudoAttacks[KING][s1] |= safe_destination(s1, step);
|
|
||||||
|
|
||||||
for (int step : {-17, -15, -10, -6, 6, 10, 15, 17})
|
|
||||||
PseudoAttacks[KNIGHT][s1] |= safe_destination(s1, step);
|
|
||||||
|
|
||||||
PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0);
|
|
||||||
PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ROOK][s1] = attacks_bb<ROOK>(s1, 0);
|
|
||||||
|
|
||||||
for (PieceType pt : {BISHOP, ROOK})
|
for (PieceType pt : {BISHOP, ROOK})
|
||||||
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
|
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
|
||||||
{
|
{
|
||||||
@@ -115,30 +95,6 @@ void Bitboards::init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
Bitboard sliding_attack(PieceType pt, Square sq, Bitboard occupied) {
|
|
||||||
|
|
||||||
Bitboard attacks = 0;
|
|
||||||
Direction RookDirections[4] = {NORTH, SOUTH, EAST, WEST};
|
|
||||||
Direction BishopDirections[4] = {NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
|
|
||||||
|
|
||||||
for (Direction d : (pt == ROOK ? RookDirections : BishopDirections))
|
|
||||||
{
|
|
||||||
Square s = sq;
|
|
||||||
while (safe_destination(s, d))
|
|
||||||
{
|
|
||||||
attacks |= (s += d);
|
|
||||||
if (occupied & s)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return attacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Computes all rook and bishop attacks at startup. Magic
|
// Computes all rook and bishop attacks at startup. Magic
|
||||||
// bitboards are used to look up attacks of sliding pieces. As a reference see
|
// bitboards are used to look up attacks of sliding pieces. As a reference see
|
||||||
// https://www.chessprogramming.org/Magic_Bitboards. In particular, here we use
|
// https://www.chessprogramming.org/Magic_Bitboards. In particular, here we use
|
||||||
@@ -167,7 +123,7 @@ void init_magics(PieceType pt, Bitboard table[], Magic magics[][2]) {
|
|||||||
// the number of 1s of the mask. Hence we deduce the size of the shift to
|
// the number of 1s of the mask. Hence we deduce the size of the shift to
|
||||||
// apply to the 64 or 32 bits word to get the index.
|
// apply to the 64 or 32 bits word to get the index.
|
||||||
Magic& m = magics[s][pt - BISHOP];
|
Magic& m = magics[s][pt - BISHOP];
|
||||||
m.mask = sliding_attack(pt, s, 0) & ~edges;
|
m.mask = Bitboards::sliding_attack(pt, s, 0) & ~edges;
|
||||||
#ifndef USE_PEXT
|
#ifndef USE_PEXT
|
||||||
m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
|
m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
|
||||||
#endif
|
#endif
|
||||||
@@ -184,7 +140,7 @@ void init_magics(PieceType pt, Bitboard table[], Magic magics[][2]) {
|
|||||||
#ifndef USE_PEXT
|
#ifndef USE_PEXT
|
||||||
occupancy[size] = b;
|
occupancy[size] = b;
|
||||||
#endif
|
#endif
|
||||||
reference[size] = sliding_attack(pt, s, b);
|
reference[size] = Bitboards::sliding_attack(pt, s, b);
|
||||||
|
|
||||||
if (HasPext)
|
if (HasPext)
|
||||||
m.attacks[pext(b, m.mask)] = reference[size];
|
m.attacks[pext(b, m.mask)] = reference[size];
|
||||||
|
|||||||
+154
-64
@@ -26,6 +26,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
@@ -62,8 +64,6 @@ extern uint8_t SquareDistance[SQUARE_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 RayPassBB[SQUARE_NB][SQUARE_NB];
|
extern Bitboard RayPassBB[SQUARE_NB][SQUARE_NB];
|
||||||
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
|
|
||||||
|
|
||||||
|
|
||||||
// Magic holds all magic bitboards relevant data for a single square
|
// Magic holds all magic bitboards relevant data for a single square
|
||||||
struct Magic {
|
struct Magic {
|
||||||
@@ -203,69 +203,12 @@ inline int distance<Square>(Square x, Square y) {
|
|||||||
|
|
||||||
inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); }
|
inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); }
|
||||||
|
|
||||||
// Returns the pseudo attacks of the given piece type
|
|
||||||
// assuming an empty board.
|
|
||||||
template<PieceType Pt>
|
|
||||||
inline Bitboard attacks_bb(Square s, Color c = COLOR_NB) {
|
|
||||||
|
|
||||||
assert((Pt != PAWN || c < COLOR_NB) && (is_ok(s)));
|
constexpr int constexpr_popcount(Bitboard b) {
|
||||||
return Pt == PAWN ? PseudoAttacks[c][s] : PseudoAttacks[Pt][s];
|
b = b - ((b >> 1) & 0x5555555555555555ULL);
|
||||||
}
|
b = (b & 0x3333333333333333ULL) + ((b >> 2) & 0x3333333333333333ULL);
|
||||||
|
b = (b + (b >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
|
||||||
|
return static_cast<int>((b * 0x0101010101010101ULL) >> 56);
|
||||||
// Returns the attacks by the given piece
|
|
||||||
// assuming the board is occupied according to the passed Bitboard.
|
|
||||||
// Sliding piece attacks do not continue passed an occupied square.
|
|
||||||
template<PieceType Pt>
|
|
||||||
inline Bitboard attacks_bb(Square s, Bitboard occupied) {
|
|
||||||
|
|
||||||
assert((Pt != PAWN) && (is_ok(s)));
|
|
||||||
|
|
||||||
switch (Pt)
|
|
||||||
{
|
|
||||||
case BISHOP :
|
|
||||||
case ROOK :
|
|
||||||
return Magics[s][Pt - BISHOP].attacks_bb(occupied);
|
|
||||||
case QUEEN :
|
|
||||||
return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
|
|
||||||
default :
|
|
||||||
return PseudoAttacks[Pt][s];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the attacks by the given piece
|
|
||||||
// assuming the board is occupied according to the passed Bitboard.
|
|
||||||
// Sliding piece attacks do not continue passed an occupied square.
|
|
||||||
inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) {
|
|
||||||
|
|
||||||
assert((pt != PAWN) && (is_ok(s)));
|
|
||||||
|
|
||||||
switch (pt)
|
|
||||||
{
|
|
||||||
case BISHOP :
|
|
||||||
return attacks_bb<BISHOP>(s, occupied);
|
|
||||||
case ROOK :
|
|
||||||
return attacks_bb<ROOK>(s, occupied);
|
|
||||||
case QUEEN :
|
|
||||||
return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
|
|
||||||
default :
|
|
||||||
return PseudoAttacks[pt][s];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Bitboard attacks_bb(Piece pc, Square s) {
|
|
||||||
if (type_of(pc) == PAWN)
|
|
||||||
return PseudoAttacks[color_of(pc)][s];
|
|
||||||
|
|
||||||
return PseudoAttacks[type_of(pc)][s];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline Bitboard attacks_bb(Piece pc, Square s, Bitboard occupied) {
|
|
||||||
if (type_of(pc) == PAWN)
|
|
||||||
return PseudoAttacks[color_of(pc)][s];
|
|
||||||
|
|
||||||
return attacks_bb(type_of(pc), s, occupied);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Counts the number of non-zero bits in a bitboard.
|
// Counts the number of non-zero bits in a bitboard.
|
||||||
@@ -373,6 +316,153 @@ inline Square pop_lsb(Bitboard& b) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Bitboards {
|
||||||
|
// Returns the bitboard of target square for the given step
|
||||||
|
// from the given square. If the step is off the board, returns empty bitboard.
|
||||||
|
constexpr Bitboard safe_destination(Square s, int step) {
|
||||||
|
constexpr auto abs = [](int v) { return v < 0 ? -v : v; };
|
||||||
|
Square to = Square(s + step);
|
||||||
|
return is_ok(to) && abs(file_of(s) - file_of(to)) <= 2 ? square_bb(to) : Bitboard(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Bitboard sliding_attack(PieceType pt, Square sq, Bitboard occupied) {
|
||||||
|
Bitboard attacks = 0;
|
||||||
|
Direction RookDirections[4] = {NORTH, SOUTH, EAST, WEST};
|
||||||
|
Direction BishopDirections[4] = {NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
|
||||||
|
|
||||||
|
for (Direction d : (pt == ROOK ? RookDirections : BishopDirections))
|
||||||
|
{
|
||||||
|
Square s = sq;
|
||||||
|
while (safe_destination(s, d))
|
||||||
|
{
|
||||||
|
attacks |= (s += d);
|
||||||
|
if (occupied & s)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return attacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Bitboard knight_attack(Square sq) {
|
||||||
|
Bitboard b = {};
|
||||||
|
for (int step : {-17, -15, -10, -6, 6, 10, 15, 17})
|
||||||
|
b |= safe_destination(sq, step);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Bitboard king_attack(Square sq) {
|
||||||
|
Bitboard b = {};
|
||||||
|
for (int step : {-9, -8, -7, -1, 1, 7, 8, 9})
|
||||||
|
b |= safe_destination(sq, step);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Bitboard pseudo_attacks(PieceType pt, Square sq) {
|
||||||
|
switch (pt)
|
||||||
|
{
|
||||||
|
case PieceType::ROOK :
|
||||||
|
case PieceType::BISHOP :
|
||||||
|
return sliding_attack(pt, sq, 0);
|
||||||
|
case PieceType::QUEEN :
|
||||||
|
return sliding_attack(PieceType::ROOK, sq, 0) | sliding_attack(PieceType::BISHOP, sq, 0);
|
||||||
|
case PieceType::KNIGHT :
|
||||||
|
return knight_attack(sq);
|
||||||
|
case PieceType::KING :
|
||||||
|
return king_attack(sq);
|
||||||
|
default :
|
||||||
|
assert(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr auto PseudoAttacks = []() constexpr {
|
||||||
|
std::array<std::array<Bitboard, SQUARE_NB>, PIECE_TYPE_NB> attacks{};
|
||||||
|
|
||||||
|
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
|
||||||
|
{
|
||||||
|
attacks[WHITE][s1] = pawn_attacks_bb<WHITE>(square_bb(s1));
|
||||||
|
attacks[BLACK][s1] = pawn_attacks_bb<BLACK>(square_bb(s1));
|
||||||
|
|
||||||
|
attacks[KING][s1] = Bitboards::pseudo_attacks(KING, s1);
|
||||||
|
attacks[KNIGHT][s1] = Bitboards::pseudo_attacks(KNIGHT, s1);
|
||||||
|
attacks[QUEEN][s1] = attacks[BISHOP][s1] = Bitboards::pseudo_attacks(BISHOP, s1);
|
||||||
|
attacks[QUEEN][s1] |= attacks[ROOK][s1] = Bitboards::pseudo_attacks(ROOK, s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return attacks;
|
||||||
|
}();
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the pseudo attacks of the given piece type
|
||||||
|
// assuming an empty board.
|
||||||
|
template<PieceType Pt>
|
||||||
|
inline Bitboard attacks_bb(Square s, Color c = COLOR_NB) {
|
||||||
|
|
||||||
|
assert((Pt != PAWN || c < COLOR_NB) && (is_ok(s)));
|
||||||
|
return Pt == PAWN ? PseudoAttacks[c][s] : PseudoAttacks[Pt][s];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the attacks by the given piece
|
||||||
|
// assuming the board is occupied according to the passed Bitboard.
|
||||||
|
// Sliding piece attacks do not continue passed an occupied square.
|
||||||
|
template<PieceType Pt>
|
||||||
|
inline Bitboard attacks_bb(Square s, Bitboard occupied) {
|
||||||
|
|
||||||
|
assert((Pt != PAWN) && (is_ok(s)));
|
||||||
|
|
||||||
|
switch (Pt)
|
||||||
|
{
|
||||||
|
case BISHOP :
|
||||||
|
case ROOK :
|
||||||
|
return Magics[s][Pt - BISHOP].attacks_bb(occupied);
|
||||||
|
case QUEEN :
|
||||||
|
return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
|
||||||
|
default :
|
||||||
|
return PseudoAttacks[Pt][s];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the attacks by the given piece
|
||||||
|
// assuming the board is occupied according to the passed Bitboard.
|
||||||
|
// Sliding piece attacks do not continue passed an occupied square.
|
||||||
|
inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) {
|
||||||
|
|
||||||
|
assert((pt != PAWN) && (is_ok(s)));
|
||||||
|
|
||||||
|
switch (pt)
|
||||||
|
{
|
||||||
|
case BISHOP :
|
||||||
|
return attacks_bb<BISHOP>(s, occupied);
|
||||||
|
case ROOK :
|
||||||
|
return attacks_bb<ROOK>(s, occupied);
|
||||||
|
case QUEEN :
|
||||||
|
return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
|
||||||
|
default :
|
||||||
|
return PseudoAttacks[pt][s];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Bitboard attacks_bb(Piece pc, Square s) {
|
||||||
|
if (type_of(pc) == PAWN)
|
||||||
|
return PseudoAttacks[color_of(pc)][s];
|
||||||
|
|
||||||
|
return PseudoAttacks[type_of(pc)][s];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Bitboard attacks_bb(Piece pc, Square s, Bitboard occupied) {
|
||||||
|
if (type_of(pc) == PAWN)
|
||||||
|
return PseudoAttacks[color_of(pc)][s];
|
||||||
|
|
||||||
|
return attacks_bb(type_of(pc), s, occupied);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Stockfish
|
} // namespace Stockfish
|
||||||
|
|
||||||
#endif // #ifndef BITBOARD_H_INCLUDED
|
#endif // #ifndef BITBOARD_H_INCLUDED
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
#include "bitboard.h"
|
#include "bitboard.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "nnue/features/full_threats.h"
|
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
#include "tune.h"
|
#include "tune.h"
|
||||||
#include "uci.h"
|
#include "uci.h"
|
||||||
@@ -33,7 +32,6 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
Bitboards::init();
|
Bitboards::init();
|
||||||
Position::init();
|
Position::init();
|
||||||
Eval::NNUE::Features::init_threat_offsets();
|
|
||||||
|
|
||||||
auto uci = std::make_unique<UCIEngine>(argc, argv);
|
auto uci = std::make_unique<UCIEngine>(argc, argv);
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,9 @@
|
|||||||
#include "full_threats.h"
|
#include "full_threats.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "../../bitboard.h"
|
#include "../../bitboard.h"
|
||||||
#include "../../misc.h"
|
#include "../../misc.h"
|
||||||
@@ -31,26 +33,28 @@
|
|||||||
|
|
||||||
namespace Stockfish::Eval::NNUE::Features {
|
namespace Stockfish::Eval::NNUE::Features {
|
||||||
|
|
||||||
// Lookup array for indexing threats
|
|
||||||
IndexType offsets[PIECE_NB][SQUARE_NB];
|
|
||||||
|
|
||||||
struct HelperOffsets {
|
struct HelperOffsets {
|
||||||
int cumulativePieceOffset, cumulativeOffset;
|
int cumulativePieceOffset, cumulativeOffset;
|
||||||
};
|
};
|
||||||
std::array<HelperOffsets, PIECE_NB> helper_offsets;
|
|
||||||
|
|
||||||
// Information on a particular pair of pieces and whether they should be excluded
|
// Information on a particular pair of pieces and whether they should be excluded
|
||||||
struct PiecePairData {
|
struct PiecePairData {
|
||||||
// Layout: bits 8..31 are the index contribution of this piece pair, bits 0 and 1 are exclusion info
|
// Layout: bits 8..31 are the index contribution of this piece pair, bits 0 and 1 are exclusion info
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
PiecePairData() {}
|
|
||||||
PiecePairData(bool excluded_pair, bool semi_excluded_pair, IndexType feature_index_base) {
|
constexpr PiecePairData() :
|
||||||
data =
|
data(0) {}
|
||||||
excluded_pair << 1 | (semi_excluded_pair && !excluded_pair) | feature_index_base << 8;
|
|
||||||
}
|
constexpr PiecePairData(bool excluded_pair,
|
||||||
|
bool semi_excluded_pair,
|
||||||
|
IndexType feature_index_base) :
|
||||||
|
data((uint32_t(excluded_pair) << 1) | (uint32_t(semi_excluded_pair && !excluded_pair))
|
||||||
|
| (uint32_t(feature_index_base) << 8)) {}
|
||||||
|
|
||||||
// lsb: excluded if from < to; 2nd lsb: always excluded
|
// lsb: excluded if from < to; 2nd lsb: always excluded
|
||||||
uint8_t excluded_pair_info() const { return (uint8_t) data; }
|
constexpr uint8_t excluded_pair_info() const { return static_cast<uint8_t>(data); }
|
||||||
IndexType feature_index_base() const { return data >> 8; }
|
|
||||||
|
constexpr IndexType feature_index_base() const { return static_cast<IndexType>(data >> 8); }
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr std::array<Piece, 12> AllPieces = {
|
constexpr std::array<Piece, 12> AllPieces = {
|
||||||
@@ -58,12 +62,119 @@ constexpr std::array<Piece, 12> AllPieces = {
|
|||||||
B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
|
B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
|
||||||
};
|
};
|
||||||
|
|
||||||
// The final index is calculated from summing data found in these two LUTs, as well
|
template<PieceType PT>
|
||||||
// as offsets[attacker][from]
|
constexpr auto make_piece_indices_type() {
|
||||||
PiecePairData index_lut1[PIECE_NB][PIECE_NB]; // [attacker][attacked]
|
static_assert(PT != PieceType::PAWN);
|
||||||
uint8_t index_lut2[PIECE_NB][SQUARE_NB][SQUARE_NB]; // [attacker][from][to]
|
|
||||||
|
std::array<std::array<uint8_t, SQUARE_NB>, SQUARE_NB> out{};
|
||||||
|
|
||||||
|
for (int from = 0; from < SQUARE_NB; ++from)
|
||||||
|
{
|
||||||
|
Bitboard attacks = PseudoAttacks[PT][Square(from)];
|
||||||
|
|
||||||
|
for (int to = 0; to < SQUARE_NB; ++to)
|
||||||
|
{
|
||||||
|
out[from][to] = constexpr_popcount(((1ULL << to) - 1) & attacks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Piece P>
|
||||||
|
constexpr auto make_piece_indices_piece() {
|
||||||
|
static_assert(type_of(P) == PieceType::PAWN);
|
||||||
|
|
||||||
|
std::array<std::array<uint8_t, SQUARE_NB>, SQUARE_NB> out{};
|
||||||
|
|
||||||
|
constexpr Color C = color_of(P);
|
||||||
|
|
||||||
|
for (int from = 0; from < SQUARE_NB; ++from)
|
||||||
|
{
|
||||||
|
Bitboard attacks = PseudoAttacks[C][from];
|
||||||
|
|
||||||
|
for (int to = 0; to < SQUARE_NB; ++to)
|
||||||
|
{
|
||||||
|
out[from][to] = constexpr_popcount(((1ULL << to) - 1) & attacks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto index_lut2_array() {
|
||||||
|
constexpr auto KNIGHT_ATTACKS = make_piece_indices_type<PieceType::KNIGHT>();
|
||||||
|
constexpr auto BISHOP_ATTACKS = make_piece_indices_type<PieceType::BISHOP>();
|
||||||
|
constexpr auto ROOK_ATTACKS = make_piece_indices_type<PieceType::ROOK>();
|
||||||
|
constexpr auto QUEEN_ATTACKS = make_piece_indices_type<PieceType::QUEEN>();
|
||||||
|
constexpr auto KING_ATTACKS = make_piece_indices_type<PieceType::KING>();
|
||||||
|
|
||||||
|
std::array<std::array<std::array<uint8_t, SQUARE_NB>, SQUARE_NB>, PIECE_NB> indices{};
|
||||||
|
|
||||||
|
indices[W_PAWN] = make_piece_indices_piece<W_PAWN>();
|
||||||
|
indices[B_PAWN] = make_piece_indices_piece<B_PAWN>();
|
||||||
|
|
||||||
|
indices[W_KNIGHT] = KNIGHT_ATTACKS;
|
||||||
|
indices[B_KNIGHT] = KNIGHT_ATTACKS;
|
||||||
|
|
||||||
|
indices[W_BISHOP] = BISHOP_ATTACKS;
|
||||||
|
indices[B_BISHOP] = BISHOP_ATTACKS;
|
||||||
|
|
||||||
|
indices[W_ROOK] = ROOK_ATTACKS;
|
||||||
|
indices[B_ROOK] = ROOK_ATTACKS;
|
||||||
|
|
||||||
|
indices[W_QUEEN] = QUEEN_ATTACKS;
|
||||||
|
indices[B_QUEEN] = QUEEN_ATTACKS;
|
||||||
|
|
||||||
|
indices[W_KING] = KING_ATTACKS;
|
||||||
|
indices[B_KING] = KING_ATTACKS;
|
||||||
|
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto init_threat_offsets() {
|
||||||
|
std::array<HelperOffsets, PIECE_NB> indices{};
|
||||||
|
std::array<std::array<IndexType, SQUARE_NB>, PIECE_NB> offsets{};
|
||||||
|
|
||||||
|
int cumulativeOffset = 0;
|
||||||
|
for (Piece piece : AllPieces)
|
||||||
|
{
|
||||||
|
int pieceIdx = piece;
|
||||||
|
int cumulativePieceOffset = 0;
|
||||||
|
|
||||||
|
for (Square from = SQ_A1; from <= SQ_H8; ++from)
|
||||||
|
{
|
||||||
|
offsets[pieceIdx][from] = cumulativePieceOffset;
|
||||||
|
|
||||||
|
if (type_of(piece) != PAWN)
|
||||||
|
{
|
||||||
|
Bitboard attacks = PseudoAttacks[type_of(piece)][from];
|
||||||
|
cumulativePieceOffset += constexpr_popcount(attacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (from >= SQ_A2 && from <= SQ_H7)
|
||||||
|
{
|
||||||
|
Bitboard attacks = (pieceIdx < 8) ? pawn_attacks_bb<WHITE>(square_bb(from))
|
||||||
|
: pawn_attacks_bb<BLACK>(square_bb(from));
|
||||||
|
cumulativePieceOffset += constexpr_popcount(attacks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
indices[pieceIdx] = {cumulativePieceOffset, cumulativeOffset};
|
||||||
|
|
||||||
|
cumulativeOffset += numValidTargets[pieceIdx] * cumulativePieceOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::pair{indices, offsets};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto helper_offsets = init_threat_offsets().first;
|
||||||
|
// Lookup array for indexing threats
|
||||||
|
constexpr auto offsets = init_threat_offsets().second;
|
||||||
|
|
||||||
|
constexpr auto init_index_luts() {
|
||||||
|
std::array<std::array<PiecePairData, PIECE_NB>, PIECE_NB> indices{};
|
||||||
|
|
||||||
static void init_index_luts() {
|
|
||||||
for (Piece attacker : AllPieces)
|
for (Piece attacker : AllPieces)
|
||||||
{
|
{
|
||||||
for (Piece attacked : AllPieces)
|
for (Piece attacked : AllPieces)
|
||||||
@@ -78,56 +189,21 @@ static void init_index_luts() {
|
|||||||
+ (color_of(attacked) * (numValidTargets[attacker] / 2) + map)
|
+ (color_of(attacked) * (numValidTargets[attacker] / 2) + map)
|
||||||
* helper_offsets[attacker].cumulativePieceOffset;
|
* helper_offsets[attacker].cumulativePieceOffset;
|
||||||
|
|
||||||
bool excluded = map < 0;
|
bool excluded = map < 0;
|
||||||
index_lut1[attacker][attacked] = PiecePairData(excluded, semi_excluded, feature);
|
indices[attacker][attacked] = PiecePairData(excluded, semi_excluded, feature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Piece attacker : AllPieces)
|
return indices;
|
||||||
{
|
|
||||||
for (int from = 0; from < SQUARE_NB; ++from)
|
|
||||||
{
|
|
||||||
for (int to = 0; to < SQUARE_NB; ++to)
|
|
||||||
{
|
|
||||||
Bitboard attacks = attacks_bb(attacker, Square(from));
|
|
||||||
index_lut2[attacker][from][to] = popcount((square_bb(Square(to)) - 1) & attacks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_threat_offsets() {
|
// The final index is calculated from summing data found in these two LUTs, as well
|
||||||
int cumulativeOffset = 0;
|
// as offsets[attacker][from]
|
||||||
for (Piece piece : AllPieces)
|
|
||||||
{
|
|
||||||
int pieceIdx = piece;
|
|
||||||
int cumulativePieceOffset = 0;
|
|
||||||
|
|
||||||
for (Square from = SQ_A1; from <= SQ_H8; ++from)
|
// [attacker][attacked]
|
||||||
{
|
constexpr auto index_lut1 = init_index_luts();
|
||||||
offsets[pieceIdx][from] = cumulativePieceOffset;
|
// [attacker][from][to]
|
||||||
|
constexpr auto index_lut2 = index_lut2_array();
|
||||||
if (type_of(piece) != PAWN)
|
|
||||||
{
|
|
||||||
Bitboard attacks = attacks_bb(piece, from, 0ULL);
|
|
||||||
cumulativePieceOffset += popcount(attacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (from >= SQ_A2 && from <= SQ_H7)
|
|
||||||
{
|
|
||||||
Bitboard attacks = (pieceIdx < 8) ? pawn_attacks_bb<WHITE>(square_bb(from))
|
|
||||||
: pawn_attacks_bb<BLACK>(square_bb(from));
|
|
||||||
cumulativePieceOffset += popcount(attacks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
helper_offsets[pieceIdx] = {cumulativePieceOffset, cumulativeOffset};
|
|
||||||
|
|
||||||
cumulativeOffset += numValidTargets[pieceIdx] * cumulativePieceOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_index_luts();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Index of a feature for a given king position and another piece on some square
|
// Index of a feature for a given king position and another piece on some square
|
||||||
inline sf_always_inline IndexType FullThreats::make_index(
|
inline sf_always_inline IndexType FullThreats::make_index(
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ namespace Stockfish::Eval::NNUE::Features {
|
|||||||
|
|
||||||
static constexpr int numValidTargets[PIECE_NB] = {0, 6, 12, 10, 10, 12, 8, 0,
|
static constexpr int numValidTargets[PIECE_NB] = {0, 6, 12, 10, 10, 12, 8, 0,
|
||||||
0, 6, 12, 10, 10, 12, 8, 0};
|
0, 6, 12, 10, 10, 12, 8, 0};
|
||||||
void init_threat_offsets();
|
|
||||||
|
|
||||||
class FullThreats {
|
class FullThreats {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "../bitboard.h"
|
#include "../bitboard.h"
|
||||||
#include "../misc.h"
|
#include "../misc.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user