diff --git a/src/nnue/features/castling_right.cpp b/src/nnue/features/castling_right.cpp index 2b3f3209..eb8a36a1 100644 --- a/src/nnue/features/castling_right.cpp +++ b/src/nnue/features/castling_right.cpp @@ -1,60 +1,60 @@ -//Definition of input feature quantity CastlingRight of NNUE evaluation function - #include "castling_right.h" #include "index_list.h" +//Definition of input feature quantity CastlingRight of NNUE evaluation function namespace Eval::NNUE::Features { - // Get a list of indices with a value of 1 among the features - void CastlingRight::AppendActiveIndices( - const Position& pos, Color perspective, IndexList* active) { - // do nothing if array size is small to avoid compiler warning - if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return; + // Get a list of indices with a value of 1 among the features + void CastlingRight::AppendActiveIndices( + const Position& pos, Color perspective, IndexList* active) { + // do nothing if array size is small to avoid compiler warning + if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return; - int castling_rights = pos.state()->castlingRights; - int relative_castling_rights; - if (perspective == WHITE) { - relative_castling_rights = castling_rights; - } - else { - // Invert the perspective. - relative_castling_rights = ((castling_rights & 3) << 2) - & ((castling_rights >> 2) & 3); + int castling_rights = pos.state()->castlingRights; + int relative_castling_rights; + if (perspective == WHITE) { + relative_castling_rights = castling_rights; + } + else { + // Invert the perspective. + relative_castling_rights = ((castling_rights & 3) << 2) + & ((castling_rights >> 2) & 3); + } + + for (Eval::NNUE::IndexType i = 0; i < kDimensions; ++i) { + if (relative_castling_rights & (1 << i)) { + active->push_back(i); + } + } } - for (Eval::NNUE::IndexType i = 0; i < kDimensions; ++i) { - if (relative_castling_rights & (1 << i)) { - active->push_back(i); - } - } - } + // Get a list of indices whose values ​​have changed from the previous one in the feature quantity + void CastlingRight::AppendChangedIndices( + const Position& pos, Color perspective, + IndexList* removed, IndexList* /* added */) { - // Get a list of indices whose values ​​have changed from the previous one in the feature quantity - void CastlingRight::AppendChangedIndices( - const Position& pos, Color perspective, - IndexList* removed, IndexList* /* added */) { - int previous_castling_rights = pos.state()->previous->castlingRights; - int current_castling_rights = pos.state()->castlingRights; - int relative_previous_castling_rights; - int relative_current_castling_rights; - if (perspective == WHITE) { - relative_previous_castling_rights = previous_castling_rights; - relative_current_castling_rights = current_castling_rights; - } - else { - // Invert the perspective. - relative_previous_castling_rights = ((previous_castling_rights & 3) << 2) - & ((previous_castling_rights >> 2) & 3); - relative_current_castling_rights = ((current_castling_rights & 3) << 2) - & ((current_castling_rights >> 2) & 3); - } + int previous_castling_rights = pos.state()->previous->castlingRights; + int current_castling_rights = pos.state()->castlingRights; + int relative_previous_castling_rights; + int relative_current_castling_rights; + if (perspective == WHITE) { + relative_previous_castling_rights = previous_castling_rights; + relative_current_castling_rights = current_castling_rights; + } + else { + // Invert the perspective. + relative_previous_castling_rights = ((previous_castling_rights & 3) << 2) + & ((previous_castling_rights >> 2) & 3); + relative_current_castling_rights = ((current_castling_rights & 3) << 2) + & ((current_castling_rights >> 2) & 3); + } - for (Eval::NNUE::IndexType i = 0; i < kDimensions; ++i) { - if ((relative_previous_castling_rights & (1 << i)) && - (relative_current_castling_rights & (1 << i)) == 0) { - removed->push_back(i); - } + for (Eval::NNUE::IndexType i = 0; i < kDimensions; ++i) { + if ((relative_previous_castling_rights & (1 << i)) && + (relative_current_castling_rights & (1 << i)) == 0) { + removed->push_back(i); + } + } } - } } // namespace Eval::NNUE::Features diff --git a/src/nnue/features/castling_right.h b/src/nnue/features/castling_right.h index 2d8c5322..3e35e432 100644 --- a/src/nnue/features/castling_right.h +++ b/src/nnue/features/castling_right.h @@ -1,34 +1,38 @@ -//Definition of input feature quantity CastlingRight of NNUE evaluation function - #ifndef _NNUE_FEATURES_CASTLING_RIGHT_H_ #define _NNUE_FEATURES_CASTLING_RIGHT_H_ -#include "../../evaluate.h" #include "features_common.h" +#include "evaluate.h" + +//Definition of input feature quantity CastlingRight of NNUE evaluation function namespace Eval::NNUE::Features { - class CastlingRight { - public: - // feature quantity name - static constexpr const char* kName = "CastlingRight"; - // Hash value embedded in the evaluation function file - static constexpr std::uint32_t kHashValue = 0x913968AAu; - // number of feature dimensions - static constexpr IndexType kDimensions = 4; - // The maximum value of the number of indexes whose value is 1 at the same time among the feature values - static constexpr IndexType kMaxActiveDimensions = 4; - // Timing of full calculation instead of difference calculation - static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; + class CastlingRight { + public: + // feature quantity name + static constexpr const char* kName = "CastlingRight"; - // Get a list of indices with a value of 1 among the features - static void AppendActiveIndices(const Position& pos, Color perspective, - IndexList* active); + // Hash value embedded in the evaluation function file + static constexpr std::uint32_t kHashValue = 0x913968AAu; - // Get a list of indices whose values ​​have changed from the previous one in the feature quantity - static void AppendChangedIndices(const Position& pos, Color perspective, - IndexList* removed, IndexList* added); - }; + // number of feature dimensions + static constexpr IndexType kDimensions = 4; + + // The maximum value of the number of indexes whose value is 1 at the same time among the feature values + static constexpr IndexType kMaxActiveDimensions = 4; + + // Timing of full calculation instead of difference calculation + static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; + + // Get a list of indices with a value of 1 among the features + static void AppendActiveIndices(const Position& pos, Color perspective, + IndexList* active); + + // Get a list of indices whose values ​​have changed from the previous one in the feature quantity + static void AppendChangedIndices(const Position& pos, Color perspective, + IndexList* removed, IndexList* added); + }; } // namespace Eval::NNUE::Features diff --git a/src/nnue/features/enpassant.cpp b/src/nnue/features/enpassant.cpp index e5ceed5c..7aa8988b 100644 --- a/src/nnue/features/enpassant.cpp +++ b/src/nnue/features/enpassant.cpp @@ -1,42 +1,45 @@ -//Definition of input feature quantity EnPassant of NNUE evaluation function - #include "enpassant.h" #include "index_list.h" +//Definition of input feature quantity EnPassant of NNUE evaluation function namespace Eval::NNUE::Features { - // Get a list of indices with a value of 1 among the features - void EnPassant::AppendActiveIndices( - const Position& pos, Color /* perspective */, IndexList* active) { - // do nothing if array size is small to avoid compiler warning - if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return; + // Get a list of indices with a value of 1 among the features + void EnPassant::AppendActiveIndices( + const Position& pos, Color /* perspective */, IndexList* active) { - auto epSquare = pos.state()->epSquare; - if (epSquare == SQ_NONE) { - return; + // do nothing if array size is small to avoid compiler warning + if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) + return; + + auto epSquare = pos.state()->epSquare; + if (epSquare == SQ_NONE) + return; + + auto file = file_of(epSquare); + active->push_back(file); } - auto file = file_of(epSquare); - active->push_back(file); - } - // Get a list of indices whose values ​​have changed from the previous one in the feature quantity - void EnPassant::AppendChangedIndices( - const Position& pos, Color /* perspective */, - IndexList* removed, IndexList* added) { + // Get a list of indices whose values ​​have changed from the previous one in the feature quantity + void EnPassant::AppendChangedIndices( + const Position& pos, Color /* perspective */, + IndexList* removed, IndexList* added) { - auto previous_epSquare = pos.state()->previous->epSquare; - auto epSquare = pos.state()->epSquare; + auto previous_epSquare = pos.state()->previous->epSquare; + auto epSquare = pos.state()->epSquare; - if (previous_epSquare != SQ_NONE) { - if (epSquare != SQ_NONE && file_of(epSquare) == file_of(previous_epSquare)) - return; - auto file = file_of(previous_epSquare); - removed->push_back(file); + if (previous_epSquare != SQ_NONE) { + if (epSquare != SQ_NONE && file_of(epSquare) == file_of(previous_epSquare)) + return; + + auto file = file_of(previous_epSquare); + removed->push_back(file); + } + + if (epSquare != SQ_NONE) { + auto file = file_of(epSquare); + added->push_back(file); + } } - if (epSquare != SQ_NONE) { - auto file = file_of(epSquare); - added->push_back(file); - } - } } // namespace Eval::NNUE::Features diff --git a/src/nnue/features/enpassant.h b/src/nnue/features/enpassant.h index 065e74a0..65819a96 100644 --- a/src/nnue/features/enpassant.h +++ b/src/nnue/features/enpassant.h @@ -1,34 +1,34 @@ -//Definition of input feature quantity EnPassant of NNUE evaluation function - #ifndef _NNUE_FEATURES_ENPASSANT_H_ #define _NNUE_FEATURES_ENPASSANT_H_ -#include "../../evaluate.h" #include "features_common.h" +#include "evaluate.h" + +//Definition of input feature quantity EnPassant of NNUE evaluation function namespace Eval::NNUE::Features { - class EnPassant { - public: - // feature quantity name - static constexpr const char* kName = "EnPassant"; - // Hash value embedded in the evaluation function file - static constexpr std::uint32_t kHashValue = 0x02924F91u; - // number of feature dimensions - static constexpr IndexType kDimensions = 8; - // The maximum value of the number of indexes whose value is 1 at the same time among the feature values - static constexpr IndexType kMaxActiveDimensions = 1; - // Timing of full calculation instead of difference calculation - static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; + class EnPassant { + public: + // feature quantity name + static constexpr const char* kName = "EnPassant"; + // Hash value embedded in the evaluation function file + static constexpr std::uint32_t kHashValue = 0x02924F91u; + // number of feature dimensions + static constexpr IndexType kDimensions = 8; + // The maximum value of the number of indexes whose value is 1 at the same time among the feature values + static constexpr IndexType kMaxActiveDimensions = 1; + // Timing of full calculation instead of difference calculation + static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; - // Get a list of indices with a value of 1 among the features - static void AppendActiveIndices(const Position& pos, Color perspective, - IndexList* active); + // Get a list of indices with a value of 1 among the features + static void AppendActiveIndices(const Position& pos, Color perspective, + IndexList* active); - // Get a list of indices whose values have changed from the previous one in the feature quantity - static void AppendChangedIndices(const Position& pos, Color perspective, - IndexList* removed, IndexList* added); - }; + // Get a list of indices whose values have changed from the previous one in the feature quantity + static void AppendChangedIndices(const Position& pos, Color perspective, + IndexList* removed, IndexList* added); + }; } // namespace Eval::NNUE::Features diff --git a/src/nnue/features/feature_set.h b/src/nnue/features/feature_set.h index a057142c..5b243424 100644 --- a/src/nnue/features/feature_set.h +++ b/src/nnue/features/feature_set.h @@ -1,19 +1,19 @@ /* - Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file) + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2020 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 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. + 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 . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ // A class template that represents the input feature set of the NNUE evaluation function @@ -22,238 +22,266 @@ #define NNUE_FEATURE_SET_H_INCLUDED #include "features_common.h" + #include namespace Eval::NNUE::Features { - // Class template that represents a list of values - template - struct CompileTimeList; + // Class template that represents a list of values + template + struct CompileTimeList; - template - struct CompileTimeList { - static constexpr bool Contains(T value) { - return value == First || CompileTimeList::Contains(value); - } - static constexpr std::array - kValues = {{First, Remaining...}}; - }; - - template - constexpr std::array - CompileTimeList::kValues; - template - struct CompileTimeList { - static constexpr bool Contains(T /*value*/) { - return false; - } - static constexpr std::array kValues = { {} }; - }; - - // Class template that adds to the beginning of the list - template - struct AppendToList; - template - struct AppendToList, AnotherValue> { - using Result = CompileTimeList; - }; - - // Class template for adding to a sorted, unique list - template - struct InsertToSet; - template - struct InsertToSet, AnotherValue> { - using Result = std::conditional_t< - CompileTimeList::Contains(AnotherValue), - CompileTimeList, - std::conditional_t<(AnotherValue < First), - CompileTimeList, - typename AppendToList, AnotherValue>::Result, - First>::Result>>; - }; - template - struct InsertToSet, Value> { - using Result = CompileTimeList; - }; - - // Base class of feature set - template - class FeatureSetBase { - - public: - // Get a list of indices for active features - template - static void AppendActiveIndices( - const Position& pos, TriggerEvent trigger, IndexListType active[2]) { - - for (Color perspective : { WHITE, BLACK }) { - Derived::CollectActiveIndices( - pos, trigger, perspective, &active[perspective]); - } - } - - // Get a list of indices for recently changed features - template - static void AppendChangedIndices( - const PositionType& pos, TriggerEvent trigger, - IndexListType removed[2], IndexListType added[2], bool reset[2]) { - - const auto& dp = pos.state()->dirtyPiece; - - for (Color perspective : { WHITE, BLACK }) { - switch (trigger) { - case TriggerEvent::kNone: - break; - case TriggerEvent::kFriendKingMoved: - if (dp.dirty_num == 0) continue; - reset[perspective] = dp.piece[0] == make_piece(perspective, KING); - break; - case TriggerEvent::kEnemyKingMoved: - if (dp.dirty_num == 0) continue; - reset[perspective] = dp.piece[0] == make_piece(~perspective, KING); - break; - case TriggerEvent::kAnyKingMoved: - if (dp.dirty_num == 0) continue; - reset[perspective] = type_of(dp.piece[0]) == KING; - break; - case TriggerEvent::kAnyPieceMoved: - reset[perspective] = true; - break; - default: - assert(false); - break; + template + struct CompileTimeList { + static constexpr bool Contains(T value) { + return value == First || CompileTimeList::Contains(value); } - if (reset[perspective]) { - Derived::CollectActiveIndices( - pos, trigger, perspective, &added[perspective]); - } else { - Derived::CollectChangedIndices( - pos, trigger, perspective, - &removed[perspective], &added[perspective]); + + static constexpr std::array + kValues = {{First, Remaining...}}; + }; + + template + constexpr std::array + CompileTimeList::kValues; + + template + struct CompileTimeList { + static constexpr bool Contains(T /*value*/) { + return false; } - } - } - }; + static constexpr std::array kValues = { {} }; + }; - // Class template that represents the feature set - // do internal processing in reverse order of template arguments in order to linearize the amount of calculation at runtime - template - class FeatureSet : - public FeatureSetBase< - FeatureSet> { - private: - using Head = FirstFeatureType; - using Tail = FeatureSet; + // Class template that adds to the beginning of the list + template + struct AppendToList; - public: - // Hash value embedded in the evaluation function file - static constexpr std::uint32_t kHashValue = - Head::kHashValue ^ (Tail::kHashValue << 1) ^ (Tail::kHashValue >> 31); - // number of feature dimensions - static constexpr IndexType kDimensions = - Head::kDimensions + Tail::kDimensions; - // The maximum value of the number of indexes whose value is 1 at the same time among the feature values - static constexpr IndexType kMaxActiveDimensions = - Head::kMaxActiveDimensions + Tail::kMaxActiveDimensions; - // List of timings to perform all calculations instead of difference calculation - using SortedTriggerSet = typename InsertToSet::Result; - static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues; + template + struct AppendToList, AnotherValue> { + using Result = CompileTimeList; + }; - // Get the feature quantity name - static std::string GetName() { - return std::string(Head::kName) + "+" + Tail::GetName(); - } + // Class template for adding to a sorted, unique list + template + struct InsertToSet; - private: - // Get a list of indices with a value of 1 among the features - template - static void CollectActiveIndices( - const Position& pos, const TriggerEvent trigger, const Color perspective, - IndexListType* const active) { - Tail::CollectActiveIndices(pos, trigger, perspective, active); - if (Head::kRefreshTrigger == trigger) { - const auto start = active->size(); - Head::AppendActiveIndices(pos, perspective, active); - for (auto i = start; i < active->size(); ++i) { - (*active)[i] += Tail::kDimensions; + template + struct InsertToSet, AnotherValue> { + using Result = + std::conditional_t< + CompileTimeList::Contains(AnotherValue), + CompileTimeList, + std::conditional_t< + (AnotherValue < First), + CompileTimeList, + typename AppendToList, AnotherValue>::Result, + First + >::Result + > + >; + }; + + template + struct InsertToSet, Value> { + using Result = CompileTimeList; + }; + + // Base class of feature set + template + class FeatureSetBase { + + public: + // Get a list of indices for active features + template + static void AppendActiveIndices( + const Position& pos, TriggerEvent trigger, IndexListType active[2]) { + + for (Color perspective : { WHITE, BLACK }) { + Derived::CollectActiveIndices( + pos, trigger, perspective, &active[perspective]); + } } - } - } - // Get a list of indices whose values have changed from the previous one in the feature quantity - template - static void CollectChangedIndices( - const Position& pos, const TriggerEvent trigger, const Color perspective, - IndexListType* const removed, IndexListType* const added) { - Tail::CollectChangedIndices(pos, trigger, perspective, removed, added); - if (Head::kRefreshTrigger == trigger) { - const auto start_removed = removed->size(); - const auto start_added = added->size(); - Head::AppendChangedIndices(pos, perspective, removed, added); - for (auto i = start_removed; i < removed->size(); ++i) { - (*removed)[i] += Tail::kDimensions; + // Get a list of indices for recently changed features + template + static void AppendChangedIndices( + const PositionType& pos, TriggerEvent trigger, + IndexListType removed[2], IndexListType added[2], bool reset[2]) { + + const auto& dp = pos.state()->dirtyPiece; + + for (Color perspective : { WHITE, BLACK }) { + switch (trigger) { + case TriggerEvent::kNone: + break; + case TriggerEvent::kFriendKingMoved: + if (dp.dirty_num == 0) continue; + reset[perspective] = dp.piece[0] == make_piece(perspective, KING); + break; + case TriggerEvent::kEnemyKingMoved: + if (dp.dirty_num == 0) continue; + reset[perspective] = dp.piece[0] == make_piece(~perspective, KING); + break; + case TriggerEvent::kAnyKingMoved: + if (dp.dirty_num == 0) continue; + reset[perspective] = type_of(dp.piece[0]) == KING; + break; + case TriggerEvent::kAnyPieceMoved: + reset[perspective] = true; + break; + default: + assert(false); + break; + } + + if (reset[perspective]) { + Derived::CollectActiveIndices( + pos, trigger, perspective, &added[perspective]); + } else { + Derived::CollectChangedIndices( + pos, trigger, perspective, + &removed[perspective], &added[perspective]); + } + } } - for (auto i = start_added; i < added->size(); ++i) { - (*added)[i] += Tail::kDimensions; + }; + + // Class template that represents the feature set + // do internal processing in reverse order of template arguments in order to linearize the amount of calculation at runtime + template + class FeatureSet : + public FeatureSetBase< + FeatureSet + > { + + private: + using Head = FirstFeatureType; + using Tail = FeatureSet; + + public: + // Hash value embedded in the evaluation function file + static constexpr std::uint32_t kHashValue = + Head::kHashValue ^ (Tail::kHashValue << 1) ^ (Tail::kHashValue >> 31); + + // number of feature dimensions + static constexpr IndexType kDimensions = + Head::kDimensions + Tail::kDimensions; + + // The maximum value of the number of indexes whose value is 1 at the same time among the feature values + static constexpr IndexType kMaxActiveDimensions = + Head::kMaxActiveDimensions + Tail::kMaxActiveDimensions; + + // List of timings to perform all calculations instead of difference calculation + using SortedTriggerSet = typename InsertToSet::Result; + + static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues; + + // Get the feature quantity name + static std::string GetName() { + return std::string(Head::kName) + "+" + Tail::GetName(); } - } - } - // Make the base class and the class template that recursively uses itself a friend - friend class FeatureSetBase; - template - friend class FeatureSet; - }; + private: + // Get a list of indices with a value of 1 among the features + template + static void CollectActiveIndices( + const Position& pos, const TriggerEvent trigger, const Color perspective, + IndexListType* const active) { + Tail::CollectActiveIndices(pos, trigger, perspective, active); + if (Head::kRefreshTrigger == trigger) { + const auto start = active->size(); + Head::AppendActiveIndices(pos, perspective, active); - // Class template that represents the feature set - template - class FeatureSet : public FeatureSetBase> { + for (auto i = start; i < active->size(); ++i) { + (*active)[i] += Tail::kDimensions; + } + } + } - public: - // Hash value embedded in the evaluation file - static constexpr std::uint32_t kHashValue = FeatureType::kHashValue; - // Number of feature dimensions - static constexpr IndexType kDimensions = FeatureType::kDimensions; - // Maximum number of simultaneously active features - static constexpr IndexType kMaxActiveDimensions = - FeatureType::kMaxActiveDimensions; - // Trigger for full calculation instead of difference calculation - using SortedTriggerSet = - CompileTimeList; - static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues; + // Get a list of indices whose values have changed from the previous one in the feature quantity + template + static void CollectChangedIndices( + const Position& pos, const TriggerEvent trigger, const Color perspective, + IndexListType* const removed, IndexListType* const added) { + Tail::CollectChangedIndices(pos, trigger, perspective, removed, added); + if (Head::kRefreshTrigger == trigger) { + const auto start_removed = removed->size(); + const auto start_added = added->size(); + Head::AppendChangedIndices(pos, perspective, removed, added); - // Get the feature quantity name - static std::string GetName() { - return FeatureType::kName; - } + for (auto i = start_removed; i < removed->size(); ++i) { + (*removed)[i] += Tail::kDimensions; + } - private: - // Get a list of indices for active features - static void CollectActiveIndices( - const Position& pos, const TriggerEvent trigger, const Color perspective, - IndexList* const active) { - if (FeatureType::kRefreshTrigger == trigger) { - FeatureType::AppendActiveIndices(pos, perspective, active); - } - } + for (auto i = start_added; i < added->size(); ++i) { + (*added)[i] += Tail::kDimensions; + } + } + } - // Get a list of indices for recently changed features - static void CollectChangedIndices( - const Position& pos, const TriggerEvent trigger, const Color perspective, - IndexList* const removed, IndexList* const added) { + // Make the base class and the class template that recursively uses itself a friend + friend class FeatureSetBase; - if (FeatureType::kRefreshTrigger == trigger) { - FeatureType::AppendChangedIndices(pos, perspective, removed, added); - } - } + template + friend class FeatureSet; + }; - // Make the base class and the class template that recursively uses itself a friend - friend class FeatureSetBase; - template - friend class FeatureSet; - }; + // Class template that represents the feature set + template + class FeatureSet : public FeatureSetBase> { + + public: + // Hash value embedded in the evaluation file + static constexpr std::uint32_t kHashValue = FeatureType::kHashValue; + + // Number of feature dimensions + static constexpr IndexType kDimensions = FeatureType::kDimensions; + + // Maximum number of simultaneously active features + static constexpr IndexType kMaxActiveDimensions = + FeatureType::kMaxActiveDimensions; + + // Trigger for full calculation instead of difference calculation + using SortedTriggerSet = + CompileTimeList; + + static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues; + + // Get the feature quantity name + static std::string GetName() { + return FeatureType::kName; + } + + private: + // Get a list of indices for active features + static void CollectActiveIndices( + const Position& pos, const TriggerEvent trigger, const Color perspective, + IndexList* const active) { + + if (FeatureType::kRefreshTrigger == trigger) { + FeatureType::AppendActiveIndices(pos, perspective, active); + } + } + + // Get a list of indices for recently changed features + static void CollectChangedIndices( + const Position& pos, const TriggerEvent trigger, const Color perspective, + IndexList* const removed, IndexList* const added) { + + if (FeatureType::kRefreshTrigger == trigger) { + FeatureType::AppendChangedIndices(pos, perspective, removed, added); + } + } + + // Make the base class and the class template that recursively uses itself a friend + friend class FeatureSetBase; + + template + friend class FeatureSet; + }; } // namespace Eval::NNUE::Features diff --git a/src/nnue/features/features_common.h b/src/nnue/features/features_common.h index 656502a3..671ceeb9 100644 --- a/src/nnue/features/features_common.h +++ b/src/nnue/features/features_common.h @@ -1,19 +1,19 @@ /* - Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file) + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2020 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 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. + 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 . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ //Common header of input features of NNUE evaluation function @@ -21,29 +21,30 @@ #ifndef NNUE_FEATURES_COMMON_H_INCLUDED #define NNUE_FEATURES_COMMON_H_INCLUDED -#include "../../evaluate.h" -#include "../nnue_common.h" +#include "evaluate.h" + +#include "nnue/nnue_common.h" namespace Eval::NNUE::Features { - class IndexList; + class IndexList; - template - class FeatureSet; + template + class FeatureSet; - // Trigger to perform full calculations instead of difference only - enum class TriggerEvent { - kNone, // Calculate the difference whenever possible - kFriendKingMoved, // calculate full evaluation when own king moves - kEnemyKingMoved, // calculate full evaluation when opponent king moves - kAnyKingMoved, // calculate full evaluation when any king moves - kAnyPieceMoved, // always calculate full evaluation - }; + // Trigger to perform full calculations instead of difference only + enum class TriggerEvent { + kNone, // Calculate the difference whenever possible + kFriendKingMoved, // calculate full evaluation when own king moves + kEnemyKingMoved, // calculate full evaluation when opponent king moves + kAnyKingMoved, // calculate full evaluation when any king moves + kAnyPieceMoved, // always calculate full evaluation + }; - enum class Side { - kFriend, // side to move - kEnemy, // opponent - }; + enum class Side { + kFriend, // side to move + kEnemy, // opponent + }; } // namespace Eval::NNUE::Features diff --git a/src/nnue/features/half_kp.cpp b/src/nnue/features/half_kp.cpp index ae1d697f..17b50472 100644 --- a/src/nnue/features/half_kp.cpp +++ b/src/nnue/features/half_kp.cpp @@ -1,19 +1,19 @@ /* - Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file) + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2020 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 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. + 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 . + 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 @@ -23,51 +23,59 @@ namespace Eval::NNUE::Features { - // Orient a square according to perspective (flip rank for black) - inline Square orient(Color perspective, Square s) { - return Square(int(s) ^ (bool(perspective) * SQ_A8)); - } - - // Find the index of the feature quantity from the king position and PieceSquare - template - inline IndexType HalfKP::MakeIndex( - Color perspective, Square s, Piece pc, Square ksq) { - - return IndexType(orient(perspective, s) + kpp_board_index[pc][perspective] + PS_END * ksq); - } - - // Get a list of indices for active features - template - void HalfKP::AppendActiveIndices( - const Position& pos, Color perspective, IndexList* active) { - - Square ksq = orient(perspective, pos.square(AssociatedKing == Side::kFriend ? perspective : ~perspective)); - Bitboard bb = pos.pieces() & ~pos.pieces(KING); - while (bb) { - Square s = pop_lsb(&bb); - active->push_back(MakeIndex(perspective, s, pos.piece_on(s), ksq)); + // Orient a square according to perspective (flip rank for black) + inline Square orient(Color perspective, Square s) { + return Square(int(s) ^ (bool(perspective) * SQ_A8)); } - } - // Get a list of indices for recently changed features - template - void HalfKP::AppendChangedIndices( - const Position& pos, Color perspective, - IndexList* removed, IndexList* added) { + // Find the index of the feature quantity from the king position and PieceSquare + template + inline IndexType HalfKP::MakeIndex( + Color perspective, Square s, Piece pc, Square ksq) { - Square ksq = orient(perspective, pos.square(AssociatedKing == Side::kFriend ? perspective : ~perspective)); - const auto& dp = pos.state()->dirtyPiece; - for (int i = 0; i < dp.dirty_num; ++i) { - Piece pc = dp.piece[i]; - if (type_of(pc) == KING) continue; - if (dp.from[i] != SQ_NONE) - removed->push_back(MakeIndex(perspective, dp.from[i], pc, ksq)); - if (dp.to[i] != SQ_NONE) - added->push_back(MakeIndex(perspective, dp.to[i], pc, ksq)); + return IndexType(orient(perspective, s) + kpp_board_index[pc][perspective] + PS_END * ksq); } - } - template class HalfKP; - template class HalfKP; + // Get a list of indices for active features + template + void HalfKP::AppendActiveIndices( + const Position& pos, Color perspective, IndexList* active) { + + Square ksq = orient(perspective, pos.square(AssociatedKing == Side::kFriend ? perspective : ~perspective)); + Bitboard bb = pos.pieces() & ~pos.pieces(KING); + while (bb) { + Square s = pop_lsb(&bb); + active->push_back(MakeIndex(perspective, s, pos.piece_on(s), ksq)); + } + } + + // Get a list of indices for recently changed features + template + void HalfKP::AppendChangedIndices( + const Position& pos, Color perspective, + IndexList* removed, IndexList* added) { + + Square ksq = orient( + perspective, + pos.square( + AssociatedKing == Side::kFriend ? perspective : ~perspective)); + + const auto& dp = pos.state()->dirtyPiece; + for (int i = 0; i < dp.dirty_num; ++i) { + Piece pc = dp.piece[i]; + + if (type_of(pc) == KING) + continue; + + if (dp.from[i] != SQ_NONE) + removed->push_back(MakeIndex(perspective, dp.from[i], pc, ksq)); + + if (dp.to[i] != SQ_NONE) + added->push_back(MakeIndex(perspective, dp.to[i], pc, ksq)); + } + } + + template class HalfKP; + template class HalfKP; } // namespace Eval::NNUE::Features diff --git a/src/nnue/features/half_kp.h b/src/nnue/features/half_kp.h index 23e8beb6..834f800e 100644 --- a/src/nnue/features/half_kp.h +++ b/src/nnue/features/half_kp.h @@ -1,65 +1,69 @@ /* - Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file) + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2020 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 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. + 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 . + 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 - #ifndef NNUE_FEATURES_HALF_KP_H_INCLUDED #define NNUE_FEATURES_HALF_KP_H_INCLUDED -#include "../../evaluate.h" #include "features_common.h" +#include "evaluate.h" + +//Definition of input features HalfKP of NNUE evaluation function namespace Eval::NNUE::Features { - // Feature HalfKP: Combination of the position of own king - // and the position of pieces other than kings - template - class HalfKP { + // Feature HalfKP: Combination of the position of own king + // and the position of pieces other than kings + template + class HalfKP { - public: - // Feature name - static constexpr const char* kName = (AssociatedKing == Side::kFriend) ? - "HalfKP(Friend)" : "HalfKP(Enemy)"; - // Hash value embedded in the evaluation file - static constexpr std::uint32_t kHashValue = - 0x5D69D5B9u ^ (AssociatedKing == Side::kFriend); - // Number of feature dimensions - static constexpr IndexType kDimensions = - static_cast(SQUARE_NB) * static_cast(PS_END); - // Maximum number of simultaneously active features - static constexpr IndexType kMaxActiveDimensions = 30; // Kings don't count - // Trigger for full calculation instead of difference calculation - static constexpr TriggerEvent kRefreshTrigger = - (AssociatedKing == Side::kFriend) ? - TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved; + public: + // Feature name + static constexpr const char* kName = (AssociatedKing == Side::kFriend) ? + "HalfKP(Friend)" : "HalfKP(Enemy)"; - // Get a list of indices for active features - static void AppendActiveIndices(const Position& pos, Color perspective, - IndexList* active); + // Hash value embedded in the evaluation file + static constexpr std::uint32_t kHashValue = + 0x5D69D5B9u ^ (AssociatedKing == Side::kFriend); - // Get a list of indices for recently changed features - static void AppendChangedIndices(const Position& pos, Color perspective, - IndexList* removed, IndexList* added); + // Number of feature dimensions + static constexpr IndexType kDimensions = + static_cast(SQUARE_NB) * static_cast(PS_END); - private: - // Index of a feature for a given king position and another piece on some square - static IndexType MakeIndex(Color perspective, Square s, Piece pc, Square sq_k); - }; + // Maximum number of simultaneously active features + static constexpr IndexType kMaxActiveDimensions = 30; // Kings don't count + + // Trigger for full calculation instead of difference calculation + static constexpr TriggerEvent kRefreshTrigger = + (AssociatedKing == Side::kFriend) ? + TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved; + + // Get a list of indices for active features + static void AppendActiveIndices(const Position& pos, Color perspective, + IndexList* active); + + // Get a list of indices for recently changed features + static void AppendChangedIndices(const Position& pos, Color perspective, + IndexList* removed, IndexList* added); + + private: + // Index of a feature for a given king position and another piece on some square + static IndexType MakeIndex(Color perspective, Square s, Piece pc, Square sq_k); + }; } // namespace Eval::NNUE::Features diff --git a/src/nnue/features/half_relative_kp.cpp b/src/nnue/features/half_relative_kp.cpp index 6b456a1f..5ab22890 100644 --- a/src/nnue/features/half_relative_kp.cpp +++ b/src/nnue/features/half_relative_kp.cpp @@ -1,74 +1,80 @@ -//Definition of input features HalfRelativeKP of NNUE evaluation function - -#include "half_relative_kp.h" +#include "half_relative_kp.h" #include "index_list.h" -namespace Eval { +//Definition of input features HalfRelativeKP of NNUE evaluation function +namespace Eval::NNUE::Features { -namespace NNUE { + // Orient a square according to perspective (flip rank for black) + inline Square orient(Color perspective, Square s) { + return Square(int(s) ^ (bool(perspective) * SQ_A8)); + } -namespace Features { + // Find the index of the feature quantity from the ball position and PieceSquare + template + inline IndexType HalfRelativeKP::MakeIndex( + Color perspective, Square s, Piece pc, Square sq_k) { + const IndexType p = IndexType(orient(perspective, s) + kpp_board_index[pc][perspective]); + return MakeIndex(sq_k, p); + } -// Orient a square according to perspective (flip rank for black) -inline Square orient(Color perspective, Square s) { - return Square(int(s) ^ (bool(perspective) * SQ_A8)); -} + // Find the index of the feature quantity from the ball position and PieceSquare + template + inline IndexType HalfRelativeKP::MakeIndex( + Square sq_k, IndexType p) { -// Find the index of the feature quantity from the ball position and PieceSquare -template -inline IndexType HalfRelativeKP::MakeIndex( - Color perspective, Square s, Piece pc, Square sq_k) { - const IndexType p = IndexType(orient(perspective, s) + kpp_board_index[pc][perspective]); - return MakeIndex(sq_k, p); -} + constexpr IndexType W = kBoardWidth; + constexpr IndexType H = kBoardHeight; + const IndexType piece_index = (p - PS_W_PAWN) / SQUARE_NB; + const Square sq_p = static_cast((p - PS_W_PAWN) % SQUARE_NB); + const IndexType relative_file = file_of(sq_p) - file_of(sq_k) + (W / 2); + const IndexType relative_rank = rank_of(sq_p) - rank_of(sq_k) + (H / 2); + return H * W * piece_index + H * relative_file + relative_rank; + } -// Find the index of the feature quantity from the ball position and PieceSquare -template -inline IndexType HalfRelativeKP::MakeIndex( - Square sq_k, IndexType p) { - constexpr IndexType W = kBoardWidth; - constexpr IndexType H = kBoardHeight; - const IndexType piece_index = (p - PS_W_PAWN) / SQUARE_NB; - const Square sq_p = static_cast((p - PS_W_PAWN) % SQUARE_NB); - const IndexType relative_file = file_of(sq_p) - file_of(sq_k) + (W / 2); - const IndexType relative_rank = rank_of(sq_p) - rank_of(sq_k) + (H / 2); - return H * W * piece_index + H * relative_file + relative_rank; -} + // Get a list of indices with a value of 1 among the features + template + void HalfRelativeKP::AppendActiveIndices( + const Position& pos, Color perspective, IndexList* active) { -// Get a list of indices with a value of 1 among the features -template -void HalfRelativeKP::AppendActiveIndices( - const Position& pos, Color perspective, IndexList* active) { - Square ksq = orient(perspective, pos.square(AssociatedKing == Side::kFriend ? perspective : ~perspective)); - Bitboard bb = pos.pieces() & ~pos.pieces(KING); - while (bb) { - Square s = pop_lsb(&bb); - active->push_back(MakeIndex(perspective, s, pos.piece_on(s), ksq)); - } -} + Square ksq = orient( + perspective, + pos.square( + AssociatedKing == Side::kFriend ? perspective : ~perspective)); -// Get a list of indices whose values ​​have changed from the previous one in the feature quantity -template -void HalfRelativeKP::AppendChangedIndices( - const Position& pos, Color perspective, - IndexList* removed, IndexList* added) { - Square ksq = orient(perspective, pos.square(AssociatedKing == Side::kFriend ? perspective : ~perspective)); - const auto& dp = pos.state()->dirtyPiece; - for (int i = 0; i < dp.dirty_num; ++i) { - Piece pc = dp.piece[i]; - if (type_of(pc) == KING) continue; - if (dp.from[i] != SQ_NONE) - removed->push_back(MakeIndex(perspective, dp.from[i], pc, ksq)); - if (dp.to[i] != SQ_NONE) - added->push_back(MakeIndex(perspective, dp.to[i], pc, ksq)); - } -} + Bitboard bb = pos.pieces() & ~pos.pieces(KING); + while (bb) { + Square s = pop_lsb(&bb); + active->push_back(MakeIndex(perspective, s, pos.piece_on(s), ksq)); + } + } -template class HalfRelativeKP; -template class HalfRelativeKP; + // Get a list of indices whose values ​​have changed from the previous one in the feature quantity + template + void HalfRelativeKP::AppendChangedIndices( + const Position& pos, Color perspective, + IndexList* removed, IndexList* added) { -} // namespace Features + Square ksq = orient( + perspective, + pos.square( + AssociatedKing == Side::kFriend ? perspective : ~perspective)); -} // namespace NNUE + const auto& dp = pos.state()->dirtyPiece; + for (int i = 0; i < dp.dirty_num; ++i) { + Piece pc = dp.piece[i]; -} // namespace Eval + if (type_of(pc) == KING) + continue; + + if (dp.from[i] != SQ_NONE) + removed->push_back(MakeIndex(perspective, dp.from[i], pc, ksq)); + + if (dp.to[i] != SQ_NONE) + added->push_back(MakeIndex(perspective, dp.to[i], pc, ksq)); + } + } + + template class HalfRelativeKP; + template class HalfRelativeKP; + +} // namespace Eval::NNUE::Features diff --git a/src/nnue/features/half_relative_kp.h b/src/nnue/features/half_relative_kp.h index 1b384c14..cc1e136f 100644 --- a/src/nnue/features/half_relative_kp.h +++ b/src/nnue/features/half_relative_kp.h @@ -1,61 +1,61 @@ -//Definition of input features HalfRelativeKP of NNUE evaluation function - -#ifndef _NNUE_FEATURES_HALF_RELATIVE_KP_H_ +#ifndef _NNUE_FEATURES_HALF_RELATIVE_KP_H_ #define _NNUE_FEATURES_HALF_RELATIVE_KP_H_ -#include "../../evaluate.h" #include "features_common.h" -namespace Eval { +#include "evaluate.h" -namespace NNUE { +//Definition of input features HalfRelativeKP of NNUE evaluation function +namespace Eval::NNUE::Features { -namespace Features { + // Feature HalfRelativeKP: Relative position of each piece other than the ball based on own ball or enemy ball + template + class HalfRelativeKP { + public: + // feature quantity name + static constexpr const char* kName = (AssociatedKing == Side::kFriend) ? + "HalfRelativeKP(Friend)" : "HalfRelativeKP(Enemy)"; -// Feature HalfRelativeKP: Relative position of each piece other than the ball based on own ball or enemy ball -template -class HalfRelativeKP { - public: - // feature quantity name - static constexpr const char* kName = (AssociatedKing == Side::kFriend) ? - "HalfRelativeKP(Friend)" : "HalfRelativeKP(Enemy)"; - // Hash value embedded in the evaluation function file - static constexpr std::uint32_t kHashValue = - 0xF9180919u ^ (AssociatedKing == Side::kFriend); - // Piece type excluding balls - static constexpr IndexType kNumPieceKinds = 5 * 2; - // width of the virtual board with the ball in the center - static constexpr IndexType kBoardWidth = FILE_NB * 2 - 1; - // height of a virtual board with balls in the center - static constexpr IndexType kBoardHeight = RANK_NB * 2 - 1; - // number of feature dimensions - static constexpr IndexType kDimensions = - kNumPieceKinds * kBoardHeight * kBoardWidth; - // The maximum value of the number of indexes whose value is 1 at the same time among the feature values - static constexpr IndexType kMaxActiveDimensions = 30; // Kings don't count - // Timing of full calculation instead of difference calculation - static constexpr TriggerEvent kRefreshTrigger = - (AssociatedKing == Side::kFriend) ? - TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved; + // Hash value embedded in the evaluation function file + static constexpr std::uint32_t kHashValue = + 0xF9180919u ^ (AssociatedKing == Side::kFriend); - // Get a list of indices with a value of 1 among the features - static void AppendActiveIndices(const Position& pos, Color perspective, - IndexList* active); + // Piece type excluding balls + static constexpr IndexType kNumPieceKinds = 5 * 2; - // Get a list of indices whose values ​​have changed from the previous one in the feature quantity - static void AppendChangedIndices(const Position& pos, Color perspective, - IndexList* removed, IndexList* added); + // width of the virtual board with the ball in the center + static constexpr IndexType kBoardWidth = FILE_NB * 2 - 1; - // Find the index of the feature quantity from the ball position and PieceSquare - static IndexType MakeIndex(Square s, IndexType p); - // Find the index of the feature quantity from the ball position and PieceSquare - static IndexType MakeIndex(Color perspective, Square s, Piece pc, Square sq_k); -}; + // height of a virtual board with balls in the center + static constexpr IndexType kBoardHeight = RANK_NB * 2 - 1; -} // namespace Features + // number of feature dimensions + static constexpr IndexType kDimensions = + kNumPieceKinds * kBoardHeight * kBoardWidth; -} // namespace NNUE + // The maximum value of the number of indexes whose value is 1 at the same time among the feature values + static constexpr IndexType kMaxActiveDimensions = 30; // Kings don't count -} // namespace Eval + // Timing of full calculation instead of difference calculation + static constexpr TriggerEvent kRefreshTrigger = + (AssociatedKing == Side::kFriend) ? + TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved; + + // Get a list of indices with a value of 1 among the features + static void AppendActiveIndices(const Position& pos, Color perspective, + IndexList* active); + + // Get a list of indices whose values ​​have changed from the previous one in the feature quantity + static void AppendChangedIndices(const Position& pos, Color perspective, + IndexList* removed, IndexList* added); + + // Find the index of the feature quantity from the ball position and PieceSquare + static IndexType MakeIndex(Square s, IndexType p); + + // Find the index of the feature quantity from the ball position and PieceSquare + static IndexType MakeIndex(Color perspective, Square s, Piece pc, Square sq_k); + }; + +} // namespace Eval::NNUE::Features #endif diff --git a/src/nnue/features/index_list.h b/src/nnue/features/index_list.h index dd055fb3..6751b26c 100644 --- a/src/nnue/features/index_list.h +++ b/src/nnue/features/index_list.h @@ -1,19 +1,19 @@ /* - Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file) + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2020 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 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. + 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 . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ // Definition of index list of input features @@ -21,43 +21,43 @@ #ifndef NNUE_FEATURES_INDEX_LIST_H_INCLUDED #define NNUE_FEATURES_INDEX_LIST_H_INCLUDED -#include "../../position.h" -#include "../nnue_architecture.h" +#include "position.h" + +#include "nnue/nnue_architecture.h" namespace Eval::NNUE::Features { - // Class template used for feature index list - template - class ValueList { + // Class template used for feature index list + template + class ValueList { - public: - std::size_t size() const { return size_; } - void resize(std::size_t size) { size_ = size; } - void push_back(const T& value) { values_[size_++] = value; } - T& operator[](std::size_t index) { return values_[index]; } - T* begin() { return values_; } - T* end() { return values_ + size_; } - const T& operator[](std::size_t index) const { return values_[index]; } - const T* begin() const { return values_; } - const T* end() const { return values_ + size_; } + public: + std::size_t size() const { return size_; } + void resize(std::size_t size) { size_ = size; } + void push_back(const T& value) { values_[size_++] = value; } + T& operator[](std::size_t index) { return values_[index]; } + T* begin() { return values_; } + T* end() { return values_ + size_; } + const T& operator[](std::size_t index) const { return values_[index]; } + const T* begin() const { return values_; } + const T* end() const { return values_ + size_; } - void swap(ValueList& other) { - const std::size_t max_size = std::max(size_, other.size_); - for (std::size_t i = 0; i < max_size; ++i) { - std::swap(values_[i], other.values_[i]); - } - std::swap(size_, other.size_); - } + void swap(ValueList& other) { + const std::size_t max_size = std::max(size_, other.size_); + for (std::size_t i = 0; i < max_size; ++i) { + std::swap(values_[i], other.values_[i]); + } + std::swap(size_, other.size_); + } - private: - T values_[MaxSize] = {}; - std::size_t size_ = 0; - }; + private: + T values_[MaxSize] = {}; + std::size_t size_ = 0; + }; - //Type of feature index list - class IndexList - : public ValueList { - }; + //Type of feature index list + class IndexList : public ValueList { + }; } // namespace Eval::NNUE::Features diff --git a/src/nnue/features/k.cpp b/src/nnue/features/k.cpp index bd8d7dd0..8911abb7 100644 --- a/src/nnue/features/k.cpp +++ b/src/nnue/features/k.cpp @@ -1,46 +1,39 @@ -//Definition of input feature quantity K of NNUE evaluation function - -#include "k.h" +#include "k.h" #include "index_list.h" -namespace Eval { +//Definition of input feature quantity K of NNUE evaluation function +namespace Eval::NNUE::Features { -namespace NNUE { + // Orient a square according to perspective (flip rank for black) + inline Square orient(Color perspective, Square s) { + return Square(int(s) ^ (bool(perspective) * SQ_A8)); + } -namespace Features { + // Index of a feature for a given king position. + IndexType K::MakeIndex(Color perspective, Square s, Color king_color) { + return IndexType(orient(perspective, s) + bool(perspective ^ king_color) * 64); + } -// Orient a square according to perspective (flip rank for black) -inline Square orient(Color perspective, Square s) { - return Square(int(s) ^ (bool(perspective) * SQ_A8)); -} + // Get a list of indices with a value of 1 among the features + void K::AppendActiveIndices( + const Position& pos, Color perspective, IndexList* active) { -// Index of a feature for a given king position. -IndexType K::MakeIndex(Color perspective, Square s, Color king_color) { - return IndexType(orient(perspective, s) + bool(perspective ^ king_color) * 64); -} + for (auto color : Colors) { + active->push_back(MakeIndex(perspective, pos.square(color), color)); + } + } -// Get a list of indices with a value of 1 among the features -void K::AppendActiveIndices( - const Position& pos, Color perspective, IndexList* active) { - for (auto color : Colors) { - active->push_back(MakeIndex(perspective, pos.square(color), color)); - } -} + // Get a list of indices whose values ​​have changed from the previous one in the feature quantity + void K::AppendChangedIndices( + const Position& pos, Color perspective, + IndexList* removed, IndexList* added) { -// Get a list of indices whose values ​​have changed from the previous one in the feature quantity -void K::AppendChangedIndices( - const Position& pos, Color perspective, - IndexList* removed, IndexList* added) { - const auto& dp = pos.state()->dirtyPiece; - if (type_of(dp.piece[0]) == KING) - { - removed->push_back(MakeIndex(perspective, dp.from[0], color_of(dp.piece[0]))); - added->push_back(MakeIndex(perspective, dp.to[0], color_of(dp.piece[0]))); - } -} + const auto& dp = pos.state()->dirtyPiece; + if (type_of(dp.piece[0]) == KING) + { + removed->push_back(MakeIndex(perspective, dp.from[0], color_of(dp.piece[0]))); + added->push_back(MakeIndex(perspective, dp.to[0], color_of(dp.piece[0]))); + } + } -} // namespace Features - -} // namespace NNUE - -} // namespace Eval +} // namespace Eval::NNUE::Features diff --git a/src/nnue/features/k.h b/src/nnue/features/k.h index 9a0be4bb..c9726ab2 100644 --- a/src/nnue/features/k.h +++ b/src/nnue/features/k.h @@ -1,48 +1,44 @@ -//Definition of input feature quantity K of NNUE evaluation function - -#ifndef _NNUE_FEATURES_K_H_ +#ifndef _NNUE_FEATURES_K_H_ #define _NNUE_FEATURES_K_H_ -#include "../../evaluate.h" #include "features_common.h" -namespace Eval { +#include "evaluate.h" -namespace NNUE { +//Definition of input feature quantity K of NNUE evaluation function +namespace Eval::NNUE::Features { -namespace Features { + // Feature K: Ball position + class K { + public: + // feature quantity name + static constexpr const char* kName = "K"; -// Feature K: Ball position -class K { - public: - // feature quantity name - static constexpr const char* kName = "K"; - // Hash value embedded in the evaluation function file - static constexpr std::uint32_t kHashValue = 0xD3CEE169u; - // number of feature dimensions - static constexpr IndexType kDimensions = SQUARE_NB * 2; - // The maximum value of the number of indexes whose value is 1 at the same time among the feature values - static constexpr IndexType kMaxActiveDimensions = 2; - // Timing of full calculation instead of difference calculation - static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; + // Hash value embedded in the evaluation function file + static constexpr std::uint32_t kHashValue = 0xD3CEE169u; - // Get a list of indices with a value of 1 among the features - static void AppendActiveIndices(const Position& pos, Color perspective, - IndexList* active); + // number of feature dimensions + static constexpr IndexType kDimensions = SQUARE_NB * 2; - // Get a list of indices whose values ​​have changed from the previous one in the feature quantity - static void AppendChangedIndices(const Position& pos, Color perspective, - IndexList* removed, IndexList* added); + // The maximum value of the number of indexes whose value is 1 at the same time among the feature values + static constexpr IndexType kMaxActiveDimensions = 2; -private: - // Index of a feature for a given king position. - static IndexType MakeIndex(Color perspective, Square s, Color king_color); -}; + // Timing of full calculation instead of difference calculation + static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; -} // namespace Features + // Get a list of indices with a value of 1 among the features + static void AppendActiveIndices(const Position& pos, Color perspective, + IndexList* active); -} // namespace NNUE + // Get a list of indices whose values ​​have changed from the previous one in the feature quantity + static void AppendChangedIndices(const Position& pos, Color perspective, + IndexList* removed, IndexList* added); -} // namespace Eval + private: + // Index of a feature for a given king position. + static IndexType MakeIndex(Color perspective, Square s, Color king_color); + }; + +} // namespace Eval::NNUE::Features #endif diff --git a/src/nnue/features/p.cpp b/src/nnue/features/p.cpp index 012311ac..b4757284 100644 --- a/src/nnue/features/p.cpp +++ b/src/nnue/features/p.cpp @@ -1,52 +1,49 @@ -//Definition of input feature P of NNUE evaluation function - -#include "p.h" +#include "p.h" #include "index_list.h" -namespace Eval { +//Definition of input feature P of NNUE evaluation function +namespace Eval::NNUE::Features { -namespace NNUE { + // Orient a square according to perspective (flip rank for black) + inline Square orient(Color perspective, Square s) { + return Square(int(s) ^ (bool(perspective) * SQ_A8)); + } -namespace Features { + // Find the index of the feature quantity from the king position and PieceSquare + inline IndexType P::MakeIndex( + Color perspective, Square s, Piece pc) { + return IndexType(orient(perspective, s) + kpp_board_index[pc][perspective]); + } -// Orient a square according to perspective (flip rank for black) -inline Square orient(Color perspective, Square s) { - return Square(int(s) ^ (bool(perspective) * SQ_A8)); -} + // Get a list of indices with a value of 1 among the features + void P::AppendActiveIndices( + const Position& pos, Color perspective, IndexList* active) { -// Find the index of the feature quantity from the king position and PieceSquare -inline IndexType P::MakeIndex( - Color perspective, Square s, Piece pc) { - return IndexType(orient(perspective, s) + kpp_board_index[pc][perspective]); -} + Bitboard bb = pos.pieces() & ~pos.pieces(KING); + while (bb) { + Square s = pop_lsb(&bb); + active->push_back(MakeIndex(perspective, s, pos.piece_on(s))); + } + } -// Get a list of indices with a value of 1 among the features -void P::AppendActiveIndices( - const Position& pos, Color perspective, IndexList* active) { - Bitboard bb = pos.pieces() & ~pos.pieces(KING); - while (bb) { - Square s = pop_lsb(&bb); - active->push_back(MakeIndex(perspective, s, pos.piece_on(s))); - } -} + // Get a list of indices whose values ​​have changed from the previous one in the feature quantity + void P::AppendChangedIndices( + const Position& pos, Color perspective, + IndexList* removed, IndexList* added) { -// Get a list of indices whose values ​​have changed from the previous one in the feature quantity -void P::AppendChangedIndices( - const Position& pos, Color perspective, - IndexList* removed, IndexList* added) { - const auto& dp = pos.state()->dirtyPiece; - for (int i = 0; i < dp.dirty_num; ++i) { - Piece pc = dp.piece[i]; - if (type_of(pc) == KING) continue; - if (dp.from[i] != SQ_NONE) - removed->push_back(MakeIndex(perspective, dp.from[i], pc)); - if (dp.to[i] != SQ_NONE) - added->push_back(MakeIndex(perspective, dp.to[i], pc)); - } -} + const auto& dp = pos.state()->dirtyPiece; + for (int i = 0; i < dp.dirty_num; ++i) { + Piece pc = dp.piece[i]; -} // namespace Features + if (type_of(pc) == KING) + continue; -} // namespace NNUE + if (dp.from[i] != SQ_NONE) + removed->push_back(MakeIndex(perspective, dp.from[i], pc)); -} // namespace Eval + if (dp.to[i] != SQ_NONE) + added->push_back(MakeIndex(perspective, dp.to[i], pc)); + } + } + +} // namespace Eval::NNUE::Features diff --git a/src/nnue/features/p.h b/src/nnue/features/p.h index 07d88952..6a8a5392 100644 --- a/src/nnue/features/p.h +++ b/src/nnue/features/p.h @@ -1,48 +1,44 @@ -//Definition of input feature P of NNUE evaluation function - -#ifndef _NNUE_FEATURES_P_H_ +#ifndef _NNUE_FEATURES_P_H_ #define _NNUE_FEATURES_P_H_ -#include "../../evaluate.h" #include "features_common.h" -namespace Eval { +#include "evaluate.h" -namespace NNUE { +//Definition of input feature P of NNUE evaluation function +namespace Eval::NNUE::Features { -namespace Features { + // Feature P: PieceSquare of pieces other than balls + class P { + public: + // feature quantity name + static constexpr const char* kName = "P"; -// Feature P: PieceSquare of pieces other than balls -class P { - public: - // feature quantity name - static constexpr const char* kName = "P"; - // Hash value embedded in the evaluation function file - static constexpr std::uint32_t kHashValue = 0x764CFB4Bu; - // number of feature dimensions - static constexpr IndexType kDimensions = PS_END; - // The maximum value of the number of indexes whose value is 1 at the same time among the feature values - static constexpr IndexType kMaxActiveDimensions = 30; // Kings don't count - // Timing of full calculation instead of difference calculation - static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; + // Hash value embedded in the evaluation function file + static constexpr std::uint32_t kHashValue = 0x764CFB4Bu; - // Get a list of indices with a value of 1 among the features - static void AppendActiveIndices(const Position& pos, Color perspective, - IndexList* active); + // number of feature dimensions + static constexpr IndexType kDimensions = PS_END; - // Get a list of indices whose values ​​have changed from the previous one in the feature quantity - static void AppendChangedIndices(const Position& pos, Color perspective, - IndexList* removed, IndexList* added); + // The maximum value of the number of indexes whose value is 1 at the same time among the feature values + static constexpr IndexType kMaxActiveDimensions = 30; // Kings don't count - private: - // Index of a feature for a given piece on some square - static IndexType MakeIndex(Color perspective, Square s, Piece pc); -}; + // Timing of full calculation instead of difference calculation + static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; -} // namespace Features + // Get a list of indices with a value of 1 among the features + static void AppendActiveIndices(const Position& pos, Color perspective, + IndexList* active); -} // namespace NNUE + // Get a list of indices whose values ​​have changed from the previous one in the feature quantity + static void AppendChangedIndices(const Position& pos, Color perspective, + IndexList* removed, IndexList* added); -} // namespace Eval + private: + // Index of a feature for a given piece on some square + static IndexType MakeIndex(Color perspective, Square s, Piece pc); + }; + +} // namespace Eval::NNUE::Features #endif