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