namespace Eval::NNUE::Features {
+ // Map square to numbering on 8x8 board
+ constexpr Square map_to_standard_board(Square s) {
+ return Square(s - rank_of(s) * (FILE_MAX - FILE_H));
+ }
+
// Orient a square according to perspective (rotates by 180 for black)
- inline Square orient(Color perspective, Square s) {
- return Square(int(s) ^ (bool(perspective) * 63));
+ inline Square orient(const Position& pos, Color perspective, Square s) {
+ return map_to_standard_board( perspective == WHITE || (pos.capture_the_flag(BLACK) & Rank8BB) ? s
+ : flip_rank(flip_file(s, pos.max_file()), pos.max_rank()));
}
- // Find the index of the feature quantity from the king position and PieceSquare
- template <Side AssociatedKing>
- inline IndexType HalfKP<AssociatedKing>::MakeIndex(
- const Position& pos, Color perspective, Square s, Piece pc, Square ksq) {
-
- return IndexType(orient(pos, perspective, s) + kpp_board_index[pc][perspective] + PS_END * ksq);
+ // Index of a feature for a given king position and another piece on some square
- inline IndexType make_index(Color perspective, Square s, Piece pc, Square ksq) {
- return IndexType(orient(perspective, s) + kpp_board_index[perspective][pc] + PS_END * ksq);
++ inline IndexType make_index(const Position& pos, Color perspective, Square s, Piece pc, Square ksq) {
++ return IndexType(orient(pos, perspective, s) + kpp_board_index[perspective][pc] + PS_END * ksq);
}
// Get a list of indices for active features
Bitboard bb = pos.pieces() & ~pos.pieces(KING);
while (bb) {
Square s = pop_lsb(&bb);
- active->push_back(MakeIndex(pos, perspective, s, pos.piece_on(s), ksq));
- active->push_back(make_index(perspective, s, pos.piece_on(s), ksq));
++ active->push_back(make_index(pos, perspective, s, pos.piece_on(s), ksq));
}
}
Piece pc = dp.piece[i];
if (type_of(pc) == KING) continue;
if (dp.from[i] != SQ_NONE)
- removed->push_back(MakeIndex(pos, perspective, dp.from[i], pc, ksq));
- removed->push_back(make_index(perspective, dp.from[i], pc, ksq));
++ removed->push_back(make_index(pos, perspective, dp.from[i], pc, ksq));
if (dp.to[i] != SQ_NONE)
- added->push_back(MakeIndex(pos, perspective, dp.to[i], pc, ksq));
- added->push_back(make_index(perspective, dp.to[i], pc, ksq));
++ added->push_back(make_index(pos, perspective, dp.to[i], pc, ksq));
}
}
enum {
PS_NONE = 0,
PS_W_PAWN = 1,
- PS_B_PAWN = 1 * SQUARE_NB + 1,
- PS_W_KNIGHT = 2 * SQUARE_NB + 1,
- PS_B_KNIGHT = 3 * SQUARE_NB + 1,
- PS_W_BISHOP = 4 * SQUARE_NB + 1,
- PS_B_BISHOP = 5 * SQUARE_NB + 1,
- PS_W_ROOK = 6 * SQUARE_NB + 1,
- PS_B_ROOK = 7 * SQUARE_NB + 1,
- PS_W_QUEEN = 8 * SQUARE_NB + 1,
- PS_B_QUEEN = 9 * SQUARE_NB + 1,
- PS_W_KING = 10 * SQUARE_NB + 1,
+ PS_B_PAWN = 1 * SQUARE_NB_CHESS + 1,
+ PS_W_KNIGHT = 2 * SQUARE_NB_CHESS + 1,
+ PS_B_KNIGHT = 3 * SQUARE_NB_CHESS + 1,
+ PS_W_BISHOP = 4 * SQUARE_NB_CHESS + 1,
+ PS_B_BISHOP = 5 * SQUARE_NB_CHESS + 1,
+ PS_W_ROOK = 6 * SQUARE_NB_CHESS + 1,
+ PS_B_ROOK = 7 * SQUARE_NB_CHESS + 1,
+ PS_W_QUEEN = 8 * SQUARE_NB_CHESS + 1,
+ PS_B_QUEEN = 9 * SQUARE_NB_CHESS + 1,
+ PS_W_KING = 10 * SQUARE_NB_CHESS + 1,
PS_END = PS_W_KING, // pieces without kings (pawns included)
- PS_B_KING = 11 * SQUARE_NB + 1,
- PS_END2 = 12 * SQUARE_NB + 1
+ PS_B_KING = 11 * SQUARE_NB_CHESS + 1,
+ PS_END2 = 12 * SQUARE_NB_CHESS + 1
};
- extern const uint32_t kpp_board_index[PIECE_NB][COLOR_NB];
+ constexpr uint32_t kpp_board_index[COLOR_NB][PIECE_NB] = {
+ // convention: W - us, B - them
+ // viewed from other side, W and B are reversed
- { PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_W_KING, PS_NONE,
- PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_B_KING, PS_NONE },
- { PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_B_KING, PS_NONE,
- PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_W_KING, PS_NONE }
++ { PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN,
++ PS_W_QUEEN, PS_W_BISHOP, PS_W_BISHOP, PS_W_BISHOP, PS_W_QUEEN,
++ PS_W_QUEEN, PS_NONE, PS_NONE, PS_W_QUEEN, PS_W_KNIGHT,
++ PS_W_BISHOP, PS_W_KNIGHT, PS_W_ROOK, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_W_BISHOP,
++ PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_W_KING,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_B_PAWN,
++ PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_B_QUEEN,
++ PS_B_BISHOP, PS_B_BISHOP, PS_B_BISHOP, PS_B_QUEEN, PS_B_QUEEN,
++ PS_NONE, PS_NONE, PS_B_QUEEN, PS_B_KNIGHT, PS_B_BISHOP,
++ PS_B_KNIGHT, PS_B_ROOK, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_B_BISHOP, PS_NONE,
++ PS_B_PAWN, PS_B_KNIGHT, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_B_KING, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE },
++ { PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN,
++ PS_B_QUEEN, PS_B_BISHOP, PS_B_BISHOP, PS_B_BISHOP, PS_B_QUEEN,
++ PS_B_QUEEN, PS_NONE, PS_NONE, PS_B_QUEEN, PS_B_KNIGHT,
++ PS_B_BISHOP, PS_B_KNIGHT, PS_B_ROOK, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_B_BISHOP,
++ PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_B_KING,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_W_PAWN,
++ PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_W_QUEEN,
++ PS_W_BISHOP, PS_W_BISHOP, PS_W_BISHOP, PS_W_QUEEN, PS_W_QUEEN,
++ PS_NONE, PS_NONE, PS_W_QUEEN, PS_W_KNIGHT, PS_W_BISHOP,
++ PS_W_KNIGHT, PS_W_ROOK, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_W_BISHOP, PS_NONE,
++ PS_W_PAWN, PS_W_KNIGHT, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_W_KING, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
++ PS_NONE, PS_NONE }
+ };
++ // Check that the fragile array definition is correct
++ static_assert(kpp_board_index[WHITE][make_piece(WHITE, PAWN)] == PS_W_PAWN);
++ static_assert(kpp_board_index[WHITE][make_piece(WHITE, KING)] == PS_W_KING);
++ static_assert(kpp_board_index[WHITE][make_piece(BLACK, PAWN)] == PS_B_PAWN);
++ static_assert(kpp_board_index[WHITE][make_piece(BLACK, KING)] == PS_B_KING);
++
// Type of input feature after conversion
using TransformedFeatureType = std::uint8_t;