Add NNUE evaluation
[stockfish] / src / nnue / features / half_kp.cpp
1 /*
2   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3   Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
4
5   Stockfish is free software: you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation, either version 3 of the License, or
8   (at your option) any later version.
9
10   Stockfish is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 //Definition of input features HalfKP of NNUE evaluation function
20
21 #include "half_kp.h"
22 #include "index_list.h"
23
24 namespace Eval::NNUE::Features {
25
26   // Find the index of the feature quantity from the king position and PieceSquare
27   template <Side AssociatedKing>
28   inline IndexType HalfKP<AssociatedKing>::MakeIndex(Square sq_k, PieceSquare p) {
29     return static_cast<IndexType>(PS_END) * static_cast<IndexType>(sq_k) + p;
30   }
31
32   // Get pieces information
33   template <Side AssociatedKing>
34   inline void HalfKP<AssociatedKing>::GetPieces(
35       const Position& pos, Color perspective,
36       PieceSquare** pieces, Square* sq_target_k) {
37
38     *pieces = (perspective == BLACK) ?
39         pos.eval_list()->piece_list_fb() :
40         pos.eval_list()->piece_list_fw();
41     const PieceId target = (AssociatedKing == Side::kFriend) ?
42         static_cast<PieceId>(PIECE_ID_KING + perspective) :
43         static_cast<PieceId>(PIECE_ID_KING + ~perspective);
44     *sq_target_k = static_cast<Square>(((*pieces)[target] - PS_W_KING) % SQUARE_NB);
45   }
46
47   // Get a list of indices for active features
48   template <Side AssociatedKing>
49   void HalfKP<AssociatedKing>::AppendActiveIndices(
50       const Position& pos, Color perspective, IndexList* active) {
51
52     // Do nothing if array size is small to avoid compiler warning
53     if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
54
55     PieceSquare* pieces;
56     Square sq_target_k;
57     GetPieces(pos, perspective, &pieces, &sq_target_k);
58     for (PieceId i = PIECE_ID_ZERO; i < PIECE_ID_KING; ++i) {
59       if (pieces[i] != PS_NONE) {
60         active->push_back(MakeIndex(sq_target_k, pieces[i]));
61       }
62     }
63   }
64
65   // Get a list of indices for recently changed features
66   template <Side AssociatedKing>
67   void HalfKP<AssociatedKing>::AppendChangedIndices(
68       const Position& pos, Color perspective,
69       IndexList* removed, IndexList* added) {
70
71     PieceSquare* pieces;
72     Square sq_target_k;
73     GetPieces(pos, perspective, &pieces, &sq_target_k);
74     const auto& dp = pos.state()->dirtyPiece;
75     for (int i = 0; i < dp.dirty_num; ++i) {
76       if (dp.pieceId[i] >= PIECE_ID_KING) continue;
77       const auto old_p = static_cast<PieceSquare>(
78           dp.old_piece[i].from[perspective]);
79       if (old_p != PS_NONE) {
80         removed->push_back(MakeIndex(sq_target_k, old_p));
81       }
82       const auto new_p = static_cast<PieceSquare>(
83           dp.new_piece[i].from[perspective]);
84       if (new_p != PS_NONE) {
85         added->push_back(MakeIndex(sq_target_k, new_p));
86       }
87     }
88   }
89
90   template class HalfKP<Side::kFriend>;
91
92 }  // namespace Eval::NNUE::Features