search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
nnue/evaluate_nnue.cpp nnue/features/half_ka_v2.cpp \
partner.cpp parser.cpp piece.cpp variant.cpp xboard.cpp \
- nnue/features/half_ka_v2_shogi.cpp nnue/features/half_ka_v2_variants.cpp
+ nnue/features/half_ka_v2_variants.cpp
OBJS = $(notdir $(SRCS:.cpp=.o))
search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
nnue/evaluate_nnue.cpp nnue/features/half_ka_v2.cpp \
partner.cpp parser.cpp piece.cpp variant.cpp xboard.cpp \
- nnue/features/half_ka_v2_shogi.cpp nnue/features/half_ka_v2_variants.cpp
+ nnue/features/half_ka_v2_variants.cpp
CXX=emcc
CXXFLAGS += --bind -DNNUE_EMBEDDING_OFF -DNO_THREADS -std=c++17 -Wall
namespace Stockfish {
-NnueFeatures currentNnueFeatures;
+const Variant* currentNnueVariant;
namespace Eval {
if (!useNNUE)
return;
- currentNnueFeatures = variants.find(variant)->second->nnueFeatures;
+ currentNnueVariant = variants.find(variant)->second;
#if defined(DEFAULT_NNUE_DIRECTORY)
#define stringify2(x) #x
#include "types.h"
+#include "variant.h"
+
namespace Stockfish {
class Position;
} // namespace Eval
-extern NnueFeatures currentNnueFeatures;
+extern const Variant* currentNnueVariant;
} // namespace Stockfish
ASSERT_ALIGNED(transformedFeatures, alignment);
ASSERT_ALIGNED(buffer, alignment);
- const std::size_t bucket = (pos.count<ALL_PIECES>() - 1) / 4;
+ const std::size_t bucket = std::min((pos.count<ALL_PIECES>() - 1) * 8 / currentNnueVariant->nnueMaxPieces, 7);
const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket);
const auto output = network[bucket]->propagate(transformedFeatures, buffer);
ASSERT_ALIGNED(buffer, alignment);
NnueEvalTrace t{};
- t.correctBucket = (pos.count<ALL_PIECES>() - 1) / 4;
+ t.correctBucket = std::min((pos.count<ALL_PIECES>() - 1) * 8 / currentNnueVariant->nnueMaxPieces, 7);
for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket) {
const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket);
const auto output = network[bucket]->propagate(transformedFeatures, buffer);
char board[3*RANK_NB+1][8*FILE_NB+2];
std::memset(board, ' ', sizeof(board));
for (int row = 0; row < 3*pos.ranks()+1; ++row)
- board[row][pos.ranks()*pos.files()+1] = '\0';
+ board[row][8*FILE_NB+1] = '\0';
// A lambda to output one box of the board
auto writeSquare = [&board, &pos](File file, Rank rank, Piece pc, Value value) {
const int x = ((int)file) * 8;
- const int y = (7 - (int)rank) * 3;
+ const int y = (pos.max_rank() - (int)rank) * 3;
for (int i = 1; i < 8; ++i)
board[y][x+i] = board[y+3][x+i] = '-';
for (int i = 1; i < 3; ++i)
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_KING,
- PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_B_QUEEN, PS_B_BISHOP,
+ PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, 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_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_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, 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_NONE, PS_NONE,
+++ /dev/null
-/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
-
- Stockfish is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Stockfish is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-//Definition of input features HalfKAv2 of NNUE evaluation function
-
-#include "half_ka_v2_shogi.h"
-
-#include "../../position.h"
-
-namespace Stockfish::Eval::NNUE::Features {
-
- constexpr Square rotate(Square s) {
- return Square(SQUARE_NB_SHOGI - 1 - int(s));
- }
-
- constexpr Square to_shogi_square(Square s) {
- return Square((8 - s % 12) * 9 + 8 - s / 12);
- }
-
- // Orient a square according to perspective (rotates by 180 for black)
- inline Square HalfKAv2Shogi::orient(Color perspective, Square s) {
- return perspective == WHITE ? to_shogi_square(s) : rotate(to_shogi_square(s));
- }
-
- // Index of a feature for a given king position and another piece on some square
- inline IndexType HalfKAv2Shogi::make_index(Color perspective, Square s, Piece pc, Square ksq) {
- return IndexType(orient(perspective, s) + PieceSquareIndexShogi[perspective][pc] + SHOGI_PS_NB * ksq);
- }
-
- // Index of a feature for a given king position and hand piece
- inline IndexType HalfKAv2Shogi::make_index(Color perspective, Color c, int hand_index, PieceType pt, Square ksq) {
- Color color = (c == perspective) ? WHITE : BLACK;
- return IndexType(hand_index + PieceSquareIndexShogiHand[color][pt] + SHOGI_PS_NB * ksq);
- }
-
- // Get a list of indices for active features
- void HalfKAv2Shogi::append_active_indices(
- const Position& pos,
- Color perspective,
- ValueListInserter<IndexType> active
- ) {
- Square ksq = orient(perspective, pos.square<KING>(perspective));
- Bitboard bb = pos.pieces();
- while (bb)
- {
- Square s = pop_lsb(bb);
- active.push_back(make_index(perspective, s, pos.piece_on(s), ksq));
- }
-
- // Indices for pieces in hand
- for (Color c : {WHITE, BLACK})
- for (PieceType pt : pos.piece_types())
- for (int i = 0; i < pos.count_in_hand(c, pt); i++)
- active.push_back(make_index(perspective, c, i, pt, ksq));
- }
-
- // append_changed_indices() : get a list of indices for recently changed features
-
- void HalfKAv2Shogi::append_changed_indices(
- Square ksq,
- StateInfo* st,
- Color perspective,
- ValueListInserter<IndexType> removed,
- ValueListInserter<IndexType> added
- ) {
- const auto& dp = st->dirtyPiece;
- Square oriented_ksq = orient(perspective, ksq);
- for (int i = 0; i < dp.dirty_num; ++i) {
- Piece pc = dp.piece[i];
- if (dp.from[i] != SQ_NONE)
- removed.push_back(make_index(perspective, dp.from[i], pc, oriented_ksq));
- else if (dp.dirty_num == 1)
- {
- Piece handPc = dp.handPiece[i];
- removed.push_back(make_index(perspective, color_of(handPc), dp.handCount[i], type_of(handPc), oriented_ksq));
- }
- if (dp.to[i] != SQ_NONE)
- added.push_back(make_index(perspective, dp.to[i], pc, oriented_ksq));
- else if (i == 1)
- {
- Piece handPc = dp.handPiece[i];
- added.push_back(make_index(perspective, color_of(handPc), dp.handCount[i] - 1, type_of(handPc), oriented_ksq));
- }
- }
- }
-
- int HalfKAv2Shogi::update_cost(StateInfo* st) {
- return st->dirtyPiece.dirty_num;
- }
-
- int HalfKAv2Shogi::refresh_cost(const Position& pos) {
- return pos.count<ALL_PIECES>();
- }
-
- bool HalfKAv2Shogi::requires_refresh(StateInfo* st, Color perspective) {
- return st->dirtyPiece.piece[0] == make_piece(perspective, KING);
- }
-
-
-} // namespace Stockfish::Eval::NNUE::Features
+++ /dev/null
-/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
-
- Stockfish is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Stockfish is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-//Definition of input features HalfKAv2 of NNUE evaluation function
-
-#ifndef NNUE_FEATURES_HALF_KA_V2_SHOGI_H_INCLUDED
-#define NNUE_FEATURES_HALF_KA_V2_SHOGI_H_INCLUDED
-
-#include "../nnue_common.h"
-
-#include "../../evaluate.h"
-#include "../../misc.h"
-
-namespace Stockfish {
- struct StateInfo;
-}
-
-namespace Stockfish::Eval::NNUE::Features {
-
- // Feature HalfKAv2: Combination of the position of own king
- // and the position of pieces
- class HalfKAv2Shogi {
-
- // unique number for each piece type on each square
- enum {
- PS_NONE = 0,
- SHOGI_HAND_W_PAWN = 0,
- SHOGI_HAND_B_PAWN = 19,
- SHOGI_HAND_W_LANCE = 38,
- SHOGI_HAND_B_LANCE = 43,
- SHOGI_HAND_W_KNIGHT = 48,
- SHOGI_HAND_B_KNIGHT = 53,
- SHOGI_HAND_W_SILVER = 58,
- SHOGI_HAND_B_SILVER = 63,
- SHOGI_HAND_W_GOLD = 68,
- SHOGI_HAND_B_GOLD = 73,
- SHOGI_HAND_W_BISHOP = 78,
- SHOGI_HAND_B_BISHOP = 81,
- SHOGI_HAND_W_ROOK = 84,
- SHOGI_HAND_B_ROOK = 87,
- SHOGI_HAND_END = 89,
-
- SHOGI_PS_W_PAWN = SHOGI_HAND_END,
- SHOGI_PS_B_PAWN = 1 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_W_LANCE = 2 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_B_LANCE = 3 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_W_KNIGHT = 4 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_B_KNIGHT = 5 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_W_SILVER = 6 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_B_SILVER = 7 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_W_GOLD = 8 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_B_GOLD = 9 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_W_BISHOP = 10 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_B_BISHOP = 11 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_W_HORSE = 12 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_B_HORSE = 13 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_W_ROOK = 14 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_B_ROOK = 15 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_W_DRAGON = 16 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_B_DRAGON = 17 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_KING = 18 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- SHOGI_PS_NB = 19 * SQUARE_NB_SHOGI + SHOGI_HAND_END,
- };
-
- static constexpr uint32_t PieceSquareIndexShogi[COLOR_NB][PIECE_NB] = {
- // convention: W - us, B - them
- // viewed from other side, W and B are reversed
- {
- PS_NONE, PS_NONE, PS_NONE, SHOGI_PS_W_BISHOP, SHOGI_PS_W_ROOK, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, SHOGI_PS_W_SILVER, PS_NONE, SHOGI_PS_W_DRAGON, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, PS_NONE, PS_NONE, SHOGI_PS_W_PAWN, SHOGI_PS_W_LANCE, SHOGI_PS_W_KNIGHT, SHOGI_PS_W_GOLD, SHOGI_PS_W_HORSE,
- 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_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, SHOGI_PS_KING,
-
- PS_NONE, PS_NONE, PS_NONE, SHOGI_PS_B_BISHOP, SHOGI_PS_B_ROOK, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, SHOGI_PS_B_SILVER, PS_NONE, SHOGI_PS_B_DRAGON, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, PS_NONE, PS_NONE, SHOGI_PS_B_PAWN, SHOGI_PS_B_LANCE, SHOGI_PS_B_KNIGHT, SHOGI_PS_B_GOLD, SHOGI_PS_B_HORSE,
- 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_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, SHOGI_PS_KING
- },
-
- {
- PS_NONE, PS_NONE, PS_NONE, SHOGI_PS_B_BISHOP, SHOGI_PS_B_ROOK, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, SHOGI_PS_B_SILVER, PS_NONE, SHOGI_PS_B_DRAGON, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, PS_NONE, PS_NONE, SHOGI_PS_B_PAWN, SHOGI_PS_B_LANCE, SHOGI_PS_B_KNIGHT, SHOGI_PS_B_GOLD, SHOGI_PS_B_HORSE,
- 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_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, SHOGI_PS_KING,
-
- PS_NONE, PS_NONE, PS_NONE, SHOGI_PS_W_BISHOP, SHOGI_PS_W_ROOK, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, SHOGI_PS_W_SILVER, PS_NONE, SHOGI_PS_W_DRAGON, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, PS_NONE, PS_NONE, SHOGI_PS_W_PAWN, SHOGI_PS_W_LANCE, SHOGI_PS_W_KNIGHT, SHOGI_PS_W_GOLD, SHOGI_PS_W_HORSE,
- 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_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, SHOGI_PS_KING
- }
- };
- static_assert(PieceSquareIndexShogi[WHITE][make_piece(WHITE, SHOGI_PAWN)] == SHOGI_PS_W_PAWN);
- static_assert(PieceSquareIndexShogi[WHITE][make_piece(WHITE, KING)] == SHOGI_PS_KING);
- static_assert(PieceSquareIndexShogi[WHITE][make_piece(BLACK, SHOGI_PAWN)] == SHOGI_PS_B_PAWN);
- static_assert(PieceSquareIndexShogi[WHITE][make_piece(BLACK, KING)] == SHOGI_PS_KING);
-
- static constexpr uint32_t PieceSquareIndexShogiHand[COLOR_NB][PIECE_TYPE_NB] = {
- // convention: W - us, B - them
- // viewed from other side, W and B are reversed
- {
- PS_NONE, PS_NONE, PS_NONE, SHOGI_HAND_W_BISHOP, SHOGI_HAND_W_ROOK, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, SHOGI_HAND_W_SILVER, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, PS_NONE, PS_NONE, SHOGI_HAND_W_PAWN, SHOGI_HAND_W_LANCE, SHOGI_HAND_W_KNIGHT, SHOGI_HAND_W_GOLD, 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_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, SHOGI_HAND_B_BISHOP, SHOGI_HAND_B_ROOK, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, SHOGI_HAND_B_SILVER, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
- PS_NONE, PS_NONE, PS_NONE, SHOGI_HAND_B_PAWN, SHOGI_HAND_B_LANCE, SHOGI_HAND_B_KNIGHT, SHOGI_HAND_B_GOLD, 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_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
- }
- };
- static_assert(PieceSquareIndexShogiHand[WHITE][SHOGI_PAWN] == SHOGI_HAND_W_PAWN);
- static_assert(PieceSquareIndexShogiHand[WHITE][GOLD] == SHOGI_HAND_W_GOLD);
- static_assert(PieceSquareIndexShogiHand[BLACK][SHOGI_PAWN] == SHOGI_HAND_B_PAWN);
- static_assert(PieceSquareIndexShogiHand[BLACK][GOLD] == SHOGI_HAND_B_GOLD);
-
- // Orient a square according to perspective (rotates by 180 for black)
- static Square orient(Color perspective, Square s);
-
- // Index of a feature for a given king position and another piece on some square
- static IndexType make_index(Color perspective, Square s, Piece pc, Square ksq);
-
- // Index of a feature for a given king position and a piece in hand
- static IndexType make_index(Color perspective, Color c, int hand_index, PieceType pt, Square ksq);
-
- public:
- // Feature name
- static constexpr const char* Name = "HalfKAv2(Friend)";
-
- // Hash value embedded in the evaluation file
- static constexpr std::uint32_t HashValue = 0x5f234cb8u;
-
- // Number of feature dimensions
- static constexpr IndexType Dimensions =
- static_cast<IndexType>(SQUARE_NB_SHOGI) * static_cast<IndexType>(SHOGI_PS_NB);
-
- // Maximum number of simultaneously active features.
- static constexpr IndexType MaxActiveDimensions = 40;
-
- // Get a list of indices for active features
- static void append_active_indices(
- const Position& pos,
- Color perspective,
- ValueListInserter<IndexType> active);
-
- // Get a list of indices for recently changed features
- static void append_changed_indices(
- Square ksq,
- StateInfo* st,
- Color perspective,
- ValueListInserter<IndexType> removed,
- ValueListInserter<IndexType> added);
-
- // Returns the cost of updating one perspective, the most costly one.
- // Assumes no refresh needed.
- static int update_cost(StateInfo* st);
- static int refresh_cost(const Position& pos);
-
- // Returns whether the change stored in this StateInfo means that
- // a full accumulator refresh is required.
- static bool requires_refresh(StateInfo* st, Color perspective);
- };
-
-} // namespace Stockfish::Eval::NNUE::Features
-
-#endif // #ifndef NNUE_FEATURES_HALF_KA_V2_SHOGI_H_INCLUDED
#include "half_ka_v2_variants.h"
-#ifdef LARGEBOARDS
-#include "half_ka_v2_shogi.h"
-#endif
-
#include "../../position.h"
namespace Stockfish::Eval::NNUE::Features {
- // Map square to numbering on 8x8 board
- constexpr Square to_chess_square(Square s) {
- return Square(s - rank_of(s) * (FILE_MAX - FILE_H));
+ // Map square to numbering on variant board
+ inline Square to_variant_square(Square s, const Position& pos) {
+ return Square(s - rank_of(s) * (FILE_MAX - pos.max_file()));
}
// Orient a square according to perspective (rotates by 180 for black)
inline Square HalfKAv2Variants::orient(Color perspective, Square s, const Position& pos) {
- return to_chess_square( perspective == WHITE || (pos.capture_the_flag(BLACK) & Rank8BB) ? s
- : flip_rank(s, pos.max_rank()));
+ return to_variant_square( perspective == WHITE || (pos.capture_the_flag(BLACK) & Rank8BB) ? s
+ : flip_rank(s, pos.max_rank()), pos);
}
// Index of a feature for a given king position and another piece on some square
inline IndexType HalfKAv2Variants::make_index(Color perspective, Square s, Piece pc, Square ksq, const Position& pos) {
- return IndexType(orient(perspective, s, pos) + PieceSquareIndex[perspective][pc] + PS_NB * ksq);
+ return IndexType(orient(perspective, s, pos) + pos.variant()->pieceSquareIndex[perspective][pc] + ksq * pos.variant()->nnuePieceIndices);
}
// Get a list of indices for active features
Color perspective,
ValueListInserter<IndexType> active
) {
- // Re-route to shogi features
-#ifdef LARGEBOARDS
- if (currentNnueFeatures == NNUE_SHOGI)
- {
- assert(HalfKAv2Shogi::Dimensions <= Dimensions);
- return HalfKAv2Shogi::append_active_indices(pos, perspective, active);
- }
-#endif
-
Square oriented_ksq = orient(perspective, pos.square(perspective, pos.nnue_king()), pos);
Bitboard bb = pos.pieces();
while (bb)
ValueListInserter<IndexType> added,
const Position& pos
) {
- // Re-route to shogi features
-#ifdef LARGEBOARDS
- if (currentNnueFeatures == NNUE_SHOGI)
- {
- assert(HalfKAv2Shogi::Dimensions <= Dimensions);
- return HalfKAv2Shogi::append_changed_indices(ksq, st, perspective, removed, added);
- }
-#endif
const auto& dp = st->dirtyPiece;
Square oriented_ksq = orient(perspective, ksq, pos);
for (int i = 0; i < dp.dirty_num; ++i) {
#include "../../evaluate.h"
#include "../../misc.h"
-#include "half_ka_v2_shogi.h"
#include "half_ka_v2.h"
namespace Stockfish {
// and the position of pieces
class HalfKAv2Variants {
- // unique number for each piece type on each square
- enum {
- PS_NONE = 0,
- PS_W_PAWN = 0,
- PS_B_PAWN = 1 * SQUARE_NB_CHESS,
- PS_W_KNIGHT = 2 * SQUARE_NB_CHESS,
- PS_B_KNIGHT = 3 * SQUARE_NB_CHESS,
- PS_W_BISHOP = 4 * SQUARE_NB_CHESS,
- PS_B_BISHOP = 5 * SQUARE_NB_CHESS,
- PS_W_ROOK = 6 * SQUARE_NB_CHESS,
- PS_B_ROOK = 7 * SQUARE_NB_CHESS,
- PS_W_QUEEN = 8 * SQUARE_NB_CHESS,
- PS_B_QUEEN = 9 * SQUARE_NB_CHESS,
- PS_KING = 10 * SQUARE_NB_CHESS,
- PS_NB = 11 * SQUARE_NB_CHESS
- };
-
- static constexpr uint32_t PieceSquareIndex[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_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_W_BISHOP, PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_NONE,
- PS_NONE, PS_NONE, PS_NONE, PS_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_NONE, PS_NONE, PS_NONE, PS_KING,
-
- 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_B_BISHOP, PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_NONE,
- PS_NONE, PS_NONE, PS_NONE, PS_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_NONE, PS_NONE, PS_NONE, PS_KING,
- },
-
- {
- 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_B_BISHOP, PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_NONE,
- PS_NONE, PS_NONE, PS_NONE, PS_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_NONE, PS_NONE, PS_NONE, PS_KING,
-
- 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_W_BISHOP, PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_NONE,
- PS_NONE, PS_NONE, PS_NONE, PS_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_NONE, PS_NONE, PS_NONE, PS_KING,
- }
- };
- // Check that the fragile array definition is correct
- static_assert(PieceSquareIndex[WHITE][make_piece(WHITE, PAWN)] == PS_W_PAWN);
- static_assert(PieceSquareIndex[WHITE][make_piece(WHITE, KING)] == PS_KING);
- static_assert(PieceSquareIndex[WHITE][make_piece(BLACK, PAWN)] == PS_B_PAWN);
- static_assert(PieceSquareIndex[WHITE][make_piece(BLACK, KING)] == PS_KING);
-
// Orient a square according to perspective (rotates by 180 for black)
static Square orient(Color perspective, Square s, const Position& pos);
static constexpr std::uint32_t HashValue = 0x5f234cb8u;
// Number of feature dimensions
- static constexpr IndexType Dimensions =
-#ifdef LARGEBOARDS
- HalfKAv2Shogi::Dimensions;
-#else
- HalfKAv2::Dimensions;
-#endif
+ static constexpr IndexType Dimensions = static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(SQUARE_NB) * 19;
static IndexType get_dimensions() {
- return currentNnueFeatures == NNUE_SHOGI ? HalfKAv2Shogi::Dimensions
- : currentNnueFeatures == NNUE_CHESS ? HalfKAv2::Dimensions
- : SQUARE_NB_CHESS * PS_NB;
+ return currentNnueVariant->nnueSquares * currentNnueVariant->nnuePieceIndices;
}
// Maximum number of simultaneously active features.
Square to[12];
};
-enum NnueFeatures {
- NNUE_CHESS,
- NNUE_SHOGI,
- NNUE_VARIANT,
-};
-
/// Score enum stores a middlegame and an endgame value in a single integer (enum).
/// The least significant 16 bits are used to store the middlegame value and the
/// upper 16 bits are used to store the endgame value. We have to take care to
// https://en.wikipedia.org/wiki/Chess
Variant* chess_variant() {
Variant* v = chess_variant_base();
- v->nnueFeatures = NNUE_CHESS;
return v;
}
// Chess960 aka Fischer random chess
v->promotionRank = RANK_7;
v->promotedPieceType[LANCE] = GOLD;
v->promotedPieceType[SHOGI_KNIGHT] = GOLD;
- v->nnueFeatures = NNUE_SHOGI;
return v;
}
// Sho-Shogi
#include <vector>
#include <string>
#include <functional>
+#include <sstream>
#include "types.h"
#include "bitboard.h"
MaterialCounting materialCounting = NO_MATERIAL_COUNTING;
CountingRule countingRule = NO_COUNTING;
- NnueFeatures nnueFeatures = NNUE_VARIANT;
-
// Derived properties
bool fastAttacks = true;
bool fastAttacks2 = true;
PieceType nnueKing = KING;
+ int nnueSquares;
+ int nnuePieceIndices;
+ int pieceSquareIndex[COLOR_NB][PIECE_NB];
+ int nnueMaxPieces;
bool endgameEval = false;
void add_piece(PieceType pt, char c, std::string betza = "", char c2 = ' ') {
})
&& !cambodianMoves
&& !diagonalLines;
+
+ // Initialize calculated NNUE properties
nnueKing = pieceTypes.find(KING) != pieceTypes.end() ? KING
: extinctionPieceTypes.find(COMMONER) != extinctionPieceTypes.end() ? COMMONER
: NO_PIECE_TYPE;
+ nnueSquares = (maxRank + 1) * (maxFile + 1);
+ nnuePieceIndices = (2 * pieceTypes.size() - 1) * nnueSquares;
+ int i = 0;
+ for (PieceType pt : pieceTypes)
+ {
+ for (Color c : { WHITE, BLACK})
+ {
+ pieceSquareIndex[c][make_piece(c, pt)] = 2 * i * nnueSquares;
+ pieceSquareIndex[c][make_piece(~c, pt)] = (2 * i + (pt != nnueKing)) * nnueSquares;
+ }
+ i++;
+ }
+ // Determine maximum piece count
+ std::istringstream ss(startFen);
+ ss >> std::noskipws;
+ unsigned char token;
+ nnueMaxPieces = 0;
+ while ((ss >> token) && !isspace(token))
+ {
+ if (pieceToChar.find(token) != std::string::npos || pieceToCharSynonyms.find(token) != std::string::npos)
+ nnueMaxPieces++;
+ }
+
// For endgame evaluation to be applicable, no special win rules must apply.
// Furthermore, rules significantly changing game mechanics also invalidate it.
endgameEval = std::none_of(pieceTypes.begin(), pieceTypes.end(), [this](PieceType pt) {