From: Fabian Fichter Date: Fri, 16 Jul 2021 10:11:09 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=3b64b1af1bd17085f02e326b204f0184a8c6472a;p=fairystockfish.git Merge official-stockfish/master bench: 4850077 --- 3b64b1af1bd17085f02e326b204f0184a8c6472a diff --cc .github/workflows/fairy.yml index e260e9e,0000000..7751597 mode 100644,000000..100644 --- a/.github/workflows/fairy.yml +++ b/.github/workflows/fairy.yml @@@ -1,87 -1,0 +1,93 @@@ +name: fairy +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + fairy: + name: ${{ matrix.config.name }} + runs-on: ${{ matrix.config.os }} + env: + COMPILER: ${{ matrix.config.compiler }} + COMP: ${{ matrix.config.comp }} + CXXFLAGS: "-Werror" + strategy: + matrix: + config: + - { + name: "Ubuntu 20.04 GCC", + os: ubuntu-20.04, + compiler: g++, + comp: gcc, + run_expensive_tests: true + } + - { + name: "Ubuntu 20.04 Clang", + os: ubuntu-20.04, + compiler: clang++, + comp: clang, + run_expensive_tests: false + } + + defaults: + run: + working-directory: src + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Download required packages + run: | + sudo apt update + sudo apt install expect valgrind g++-multilib + + - name: Download the used network from the fishtest framework + run: | + make net + + - name: Test NNUE + run: | + make clean + make -j2 ARCH=x86-64 nnue=yes debug=yes build + ./stockfish bench + ++ - name: Test NNUE largeboards ++ run: | ++ make clean ++ make -j2 ARCH=x86-64 largeboards=yes nnue=yes debug=yes build ++ ./stockfish bench ++ + - name: Build all variants + run: | + make clean + make -j2 ARCH=x86-64 largeboards=yes all=yes debug=yes build + + - name: Test protocols + run: | + ../tests/protocol.sh + + - name: Test variants.ini + run: | + ! ./stockfish check variants.ini 2>&1 >/dev/null | grep -v "Parsing variant" + + - name: Test variant perft + run: | + ../tests/perft.sh all + + - name: Test variant bench + run: | + ./stockfish bench xiangqi + ./stockfish bench shogi + ./stockfish bench capablanca + ./stockfish bench sittuyin + + - name: Test 32bit largeboards + run: | + if [[ "$COMP" == "gcc" ]]; then export EXTRACXXFLAGS=-Wno-class-memaccess; fi + make clean + make -j2 ARCH=x86-32 largeboards=yes build + ../tests/perft.sh largeboard diff --cc src/Makefile index 8d3dc98,066e769..db4808f --- a/src/Makefile +++ b/src/Makefile @@@ -41,9 -41,7 +41,9 @@@ endi SRCS = benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp main.cpp \ material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \ search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \ - nnue/evaluate_nnue.cpp nnue/features/half_kp.cpp \ - nnue/evaluate_nnue.cpp nnue/features/half_ka_v2.cpp ++ nnue/evaluate_nnue.cpp nnue/features/half_ka_v2.cpp \ + partner.cpp parser.cpp piece.cpp variant.cpp xboard.cpp \ - nnue/features/half_kp_shogi.cpp nnue/features/half_kp_variants.cpp ++ nnue/features/half_ka_v2_shogi.cpp nnue/features/half_ka_v2_variants.cpp OBJS = $(notdir $(SRCS:.cpp=.o)) diff --cc src/Makefile_js index 3cf9f50,0000000..fdc4b15 mode 100644,000000..100644 --- a/src/Makefile_js +++ b/src/Makefile_js @@@ -1,89 -1,0 +1,89 @@@ +# ffish.js, a JavaScript chess variant library derived from Fairy-Stockfish +# Copyright (C) 2021 Fabian Fichter, Johannes Czech +# +# ffish.js 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. +# +# ffish.js 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 . + +EXE = ../tests/js/ffish.js + +SRCS = ffishjs.cpp benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp \ + material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \ + search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \ - nnue/evaluate_nnue.cpp nnue/features/half_kp.cpp \ ++ nnue/evaluate_nnue.cpp nnue/features/half_ka_v2.cpp \ + partner.cpp parser.cpp piece.cpp variant.cpp xboard.cpp \ - nnue/features/half_kp_shogi.cpp nnue/features/half_kp_variants.cpp ++ nnue/features/half_ka_v2_shogi.cpp nnue/features/half_ka_v2_variants.cpp + +CXX=emcc +CXXFLAGS += --bind -DNNUE_EMBEDDING_OFF -DNO_THREADS -std=c++17 -Wall + +largeboards = yes +optimize = yes +debug = no + +### Debugging +ifeq ($(debug),no) + CXXFLAGS += -DNDEBUG -s ASSERTIONS=0 -s SAFE_HEAP=0 +else + CXXFLAGS += -g -s ASSERTIONS=1 -s SAFE_HEAP=1 +endif + +### Optimization +ifeq ($(optimize),yes) + CXXFLAGS += -O3 +endif + +# Compile version with support for large board variants +# Use precomputed magics by default +ifneq ($(largeboards),no) + CXXFLAGS += -DLARGEBOARDS -DPRECOMPUTED_MAGICS -s TOTAL_MEMORY=32MB -s ALLOW_MEMORY_GROWTH=1 -s WASM_MEM_MAX=1GB +endif + +### Compile as ES6/ES2015 module +ifeq ($(es6),yes) + CXXFLAGS += -s ENVIRONMENT='web,worker' -s EXPORT_ES6=1 -s MODULARIZE=1 -s USE_ES6_IMPORT_META=0 +endif + +.PHONY: help objclean clean build deps test serve + +help: + @echo "" + @echo "To compile ffishjs, type: " + @echo "" + @echo "make -f Makefile_js build" + @echo "" + @echo "Supported targets:" + @echo "" + @echo "help > Display this help" + @echo "build > Standard build" + @echo "clean > Clean up" + @echo "deps > Install runtime dependencies using npm" + @echo "test > Run tests" + @echo "serve > Run example server" + @echo "" + +objclean: + @rm -f $(EXE) *.o ./syzygy/*.o ./nnue/*.o ./nnue/features/*.o + +clean: objclean + +build: + $(CXX) $(CXXFLAGS) $(SRCS) -o $(EXE) + +deps: + cd ../tests/js && npm install + +test: deps + cd ../tests/js && npm test + +serve: deps + cd ../tests/js && node index.js diff --cc src/evaluate.cpp index 7db474b,256bd99..f5a0e0e --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@@ -1613,13 -1124,6 +1611,13 @@@ Value Eval::evaluate(const Position& po if (pos.is_chess960()) nnue += fix_FRC(pos); + if (pos.check_counting()) + { + Color us = pos.side_to_move(); - nnue += material / (30 * pos.checks_remaining( us)) - - material / (30 * pos.checks_remaining(~us)); ++ nnue += 6 * scale / (5 * pos.checks_remaining( us)) ++ - 6 * scale / (5 * pos.checks_remaining(~us)); + } + return nnue; }; @@@ -1627,9 -1131,8 +1625,9 @@@ // a small probability of using the classical eval when PSQ imbalance is small. Value psq = Value(abs(eg_value(pos.psq_score()))); int r50 = 16 + pos.rule50_count(); - bool largePsq = psq * 16 > (NNUEThreshold1 + pos.non_pawn_material() / 64) * r50; + bool pure = !pos.check_counting(); + bool largePsq = psq * 16 > (NNUEThreshold1 + pos.non_pawn_material() / 64) * r50 && !pure; - bool classical = largePsq || (psq > PawnValueMg / 4 && !(pos.this_thread()->nodes & 0xB) && !pure); + bool classical = largePsq; // Use classical evaluation for really low piece endgames. // One critical case is the draw for bishop + A/H file pawn vs naked king. diff --cc src/nnue/features/half_ka_v2.cpp index 9481136,57f43e5..15cdf2b --- a/src/nnue/features/half_ka_v2.cpp +++ b/src/nnue/features/half_ka_v2.cpp @@@ -24,14 -24,9 +24,14 @@@ 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)); + } + // Orient a square according to perspective (rotates by 180 for black) - inline Square HalfKPChess::orient(Color perspective, Square s) { - return Square(int(to_chess_square(s)) ^ (bool(perspective) * 63)); + inline Square HalfKAv2::orient(Color perspective, Square s) { - return Square(int(s) ^ (bool(perspective) * 56)); ++ return Square(int(to_chess_square(s)) ^ (bool(perspective) * 56)); } // Index of a feature for a given king position and another piece on some square diff --cc src/nnue/features/half_ka_v2.h index 7bccd1e,e4b2edd..ddee206 --- a/src/nnue/features/half_ka_v2.h +++ b/src/nnue/features/half_ka_v2.h @@@ -16,10 -16,10 +16,10 @@@ along with this program. If not, see . */ --//Definition of input features HalfKP of NNUE evaluation function ++//Definition of input features HalfKAv2 of NNUE evaluation function - #ifndef NNUE_FEATURES_HALF_KP_H_INCLUDED - #define NNUE_FEATURES_HALF_KP_H_INCLUDED + #ifndef NNUE_FEATURES_HALF_KA_V2_H_INCLUDED + #define NNUE_FEATURES_HALF_KA_V2_H_INCLUDED #include "../nnue_common.h" @@@ -39,68 -39,28 +39,69 @@@ namespace Stockfish::Eval::NNUE::Featur // unique number for each piece type on each square enum { PS_NONE = 0, - PS_W_PAWN = 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_NB = 10 * SQUARE_NB_CHESS + 1, + PS_W_PAWN = 0, - PS_B_PAWN = 1 * SQUARE_NB, - PS_W_KNIGHT = 2 * SQUARE_NB, - PS_B_KNIGHT = 3 * SQUARE_NB, - PS_W_BISHOP = 4 * SQUARE_NB, - PS_B_BISHOP = 5 * SQUARE_NB, - PS_W_ROOK = 6 * SQUARE_NB, - PS_B_ROOK = 7 * SQUARE_NB, - PS_W_QUEEN = 8 * SQUARE_NB, - PS_B_QUEEN = 9 * SQUARE_NB, - PS_KING = 10 * SQUARE_NB, - PS_NB = 11 * SQUARE_NB ++ 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 IndexType PieceSquareIndex[COLOR_NB][PIECE_NB] = { + 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_KING, PS_NONE, - PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE }, - { PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE, - PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_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_W_BISHOP, PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_NONE, ++ PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_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_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, ++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, ++ PS_NONE, PS_NONE, PS_NONE, PS_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_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, ++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, ++ PS_NONE, PS_NONE, PS_NONE, PS_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_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, ++ PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, ++ PS_NONE, PS_NONE, PS_NONE, PS_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_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_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_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_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_NONE); ++ 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_NONE); ++ 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); @@@ -117,10 -77,10 +118,10 @@@ // Number of feature dimensions static constexpr IndexType Dimensions = - static_cast(SQUARE_NB) * static_cast(PS_NB); + static_cast(SQUARE_NB_CHESS) * static_cast(PS_NB); - // Maximum number of simultaneously active features. 30 because kins are not included. - static constexpr IndexType MaxActiveDimensions = 30; + // Maximum number of simultaneously active features. + static constexpr IndexType MaxActiveDimensions = 32; // Get a list of indices for active features static void append_active_indices( diff --cc src/nnue/features/half_ka_v2_shogi.cpp index 0d7e2fa,0000000..6c58d87 mode 100644,000000..100644 --- a/src/nnue/features/half_ka_v2_shogi.cpp +++ b/src/nnue/features/half_ka_v2_shogi.cpp @@@ -1,116 -1,0 +1,115 @@@ +/* + 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 . +*/ + - //Definition of input features HalfKP of NNUE evaluation function ++//Definition of input features HalfKAv2 of NNUE evaluation function + - #include "half_kp_shogi.h" ++#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 HalfKPShogi::orient(Color perspective, Square s) { ++ 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 HalfKPShogi::make_index(Color perspective, Square s, Piece pc, Square ksq) { - return IndexType(orient(perspective, s) + PieceSquareIndexShogi[perspective][pc] + SHOGI_PS_END * ksq); ++ 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 HalfKPShogi::make_index(Color perspective, Color c, int hand_index, PieceType pt, Square ksq) { ++ 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_END * ksq); ++ return IndexType(hand_index + PieceSquareIndexShogiHand[color][pt] + SHOGI_PS_NB * ksq); + } + + // Get a list of indices for active features - void HalfKPShogi::append_active_indices( ++ void HalfKAv2Shogi::append_active_indices( + const Position& pos, + Color perspective, + ValueListInserter active + ) { + Square ksq = orient(perspective, pos.square(perspective)); - Bitboard bb = pos.pieces() & ~pos.pieces(KING); - while (bb) { ++ 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 HalfKPShogi::append_changed_indices( ++ void HalfKAv2Shogi::append_changed_indices( + Square ksq, + StateInfo* st, + Color perspective, + ValueListInserter removed, - ValueListInserter added, - const Position& pos ++ ValueListInserter 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 (type_of(pc) == pos.nnue_king()) continue; + 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 HalfKPShogi::update_cost(StateInfo* st) { ++ int HalfKAv2Shogi::update_cost(StateInfo* st) { + return st->dirtyPiece.dirty_num; + } + - int HalfKPShogi::refresh_cost(const Position& pos) { - return pos.count() - 2; ++ int HalfKAv2Shogi::refresh_cost(const Position& pos) { ++ return pos.count(); + } + - bool HalfKPShogi::requires_refresh(StateInfo* st, Color perspective, const Position& pos) { - return st->dirtyPiece.piece[0] == make_piece(perspective, pos.nnue_king()); ++ bool HalfKAv2Shogi::requires_refresh(StateInfo* st, Color perspective) { ++ return st->dirtyPiece.piece[0] == make_piece(perspective, KING); + } + + +} // namespace Stockfish::Eval::NNUE::Features diff --cc src/nnue/features/half_ka_v2_shogi.h index f6033b0,0000000..17f4c59 mode 100644,000000..100644 --- a/src/nnue/features/half_ka_v2_shogi.h +++ b/src/nnue/features/half_ka_v2_shogi.h @@@ -1,209 -1,0 +1,207 @@@ +/* + 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 . +*/ + - //Definition of input features HalfKP of NNUE evaluation function ++//Definition of input features HalfKAv2 of NNUE evaluation function + - #ifndef NNUE_FEATURES_HALF_KP_SHOGI_H_INCLUDED - #define NNUE_FEATURES_HALF_KP_SHOGI_H_INCLUDED ++#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 HalfKP: Combination of the position of own king - // and the position of pieces other than kings - class HalfKPShogi { ++ // 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 = 1, - SHOGI_HAND_B_PAWN = 20, - SHOGI_HAND_W_LANCE = 39, - SHOGI_HAND_B_LANCE = 44, - SHOGI_HAND_W_KNIGHT = 49, - SHOGI_HAND_B_KNIGHT = 54, - SHOGI_HAND_W_SILVER = 59, - SHOGI_HAND_B_SILVER = 64, - SHOGI_HAND_W_GOLD = 69, - SHOGI_HAND_B_GOLD = 74, - SHOGI_HAND_W_BISHOP = 79, - SHOGI_HAND_B_BISHOP = 82, - SHOGI_HAND_W_ROOK = 85, - SHOGI_HAND_B_ROOK = 88, - SHOGI_HAND_END = 90, ++ 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_W_KING = 18 * SQUARE_NB_SHOGI + SHOGI_HAND_END, - SHOGI_PS_END = SHOGI_PS_W_KING, // pieces without kings (pawns included) - SHOGI_PS_B_KING = 19 * SQUARE_NB_SHOGI + SHOGI_HAND_END, - SHOGI_PS_END2 = 20 * 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_W_KING, ++ 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_B_KING ++ 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_B_KING, ++ 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_W_KING ++ 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_W_KING); ++ 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_B_KING); ++ 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 = "HalfKP(Friend)"; ++ static constexpr const char* Name = "HalfKAv2(Friend)"; + + // Hash value embedded in the evaluation file - static constexpr std::uint32_t HashValue = 0x5D69D5B8u; ++ static constexpr std::uint32_t HashValue = 0x5f234cb8u; + + // Number of feature dimensions + static constexpr IndexType Dimensions = - static_cast(SQUARE_NB_SHOGI) * static_cast(SHOGI_PS_END); ++ static_cast(SQUARE_NB_SHOGI) * static_cast(SHOGI_PS_NB); + - // Maximum number of simultaneously active features. 38 because kins are not included. - static constexpr IndexType MaxActiveDimensions = 38; ++ // 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 active); + + // Get a list of indices for recently changed features + static void append_changed_indices( + Square ksq, + StateInfo* st, + Color perspective, + ValueListInserter removed, - ValueListInserter added, - const Position& pos); ++ ValueListInserter 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, const Position& pos); ++ static bool requires_refresh(StateInfo* st, Color perspective); + }; + +} // namespace Stockfish::Eval::NNUE::Features + - #endif // #ifndef NNUE_FEATURES_HALF_KP_SHOGI_H_INCLUDED ++#endif // #ifndef NNUE_FEATURES_HALF_KA_V2_SHOGI_H_INCLUDED diff --cc src/nnue/features/half_ka_v2_variants.cpp index d93107f,0000000..fc07923 mode 100644,000000..100644 --- a/src/nnue/features/half_ka_v2_variants.cpp +++ b/src/nnue/features/half_ka_v2_variants.cpp @@@ -1,112 -1,0 +1,112 @@@ +/* + 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 . +*/ + - //Definition of input features HalfKP of NNUE evaluation function ++//Definition of input features HalfKAv2 of NNUE evaluation function + - #include "half_kp_variants.h" ++#include "half_ka_v2_variants.h" + +#ifdef LARGEBOARDS - #include "half_kp_shogi.h" ++#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)); + } + + // Orient a square according to perspective (rotates by 180 for black) - inline Square HalfKPVariants::orient(Color perspective, Square s, const Position& pos) { ++ 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(flip_file(s, pos.max_file()), pos.max_rank())); ++ : flip_rank(s, pos.max_rank())); + } + + // Index of a feature for a given king position and another piece on some square - inline IndexType HalfKPVariants::make_index(Color perspective, Square s, Piece pc, Square ksq, const Position& pos) { ++ 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); + } + + // Get a list of indices for active features - void HalfKPVariants::append_active_indices( ++ void HalfKAv2Variants::append_active_indices( + const Position& pos, + Color perspective, + ValueListInserter active + ) { + // Re-route to shogi features +#ifdef LARGEBOARDS + if (currentNnueFeatures == NNUE_SHOGI) + { - assert(HalfKPShogi::Dimensions <= Dimensions); - return HalfKPShogi::append_active_indices(pos, perspective, active); ++ 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() & ~pos.pieces(pos.nnue_king()); - while (bb) { ++ Bitboard bb = pos.pieces(); ++ while (bb) ++ { + Square s = pop_lsb(bb); + active.push_back(make_index(perspective, s, pos.piece_on(s), oriented_ksq, pos)); + } + } + + // append_changed_indices() : get a list of indices for recently changed features + - void HalfKPVariants::append_changed_indices( ++ void HalfKAv2Variants::append_changed_indices( + Square ksq, + StateInfo* st, + Color perspective, + ValueListInserter removed, + ValueListInserter added, + const Position& pos + ) { + // Re-route to shogi features +#ifdef LARGEBOARDS + if (currentNnueFeatures == NNUE_SHOGI) + { - assert(HalfKPShogi::Dimensions <= Dimensions); - return HalfKPShogi::append_changed_indices(ksq, st, perspective, removed, added, pos); ++ 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) { + Piece pc = dp.piece[i]; - if (type_of(pc) == pos.nnue_king()) continue; + if (dp.from[i] != SQ_NONE) + removed.push_back(make_index(perspective, dp.from[i], pc, oriented_ksq, pos)); + if (dp.to[i] != SQ_NONE) + added.push_back(make_index(perspective, dp.to[i], pc, oriented_ksq, pos)); + } + } + - int HalfKPVariants::update_cost(StateInfo* st) { ++ int HalfKAv2Variants::update_cost(StateInfo* st) { + return st->dirtyPiece.dirty_num; + } + - int HalfKPVariants::refresh_cost(const Position& pos) { - return pos.count() - 2; ++ int HalfKAv2Variants::refresh_cost(const Position& pos) { ++ return pos.count(); + } + - bool HalfKPVariants::requires_refresh(StateInfo* st, Color perspective, const Position& pos) { ++ bool HalfKAv2Variants::requires_refresh(StateInfo* st, Color perspective, const Position& pos) { + return st->dirtyPiece.piece[0] == make_piece(perspective, pos.nnue_king()); + } + +} // namespace Stockfish::Eval::NNUE::Features diff --cc src/nnue/features/half_ka_v2_variants.h index f095737,0000000..118e2db mode 100644,000000..100644 --- a/src/nnue/features/half_ka_v2_variants.h +++ b/src/nnue/features/half_ka_v2_variants.h @@@ -1,164 -1,0 +1,165 @@@ +/* + 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 . +*/ + - //Definition of input features HalfKP of NNUE evaluation function ++//Definition of input features HalfKAv2 of NNUE evaluation function + - #ifndef NNUE_FEATURES_HALF_KP_VARIANTS_H_INCLUDED - #define NNUE_FEATURES_HALF_KP_VARIANTS_H_INCLUDED ++#ifndef NNUE_FEATURES_HALF_KA_V2_VARIANTS_H_INCLUDED ++#define NNUE_FEATURES_HALF_KA_V2_VARIANTS_H_INCLUDED + +#include "../nnue_common.h" + +#include "../../evaluate.h" +#include "../../misc.h" + - #include "half_kp_shogi.h" - #include "half_kp.h" ++#include "half_ka_v2_shogi.h" ++#include "half_ka_v2.h" + +namespace Stockfish { + struct StateInfo; +} + +namespace Stockfish::Eval::NNUE::Features { + - // Feature HalfKP: Combination of the position of own king - // and the position of pieces other than kings - class HalfKPVariants { ++ // Feature HalfKAv2: Combination of the position of own king ++ // and the position of pieces ++ class HalfKAv2Variants { + + // unique number for each piece type on each square + enum { + PS_NONE = 0, - PS_W_PAWN = 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_NB = 10 * SQUARE_NB_CHESS + 1, ++ 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_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, - PS_NONE, PS_NONE, PS_NONE, PS_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_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, - PS_NONE, PS_NONE, PS_NONE, PS_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_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, - PS_NONE, PS_NONE, PS_NONE, PS_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_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, + PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, - PS_NONE, PS_NONE, PS_NONE, PS_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_NONE); ++ 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_NONE); ++ 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); + + // 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, const Position& pos); + + public: + // Feature name - static constexpr const char* Name = "HalfKP(Friend)"; ++ static constexpr const char* Name = "HalfKAv2(Friend)"; + + // Hash value embedded in the evaluation file - static constexpr std::uint32_t HashValue = 0x5D69D5B8u; ++ static constexpr std::uint32_t HashValue = 0x5f234cb8u; + + // Number of feature dimensions + static constexpr IndexType Dimensions = +#ifdef LARGEBOARDS - HalfKPShogi::Dimensions; ++ HalfKAv2Shogi::Dimensions; +#else - HalfKPChess::Dimensions; ++ HalfKAv2::Dimensions; +#endif + + static IndexType get_dimensions() { - return currentNnueFeatures == NNUE_SHOGI ? HalfKPShogi::Dimensions - : currentNnueFeatures == NNUE_CHESS ? HalfKPChess::Dimensions ++ return currentNnueFeatures == NNUE_SHOGI ? HalfKAv2Shogi::Dimensions ++ : currentNnueFeatures == NNUE_CHESS ? HalfKAv2::Dimensions + : SQUARE_NB_CHESS * PS_NB; + } + - // Maximum number of simultaneously active features. 30 because kins are not included. ++ // Maximum number of simultaneously active features. + static constexpr IndexType MaxActiveDimensions = 64; + + // Get a list of indices for active features + static void append_active_indices( + const Position& pos, + Color perspective, + ValueListInserter active); + + // Get a list of indices for recently changed features + static void append_changed_indices( + Square ksq, + StateInfo* st, + Color perspective, + ValueListInserter removed, + ValueListInserter added, + const Position& pos); + + // 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, const Position& pos); + }; + +} // namespace Stockfish::Eval::NNUE::Features + - #endif // #ifndef NNUE_FEATURES_HALF_KP_VARIANTS_H_INCLUDED ++#endif // #ifndef NNUE_FEATURES_HALF_KA_V2_VARIANTS_H_INCLUDED diff --cc src/nnue/nnue_architecture.h index 3dd6fe2,879a39c..0079969 --- a/src/nnue/nnue_architecture.h +++ b/src/nnue/nnue_architecture.h @@@ -23,8 -23,7 +23,7 @@@ #include "nnue_common.h" - //#include "features/half_kp.h" - #include "features/half_kp_variants.h" -#include "features/half_ka_v2.h" ++#include "features/half_ka_v2_variants.h" #include "layers/input_slice.h" #include "layers/affine_transform.h" @@@ -33,11 -32,12 +32,12 @@@ namespace Stockfish::Eval::NNUE { // Input features used in evaluation function - //using FeatureSet = Features::HalfKPChess; - using FeatureSet = Features::HalfKPVariants; - using FeatureSet = Features::HalfKAv2; ++ using FeatureSet = Features::HalfKAv2Variants; // Number of input feature dimensions after conversion - constexpr IndexType TransformedFeatureDimensions = 256; + constexpr IndexType TransformedFeatureDimensions = 512; + constexpr IndexType PSQTBuckets = 8; + constexpr IndexType LayerStacks = 8; namespace Layers { diff --cc src/nnue/nnue_feature_transformer.h index 53def48,2c0a0c6..5efccbb --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@@ -87,9 -124,13 +124,13 @@@ namespace Stockfish::Eval::NNUE // Number of output dimensions for one side static constexpr IndexType HalfDimensions = TransformedFeatureDimensions; - static constexpr int LazyThreshold = 1400; ++ static constexpr int LazyThreshold = 14000; // low lazy threshold is detrimental for variants + #ifdef VECTOR static constexpr IndexType TileHeight = NumRegs * sizeof(vec_t) / 2; + static constexpr IndexType PsqtTileHeight = NumPsqtRegs * sizeof(psqt_vec_t) / 4; static_assert(HalfDimensions % TileHeight == 0, "TileHeight must divide HalfDimensions"); + static_assert(PSQTBuckets % PsqtTileHeight == 0, "PsqtTileHeight must divide PSQTBuckets"); #endif public: @@@ -111,11 -152,12 +152,13 @@@ // Read network parameters bool read_parameters(std::istream& stream) { + for (std::size_t i = 0; i < HalfDimensions; ++i) biases[i] = read_little_endian(stream); - for (std::size_t i = 0; i < HalfDimensions * InputDimensions; ++i) + for (std::size_t i = 0; i < HalfDimensions * FeatureSet::get_dimensions(); ++i) weights[i] = read_little_endian(stream); - for (std::size_t i = 0; i < PSQTBuckets * InputDimensions; ++i) ++ for (std::size_t i = 0; i < PSQTBuckets * FeatureSet::get_dimensions(); ++i) + psqtWeights[i] = read_little_endian(stream); return !stream.fail(); } @@@ -123,7 -165,7 +166,7 @@@ bool write_parameters(std::ostream& stream) const { for (std::size_t i = 0; i < HalfDimensions; ++i) write_little_endian(stream, biases[i]); -- for (std::size_t i = 0; i < HalfDimensions * InputDimensions; ++i) ++ for (std::size_t i = 0; i < HalfDimensions * FeatureSet::get_dimensions(); ++i) write_little_endian(stream, weights[i]); return !stream.fail(); } diff --cc src/search.cpp index 04fcdeb,ac026a7..c15a5a7 --- a/src/search.cpp +++ b/src/search.cpp @@@ -937,11 -801,9 +937,11 @@@ namespace && (ss-1)->statScore < 24185 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 24 * depth - 34 * improving + 162 * ss->ttPv + 159 + 200 * (!pos.double_step_enabled() && pos.piece_to_char()[PAWN] != ' ') - && ss->staticEval >= beta - 22 * depth - 34 * improving + 162 * ss->ttPv + 159 ++ && ss->staticEval >= beta - 22 * depth - 34 * improving + 162 * ss->ttPv + 159 + 200 * (!pos.double_step_enabled() && pos.piece_to_char()[PAWN] != ' ') && !excludedMove && pos.non_pawn_material(us) + && pos.count(~us) != pos.count(~us) + && !pos.flip_enclosed_pieces() && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor)) { assert(eval - beta >= 0); @@@ -1317,10 -1169,10 +1317,10 @@@ moves_loop: // When in check, search st r += 2; ss->statScore = thisThread->mainHistory[us][from_to(move)] - + (*contHist[0])[movedPiece][to_sq(move)] - + (*contHist[1])[movedPiece][to_sq(move)] - + (*contHist[3])[movedPiece][to_sq(move)] + + (*contHist[0])[history_slot(movedPiece)][to_sq(move)] + + (*contHist[1])[history_slot(movedPiece)][to_sq(move)] + + (*contHist[3])[history_slot(movedPiece)][to_sq(move)] - - 4741; + - 4791; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) if (!ss->inCheck)