--- /dev/null
+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
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))
--- /dev/null
+# 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 <http://www.gnu.org/licenses/>.
+
+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
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;
};
// 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.
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
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
--//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"
// 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);
// Number of feature dimensions
static constexpr IndexType Dimensions =
- static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(PS_NB);
+ static_cast<IndexType>(SQUARE_NB_CHESS) * static_cast<IndexType>(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(
--- /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 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<IndexType> active
+ ) {
+ Square ksq = orient(perspective, pos.square<KING>(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<IndexType> removed,
- ValueListInserter<IndexType> added,
- const Position& pos
++ 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 (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<ALL_PIECES>() - 2;
++ int HalfKAv2Shogi::refresh_cost(const Position& pos) {
++ return pos.count<ALL_PIECES>();
+ }
+
- 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
--- /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 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<IndexType>(SQUARE_NB_SHOGI) * static_cast<IndexType>(SHOGI_PS_END);
++ static_cast<IndexType>(SQUARE_NB_SHOGI) * static_cast<IndexType>(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<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,
- const Position& pos);
++ 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, 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
--- /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 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<IndexType> 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<IndexType> removed,
+ ValueListInserter<IndexType> 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<ALL_PIECES>() - 2;
++ int HalfKAv2Variants::refresh_cost(const Position& pos) {
++ return pos.count<ALL_PIECES>();
+ }
+
- 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
--- /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 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<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,
+ 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
#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"
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 {
// 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:
// Read network parameters
bool read_parameters(std::istream& stream) {
+
for (std::size_t i = 0; i < HalfDimensions; ++i)
biases[i] = read_little_endian<BiasType>(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<WeightType>(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<PSQTWeightType>(stream);
return !stream.fail();
}
bool write_parameters(std::ostream& stream) const {
for (std::size_t i = 0; i < HalfDimensions; ++i)
write_little_endian<BiasType>(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<WeightType>(stream, weights[i]);
return !stream.fail();
}
&& (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<ALL_PIECES>(~us) != pos.count<PAWN>(~us)
+ && !pos.flip_enclosed_pieces()
&& (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
{
assert(eval - beta >= 0);
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)